Skip to content

feat(payment_terms): Snapshot payment_term on invoice level - #6195

Open
D1353L wants to merge 3 commits into
feat-payment-terms-nullable-aliasfrom
feat-payment-terms-snapshot-term-invoice
Open

feat(payment_terms): Snapshot payment_term on invoice level#6195
D1353L wants to merge 3 commits into
feat-payment-terms-nullable-aliasfrom
feat-payment-terms-snapshot-term-invoice

Conversation

@D1353L

@D1353L D1353L commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Context

Before this change, invoice due dates were computed from customer.applicable_net_payment_term at every refresh. A later term change on the customer or the billing entity could silently move the due date of open drafts. To support structured terms (end_of_month, day_of_month, due_on_receipt), each invoice must keep the exact term that was used when it was created.

Description

  • On invoice creation, the payment term is resolved once and stored on the invoice: the payment_term jsonb, the payment_term_source (customer or billing entity), and the integer net_payment_term alias.
  • payment_due_date is computed from the snapshotted term.
  • All refresh paths (draft refresh, VIES finalization, provider taxes, regeneration from voided, issuing date updates) read the invoice's own snapshot.
  • Behavior change "Freeze on draft invoices": A term change on a customer or a billing entity no longer rewrites open drafts. It applies to future invoices only. The UpdateInvoicePaymentDueDateService classes are removed.
  • Existing invoices have no jsonb snapshot. For them, Invoice#snapshotted_payment_term builds a net term from their own integer alias.
  • Final nil relaxing for BillingEntity#net_payment_term on the model level.

Stack created with GitHub Stacks CLIGive Feedback 💬

@D1353L
D1353L force-pushed the feat-payment-terms-snapshot-term-invoice branch 4 times, most recently from 2f3d208 to bc93890 Compare August 21, 2026 14:53
@D1353L
D1353L force-pushed the feat-payment-terms-snapshot-term-invoice branch 4 times, most recently from 83dc1cf to d46dc76 Compare August 25, 2026 14:21
@D1353L
D1353L force-pushed the feat-payment-terms-snapshot-term-invoice branch 2 times, most recently from f082abf to ddf834b Compare August 25, 2026 14:31
@D1353L
D1353L marked this pull request as ready for review August 26, 2026 10:02
@lago-claude-ai-agent

Copy link
Copy Markdown
Contributor

Automated pre-review (advisory, not a required check) — verdict: HOLD · CI green

HOLD — invoices can snapshot the wrong billing entity's payment term.

  • Resolve the fallback term from the invoice's effective billing entity in CreateGeneratingService and PreviewService; both select an alternate entity for the invoice but currently resolve through customer.billing_entity, producing the wrong snapshot, source, and due date when no customer term exists.
  • Add regression coverage for generated and preview invoices using a subscription-specific or explicitly selected alternate billing entity.

@D1353L
D1353L force-pushed the feat-payment-terms-snapshot-term-invoice branch from e828347 to 1603bb5 Compare August 26, 2026 16:24
@lago-claude-ai-agent

Copy link
Copy Markdown
Contributor

Automated pre-review (advisory, not a required check) — verdict: HOLD · CI green

HOLD — invoice generation and previews can snapshot a payment term from the wrong billing entity.

  • Resolve the fallback term against the effective invoice billing entity in both CreateGeneratingService and PreviewService; they select an explicit/subscription billing entity but currently resolve from customer.billing_entity, producing the wrong term and due date in multi-entity flows. Add regression coverage where the two entities have different terms.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant