Odoo Walkthroughs
Walkthrough 01

Sales Order

From quotation to paid invoice — the complete sales-to-cash flow.

Phase 1

Place the Order

A salesperson opens the Sales app, creates a new quotation, captures customer + products, and saves. The quotation cannot be confirmed yet — confirmation is Phase 2.

0

Before you start — what must already exist

  • A customer profile in Contacts. If the customer is brand-new, an Admin (Sejal / Wesley) must create it first via the Contacts app → New. The customer's status will default to Pending until approved.
  • Products with prices, weights and rock-bottom prices set in the Products module.
  • Your user must have the Salesperson role (Bhadresh, Byron, Nikhil, Amit, Aboo) or be Admin.
📌 Onboarding a new customer

Customer onboarding is a separate procedure. See Sprint 1 User Guide TC 2.0 for the full flow: creating the main profile, adding invoicing-address branches, adding delivery-address contacts, and assigning a credit limit.

1

Create the quotation

— Bhadresh, Byron, Nikhil, Amit or Aboo.

Navigate to the Sales app → click New.

Select the customer from the Customer dropdown. The pricelist linked to that customer applies automatically; their default invoicing address and delivery address are inherited from the contact record.

Sprint 1 — creating a sales order
Sprint 1, p.4 — Salesperson creates a new quotation against an existing customer.
⚠ Customer status gates the order

If the customer status is Pending, the Confirm button will not appear. You can save the quotation but cannot proceed until an Admin approves the customer (Phase 1.5 below).

2

Confirm invoicing & delivery addresses

By default the quotation uses the customer's main address for both invoicing and delivery. To override (common for multi-branch customers):

  1. Click into the Invoice address field — pick the relevant accounting branch (e.g. "Head Office Accounts").
  2. Click into the Delivery address field — pick the branch / site that physically receives the goods.
Sprint 1 — selecting invoicing and delivery addresses on the SO
Sprint 1, p.22 — Choosing invoicing vs delivery branches on the quotation.
📌 Setting up branch addresses

Branches are added as child contacts under the main customer with the address type set to Invoice address or Delivery address. See Sprint 1, pages 17–21.

3

Add products & quantities

On the Order Lines tab, click Add a product for each item:

  1. Pick the product from the dropdown.
  2. Set the Quantity.
  3. Confirm the Unit Price — the pricelist auto-fills this. Only override it if the customer has a negotiated price.
Sprint 2 — adding products to a quotation
Sprint 2, p.17 — Order Lines with quantities and pricelist-driven unit prices.
🚫 Rock-bottom price floor

Every product has a rock-bottom price set on the product record. If you discount a line below that floor, the system will block confirmation and trigger a discount-approval activity for the Sales Manager (Kishan). See Phase 1.5 → Discount approval.

4

Save the quotation

Click Save (the cloud icon). Odoo assigns a SO### reference number.

At this point one of three things happens depending on customer + pricing state:

StateResult
Customer approved, prices ≥ rock-bottom, value within credit limitConfirm button visible — skip to Phase 2.
Customer status = PendingNo Confirm button. Go to Phase 1.5 → Customer approval.
Any line below rock-bottom OR total over credit limitConfirm visible but throws an approval error on click. Go to Phase 1.5.
Phase 1.5 — conditional

Approvals

Three gates can block confirmation: a pending customer, an excess discount, or an over-limit credit balance. Each routes to a different approver.

A

Approval 1 — Pending customer status

Trigger: Customer's status is Pending at the time of quoting.

How the salesperson raises it: On the quotation, hover the customer name → click the internal-link arrow → on the customer profile click Request for Approval.

Sprint 1 — requesting customer approval
Sprint 1, p.6–7 — Request for Approval button on the customer profile.

How Admin clears it: → click the Activities icon (top bar) → open the customer-approval activity. On the customer record:

  1. Change Customer Status to Approved (credit partner) — or COD if cash-on-delivery only.
  2. Open the Accounting tab → tick Partner Limit → enter the credit limit amount.
  3. Click Save.
  4. On the chatter, mark the activity Done.
Sprint 1 — setting the partner limit
Sprint 1, p.10–11 — Setting the partner credit limit on the customer record.

The salesperson can now reopen the quotation and click Confirm.

B

Approval 2 — Discount below rock-bottom price

