Skip to content

Commit 38a7407

Browse files
committed
refactor: make taxcodeid mandatory for charges
1 parent 1cc1c6d commit 38a7407

73 files changed

Lines changed: 579 additions & 992 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

api/v3/handlers/customers/charges/convert.go

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -370,22 +370,16 @@ func ConvertCurrencyCodeToAPI(c currencyx.Code) api.CurrencyCode {
370370
}
371371

372372
// convertTaxCodeConfigToAPI maps a TaxCodeConfig (Behavior + TaxCodeID) to the API type.
373-
func convertTaxCodeConfigToAPI(cfg *productcatalog.TaxCodeConfig) *api.BillingTaxConfig {
374-
if cfg == nil {
373+
func convertTaxCodeConfigToAPI(cfg productcatalog.TaxCodeConfig) *api.BillingTaxConfig {
374+
if lo.IsEmpty(cfg) {
375375
return nil
376376
}
377-
out := &api.BillingTaxConfig{}
378-
if cfg.Behavior != nil {
379-
out.Behavior = lo.ToPtr(api.BillingTaxBehavior(*cfg.Behavior))
380-
}
381-
if cfg.TaxCodeID != nil {
382-
out.TaxCode = &api.TaxCodeReference{Id: *cfg.TaxCodeID}
383-
out.TaxCodeId = cfg.TaxCodeID
384-
}
385-
if out.Behavior == nil && out.TaxCode == nil {
386-
return nil
377+
378+
return &api.BillingTaxConfig{
379+
Behavior: (*api.BillingTaxBehavior)(cfg.Behavior),
380+
TaxCode: &api.TaxCodeReference{Id: cfg.TaxCodeID},
381+
TaxCodeId: lo.ToPtr(cfg.TaxCodeID),
387382
}
388-
return out
389383
}
390384

391385
// convertAPIChargeStatus maps an API status string to its domain equivalent.
@@ -432,6 +426,7 @@ func convertFlatFeeChargeAPIToIntent(customerID string, flatFee api.CreateFlatFe
432426
Percentage: models.NewPercentage(float64(lo.FromPtr(flatFee.Discounts.Percentage))),
433427
}
434428
}
429+
435430
var proRating productcatalog.ProRatingConfig
436431
if flatFee.ProrationConfiguration.Mode == api.BillingRateCardProrationModeProratePrices {
437432
proRating = productcatalog.ProRatingConfig{
@@ -504,7 +499,6 @@ func convertUsageBaseChargeAPIToIntent(customerID string, usageBasedFee api.Crea
504499
if err != nil {
505500
return zero, fmt.Errorf("invalid price: %w", err)
506501
}
507-
508502
return billingcharges.NewChargeIntent(usagebased.Intent{
509503
Intent: meta.Intent{
510504
Name: usageBasedFee.Name,

api/v3/handlers/customers/charges/convert_test.go

Lines changed: 7 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -13,41 +13,18 @@ import (
1313
func TestConvertTaxCodeConfigToAPI(t *testing.T) {
1414
tests := []struct {
1515
name string
16-
input *productcatalog.TaxCodeConfig
16+
input productcatalog.TaxCodeConfig
1717
want *api.BillingTaxConfig
1818
}{
1919
{
20-
name: "nil returns nil",
21-
input: nil,
20+
name: "empty config returns nil",
21+
input: productcatalog.TaxCodeConfig{},
2222
want: nil,
2323
},
24-
{
25-
name: "empty config (both fields nil) returns nil",
26-
input: &productcatalog.TaxCodeConfig{},
27-
want: nil,
28-
},
29-
{
30-
name: "behavior only",
31-
input: &productcatalog.TaxCodeConfig{
32-
Behavior: lo.ToPtr(productcatalog.InclusiveTaxBehavior),
33-
},
34-
want: &api.BillingTaxConfig{
35-
Behavior: lo.ToPtr(api.BillingTaxBehaviorInclusive),
36-
},
37-
},
38-
{
39-
name: "exclusive behavior",
40-
input: &productcatalog.TaxCodeConfig{
41-
Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior),
42-
},
43-
want: &api.BillingTaxConfig{
44-
Behavior: lo.ToPtr(api.BillingTaxBehaviorExclusive),
45-
},
46-
},
4724
{
4825
name: "tax code ID only",
49-
input: &productcatalog.TaxCodeConfig{
50-
TaxCodeID: lo.ToPtr("01JTEST00000000000000000001"),
26+
input: productcatalog.TaxCodeConfig{
27+
TaxCodeID: "01JTEST00000000000000000001",
5128
},
5229
want: &api.BillingTaxConfig{
5330
TaxCode: &api.TaxCodeReference{Id: "01JTEST00000000000000000001"},
@@ -56,9 +33,9 @@ func TestConvertTaxCodeConfigToAPI(t *testing.T) {
5633
},
5734
{
5835
name: "both behavior and tax code ID",
59-
input: &productcatalog.TaxCodeConfig{
36+
input: productcatalog.TaxCodeConfig{
6037
Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior),
61-
TaxCodeID: lo.ToPtr("01JTEST00000000000000000002"),
38+
TaxCodeID: "01JTEST00000000000000000002",
6239
},
6340
want: &api.BillingTaxConfig{
6441
Behavior: lo.ToPtr(api.BillingTaxBehaviorExclusive),

api/v3/handlers/customers/credits/convert.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -170,19 +170,20 @@ func toAPIBillingCreditAvailabilityPolicy(status creditpurchase.InitialPaymentSe
170170
}
171171

172172
func toAPIBillingCreditGrantTaxConfig(charge creditpurchase.Charge) *api.BillingCreditGrantTaxConfig {
173-
if charge.Intent.TaxConfig == nil {
173+
cfg := charge.Intent.TaxConfig
174+
if lo.IsEmpty(cfg) {
174175
return nil
175176
}
176177

177178
tc := &api.BillingCreditGrantTaxConfig{}
178179

179-
if charge.Intent.TaxConfig.Behavior != nil {
180-
behavior := api.BillingTaxBehavior(*charge.Intent.TaxConfig.Behavior)
180+
if cfg.Behavior != nil {
181+
behavior := api.BillingTaxBehavior(*cfg.Behavior)
181182
tc.Behavior = &behavior
182183
}
183184

184-
if charge.Intent.TaxConfig.TaxCodeID != nil {
185-
tc.TaxCode = &api.TaxCodeReference{Id: *charge.Intent.TaxConfig.TaxCodeID}
185+
if cfg.TaxCodeID != "" {
186+
tc.TaxCode = &api.TaxCodeReference{Id: cfg.TaxCodeID}
186187
}
187188

188189
return tc

openmeter/billing/charges/adapter/search_test.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"github.com/openmeterio/openmeter/openmeter/customer"
1919
"github.com/openmeterio/openmeter/openmeter/ent/db"
2020
"github.com/openmeterio/openmeter/openmeter/productcatalog"
21+
taxcodetestutils "github.com/openmeterio/openmeter/openmeter/taxcode/testutils"
2122
"github.com/openmeterio/openmeter/openmeter/testutils"
2223
"github.com/openmeterio/openmeter/pkg/currencyx"
2324
"github.com/openmeterio/openmeter/pkg/pagination"
@@ -34,6 +35,8 @@ type ListCustomersToAdvanceSuite struct {
3435
testDB *testutils.TestDB
3536
dbClient *db.Client
3637
adapter charges.ChargesSearchAdapter
38+
39+
taxCodeEnv *taxcodetestutils.TestEnv
3740
}
3841

3942
func (s *ListCustomersToAdvanceSuite) SetupSuite() {
@@ -57,6 +60,8 @@ func (s *ListCustomersToAdvanceSuite) SetupSuite() {
5760
})
5861
require.NoError(t, err)
5962
s.adapter = a
63+
64+
s.taxCodeEnv = taxcodetestutils.NewTestEnvFromClient(t, s.dbClient, slog.Default())
6065
}
6166

6267
func (s *ListCustomersToAdvanceSuite) TearDownSuite() {
@@ -94,6 +99,7 @@ func (s *ListCustomersToAdvanceSuite) insertFlatFeeCharge(namespace, customerID
9499
SetPaymentTerm(productcatalog.InArrearsPaymentTerm).
95100
SetInvoiceAt(now).
96101
SetSettlementMode(productcatalog.CreditOnlySettlementMode).
102+
SetTaxCodeID(s.taxCodeEnv.CreateTaxCode(s.T(), namespace).ID).
97103
SetProRating(flatfee.NoProratingAdapterMode).
98104
SetAmountBeforeProration(alpacadecimal.NewFromInt(100)).
99105
SetAmountAfterProration(alpacadecimal.NewFromInt(100)).

openmeter/billing/charges/charge.go

Lines changed: 3 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -421,13 +421,7 @@ func (i ChargeIntent) WithTaxCodeID(id string) (ChargeIntent, error) {
421421
return ChargeIntent{}, err
422422
}
423423

424-
if ff.Intent.TaxConfig == nil {
425-
ff.Intent.TaxConfig = &productcatalog.TaxCodeConfig{TaxCodeID: &id}
426-
} else {
427-
cfg := *ff.Intent.TaxConfig
428-
cfg.TaxCodeID = &id
429-
ff.Intent.TaxConfig = &cfg
430-
}
424+
ff.Intent.TaxConfig.TaxCodeID = id
431425

432426
return NewChargeIntent(ff), nil
433427
case meta.ChargeTypeUsageBased:
@@ -436,13 +430,7 @@ func (i ChargeIntent) WithTaxCodeID(id string) (ChargeIntent, error) {
436430
return ChargeIntent{}, err
437431
}
438432

439-
if ub.Intent.TaxConfig == nil {
440-
ub.Intent.TaxConfig = &productcatalog.TaxCodeConfig{TaxCodeID: &id}
441-
} else {
442-
cfg := *ub.Intent.TaxConfig
443-
cfg.TaxCodeID = &id
444-
ub.Intent.TaxConfig = &cfg
445-
}
433+
ub.Intent.TaxConfig.TaxCodeID = id
446434

447435
return NewChargeIntent(ub), nil
448436
case meta.ChargeTypeCreditPurchase:
@@ -451,13 +439,7 @@ func (i ChargeIntent) WithTaxCodeID(id string) (ChargeIntent, error) {
451439
return ChargeIntent{}, err
452440
}
453441

454-
if cp.Intent.TaxConfig == nil {
455-
cp.Intent.TaxConfig = &productcatalog.TaxCodeConfig{TaxCodeID: &id}
456-
} else {
457-
cfg := *cp.Intent.TaxConfig
458-
cfg.TaxCodeID = &id
459-
cp.Intent.TaxConfig = &cfg
460-
}
442+
cp.Intent.TaxConfig.TaxCodeID = id
461443

462444
return NewChargeIntent(cp), nil
463445
}

openmeter/billing/charges/creditpurchase/adapter/funded_credit_activity_test.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
"github.com/openmeterio/openmeter/openmeter/billing/charges/meta"
1717
"github.com/openmeterio/openmeter/openmeter/customer"
1818
"github.com/openmeterio/openmeter/openmeter/ent/db"
19+
taxcodetestutils "github.com/openmeterio/openmeter/openmeter/taxcode/testutils"
1920
"github.com/openmeterio/openmeter/openmeter/testutils"
2021
"github.com/openmeterio/openmeter/pkg/currencyx"
2122
"github.com/openmeterio/openmeter/tools/migrate"
@@ -30,6 +31,8 @@ type ListFundedCreditActivitiesSuite struct {
3031

3132
testDB *testutils.TestDB
3233
dbClient *db.Client
34+
35+
taxCodeEnv *taxcodetestutils.TestEnv
3336
}
3437

3538
func (s *ListFundedCreditActivitiesSuite) SetupSuite() {
@@ -46,6 +49,8 @@ func (s *ListFundedCreditActivitiesSuite) SetupSuite() {
4649
require.NoError(t, err)
4750
defer migrator.CloseOrLogError()
4851
require.NoError(t, migrator.Up())
52+
53+
s.taxCodeEnv = taxcodetestutils.NewTestEnvFromClient(t, s.dbClient, slog.Default())
4954
}
5055

5156
func (s *ListFundedCreditActivitiesSuite) TearDownSuite() {
@@ -93,6 +98,7 @@ func (s *ListFundedCreditActivitiesSuite) insertCreditPurchaseWithGrant(
9398
SetManagedBy(billing.SubscriptionManagedLine).
9499
SetName(name).
95100
SetNillableDescription(description).
101+
SetTaxCodeID(s.taxCodeEnv.CreateTaxCode(s.T(), namespace).ID).
96102
SetCreditAmount(alpacadecimal.NewFromInt(100)).
97103
SetSettlement(creditpurchase.NewSettlement(creditpurchase.PromotionalSettlement{})).
98104
SetCreatedAt(chargeCreatedAt).

openmeter/billing/charges/creditpurchase/service/create.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ func (s *service) buildInvoiceCreditPurchaseGatheringLine(charge creditpurchase.
129129
Currency: invoiceSettlement.Currency,
130130
ServicePeriod: intent.ServicePeriod,
131131
InvoiceAt: intent.CalculateEffectiveAt(),
132-
TaxConfig: intent.TaxConfig.ToTaxConfig(),
132+
TaxConfig: lo.ToPtr(intent.TaxConfig.ToTaxConfig()),
133133
ChargeID: lo.ToPtr(charge.ID),
134134
Engine: billing.LineEngineTypeChargeCreditPurchase,
135135
},

openmeter/billing/charges/flatfee/adapter/detailedline_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
dbchargeflatfee "github.com/openmeterio/openmeter/openmeter/ent/db/chargeflatfee"
2121
dbchargeflatfeerundetailedline "github.com/openmeterio/openmeter/openmeter/ent/db/chargeflatfeerundetailedline"
2222
"github.com/openmeterio/openmeter/openmeter/productcatalog"
23+
taxcodetestutils "github.com/openmeterio/openmeter/openmeter/taxcode/testutils"
2324
"github.com/openmeterio/openmeter/openmeter/testutils"
2425
"github.com/openmeterio/openmeter/pkg/currencyx"
2526
"github.com/openmeterio/openmeter/pkg/models"
@@ -37,6 +38,8 @@ type FlatFeeDetailedLineAdapterSuite struct {
3738
testDB *testutils.TestDB
3839
dbClient *entdb.Client
3940
adapter flatfee.Adapter
41+
42+
taxCodeEnv *taxcodetestutils.TestEnv
4043
}
4144

4245
type newDetailedLineInput struct {
@@ -76,6 +79,7 @@ func (s *FlatFeeDetailedLineAdapterSuite) SetupSuite() {
7679
require.NoError(t, err)
7780

7881
s.adapter = a
82+
s.taxCodeEnv = taxcodetestutils.NewTestEnvFromClient(t, s.dbClient, slog.Default())
7983
}
8084

8185
func (s *FlatFeeDetailedLineAdapterSuite) TearDownSuite() {
@@ -88,6 +92,7 @@ func (s *FlatFeeDetailedLineAdapterSuite) TestUpsertDetailedLinesReplacesAndSoft
8892
ctx := s.T().Context()
8993
namespace := "flatfee-detailedline-adapter"
9094
customerID := s.createCustomer(namespace)
95+
taxCodeID := s.taxCodeEnv.CreateTaxCode(s.T(), namespace).ID
9196

9297
servicePeriod := timeutil.ClosedPeriod{
9398
From: time.Date(2026, 1, 1, 0, 0, 0, 0, time.UTC),
@@ -107,6 +112,9 @@ func (s *FlatFeeDetailedLineAdapterSuite) TestUpsertDetailedLinesReplacesAndSoft
107112
ServicePeriod: servicePeriod,
108113
FullServicePeriod: servicePeriod,
109114
BillingPeriod: servicePeriod,
115+
TaxConfig: productcatalog.TaxCodeConfig{
116+
TaxCodeID: taxCodeID,
117+
},
110118
},
111119
InvoiceAt: servicePeriod.To,
112120
SettlementMode: productcatalog.CreditThenInvoiceSettlementMode,

openmeter/billing/charges/flatfee/adapter/realizationrun_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
metaadapter "github.com/openmeterio/openmeter/openmeter/billing/charges/meta/adapter"
1616
entdb "github.com/openmeterio/openmeter/openmeter/ent/db"
1717
"github.com/openmeterio/openmeter/openmeter/productcatalog"
18+
taxcodetestutils "github.com/openmeterio/openmeter/openmeter/taxcode/testutils"
1819
"github.com/openmeterio/openmeter/openmeter/testutils"
1920
"github.com/openmeterio/openmeter/pkg/currencyx"
2021
"github.com/openmeterio/openmeter/pkg/timeutil"
@@ -31,6 +32,8 @@ type FlatFeeRealizationRunAdapterSuite struct {
3132
testDB *testutils.TestDB
3233
dbClient *entdb.Client
3334
adapter flatfee.Adapter
35+
36+
taxCodeEnv *taxcodetestutils.TestEnv
3437
}
3538

3639
func (s *FlatFeeRealizationRunAdapterSuite) SetupSuite() {
@@ -62,6 +65,7 @@ func (s *FlatFeeRealizationRunAdapterSuite) SetupSuite() {
6265
require.NoError(t, err)
6366

6467
s.adapter = a
68+
s.taxCodeEnv = taxcodetestutils.NewTestEnvFromClient(t, s.dbClient, slog.Default())
6569
}
6670

6771
func (s *FlatFeeRealizationRunAdapterSuite) TearDownSuite() {
@@ -74,6 +78,7 @@ func (s *FlatFeeRealizationRunAdapterSuite) TestCreateCurrentRunFailsWhenCurrent
7478
ctx := s.T().Context()
7579
namespace := "flatfee-current-run-adapter"
7680
customerID := s.createCustomer(namespace)
81+
taxCodeID := s.taxCodeEnv.CreateTaxCode(s.T(), namespace).ID
7782

7883
servicePeriod := timeutil.ClosedPeriod{
7984
From: time.Date(2026, 1, 1, 0, 0, 0, 0, time.UTC),
@@ -93,6 +98,9 @@ func (s *FlatFeeRealizationRunAdapterSuite) TestCreateCurrentRunFailsWhenCurrent
9398
ServicePeriod: servicePeriod,
9499
FullServicePeriod: servicePeriod,
95100
BillingPeriod: servicePeriod,
101+
TaxConfig: productcatalog.TaxCodeConfig{
102+
TaxCodeID: taxCodeID,
103+
},
96104
},
97105
InvoiceAt: servicePeriod.To,
98106
SettlementMode: productcatalog.CreditThenInvoiceSettlementMode,

openmeter/billing/charges/flatfee/service/create.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ func buildFlatFeeGatheringLine(input buildFlatFeeGatheringLineInput) (billing.Ga
189189
ServicePeriod: lineIntent.ServicePeriod,
190190
InvoiceAt: lineIntent.InvoiceAt,
191191

192-
TaxConfig: lineIntent.TaxConfig.ToTaxConfig(),
192+
TaxConfig: lo.ToPtr(lineIntent.TaxConfig.ToTaxConfig()),
193193

194194
Engine: billing.LineEngineTypeChargeFlatFee,
195195
ChargeID: lo.ToPtr(flatFee.ID),

0 commit comments

Comments
 (0)