Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions openmeter/billing/adapter/gatheringinvoice.go
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,8 @@ func (a *adapter) mapGatheringInvoiceFromDB(ctx context.Context, invoice *db.Bil
NextCollectionAt: invoice.CollectionAt.In(time.UTC),
SchemaLevel: invoice.SchemaLevel,
},

Expands: expand,
}

if expand.Has(billing.GatheringInvoiceExpandLines) {
Expand Down
15 changes: 14 additions & 1 deletion openmeter/billing/gatheringinvoice.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ type GatheringInvoice struct {
// these lines too.
AvailableActions *GatheringInvoiceAvailableActions `json:"availableActions,omitempty"`

SplitLineHierarchy *SplitLineHierarchy `json:"splitLineHierarchy,omitempty"`
Expands GatheringInvoiceExpands `json:"expands,omitempty"`
}

func (g GatheringInvoice) WithoutDBState() (GatheringInvoice, error) {
Expand Down Expand Up @@ -158,6 +158,7 @@ func (g GatheringInvoice) Clone() (GatheringInvoice, error) {
}

clone.Lines = clonedLines
clone.Expands = g.Expands.Clone()

return clone, nil
}
Expand Down Expand Up @@ -681,6 +682,16 @@ func (g GatheringLine) AsNewStandardLine(invoiceID string) (*StandardLine, error
subscription = g.Subscription.Clone()
}

var splitLineHierarchy *SplitLineHierarchy
if g.SplitLineHierarchy != nil {
clonedSHierarchy, err := g.SplitLineHierarchy.Clone()
if err != nil {
return nil, fmt.Errorf("cloning split line hierarchy: %w", err)
}

splitLineHierarchy = lo.ToPtr(clonedSHierarchy)
}

convertedLine := &StandardLine{
StandardLineBase: StandardLineBase{
ManagedResource: g.ManagedResource,
Expand Down Expand Up @@ -708,6 +719,8 @@ func (g GatheringLine) AsNewStandardLine(invoiceID string) (*StandardLine, error
FeatureKey: g.FeatureKey,
},

SplitLineHierarchy: splitLineHierarchy,

DBState: nil, // We don't want to reuse the state from the gathering line (so let's make it explicit)
}

Expand Down
30 changes: 26 additions & 4 deletions openmeter/billing/service/invoice.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,13 +166,35 @@ func (s *Service) calculateGatheringInvoiceAsStandardInvoice(ctx context.Context
return nil, fmt.Errorf("creating standard invoice from gathering invoice: %w", err)
}

wasLinesAbsent := invoice.Lines.IsAbsent()
wasLinesPresent := invoice.Lines.IsPresent()

if wasLinesAbsent {
shouldReloadLines := !wasLinesPresent

if !invoice.Expands.Has(billing.GatheringInvoiceExpandSplitLineHierarchy) && wasLinesPresent {
// If the invoice has lines and the splitline hierarchy is not expanded, we need to check if there are any progressive billed lines
// and reload the invoice as price calculations depend on the presence of the split line hierarchy.

progressiveBilledLineCount := lo.CountBy(invoice.Lines.OrEmpty(), func(line billing.GatheringLine) bool {
if line.DeletedAt != nil {
return false
}

return line.SplitLineGroupID != nil
})

if progressiveBilledLineCount > 0 {
shouldReloadLines = true
}
}

// If the gathering invoice has no splitline hierarchy expanded we need to reload the invoice so that the price calculations can
// properly proceed.
if shouldReloadLines {
// Let's reload the whole invoice with lines expanded
invoice, err = s.adapter.GetGatheringInvoiceById(ctx, billing.GetGatheringInvoiceByIdInput{
Invoice: in.Invoice.GetInvoiceID(),
Expand: billing.GatheringInvoiceExpandAll,
Expand: billing.GatheringInvoiceExpandAll.
With(billing.GatheringInvoiceExpandSplitLineHierarchy),
})
if err != nil {
return nil, fmt.Errorf("fetching gathering invoice: %w", err)
Expand Down Expand Up @@ -223,7 +245,7 @@ func (s *Service) calculateGatheringInvoiceAsStandardInvoice(ctx context.Context
return nil, fmt.Errorf("calculating invoice: %w", err)
}

if wasLinesAbsent {
if !wasLinesPresent {
// If the original user intent was to not to receive the lines, let's not send them
out.Lines = billing.StandardInvoiceLines{}
} else {
Expand Down
2 changes: 2 additions & 0 deletions test/billing/invoice_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,8 @@ func (s *InvoicingTestSuite) TestPendingLineCreation() {
},

Lines: billing.NewGatheringInvoiceLines([]billing.GatheringLine{expectedUSDLine}),

Expands: []billing.GatheringInvoiceExpand{billing.GatheringInvoiceExpandLines},
}

s.NoError(invoicecalc.GatheringInvoiceCollectionAt(&expectedInvoice))
Expand Down
Loading