feat(billing): post + reconcile only PAID invoices, keeping original dates
_post_and_reconcile_paid: for invoices NexaCloud marks paid, set the ledger entry's invoice_date AND accounting date to the original NexaCloud date, post, then reconcile the Stripe payment dated to the actual paid_at. Unpaid invoices stay draft. Per-invoice isolated. 76 tests green on odoo-trial.
This commit is contained in:
@@ -197,6 +197,41 @@ class FusionBillingInvoiceLedgerWizard(models.TransientModel):
|
||||
_logger.exception("Ledger post: move %s failed", mv.id)
|
||||
return posted
|
||||
|
||||
@api.model
|
||||
def _post_and_reconcile_paid(self, data):
|
||||
"""Post + reconcile ONLY the invoices NexaCloud marks paid, dating the ledger entry
|
||||
to the ORIGINAL invoice date and the payment to the actual paid_at. Leaves unpaid
|
||||
invoices as draft. Per-invoice isolated."""
|
||||
Move = self.env["account.move"]
|
||||
summary = {"posted": 0, "reconciled": 0, "skipped_unpaid": 0,
|
||||
"skipped_missing": 0, "failed": []}
|
||||
for inv in data:
|
||||
nc_id = str(inv.get("id") or "")
|
||||
paid = float(inv.get("amount_paid") or 0.0)
|
||||
if inv.get("status") != "paid" and paid <= 0:
|
||||
summary["skipped_unpaid"] += 1
|
||||
continue
|
||||
mv = Move.search([("x_fc_nexacloud_invoice_id", "=", nc_id),
|
||||
("move_type", "=", "out_invoice")], limit=1)
|
||||
if not mv:
|
||||
summary["skipped_missing"] += 1
|
||||
continue
|
||||
try:
|
||||
with self.env.cr.savepoint():
|
||||
if mv.state == "draft":
|
||||
inv_date = inv.get("invoice_date")
|
||||
# keep the original invoice + accounting date (not today)
|
||||
mv.write({"invoice_date": inv_date, "date": inv_date})
|
||||
mv.action_post()
|
||||
summary["posted"] += 1
|
||||
if mv.payment_state not in ("paid", "in_payment", "reversed"):
|
||||
if self._fc_reconcile_payment(mv, inv):
|
||||
summary["reconciled"] += 1
|
||||
except Exception as e: # noqa: BLE001 - per-invoice isolation
|
||||
_logger.exception("Post+pay: invoice %s failed", nc_id)
|
||||
summary["failed"].append({"id": nc_id, "error": "%s: %s" % (type(e).__name__, e)})
|
||||
return summary
|
||||
|
||||
def _cron_ingest_recent(self):
|
||||
since = fields.Datetime.to_string(fields.Datetime.now() - timedelta(days=2))
|
||||
return self._ingest_invoices(self._read_nexacloud_invoices(since=since), post=True)
|
||||
|
||||
Reference in New Issue
Block a user