Skip to content

OVES ABS–Odoo Integration Handbook (n8n-led, Native Odoo Only)

Date: 2025-08-26 · Timezone: Asia/Singapore

This single document captures how OVES should run people, products, services, assets, billing, and payments across Odoo (system of record for people & money) and the ABS/Thing/Client microservices (systems of record for services, assets, and distributor ownership), with n8n as the integration glue.


0) Scope & First Principles

Business summary (for managers)

  • Odoo is the truth for people, companies, orders, invoices, payments, pricing, taxes, currency.
  • Client MS is the truth only for Client → Fleet (1-to-many ownership).
  • Thing MS is the truth only for Fleet → Item (1-to-many assignment) and station topology.
  • ABS governs ServicePlan (customer ↔ service bundle of assets) and payment instructions to Odoo.
  • Federation prevents duplication: each system owns its domain, Odoo mirrors context for accounting.

Notes to developers

Source-of-Truth (SoT) boundaries

Domain System of Record (SoT) In Odoo we store Write rules
People & Companies Odoo (res.partner, res.company) Full identity; ref holds external IDs Odoo owns create/update/merge; emit people.changed
Distributor ↦ Fleet ownership (Client→Fleet 1:N) Client MS Distributor as res.partner; Fleet as account.analytic.account (anchor only) Client pushes creates/updates of Fleets and their owner Distributor; Odoo never changes Fleet owner
Fleet ↦ Item (Fleet→Item 1:N) Thing MS Optional mirrors: stock.production.lot (Item serial), stock.location (station topology) Thing pushes item create/move/owner-of-stock (consignment) events; Odoo never edits Items
Commercial docs (SO/Invoice/Payment/Subscription) Odoo Full ledger & statuses ABS/Thing/Client consume facts; do not mutate accounting

Authority split: Odoo owns People & Money; Client owns who owns which Fleet; Thing owns which Items sit in which Fleet/station. All cross-links are federated, never duplicated.


1) Customers (People)

Business summary

  • Retail buyers and subscribers are “customers.”
  • For walk-in POS, we may not collect identity (anonymous customer).
  • For web and subscriptions, we collect minimal details and provide a portal.

Notes to developers

  • Model: res.partner (SoT = Odoo).
  • Key fields: is_company, name, email, phone, company_id, category_id (tags), ref (external IDs: client:user-…).
  • Portal users: res.users (group Portal) auto-linked to partner.
  • Dedupe: run contact merge periodically.

Decision matrix (create partner?)

Channel Create real partner? Typical practice
POS cash receipt No (use “Walk-in”) Fast checkout, no PII
POS with loyalty/invoice Yes (light profile) Name + phone/email
eCommerce Yes Auto via website signup/checkout
Subscription (BSS) Yes (required) KYC + portal

2) OVES Companies (Multi-Company)

Business summary

  • Each OVES operating entity is its own Odoo company.
  • Websites, warehouses, journals, and payment acquirers are scoped to that company.
  • Currency and tax logic follow the serving company.

Notes to developers

  • Model: res.company.
  • Currency: res.company.currency_id (base); sales currency via Pricelists.
  • Propagation: company_id exists on SO/Invoice/Subscription/Inventory.
  • Mapping:
  • Websitewebsite.company_id
  • POSpos.config.company_id
  • Subscriptionsale.subscription.company_id
  • Fiscal position for taxes: account.fiscal.position rules.

3) Franchises / Distributors (Client Service)

Business summary

  • Internal distributors = OVES companies.
  • External franchises = third-party dealers captured as partners.
  • Client microservice “owns” distributor hierarchy; Odoo mirrors enough to transact and report.

Notes to developers

  • Internal: use res.company.
  • External: res.partner (is_company=True, tag Distributor, ref=client:dist-…).
  • End-users under external distributors generally not created in Odoo (unless warranty/support/portal needed).
  • Settlements: wholesale invoices, or revenue share via credit notes based on analytic reports.
  • n8n upserts distributors to Odoo; Odoo’s company_id on partner = the selling OVES company.

Fleet ownership authority - The field account.analytic.account.partner_id (Fleet owner) is controlled by Client MS.
- n8n performs upsert of Fleet (create if missing; update partner_id, active, name/code/ref only).
- Do not allow Odoo UI to change partner_id on Fleets.
- Recommended: server action or record rule to block manual edits to Fleet partner_id.


4) Assets: FLEETs & ITEMs (Thing Service)

Business summary

  • FLEET is a financial/entitlement unit (e.g., “Nairobi Fleet 1”).
  • ITEM is a serialised asset (battery, cabinet slot).
  • Thing is the truth for both; Odoo mirrors only what it needs for accounting and traceability.

Notes to developers

  • FLEET ⇒ account.analytic.account
  • partner_id = owning Distributor (from Client MS).
  • company_id = OVES company.
  • code/ref = external Fleet ID.
  • ITEM ⇒ stock.production.lot (optional mirror)
  • lot.name = Thing Item ID (authoritative).
  • Creation, location changes, and ownership (consignment) arrive from Thing events only.
  • Odoo UI edits of mirrored Items should be disabled/flagged.
  • Containment rule: Fleet→Item membership is SoT = Thing. Odoo does not persist a Fleet FK on Items; only carries Fleet context on accounting lines.
  • Stations/Lockers ⇒ stock.location hierarchy, company-scoped.
  • Consignment ownership: stock.quant.owner_id / stock.move.owner_id.