Trigger: Salesperson sets a unit price below the product's rock-bottom and clicks Confirm.

An error message appears and an approval activity is logged to the Sales Manager (Kishan).

Sprint 2 — rock-bottom price violation error
Sprint 2, p.22–23 — Validation error blocks confirm; approval activity is created automatically.

How Kishan clears it: → click the notifications/activities icon → open the most recent Sales Order activity → on the quotation click Approve Discount. The order can now be confirmed.

C

Approval 3 — Sales order exceeds the customer's credit limit

Trigger: Sum of unpaid invoices + this order > the partner limit set on the customer's Accounting tab.

An approval-error message appears on Confirm, and activities are routed to Kishan and the Admin.

Sprint 1 — credit limit approval error
Sprint 1, p.14–15 — Over-limit approval error and notification.

How Kishan / Admin clears it: Activities icon → Sales Order activity → click Confirm on the activity card. The order is now approved.

📌 What counts toward the credit limit

Odoo compares the partner limit against the total open receivables for that customer (open invoices + draft sales orders), not a single transaction. If the customer is at 95% of limit, even a small new order can trigger this gate.

Phase 2

Confirm & Fulfil

Quotation becomes Sales Order, Odoo auto-generates a delivery, the warehouse picks the stock and validates the delivery — stock levels decrement.

5

Confirm the quotation

→ open the quotation → click Confirm.

