File size: 2,553 Bytes
5a22efd | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | package sequence
import (
"fmt"
"slices"
"strings"
"github.com/openmeterio/openmeter/pkg/currencyx"
)
type NextSequenceNumberInput struct {
Namespace string
Scope string
}
func (n NextSequenceNumberInput) Validate() error {
if n.Namespace == "" {
return fmt.Errorf("namespace is required")
}
if n.Scope == "" {
return fmt.Errorf("scope is required")
}
return nil
}
type Definition struct {
Prefix string
SuffixTemplate string
Scope string
CommitMode CommitMode
}
func (d Definition) Validate() error {
if d.Prefix == "" {
return fmt.Errorf("prefix is required")
}
if d.SuffixTemplate == "" {
return fmt.Errorf("suffix template is required")
}
if d.Scope == "" {
return fmt.Errorf("scope is required")
}
if err := d.CommitMode.Validate(); err != nil {
return err
}
return nil
}
func (d Definition) PrefixMatches(s string) bool {
return strings.HasPrefix(s, d.Prefix+"-")
}
// CommitMode controls when a sequence allocation is committed. WithCaller
// allows the number to be reused if the caller rolls back; Independent retains
// the allocation despite caller rollback, which can create gaps.
type CommitMode string
const (
CommitModeWithCaller CommitMode = "with_caller"
CommitModeIndependent CommitMode = "independent"
)
func (m CommitMode) Validate() error {
if m == "" {
return fmt.Errorf("commit mode is required")
}
if !slices.Contains([]CommitMode{CommitModeWithCaller, CommitModeIndependent}, m) {
return fmt.Errorf("commit mode is invalid: %s", m)
}
return nil
}
var (
GatheringInvoiceSequenceNumber = Definition{
Prefix: "GATHER",
SuffixTemplate: "{{.CustomerPrefix}}-{{.Currency}}-{{.NextSequenceNumber}}",
Scope: "invoices/gathering",
CommitMode: CommitModeIndependent,
}
DraftInvoiceSequenceNumber = Definition{
Prefix: "DRAFT",
SuffixTemplate: "{{.CustomerPrefix}}-{{.NextSequenceNumber}}",
Scope: "invoices/draft",
// Draft numbers are temporary and replaced by the invoicing app's final
// invoice number, so gaps from retained allocations are acceptable.
CommitMode: CommitModeIndependent,
}
)
type GenerationInput struct {
Namespace string
CustomerName string
Currency currencyx.Code
}
func (i GenerationInput) Validate() error {
if i.CustomerName == "" {
return fmt.Errorf("customer name is required")
}
if i.Currency == "" {
return fmt.Errorf("currency is required")
}
if i.Namespace == "" {
return fmt.Errorf("namespace is required")
}
return nil
}
|