Settlement Reports¶
Who this is for
Accounting and finance. You'll use this to reconcile what Reyder owes Axis Mobile after each consignment sale and to close out the books.
What you'll accomplish: verify each settlement report, match it to its auto-generated vendor bill, and mark it paid once the payment to Axis clears.
Before you start: reports are generated automatically when a delivery ships or a retail sale confirms. You don't create them manually.
What a settlement report is¶
A settlement report is the accounting document that says "here are the devices we sold on Axis's behalf, here's the commission Reyder kept, here's the amount Axis is owed."
Every consignment sale produces two paired reports:
| Report type | Who it belongs to | What it shows |
|---|---|---|
Owner report (SETTLE/OWN/...) |
Axis Mobile | IMEI, model, grade, owner amount, and summary totals. No customer, sale price, sale date, order number, or per-device commission. |
Consignee report (SETTLE/CON/...) |
Reyder Enterprises | Everything — IMEI, model, grade, sale price, customer, order number, commission, owner amount, link to the vendor bill. |
This asymmetry is deliberate and non-negotiable. Axis is the device owner, not Reyder's business partner. They're entitled to reconcile the amount owed on their devices; Reyder's customer, order, sale-date, and retail-price details stay on the consignee report.
What each side actually sees¶
Full picture — every field filled in, plus a link to the auto-generated vendor bill payable to Axis.

Same device, but the customer, order number, sale date, sale price, and per-device commission are not in the owner report line at all — not hidden, not stored. There's nothing for an Axis user to reveal even if they found a way to bypass the UI.

Compare what's on each report:
| Field | Owner sees | Consignee sees |
|---|---|---|
| IMEI | ✅ | ✅ |
| Model / Storage / Grade | ✅ | ✅ |
| Sale date | — | ✅ |
| Per-device commission | — | ✅ |
| Total commission | ✅ | ✅ |
| Owner amount | ✅ | ✅ |
| Sale price | — | ✅ |
| Customer name | — | ✅ |
| Sale order number | — | ✅ |
| Vendor bill link | — | ✅ |
Step 1 — Open the settlement reports list¶
Go to Inventory → Device Inventory → Settlement Reports.

