openmeter / ledger /transactions /correction.go
Leon4gr45's picture
Upload folder using huggingface_hub (part 5)
cee2387 verified
Raw
History Blame Contribute Delete
3.42 kB
package transactions
import (
"context"
"fmt"
"time"
"github.com/alpacahq/alpacadecimal"
"github.com/openmeterio/openmeter/openmeter/ledger"
"github.com/openmeterio/openmeter/pkg/models"
)
const legacyAnnotationTransactionTemplateName = "ledger.transaction.template_name"
type CorrectionInput struct {
At time.Time
Amount alpacadecimal.Decimal
OriginalTransaction ledger.Transaction
OriginalGroup ledger.TransactionGroup
}
type CorrectionScope = CorrectionInput
func (i CorrectionScope) Validate() error {
if i.At.IsZero() {
return fmt.Errorf("at is required")
}
if err := ledger.ValidateTransactionAmount(i.Amount); err != nil {
return fmt.Errorf("amount: %w", err)
}
if i.OriginalTransaction == nil {
return fmt.Errorf("original transaction is required")
}
return nil
}
func CorrectTransaction(
_ context.Context,
deps ResolverDependencies,
scope CorrectionScope,
) ([]ledger.TransactionInput, error) {
if err := scope.Validate(); err != nil {
return nil, fmt.Errorf("validate correction input: %w", err)
}
direction, err := ledger.TransactionDirectionFromAnnotations(scope.OriginalTransaction.Annotations())
if err != nil {
return nil, fmt.Errorf("transaction direction: %w", err)
}
if direction == ledger.TransactionDirectionCorrection {
return nil, fmt.Errorf("cannot correct a correction transaction")
}
template, err := transactionTemplateFromAnnotations(scope.OriginalTransaction.Annotations())
if err != nil {
return nil, fmt.Errorf("transaction template: %w", err)
}
outputs, err := correctTemplate(scope, template)
if err != nil {
return nil, err
}
annotated := make([]ledger.TransactionInput, 0, len(outputs))
for _, output := range outputs {
annotatedOutput, err := annotateTemplateTransaction(output, template, ledger.TransactionDirectionCorrection)
if err != nil {
return nil, err
}
annotated = append(annotated, annotatedOutput)
}
return annotated, nil
}
func transactionTemplateFromAnnotations(annotations models.Annotations) (TransactionTemplate, error) {
if _, ok := annotations[ledger.AnnotationTransactionTemplateCode]; ok {
code, err := ledger.TransactionTemplateCodeFromAnnotations(annotations)
if err != nil {
return nil, fmt.Errorf("code: %w", err)
}
return transactionTemplateByCode(code)
}
name, err := transactionTemplateNameFromAnnotations(annotations)
if err != nil {
return nil, fmt.Errorf("name: %w", err)
}
return transactionTemplateByLegacyName(name)
}
func transactionTemplateNameFromAnnotations(annotations models.Annotations) (string, error) {
raw, ok := annotations[legacyAnnotationTransactionTemplateName]
if !ok {
return "", fmt.Errorf("transaction template name annotation is required")
}
templateName, ok := raw.(string)
if !ok || templateName == "" {
return "", fmt.Errorf("transaction template name annotation is invalid")
}
return templateName, nil
}
func correctTemplate(scope CorrectionScope, template TransactionTemplate) ([]ledger.TransactionInput, error) {
switch typ := any(template).(type) {
case CustomerTransactionTemplate:
return typ.correct(scope)
case OrgTransactionTemplate:
return typ.correct(scope)
default:
return nil, fmt.Errorf("unsupported correction template type %T", template)
}
}
func templateCorrectionNotImplemented(template string) error {
return fmt.Errorf("%s correction is not implemented", template)
}