feat(billing): 2d dual-run reconciliation (Odoo-computed vs NexaCloud-actual)

fusion.billing.reconciliation gains the compute: _compute_reconciliation
(flat + charge overage vs external, status match/delta at a tolerance) and
_reconcile_rows (resolve shadow sub -> flat + charge, upsert one row per
service/partner/period, per-row isolated). The wizard gains a read-only
_read_reconciliation_rows (NexaCloud usage cpu_hours*3600 + invoice-item
subtotals per YYYY-MM) and a "Run Reconciliation" button. 2a amended to
stamp x_fc_nexacloud_plan_id on shadow subs so reconciliation can find the
charge. Read-only on NexaCloud; writes only reconciliation rows (shadow
guarantees intact). 8 new tests, full suite green on odoo-trial.
This commit is contained in:
gsinghpal
2026-05-27 14:34:23 -04:00
parent 3ba9f2821e
commit 2bdf4ef6a0
7 changed files with 244 additions and 1 deletions

View File

@@ -118,6 +118,11 @@ class TestImporterSubscriptions(TransactionCase):
self.assertAlmostEqual(line2.price_unit, 200.0) # price_yearly
self.assertEqual(sub2.plan_id.billing_period_unit, 'year')
def test_subscription_records_nexacloud_plan_id(self):
self.Wizard._import_rows(_fixture())
sub1 = self.env['sale.order'].search([('x_fc_nexacloud_subscription_id', '=', 's-1')])
self.assertEqual(sub1.x_fc_nexacloud_plan_id, 'p-1')
def test_subscription_skipped_when_user_or_plan_unresolved(self):
data = _fixture()
data['subscriptions'].append(