-
Notifications
You must be signed in to change notification settings - Fork 152
refactor: split line manipulation should use invoice API #3788
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
📝 WalkthroughWalkthroughRemoves adapter-based line-association APIs and legacy invoice-pending orchestration; introduces a new, service-level gathering InvoicePendingLines workflow, simplifies line service interfaces, and tightens invoice input validation. Changes
Sequence DiagramsequenceDiagram
participant Client
participant Service as Service (InvoicePendingLines)
participant Repo as Repository
participant LineService as Line Service
participant EventPub as EventPublisher
Client->>Service: InvoicePendingLines(ctx, input)
activate Service
Service->>Service: Validate input & namespace lock
Service->>Repo: Resolve customer/profile
Service->>Repo: Fetch gathering invoices (per currency)
Service->>LineService: Compute in-scope billable lines
loop per currency
Service->>Service: prepareLinesToBill (validate, split decisions)
alt split required
Service->>Service: splitGatheringInvoiceLine
Service->>Repo: Update gathering invoice (post-split)
end
Service->>Repo: Create standard invoice
Service->>Repo: Move/associate lines to new invoice
Service->>Repo: Update gathering invoice state (or delete if empty)
end
Service->>EventPub: Publish InvoiceCreatedEvent(s)
Service-->>Client: Return created invoices
deactivate Service
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested labels
Suggested reviewers
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
781b6ef to
af75b51
Compare
52c024b to
c99a728
Compare
c99a728 to
3a1f998
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
🤖 Fix all issues with AI agents
In `@openmeter/billing/service/gatheringinvoicependinglines.go`:
- Around line 292-321: After filtering res by the requested IDs (using
LinesToInclude.OrEmpty(), linesShouldBeIncluded, and lo.Filter), remove any
currency entries that end up with zero lines so empty currencies don't remain in
res; update the loop that sets res[currency] to compute the filtered slice and
if its length is zero delete(res, currency) else assign the filtered slice back
to res[currency], ensuring downstream validation only sees currencies with at
least one line.
- Around line 377-403: The code currently appends a pre‑split line even when
splitGatheringInvoiceLine marks it deleted and also logs the same "period_end"
key twice; update the block handling splitGatheringInvoiceLine so that after the
nil check you also skip adding the pre‑split line if
splitLine.PreSplitAtLine.Deleted is true (i.e., do not append to invoiceLines or
include its ID in LineIDsToBill), and fix the duplicate log key in the
logger.WarnContext call (replace the second "period_end" key with a distinct key
such as "period_original_end" or remove the duplicate) — references:
splitGatheringInvoiceLine, splitGatheringInvoiceLineInput,
splitLine.PreSplitAtLine, invoiceLines, LineIDsToBill, logger.WarnContext.
- Around line 148-157: The transaction callback in gatheringInvoicePendingLines
(inside transaction.Run) currently calls s.publisher.Publish for each invoice,
which can emit events for data that may be rolled back; instead, collect the
created invoices inside the callback (e.g., append to createdInvoices slice
returned from the transaction) and return successfully, then after
transaction.Run completes (i.e., after commit) iterate over the committed
invoices, create events via billing.NewInvoiceCreatedEvent(invoice) and call
s.publisher.Publish(ctx, event) outside the transaction; update the code path
around createdInvoices and the transaction.Run call so publishing only happens
after a successful commit.
In `@openmeter/billing/service/lineservice/service.go`:
- Around line 189-202: ValidateForInvoice currently assumes each element in the
Lines slice is non-nil and will panic if a nil Line is present; update the
mapping function inside ValidateForInvoice to first check if the `line` is nil
(type `Line`) and return a descriptive error (e.g. including the index or
identifier) instead of calling `line.Validate` or `line.ID()`, then proceed to
call `line.Validate(ctx, invoice)` and `line.ID()` only when `line` is non-nil;
reference the ValidateForInvoice function and the Line.Validate / Line.ID
methods when making this change.
🧹 Nitpick comments (2)
openmeter/billing/invoiceline.go (2)
251-252: Consider exporting the edit type (or adding helpers) if external callers should use it.
CloneWithoutDependenciesis public, butlineEditFunctionisn’t, so packages outsidebillingcan’t pass edits. If you want external customization, exporting the type (or adding exported helper funcs) would keep the API usable. If not, all good.
255-277: Skip nil edits to avoid a panic.A
niledit function will panic on call. A tiny guard keeps this safe and costs nothing.🛠️ Suggested tweak
- for _, edit := range edits { - edit(clone) - } + for _, edit := range edits { + if edit == nil { + continue + } + edit(clone) + }
Overview
The InvoicePendingLines call is one of the most complex ones in the existing invoicing stack, due to algorithmical complexity, but also the code was scattered in multiple places with different layers handling different parts of the flow.
This patch makes sure that the whole logic is:
As a side-effect we can remove the adapter dependency from the line service, making it closer to a "calculation" only package.
I have also removed the AssociateLinesToInvoice as extra care was needed to correct the inconsistencies caused by that call.
Summary by CodeRabbit
New Features
Bug Fixes
Refactor
✏️ Tip: You can customize this high-level summary in your review settings.