The list shows all reports across both companies (filtered by what you have access to — an Axis user sees only SETTLE/OWN/*, a Reyder user sees both but can only open the owner reports read-only).
For typical daily reconciliation work, use the Pending Settlements filter (same menu) which shows only reports that haven't been marked paid yet.
Step 2 — Verify the report and its vendor bill¶
Open a consignee report. You'll see four sections:
- Report Details — type, agreement, SO, generation date
- Companies — owner and consignee
- Financial Summary — total devices, total sale price, total commission, total owner amount
- Payment — vendor bill reference and payment date (blank until paid)
Open the vendor bill¶
Click the Vendor Bill button at the top. This opens the auto-generated account.move (in_invoice) payable to Axis Mobile. The amount matches the Total Owner Amount on the settlement report exactly.
The bill was auto-posted at the moment the settlement report was created — so in normal operation you don't need to post it manually. Your job is to verify:
- Amount matches the report.
- Partner is the correct Axis Mobile vendor contact.
- Journal is your configured settlement journal (or a purchase journal fallback).
If anything looks wrong, don't modify the bill in place — raise it with whoever owns the device settlement flow. The bill and the report are linked via vendor_bill_id; unlinking them by hand breaks the paired-report accounting.
Check the paired report (optional)¶
From the consignee report, click the Paired Report button. That takes you to the Axis-side owner report — useful to confirm the two sides agree on device count and amount before payment.
Step 3 — Mark the report as paid¶
Once you've actually paid Axis (bank transfer, check, etc.) and the vendor bill is fully paid/reconciled in Odoo, come back to the consignee settlement report and click Mark as Paid. Owner reports are view-only for payment status.
The button validates the vendor bill before changing state. If the linked bill is missing or its payment_state is not paid, Odoo blocks the action and tells you the current bill payment status. Do the accounting reconciliation first, then return to the report.

That:
- Moves the report state from
ConfirmedtoPaid. - Records today as the payment date.
- Updates the same fields on the paired owner report.
- Updates each referenced device's
settlement_statustosettled, which closes the accounting loop on that specific IMEI.
Report states¶
- Draft — reports are almost never in this state. They're auto-confirmed at creation.
- Confirmed — exists, vendor bill has been created and posted, waiting for payment.
- Paid — you marked it paid; devices are flagged as settled.
Report totals¶
| Field | What it means |
|---|---|
| Total Devices | Count of device lines on this report |
| Total Sale Price | Sum of sale prices across all devices; shown only on consignee reports and not stored on owner-report lines |
| Total Commission | Sum of Reyder's commission across all devices |
| Total Owner Amount | Sum of what's owed to Axis — sale price − commission |
Download a PDF statement¶
Click Download PDF on the report form. You get a formatted PDF appropriate to the report type:
- Owner PDF — IMEI, model, storage, grade, owner amount. Nothing else.
- Consignee PDF — everything on the form, with the full sale detail.
Use the owner PDF when sending a statement to Axis. Use the consignee PDF for Reyder's internal records.
Common problems¶
The vendor bill doesn't match the report total
The report is the source of truth — it's computed from actual device records at creation time. If the bill diverges, the likely cause is someone edited the bill after it was auto-posted. Compare the bill's line amounts against the report's Device tab IMEI-by-IMEI. Re-issue the bill if needed; don't edit the report.
I can't see the consignee report — only the owner version
You're logged in as an Axis Mobile user, not a Reyder user. Axis users only see owner reports by design. If you need to see the consignee side, log in with a Reyder account.
A device shows up in the wrong settlement report
Each device is settled exactly once. If a device is appearing in a new report even though it was settled previously, check its settlement_status — it should read settled after the paired report was marked paid. If the status is wrong, the paired report for that device wasn't marked paid properly; find the earlier report and mark it.
No settlement report was created after a delivery
Settlement reports only generate for consignment devices — i.e. devices where the owner company differs from the selling company. If the device was owned by Reyder (not Axis), no settlement is needed. Check the device's owner_company_id.
The 'Mark as Paid' button is missing
The button appears only on confirmed consignee reports. It is hidden on owner reports by design, and it disappears once the report is already Paid. If it appears but raises an error, open the linked vendor bill and make sure it is paid/reconciled first.
Where to look for settlements in-app¶
| You want to see… | Go to |
|---|---|
| Every settlement report ever | Inventory → Device Inventory → Settlement Reports |
| Only reports awaiting payment | Inventory → Device Inventory → Pending Settlements |
| Only your company's pending | Inventory → Device Inventory → My Pending Settlements |
| Create settlements manually (bulk) | Inventory → Device Inventory → Settlement Wizard |
Under the hood¶
Technical details for developers
Model: consignment.settlement.report (+ consignment.settlement.report.line)
Record rule (defined in security.xml):
consignment.settlement.report. Enforces that an Axis user sees only reports where company_id == Axis, and vice versa. This is the primary data-separation mechanism.
The paired_report_id asymmetry
Only the consignee report stores paired_report_id pointing to the owner report. The owner report does not store a reverse reference. This blocks an Axis user from navigating owner → consignee even if they somehow gained ORM access. Combined with the record rule (which would block the consignee report anyway) this is belt-and-braces.
Line-level omission
_create_single_report('owner', ...) writes line records where sale_price, sale_order_name, customer_name are never set. Not nulled — just not included in the create() dict. If you dump the table directly, those columns are empty for owner-report lines.
Creation flow
create_paired_reports(lot_ids, sale_order) is the single entry point. Called from:
device.manifest._process_customer_delivery()when a delivery manifest completesdevice.retail.sale.action_confirm()for retail sales
Steps:
SELECT ... FOR UPDATE NOWAITon the relevantstock.lotrows to prevent double-settlement if the same delivery is processed twice concurrently.- Look up the active
device.consignment.agreementbetween owner and consignee. - Build the owner report via
_create_single_report('owner', ...)— uses.sudo()because the writing user's company is Reyder, not Axis. - Build the consignee report via
_create_single_report('consignee', ...). - Set
consignee.paired_report_id = owner.id. - Call
action_confirm()on both → auto-posts the vendor bill on the consignee side.
Vendor bill creation — _create_settlement_vendor_bill() on the consignee report:
- Uses
sudo().with_company(consignee)so the bill posts to the consignee's books. - Partner = owner company's
partner_id. - Amount =
total_owner_amount. - Journal =
settlement_journal_id(settings) with fallback to first available purchase journal. - Auto-posted, stored as
vendor_bill_id.
Mark paid — action_mark_paid():
- Require a consignee report in
confirmedstate. - Require a linked vendor bill with
payment_state == 'paid'. - Set
state='paid'on both paired reports. - Stamp
payment_date = fields.Date.today(). - For each
lot_idreferenced by report lines, setstock.lot.settlement_status = 'settled'.
Database constraints
UNIQUE(lot_id, report_id)onconsignment.settlement.report.line— an IMEI can appear at most once per report.
View-level enforcement
sale_order_id on the report form is wrapped in a <field> with invisible="report_type == 'owner'" so the UI doesn't leak SO references in owner-report rendering even when data is absent.