Odoo immediately:

  • Converts the quotation reference (Q###) into a Sales Order (SO###).
  • Creates a linked delivery order in the Inventory app.
  • Reserves stock against on-hand quantity (if the Reserve rule is enabled on the warehouse).
Sprint 2 — delivery smart button on confirmed SO
Sprint 2, p.18 — The Delivery smart button appears on the confirmed sales order.
6

Inspect the auto-generated delivery

Click the Delivery smart button (top right of the SO). This jumps you to the linked OP/OUT/000… delivery record in the Inventory app.

The delivery moves through these states: DraftWaitingReadyDone. A freshly created delivery usually opens in Waiting — Odoo has not yet evaluated whether stock is available. Steps 7 and 8 walk you through the availability check and quantity confirmation; Step 9 is the actual validate.

Live Odoo — OP/OUT/00193 in Waiting state, both lines Not Available
Live Odoo — A just-created delivery OP/OUT/00193 in Waiting state. Both lines show Not Available until Check Availability is run.
📌 Two ways forward from here

From this point a sales order branches into two delivery paths:

  1. Standard delivery — the delivery is added to a vehicle batch with a route, a driver, and a scheduled date. See Walkthrough 03 — Vehicle Scheduling.
  2. Customer collection — the customer is collecting from our premises; the delivery is validated at the counter when they arrive. See Walkthrough 02 — Customer Collection.

The Steps 7–10 below are the same for both paths — they're how the delivery itself is processed inside Odoo.

7

Click "Check Availability"

Open the delivery record (Sales Order → Delivery smart button, or Inventory app → Operations → Deliveries → click the OP/OUT).

Click Check Availability in the top toolbar. Odoo evaluates stock against the source location (OP/Stock) and updates each line:

  • Available — stock is on hand and reserved for this delivery.
  • Not Available — either no physical stock or the stock is locked behind a lot tracking rule that hasn't been satisfied. See Step 8 to troubleshoot.

If every line is Available, the delivery state flips to Ready. Skip to Step 9.

If any line is still Not Available, continue to Step 8.

Live Odoo — after Check Availability, one line Available, one Not Available
Live Odoo — After clicking Check Availability, one product is now Available; the other remains Not Available due to lot tracking (see Step 8).
Live Odoo — second view of the Check Availability result on the delivery
Live Odoo — Second view of the same delivery after Check Availability, showing the line-level status breakdown.
8

Fix "Not Available" — usually lot tracking

A line stays Not Available for one of two reasons:

CauseWhat to do
No physical stock in OP/Stock Either receive more stock first, reduce the quantity on this line (Step 9), or split the order into a backorder for the missing portion (Step 10).
Lot tracking is blocking the issue — the product has Track Inventory by Lots enabled but no lot is assigned to this delivery line Open the product, turn off lot tracking (or assign a lot), then return to the delivery and re-Check Availability.

To turn off lot tracking on a product:

  1. On the delivery line, click the product name to open the product record.
  2. On the General Information tab, find Track Inventory.
  3. Untick the By Lots checkbox.
  4. Click Save.
  5. Use the breadcrumb to return to the delivery OP/OUT/000….
  6. Click Check Availability again — the line should now show Available.
Live Odoo — Product page showing the Track Inventory By Lots checkbox
Live Odoo — The Track Inventory "By Lots" checkbox on the product record. Untick this to release the line from lot-tracking blocking.
⚠ Why we disable lot tracking

Lot tracking is useful if we actually run lot management end-to-end. If lots haven't been assigned at receipt time, the lot-tracking rule blocks every outgoing delivery for that product — which is what's happening here. The practical fix at Olympic Paints today is to leave products as untracked. VERIFY: confirm with management whether lot tracking is a feature we intend to use long-term, or whether all products should be configured untracked at receipt.

9

Update the Quantity column to what was actually picked

Two columns on each line matter here:

  • Demand — what the customer ordered (read-only, mirrors the SO).
  • Quantity — what was actually picked in the warehouse. Editable. Defaults to match Demand; change it when the pick is partial.

Edit the Quantity on any line where the picked amount differs from the demand. Example: customer ordered 10 × 5L drums but the warehouse could only pick 9 — set Quantity to 9.00, leave Demand at 10.00.

Live Odoo — Quantity column being edited from 10 to 9
Live Odoo — Editing the Quantity column. Demand stays 10.00; Quantity drops to 9.00 to reflect the actual pick.
📌 This is also where lots are assigned, if used

If lot tracking is enabled and you didn't disable it in Step 8, click the Details link on each line to pick the specific lot being picked.

10

Validate the delivery (and create a backorder if needed)

With every line now Available and the Quantity set correctly, click Validate (top toolbar).

Live Odoo — Delivery in Ready state with both lines Available, Validate highlighted
Live Odoo — Delivery is in Ready state, all lines Available. The Validate button finalises the pick.

If you reduced any Quantity below the Demand on Step 9, Odoo prompts:

Live Odoo — Create Backorder popup
Live Odoo — The Create Backorder? popup appears whenever processed quantity is less than initial demand.
ChoiceWhat happens
Create BackorderCurrent delivery is marked Done for the picked quantity (e.g. 9 of 10). A new OP/OUT is created with the residual (1 unit) in Ready status, ready to be processed on a future pick.
No BackorderCurrent delivery is marked Done; the residual is written off — the customer is effectively short-supplied and the SO records 9 delivered against 10 ordered.
DiscardCancels the validate; nothing changes. Useful if you spot a mistake on the popup.

After clicking Create Backorder you'll see two deliveries linked to the same SO:

Live Odoo — Two delivery records: original Done, backorder Ready
Live Odoo — Two deliveries against S00457: OP/OUT/00193 Done (the 9 that were picked) and OP/OUT/00194 Ready (the 1 unit backorder).
✓ What "Validate" does
  • Stock decrements in OP/Stock by the picked Quantity (not the Demand).
  • The current delivery flips to Done.
  • The Sales Order's Delivered column updates to the picked Quantity.
  • A new backorder delivery is created in Ready if you chose Create Backorder.
  • Create Invoice becomes available on the SO.
Live Odoo — Sales Order showing Quantity 10, Delivered 9, Invoiced 0
Live Odoo — The Sales Order now shows three quantities per line: Quantity 10 (ordered), Delivered 9 (actually picked), Invoiced 0 (yet to be invoiced). Note the Delivery smart button shows 2 — the original plus the backorder.
Phase 3

Invoice & Collect

Create the customer invoice from the delivered Sales Order, send it for payment, and register the payment when it arrives.

11

Create the draft invoice from the Sales Order

Open the Sales Order (Sales app → Orders → Orders) and click Create Invoice.

Odoo offers three options on the popup:

OptionWhen to use
Regular invoiceStandard — invoice for the quantities actually delivered. Pick this for almost every Olympic Paints sale.
Down payment (percentage)If the customer pre-pays a % before delivery. Rarely used in our flow.
Down payment (fixed amount)Pre-payment for a fixed rand amount.

Pick Regular invoice → click Create and View Invoice. Odoo opens the draft invoice with a Draft status badge.

Live Odoo — Draft invoice showing ordered quantity 10, not delivered quantity 9
Live Odoo — Draft invoice pre-filled with the ordered quantity (10), not the delivered quantity (9). This MUST be corrected before confirming — see Step 12.
12

⚠ CRITICAL — Correct the invoice quantities to match what was delivered

🚫 Odoo pre-fills the invoice with the ORDERED quantity, not the DELIVERED quantity

In the example: customer ordered 10, we delivered 9 (with a 1-unit backorder). The draft invoice pre-populates the line at Quantity = 10. If you confirm without correcting, you will invoice the customer for stock they have not yet received.

Before clicking Confirm:

  1. On every line of the draft invoice, compare the Quantity column against what was actually delivered (see the Sales Order's Delivered column — Step 10's last screenshot).
  2. Edit the invoice Quantity down to match the delivered figure.
  3. If a backorder is going to be delivered later, the residual will be invoiced via a second Create Invoice run against the same SO once OP/OUT/00194 is validated. Do not bundle the future-delivery quantity into this invoice.
  4. Once the Quantity column matches Delivered on every line, click Confirm — the invoice number finalises (e.g. INV/26-27/0032) and the invoice status moves to Posted.
Live Odoo — Posted invoice with corrected quantity 9
Live Odoo — After correcting Quantity 10→9 and clicking Confirm: invoice posts as INV/26-27/0032, Total R 8,139.62 (correct), status Posted.
⚠ Quick sanity check before every Confirm

Eyeball the invoice Total against the Delivered subtotal on the SO. If they don't match, the Quantity column needs correcting somewhere. In this example: SO Delivered total = 9 × R479.77 + 6 × R460 = R 7,077.93 net + 15% VAT = R 8,139.62 ✓

13

Send the invoice to the customer

  1. On the posted invoice, click Send to email the PDF to the customer's billing contact. Body text can be edited before sending.
  2. Or click Print to generate the PDF for handover at the counter / via courier.
📌 Customers with portal access

If the customer has been granted portal access (Sprint 2 TC1.8), the invoice is immediately visible on their portal and they can pay online. See Customer portal below for the portal setup procedure.

Sprint 2 — customer viewing invoices via portal
Sprint 2, p.28 — Customers can view and pay invoices via the portal.
14

Register the payment

When the customer pays:

  1. Open the posted invoice.
  2. Click Register Payment.
  3. On the popup, confirm:
    • Journal — Bank (or Petty Cash for cash payments).
    • Amount — defaults to the full invoice; reduce for a partial payment.
    • Payment Date.
    • Memo — usually the EFT reference.
  4. Click Create Payment. The invoice flips to Paid (or Partial).
📷 VERIFY — screenshot needed from live system

Capture the Register Payment popup as it appears in our environment.

✓ End of the sales-to-cash flow

Invoice paid → customer's open balance reduced → Sales Order shows Fully Invoiced & Paid. The whole record stays searchable in Sales → Orders.

Variations

Alternative entry points

Two ways to start a sales order other than typing it line-by-line.

V1

Email order — import an Excel template

When a customer emails an order on the sales order template Excel sheet:

  1. (or any sales user).
  2. Navigate Sales app → Quotations.
  3. Click the ⚙ gear icon → Import records.
  4. Click Upload Data File → select the Excel order from your computer.
  5. The Partner ID column must match a customer name already on the system. The price is entered manually per line.
  6. Click Test. If green, click Import.

The records appear as draft quotations. Open each one to verify the order lines, then proceed normally from Step 4 — Save.

Sprint 2 — importing a sales order from Excel
Sprint 2, p.19–20 — Importing an emailed Excel order via the gear menu.
V2

Customer portal — letting customers view & pay online

One-time setup per customer:

  1. (Admin).
  2. Navigate Sales app → Orders → Customers → open the customer profile.
  3. Action menu → Grant portal access. This emails the customer an invitation to set a password.
  4. (Optional override:) Settings app → Manage Users → remove the Internal Users filter → open the customer record → Security tabChange Password to set a password on their behalf.

Once active, the customer logs in to the Odoo portal and can:

  • View their open invoices and pay them online.
  • Accept or reject quotations sent to them.
  • View order history.
Sprint 2 — granting portal access to a customer
Sprint 2, p.27 — Setting a portal password under the Security tab.