# Fusion Centralized Billing (`fusion_centralize_billing`) Centralized billing engine that makes this Odoo 19 **Enterprise** instance the single billing brain for every NexaSystems service — **NexaCloud** hosting, **NexaDesk** chat, **NexaMaps** API, custom apps, and memberships. It replaces Lago and absorbs NexaCloud's home-grown Stripe billing into one customer ledger and one accounting system. > **Design spec:** [`docs/superpowers/specs/2026-05-27-nexa-billing-centralized-design.md`](../docs/superpowers/specs/2026-05-27-nexa-billing-centralized-design.md) > > **Status:** **SCAFFOLD.** Models + security + the API auth shell are in place and the > module installs. The usage engine, full inbound API, and webhook processor are stubs > to be implemented from the writing-plans output. ## Why this module is small We build **only** the metering + integration layer. Everything financial — recurring invoicing, HST tax, proration, dunning, customer portal, credit notes, Stripe — is **native Odoo Enterprise** (`sale_subscription`, `account_accountant`, `payment_stripe`), already installed and running. ## Design decisions (locked) 1. Odoo fully replaces Lago (we build the metered-billing engine; Lago is decommissioned last). 2. One unified `res.partner` per client; **separate invoice per service**. 3. **Apps drive**, Odoo is the billing system of record — apps call the inbound API (as they call Lago today); Odoo bills and webhooks back. 4. Odoo owns the **billing catalog**; apps own **feature entitlements** (shared `plan_code`). 5. Pilot = **NexaCloud**, phased dual-run cutover. 6. **Aggregate-push** usage ingestion (periodic counters, not a raw-event firehose). ## Models (`fusion.billing.*`) | Model | Purpose | |---|---| | `fusion.billing.service` | One source app; bearer API key (hashed) + webhook config. | | `fusion.billing.account.link` | External account id → one `res.partner` (identity resolution). | | `fusion.billing.metric` | Billable metric + aggregation (sum/max/last/unique). | | `fusion.billing.charge` | Plan + metric → included quota + overage pricing. | | `fusion.billing.usage` | Aggregated per-period usage rollups (idempotent). | | `fusion.billing.webhook` | Outbound lifecycle event queue (HMAC + retry). | | `fusion.billing.reconciliation` | Dual-run Odoo-vs-app delta during cutover. | > **Odoo 19 note (verified):** a subscription is a `sale.order` with `is_subscription=True` > (`plan_id` → `sale.subscription.plan`). There is **no** `sale.subscription` model. > `fusion.billing.usage.subscription_id` therefore points at `sale.order`. ## Inbound API Lago-shaped REST under `/api/billing/v1/*`, bearer auth. Endpoints mirror NexaDesk's existing `lago-client.ts` so migration is a thin client swap. `/health` works today; the rest return `501` until implemented. ## Relationship to `fusion_api` `fusion_api` manages **outbound** provider keys (OpenAI, Maps, Twilio) + cost tracking — i.e. COGS. This module tracks **customer** revenue. Complementary: feed `fusion_api` cost into margin reporting; reuse its daily-rollup aggregation pattern. ## Dependencies `account_accountant`, `sale_subscription`, `sale_management`, `payment_stripe`. ## Local dev ```bash docker exec odoo-nexa-app odoo -d nexamain -u fusion_centralize_billing --stop-after-init # tests (once added): docker exec odoo-nexa-app odoo -d nexamain --test-enable --test-tags /fusion_centralize_billing -u fusion_centralize_billing --stop-after-init ``` Canadian English, CAD, HST via `account.tax`. New fields on native models use the `x_fc_*` prefix.