openmeter / billing /lineengine /stdinvoice.go
Leon4gr45's picture
Upload folder using huggingface_hub (part 2)
5a22efd verified
Raw
History Blame Contribute Delete
2.9 kB
package lineengine
import (
"context"
"fmt"
"github.com/samber/lo"
"github.com/openmeterio/openmeter/openmeter/billing"
"github.com/openmeterio/openmeter/openmeter/billing/service/invoicecalc"
)
type QuantitySnapshotter interface {
SnapshotLineQuantities(ctx context.Context, invoice billing.StandardInvoice, lines billing.StandardLines) error
}
func (e *Engine) BuildStandardInvoiceLines(ctx context.Context, input billing.BuildStandardInvoiceLinesInput) (billing.StandardLines, error) {
stdLines, err := e.buildStandardInvoiceLinesWithQuantitySnapshot(ctx, input)
if err != nil {
return nil, err
}
return e.CalculateLines(billing.CalculateLinesInput{
Invoice: input.Invoice,
Lines: stdLines,
})
}
func (e *Engine) BuildStandardLinesForGatheringPreview(ctx context.Context, input billing.BuildStandardInvoiceLinesInput) (billing.StandardLines, error) {
return e.buildStandardInvoiceLinesWithQuantitySnapshot(ctx, input)
}
func (e *Engine) buildStandardInvoiceLinesWithQuantitySnapshot(ctx context.Context, input billing.BuildStandardInvoiceLinesInput) (billing.StandardLines, error) {
if input.Invoice.ID == "" {
return nil, fmt.Errorf("invoice id is required")
}
if len(input.GatheringLines) == 0 {
return nil, fmt.Errorf("gathering lines are required")
}
stdLines, err := input.GatheringLines.ToStandardLines(input.Invoice.ID)
if err != nil {
return nil, err
}
if err := e.ResolveSplitLineGroupHeaders(ctx, input.Invoice.Namespace, stdLines); err != nil {
return nil, fmt.Errorf("resolving split line group headers: %w", err)
}
if err := e.quantitySnapshotter.SnapshotLineQuantities(ctx, input.Invoice, stdLines); err != nil {
return nil, fmt.Errorf("snapshotting line quantities: %w", err)
}
return stdLines, nil
}
func (e *Engine) CalculateLines(input billing.CalculateLinesInput) (billing.StandardLines, error) {
if input.Invoice.ID == "" {
return nil, fmt.Errorf("invoice id is required")
}
if len(input.Lines) == 0 {
return nil, fmt.Errorf("lines are required")
}
for _, stdLine := range input.Lines {
generatedDetailedLines, err := e.ratingService.GenerateDetailedLines(stdLine)
if err != nil {
return nil, fmt.Errorf("generating detailed lines for line[%s]: %w", stdLine.ID, err)
}
if err := invoicecalc.MergeGeneratedDetailedLines(stdLine, generatedDetailedLines); err != nil {
return nil, fmt.Errorf("merging generated detailed lines for line[%s]: %w", stdLine.ID, err)
}
if err := stdLine.Validate(); err != nil {
return nil, fmt.Errorf("validating standard line[%s]: %w", stdLine.ID, err)
}
}
return input.Lines, nil
}
func (e *Engine) IsLineBillableAsOf(_ context.Context, input billing.IsLineBillableAsOfInput) (bool, error) {
if err := input.Validate(); err != nil {
return false, fmt.Errorf("validating input: %w", err)
}
return !lo.IsEmpty(input.ResolvedBillablePeriod), nil
}