feat(billing): NexaCloud invoice ledger — ingest invoices to account.move
Odoo becomes the accounting SoR by ingesting NexaCloud's real Stripe invoices (read-only via the existing DSN) into native account.move customer invoices: per-service-family income accounts, tax derived to match the source invoice.tax, Stripe payments reconciled via account.payment.register (invoice shows paid), idempotent on x_fc_nexacloud_invoice_id, draft-first with bulk-post + a daily cron (inactive). Plus a prune helper for the now-obsolete metered shadow data. 73 tests green on odoo-trial. Account codes use dots (Odoo 19 rejects '-').
This commit is contained in:
@@ -7,3 +7,4 @@ from . import webhook
|
||||
from . import reconciliation
|
||||
from . import sale_order
|
||||
from . import res_partner
|
||||
from . import account_move
|
||||
|
||||
17
fusion_centralize_billing/models/account_move.py
Normal file
17
fusion_centralize_billing/models/account_move.py
Normal file
@@ -0,0 +1,17 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2026 Nexa Systems Inc.
|
||||
# License OPL-1
|
||||
from odoo import fields, models
|
||||
|
||||
|
||||
class AccountMove(models.Model):
|
||||
_inherit = "account.move"
|
||||
|
||||
x_fc_nexacloud_invoice_id = fields.Char(
|
||||
index=True, copy=False, help="Source NexaCloud invoice id — ledger idempotency key.")
|
||||
x_fc_stripe_invoice_id = fields.Char(index=True, copy=False)
|
||||
|
||||
_fc_nc_invoice_uniq = models.Constraint(
|
||||
"unique(x_fc_nexacloud_invoice_id)",
|
||||
"One Odoo invoice per NexaCloud invoice id.",
|
||||
)
|
||||
Reference in New Issue
Block a user