5) Asset Accounts (Analytic, Deposits, Wallets)

Business summary

  • Fleet P&L is reported using analytic accounts.
  • Deposits are liabilities; top-ups/prepaid credits recognized on consumption.

Notes to developers

  • Fleet analytic: account.analytic.account.
  • Revenue/cost tagging always via Fleet analytic, not Item.
  • Deposits: liability account via product.
  • Prepaid credits: top-up product; recognize revenue via journal with analytic = Fleet.
  • No Item→Fleet FK in Odoo. Item membership is authoritative in Thing.

6) Payments & Billing (ABS ⇄ Odoo)

Business summary

  • ABS instructs Odoo to bill or collect.
  • Odoo returns a pay link and confirms when payment posts.
  • Two modes: Invoice-first or Pay-intent (top-up).
  • Both end in a signed payment.confirmed back to ABS.

Notes to developers

  • ServicePlan ref: carried in subscription.reference, account.move.invoice_origin, payment.transaction.reference.
  • Invoice-first: ABS requests invoice; Odoo returns pay link; PSP confirms; Odoo posts payment; callback.
  • Pay-intent: ABS requests intent; Odoo creates payment.transaction; PSP confirms; Odoo posts paid invoice; callback.
  • No Fleet or Item mutations in these flows.
  • Fleet reference used only for analytics; Item references optional (free text).
  • Security: HMAC, idempotency, timestamp checks.

7) POS (Shopfront B2C)

Business summary

  • POS sales are cash-like; receipts/invoices are paid instantly.
  • Usually book to a single Walk-in customer, unless named invoice/loyalty is requested.

Notes to developers

  • App: point_of_sale.
  • pos.config.company_id, bank/cash journals per company.
  • Default partner: “Retail Walk-in (POS)” with company_id.
  • Named invoice: create minimal partner.

8) eCommerce (Cash-only)

Business summary

  • Web checkout captures payment immediately; invoices close as paid.
  • Each site maps to one OVES company & currency.

Notes to developers

  • App: website_sale + payment acquirers.
  • website.company_idsale.order.company_id → invoice.
  • Currency via pricelist bound to website/country group.
  • Guest checkout: “Web Anonymous” partner.

9) Subscriptions / Service Plans (BSS)

Business summary

  • Recurring plans billed monthly/weekly; entitlement depends on paid status.
  • Fleets group revenue and usage.

Notes to developers

  • App: sale_subscription (Enterprise).
  • Fields: partner_id, company_id, pricelist_id, analytic_account_id (Fleet), reference = ServicePlan ref.
  • Entitlement: Station/Thing queries invoice payment_state.
  • Fleet membership context: SoT = Client (Fleet owner) + Thing (Items). Odoo only reflects paid/unpaid.

For configuration and operations details, see: Subscriptions (Odoo + ABS).


10) Customer Experience

Business summary

  • Keep PII minimal; provide portal to view orders, invoices, subscriptions, and payments.
  • Returns/warranty handled with named partner or order reference.

Notes to developers

  • Portal templates per company.
  • Tags and UTM fields for segmentation.
  • GDPR compliance: opt-in, archiving.

11) Inventory (Odoo) tied to Thing

Business summary

  • We reflect where assets are (stations/lockers), optionally down to serials.
  • We can operate real-time or in nightly reconciliation.
  • SoT = Thing for Item placement; Odoo mirrors for accounting.

Notes to developers

  • Products: serial-tracked; valuation as per finance.
  • Lots: stock.production.lot.name = Thing Item ID (authoritative).
  • Locations: WH/<Region>/<Station>/<Locker> per company.
  • Ownership: owner_id on quants/moves.
  • Moves: Always come from Thing via n8n; Odoo UI disabled.
  • Fleet context: carried as payload info (for accounting analytics), not persisted as FK.

