From ddab84e7e5a4e1c26f1bbbf9c3584d0dee19dd6c Mon Sep 17 00:00:00 2001 From: Abhishek Sah Date: Fri, 28 Aug 2026 13:17:47 +0530 Subject: [PATCH] fix(billing): keep the synced invoice amount up to date MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The invoice sync only ever updated the state, effective date, and hosted URL of an existing local row — the amount stayed frozen at whatever the first sync saw. A draft that Stripe created empty and filled with usage later kept amount 0 locally forever, so everything reading the local rows saw wrong totals: billing pages showed stale numbers, and the org delete check skipped a real unpaid invoice and enabled a delete the server then refused. The sync now writes the total when it changes, and the repository update includes the amount column. Zero is a real value (a draft whose items were credited away), so it is written like any other total. --- billing/invoice/service.go | 4 ++++ internal/store/postgres/billing_invoice_repository.go | 3 +++ 2 files changed, 7 insertions(+) diff --git a/billing/invoice/service.go b/billing/invoice/service.go index 15b4fb8969..d7b0d05782 100644 --- a/billing/invoice/service.go +++ b/billing/invoice/service.go @@ -363,6 +363,10 @@ func (s *Service) upsert(ctx context.Context, customerID string, existingInvoice.HostedURL = stripeInvoice.HostedInvoiceURL updateNeeded = true } + if existingInvoice.Amount != stripeInvoice.Total { + existingInvoice.Amount = stripeInvoice.Total + updateNeeded = true + } if updateNeeded { if _, err := s.repository.UpdateByID(ctx, *existingInvoice); err != nil { diff --git a/internal/store/postgres/billing_invoice_repository.go b/internal/store/postgres/billing_invoice_repository.go index c1d36d791e..f80d4f3837 100644 --- a/internal/store/postgres/billing_invoice_repository.go +++ b/internal/store/postgres/billing_invoice_repository.go @@ -297,6 +297,9 @@ func (r BillingInvoiceRepository) UpdateByID(ctx context.Context, toUpdate invoi if toUpdate.HostedURL != "" { updateRecord["hosted_url"] = toUpdate.HostedURL } + // Do not guard this with `!= 0` like the fields above: an invoice can + // be credited down to zero, and that zero must be saved. + updateRecord["amount"] = toUpdate.Amount query, params, err := dialect.Update(TABLE_BILLING_INVOICES).Set(updateRecord).Where(goqu.Ex{ "id": toUpdate.ID,