openmeter / app /config /taxcode.go
Leon4gr45's picture
Upload folder using huggingface_hub (part 4)
1f10f31 verified
Raw
History Blame Contribute Delete
3.45 kB
package config
import (
"errors"
"fmt"
"strings"
"github.com/spf13/viper"
"github.com/openmeterio/openmeter/openmeter/taxcode"
)
type TaxCodeConfiguration struct {
Seeds []TaxCodeSeed `mapstructure:"seeds"`
}
// TaxCodeSeed defines a single tax code entry to provision for every namespace.
// A single seed may carry both DefaultInvoicing and DefaultCreditGrant; the two flags are
// independent and the exactly-one rule is enforced per flag.
type TaxCodeSeed struct {
Key string `mapstructure:"key"`
Name string `mapstructure:"name"`
Description *string `mapstructure:"description"`
AppMappings []TaxCodeAppMapping `mapstructure:"appMappings"`
DefaultInvoicing bool `mapstructure:"defaultInvoicing"`
DefaultCreditGrant bool `mapstructure:"defaultCreditGrant"`
}
type TaxCodeAppMapping struct {
AppType string `mapstructure:"appType"`
TaxCode string `mapstructure:"taxCode"`
}
func (c TaxCodeConfiguration) Validate() error {
var errs []error
if len(c.Seeds) == 0 {
errs = append(errs, errors.New("seeds must not be empty"))
return errors.Join(errs...)
}
keys := make(map[string]struct{}, len(c.Seeds))
defaultInvoicingCount := 0
defaultCreditGrantCount := 0
for i, seed := range c.Seeds {
trimmedKey := strings.TrimSpace(seed.Key)
if trimmedKey == "" {
errs = append(errs, fmt.Errorf("seed[%d]: key must not be empty", i))
}
if strings.TrimSpace(seed.Name) == "" {
errs = append(errs, fmt.Errorf("seed[%d]: name must not be empty", i))
}
if trimmedKey != "" {
if _, exists := keys[trimmedKey]; exists {
errs = append(errs, fmt.Errorf("seed[%d]: duplicate key %q", i, seed.Key))
}
keys[trimmedKey] = struct{}{}
}
if seed.DefaultInvoicing {
defaultInvoicingCount++
}
if seed.DefaultCreditGrant {
defaultCreditGrantCount++
}
for j, mapping := range seed.AppMappings {
trimmedAppType := strings.TrimSpace(mapping.AppType)
trimmedTaxCode := strings.TrimSpace(mapping.TaxCode)
if trimmedAppType == "" {
errs = append(errs, fmt.Errorf("seed[%d].appMappings[%d]: appType must not be empty", i, j))
}
if trimmedTaxCode == "" {
errs = append(errs, fmt.Errorf("seed[%d].appMappings[%d]: taxCode must not be empty", i, j))
} else if trimmedAppType == "stripe" && !taxcode.TaxCodeStripeRegexp.MatchString(trimmedTaxCode) {
errs = append(errs, fmt.Errorf("seed[%d].appMappings[%d]: taxCode %q is not a valid Stripe tax code (must match %s)", i, j, trimmedTaxCode, taxcode.TaxCodeStripeRegexp.String()))
}
}
}
if defaultInvoicingCount != 1 {
errs = append(errs, fmt.Errorf("exactly one seed must have defaultInvoicing=true, got %d", defaultInvoicingCount))
}
if defaultCreditGrantCount != 1 {
errs = append(errs, fmt.Errorf("exactly one seed must have defaultCreditGrant=true, got %d", defaultCreditGrantCount))
}
return errors.Join(errs...)
}
func ConfigureTaxCode(v *viper.Viper) {
v.SetDefault("taxcode.seeds", []map[string]any{
{
"key": taxcode.ProviderDefaultTaxCodeKey,
"name": "Provider default",
"defaultInvoicing": true,
},
{
"key": "nontaxable",
"name": "Nontaxable",
"defaultCreditGrant": true,
"appMappings": []map[string]any{
{
"appType": "stripe",
"taxCode": "txcd_00000000",
},
},
},
})
}