Move payload example: ```json { "event_id":"uuid", "company_ext":"oves:ke", "action":"stock.move", "data":{ "item_id":"thing:item-9F3A", "product_sku":"BATT-SWAP-48V50", "from_location":"WH/NRB/Station-12/Locker-A1", "to_location":"WH/NRB/Station-12/Locker-B7", "owner_partner_ref":"client:dist-023", "fleet_code":"fleet:KE-NBI-001", // context only, SoT = Thing "origin":"abs:svc-abc1234" } } ````


12) Analytics & Reporting

Business summary

  • See profitability by Fleet, Distributor, Company, and Product.
  • Track MRR, churn, DSO, payment success rates, inventory presence vs usage.

Notes to developers

  • Analytic reports: Fleet via account.analytic.account.
  • Subscription dashboards.
  • Payment state tracking.
  • Marketing attribution: UTM fields.

13) Financials, Currency & Taxes

Business summary

  • Customers see the sales currency (pricelist).
  • Accounting books in the company base currency.
  • Taxes mapped by location via fiscal positions.

Notes to developers

  • Currency: product.pricelist.currency_id (sales) vs res.company.currency_id (accounting).
  • Taxes: company localization + account.fiscal.position.
  • Entries: Invoice (Dr AR / Cr Revenue+Tax), Payment (Dr Bank / Cr AR), Inventory moves (valuation as per config).

14) n8n Integration Patterns

Business summary

  • n8n is our message bus: receives ABS/Thing/Client events, calls Odoo, and sends callbacks.
  • Reliability via idempotency, signatures, retries, and exception queues.

Notes to developers

Core flows

  1. People (Odoo→Client): Odoo emits people.changed. Client does not overwrite.
  2. Distributor & Fleet (Client→Odoo): Client upserts Distributor partner + Fleet (partner_id = owner). Odoo never changes Fleet owner.
  3. Fleet→Item (Thing→Odoo): Thing emits lot.upsert, stock.move, change_owner; Odoo mirrors moves. Odoo never edits Items.
  4. Billing (ABS→Odoo): Invoice-first / Pay-intent; Odoo sends payment.confirmed. No Fleet or Item edits.
  5. Entitlement (Thing↔Gateway): Gateway reads Odoo invoice status; Thing enforces service allow/block.

Conflict resolution policy

  • Owner conflict → Client wins (Fleet owner).
  • Item placement conflict → Thing wins (Fleet→Item).
  • Odoo remains read-side.

Controls

  • HMAC on all payloads.
  • Idempotency with event_id and idempotency_key.
  • Always include company_ext.
  • Dead-letter queue for failed syncs.

15) Version & Deployment Matrix

Capability Community Enterprise Odoo Cloud Odoo.sh On-Prem
Multi-company, Partners, Pricelists, Fiscal Positions ✔️ ✔️ ✔️ ✔️ ✔️
POS, eCommerce, Payment acquirers* ✔️ ✔️ ✔️ ✔️ ✔️
Subscriptions (sale_subscription) ✔️ ✔️ ✔️ ✔️
Inventory (serials, locations, consignment) ✔️ ✔️ ✔️ ✔️ ✔️
Webhooks/controllers (custom) ⚠️ ⚠️ ✔️ ✔️

* Acquirer availability varies by provider on Community.


16) SOPs & Checklists

Onboarding (market/company)

  • Create res.company, journals, warehouses, fiscal position, pricelists
  • Website/POS bound to company
  • Walk-in and Web Anonymous partners created

Distributor/Fleet setup

  • Client upsert Distributor partner (ref, tag)
  • Client upsert Fleet analytic (code/ref, partner_id, company_id)

BSS subscription

  • Create sale.subscription (partner, company, pricelist, analytic=Fleet, reference=ServicePlan)
  • Capture payment token; test invoice auto-charge
  • Enable entitlement gateway

Inventory sync

  • Station stock.location map ready
  • n8n flows: lot.upsert, stock.move, change_owner, reconcile
  • Disable manual transfers

Month-end close

  • Reconcile dunning/failed payments
  • Recognize prepaid revenue via journal (analytic by Fleet)
  • Inventory exceptions resolved

17) Quick Field & Model Reference (dev crib)

  • Partner (res.partner): company_id, ref, tags, pricelist, fiscal position
  • Company (res.company): currency_id, localization
  • Fleet (account.analytic.account): partner_id (SoT = Client), company_id, code/ref
  • Item (stock.production.lot): name = Thing Item ID; created/updated by Thing events only
  • Subscription (sale.subscription): partner_id, company_id, pricelist_id, analytic_account_id, reference (ServicePlan)
  • Invoice (account.move): company_id, currency_id, invoice_origin (ServicePlan), payment_state
  • Payment (account.payment / payment.transaction): reference includes service_ref
  • Inventory: product.template (serial tracking), stock.production.lot, stock.location, owner_id
  • POS: pos.config.company_id
  • Website: website.company_id

18) Governance & Conflict Rules

  • People: Odoo is master. Inbound identity edits rejected; merges emit people.merged.
  • Fleet ownership: Client is master for partner_id on Fleets. Odoo UI blocked from edits.
  • Item placement: Thing is master for Fleet→Item. Odoo mirrors via inventory events.
  • Accounting: Odoo is master. External systems consume, not mutate.
  • Conflicts: Client wins on Fleet owner; Thing wins on Item placement.
  • Idempotency & Signatures: HMAC + replay-safe.
  • Company & Currency: always carried in payloads.

19) Glossary

  • FLEET: Group of assets and service entitlements. Anchor in Odoo = account.analytic.account.
  • ITEM: Serialised asset. SoT = Thing; optional Odoo lot mirror.
  • ServicePlan: ABS object binding a person to a service bundle. Referenced in Odoo subscription.reference and invoice.invoice_origin.
  • Distributor: External dealer (res.partner) or internal OVES company (res.company).
  • Entitlement: Right to use service; computed from Odoo payment state; enforced by Thing.

Final Notes

  • This blueprint honors OVES’s “minimize model extensions” rule.
  • Everything rides on native Odoo objects with