From 59b481eddf48e7030685030c71794c7dc1a8cd5f Mon Sep 17 00:00:00 2001 From: Robert Borbely Date: Tue, 27 Oct 2026 15:08:38 +0100 Subject: [PATCH 1/8] refactor(test): reference live tax codes in subscription example inputs --- api/v3/handlers/subscriptions/convert_test.go | 6 +- api/v3/handlers/subscriptions/migrate_test.go | 7 +- .../plan/adapter/adapter_test.go | 24 +-- .../planaddon/adapter/adapter_test.go | 10 +- .../subscription/service/change_test.go | 32 ++-- .../subscription/service/create_test.go | 28 +++- .../subscription/service/migrate_test.go | 20 ++- .../subscription/service/plan_test.go | 7 +- openmeter/productcatalog/testutils/plan.go | 32 +++- .../subscription/addon/diff/apply_test.go | 107 ++++++------- .../subscription/addon/diff/restore_test.go | 35 ++-- .../subscription/addon/service/change_test.go | 11 +- .../subscription/addon/service/create_test.go | 92 +++++------ .../addon/service/currency_test.go | 7 +- .../subscription/addon/service/list_test.go | 11 +- openmeter/subscription/patch/patch_test.go | 2 +- .../subscription/service/listviews_test.go | 10 +- .../subscription/service/migration_test.go | 13 +- .../subscription/service/service_test.go | 95 +++++++---- openmeter/subscription/service/sync_test.go | 16 +- openmeter/subscription/testutils/compare.go | 62 ++++--- openmeter/subscription/testutils/plan.go | 9 +- openmeter/subscription/testutils/ratecard.go | 107 +++++++------ .../workflow/service/addon_test.go | 58 +++++-- .../workflow/service/migrate_test.go | 6 +- .../workflow/service/subscription_test.go | 151 +++++++++++------- test/subscription/migrate_phases_test.go | 21 ++- test/subscription/migrate_scheduling_test.go | 30 ++-- test/subscription/migrate_test.go | 34 ++-- .../subscription/scenario_editaligned_test.go | 15 +- test/subscription/scenario_editcancel_test.go | 15 +- .../scenario_entinnextphase_test.go | 21 +-- .../scenario_firstofmonth_test.go | 21 +-- 33 files changed, 638 insertions(+), 477 deletions(-) diff --git a/api/v3/handlers/subscriptions/convert_test.go b/api/v3/handlers/subscriptions/convert_test.go index bffd0c8284..aebaf872e6 100644 --- a/api/v3/handlers/subscriptions/convert_test.go +++ b/api/v3/handlers/subscriptions/convert_test.go @@ -4,11 +4,13 @@ import ( "encoding/json" "testing" + "github.com/samber/lo" "github.com/stretchr/testify/require" api "github.com/openmeterio/openmeter/api/v3" "github.com/openmeterio/openmeter/openmeter/currencies" "github.com/openmeterio/openmeter/openmeter/customer" + "github.com/openmeterio/openmeter/openmeter/productcatalog" "github.com/openmeterio/openmeter/openmeter/subscription" subscriptiontestutils "github.com/openmeterio/openmeter/openmeter/subscription/testutils" "github.com/openmeterio/openmeter/openmeter/testutils" @@ -137,7 +139,9 @@ func TestToAPIBillingSubscriptionViewRoundtrip(t *testing.T) { // given: a subscription created from the example plan, which has phases and rate cards cust := deps.CustomerAdapter.CreateExampleCustomer(t) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) spec, err := subscription.NewSpecFromPlan(plan, subscription.CreateSubscriptionCustomerInput{ CustomerId: cust.ID, diff --git a/api/v3/handlers/subscriptions/migrate_test.go b/api/v3/handlers/subscriptions/migrate_test.go index 2f7cadf531..dcd56e43d7 100644 --- a/api/v3/handlers/subscriptions/migrate_test.go +++ b/api/v3/handlers/subscriptions/migrate_test.go @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/require" api "github.com/openmeterio/openmeter/api/v3" + "github.com/openmeterio/openmeter/openmeter/productcatalog" "github.com/openmeterio/openmeter/openmeter/productcatalog/featureresolver" plansubscription "github.com/openmeterio/openmeter/openmeter/productcatalog/subscription" pcservice "github.com/openmeterio/openmeter/openmeter/productcatalog/subscription/service" @@ -68,13 +69,15 @@ func TestMigrateSubscriptionHandler(t *testing.T) { defer db.Cleanup(t) deps := subscriptiontestutils.NewService(t, db) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.BuildTestPlanInput(t). - AddPhase(nil, subscriptiontestutils.ExampleRateCard1.Clone()).Build()) + AddPhase(nil, subscriptiontestutils.ExampleRateCard1(taxConfig)).Build()) before := subscriptiontestutils.CreateSubscriptionFromPlan(t, &deps, plan, start) clock.FreezeTime(start.Add(24 * time.Hour)) deps.PlanHelper.CreatePlan(t, subscriptiontestutils.BuildTestPlanInput(t). - AddPhase(nil, subscriptiontestutils.ExampleRateCard1.Clone(), subscriptiontestutils.ExampleRateCard2.Clone()).Build()) + AddPhase(nil, subscriptiontestutils.ExampleRateCard1(taxConfig), subscriptiontestutils.ExampleRateCard2.Clone()).Build()) clock.FreezeTime(start.Add(10 * 24 * time.Hour)) resolver, err := featureresolver.New(deps.FeatureConnector) diff --git a/openmeter/productcatalog/plan/adapter/adapter_test.go b/openmeter/productcatalog/plan/adapter/adapter_test.go index 0c372cb6d9..417bbdd047 100644 --- a/openmeter/productcatalog/plan/adapter/adapter_test.go +++ b/openmeter/productcatalog/plan/adapter/adapter_test.go @@ -305,7 +305,6 @@ func TestPostgresAdapter(t *testing.T) { t, namespace, pctestutils.WithPlanKey("custom-plan-currency"), - withoutTaxConfig, func(t *testing.T, p *productcatalog.Plan) { t.Helper() p.Currency = custom.Reference() @@ -686,11 +685,11 @@ func TestListPlansExcludeUnrepresentableCurrencies(t *testing.T) { namespace := pctestutils.NewTestNamespace(t) - plain := pctestutils.NewTestPlan(t, namespace, pctestutils.WithPlanKey("plain"), withoutTaxConfig) + plain := pctestutils.NewTestPlan(t, namespace, pctestutils.WithPlanKey("plain")) _, err := env.PlanRepository.CreatePlan(t.Context(), plain) require.NoError(t, err, "creating plain plan must not fail") - withOverride := pctestutils.NewTestPlan(t, namespace, pctestutils.WithPlanKey("with-override"), withoutTaxConfig) + withOverride := pctestutils.NewTestPlan(t, namespace, pctestutils.WithPlanKey("with-override")) overriddenRateCard, ok := withOverride.Phases[0].RateCards[0].(*productcatalog.FlatFeeRateCard) require.True(t, ok, "default test plan rate card must be flat fee") custom, err := env.Currency.CreateCurrency(t.Context(), currencytestutils.NewCreateCurrencyInput(namespace, "TOKEN", "Tokens", "tok")) @@ -699,7 +698,7 @@ func TestListPlansExcludeUnrepresentableCurrencies(t *testing.T) { _, err = env.PlanRepository.CreatePlan(t.Context(), withOverride) require.NoError(t, err, "creating plan with rate-card currency override must not fail") - withCustomDefault := pctestutils.NewTestPlan(t, namespace, pctestutils.WithPlanKey("with-custom-default"), withoutTaxConfig) + withCustomDefault := pctestutils.NewTestPlan(t, namespace, pctestutils.WithPlanKey("with-custom-default")) withCustomDefault.Currency = custom.Reference() _, err = env.PlanRepository.CreatePlan(t.Context(), withCustomDefault) require.NoError(t, err, "creating plan with custom default currency must not fail") @@ -728,21 +727,6 @@ func TestListPlansExcludeUnrepresentableCurrencies(t *testing.T) { }) } -func withoutTaxConfig(t *testing.T, p *productcatalog.Plan) { - t.Helper() - - for _, phase := range p.Phases { - for _, rateCard := range phase.RateCards { - err := rateCard.ChangeMeta(func(meta productcatalog.RateCardMeta) (productcatalog.RateCardMeta, error) { - meta.TaxConfig = nil - - return meta, nil - }) - require.NoError(t, err) - } - } -} - type createPlanVersionInput struct { Namespace string Version int @@ -776,7 +760,7 @@ func testListPlanStatusFilter(ctx context.Context, t *testing.T, repo plan.Repos ns := "list-plan-status-filter" - planV1Input := pctestutils.NewTestPlan(t, ns, withoutTaxConfig) + planV1Input := pctestutils.NewTestPlan(t, ns) err := createPlanVersion(ctx, repo, createPlanVersionInput{ Namespace: ns, diff --git a/openmeter/productcatalog/planaddon/adapter/adapter_test.go b/openmeter/productcatalog/planaddon/adapter/adapter_test.go index 90a13f677e..7034086dc2 100644 --- a/openmeter/productcatalog/planaddon/adapter/adapter_test.go +++ b/openmeter/productcatalog/planaddon/adapter/adapter_test.go @@ -42,15 +42,7 @@ func TestPlanAddonAdapterBackfillsTaxConfigFromTaxCode(t *testing.T) { }, }) - planInput := pctestutils.NewTestPlan(t, namespace) - err := planInput.Phases[0].RateCards[0].ChangeMeta(func(meta productcatalog.RateCardMeta) (productcatalog.RateCardMeta, error) { - meta.TaxConfig = &productcatalog.TaxConfig{ - TaxCodeID: lo.ToPtr(taxCode.ID), - } - - return meta, nil - }) - require.NoError(t, err) + planInput := pctestutils.NewTestPlan(t, namespace, pctestutils.WithRateCardTaxCode(taxCode)) createdPlan, err := env.PlanRepository.CreatePlan(ctx, planInput) require.NoError(t, err) diff --git a/openmeter/productcatalog/subscription/service/change_test.go b/openmeter/productcatalog/subscription/service/change_test.go index e4a7cf5aa6..0570490789 100644 --- a/openmeter/productcatalog/subscription/service/change_test.go +++ b/openmeter/productcatalog/subscription/service/change_test.go @@ -46,7 +46,9 @@ func TestChange(t *testing.T) { t.Run("Should change to different plan", func(t *testing.T) { withDeps(t, func(t *testing.T, deps tDeps) { - examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t) + taxCode := deps.subDeps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) now := testutils.GetRFC3339Time(t, "2021-01-01T00:01:10Z") clock.SetTime(now) @@ -98,7 +100,7 @@ func TestChange(t *testing.T) { Description: lo.ToPtr("Test Phase 4 Description"), }, RateCards: productcatalog.RateCards{ - subscriptiontestutils.ExampleRateCard1.Clone(), + subscriptiontestutils.ExampleRateCard1(taxConfig), }, }) @@ -146,7 +148,9 @@ func TestChange(t *testing.T) { t.Run("Should change to different plan starting from specific phase", func(t *testing.T) { withDeps(t, func(t *testing.T, deps tDeps) { - examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t) + taxCode := deps.subDeps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) now := testutils.GetRFC3339Time(t, "2021-01-01T00:01:10Z") clock.SetTime(now) @@ -198,7 +202,7 @@ func TestChange(t *testing.T) { Description: lo.ToPtr("Test Phase 4 Description"), }, RateCards: productcatalog.RateCards{ - subscriptiontestutils.ExampleRateCard1.Clone(), + subscriptiontestutils.ExampleRateCard1(taxConfig), }, }) @@ -268,7 +272,9 @@ func TestChange(t *testing.T) { t.Run("Should not allow changing to inactive plan", func(t *testing.T) { withDeps(t, func(t *testing.T, deps tDeps) { - examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t) + taxCode := deps.subDeps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) now := testutils.GetRFC3339Time(t, "2021-01-01T00:01:10Z") clock.SetTime(now) @@ -320,7 +326,7 @@ func TestChange(t *testing.T) { Description: lo.ToPtr("Test Phase 4 Description"), }, RateCards: productcatalog.RateCards{ - subscriptiontestutils.ExampleRateCard1.Clone(), + subscriptiontestutils.ExampleRateCard1(taxConfig), }, }) @@ -386,7 +392,9 @@ func TestChange(t *testing.T) { t.Run("Should apply the settlement mode override when creating from a plan reference", func(t *testing.T) { withDeps(t, func(t *testing.T, deps tDeps) { - examplePlanInput := subscriptiontestutils.GetExamplePlanInput(t) + taxCode := deps.subDeps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + examplePlanInput := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) require.Equal(t, productcatalog.CreditThenInvoiceSettlementMode, examplePlanInput.Plan.SettlementMode) now := testutils.GetRFC3339Time(t, "2021-01-01T00:01:10Z") @@ -430,7 +438,9 @@ func TestChange(t *testing.T) { t.Run("Should apply the settlement mode override when changing to a plan reference", func(t *testing.T) { withDeps(t, func(t *testing.T, deps tDeps) { - examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t) + taxCode := deps.subDeps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) now := testutils.GetRFC3339Time(t, "2021-01-01T00:01:10Z") clock.SetTime(now) @@ -532,7 +542,9 @@ func TestChangeInlineCustomPlanRejectsMissingFeature(t *testing.T) { customer := deps.CustomerAdapter.CreateExampleCustomer(t) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - currentPlanInput := subscriptiontestutils.GetExamplePlanInput(t) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + currentPlanInput := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) currentPlanInput.Plan.Key = "" currentPlanInput.Plan.Version = 0 currentPlan := plansubscription.PlanInput{} @@ -552,7 +564,7 @@ func TestChangeInlineCustomPlanRejectsMissingFeature(t *testing.T) { require.NoError(t, err) const missingFeatureKey = "missing-change-feature" - replacementPlanInput := subscriptiontestutils.GetExamplePlanInput(t) + replacementPlanInput := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) replacementPlanInput.Plan.Key = "" replacementPlanInput.Plan.Version = 0 require.NoError(t, replacementPlanInput.Plan.Phases[0].RateCards[0].ChangeMeta(func(meta productcatalog.RateCardMeta) (productcatalog.RateCardMeta, error) { diff --git a/openmeter/productcatalog/subscription/service/create_test.go b/openmeter/productcatalog/subscription/service/create_test.go index c3aafd210b..4e0587bf45 100644 --- a/openmeter/productcatalog/subscription/service/create_test.go +++ b/openmeter/productcatalog/subscription/service/create_test.go @@ -79,7 +79,9 @@ func TestCreateInlineCustomPlanRejectsMissingFeature(t *testing.T) { deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) const missingFeatureKey = "missing-feature" - planInput := subscriptiontestutils.GetExamplePlanInput(t) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + planInput := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) planInput.Plan.Key = "" planInput.Plan.Version = 0 require.NoError(t, planInput.Plan.Phases[0].RateCards[0].ChangeMeta(func(meta productcatalog.RateCardMeta) (productcatalog.RateCardMeta, error) { @@ -151,8 +153,10 @@ func TestCreateSettlementModeOverride(t *testing.T) { cust := deps.subDeps.CustomerAdapter.CreateExampleCustomer(t) deps.subDeps.FeatureConnector.CreateExampleFeatures(t, deps.subDeps.ExampleMeterID) + taxCode := deps.subDeps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} // Build a custom plan input; clear Key/Version so PlanFromPlanInput accepts it. - planInput := subscriptiontestutils.GetExamplePlanInput(t) + planInput := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) require.Equal(t, productcatalog.CreditThenInvoiceSettlementMode, planInput.Plan.SettlementMode, "precondition: plan default must be CreditThenInvoice") planInput.Plan.Key = "" planInput.Plan.Version = 0 @@ -198,7 +202,9 @@ func TestCreateSettlementModeOverride(t *testing.T) { cust := deps.subDeps.CustomerAdapter.CreateExampleCustomer(t) deps.subDeps.FeatureConnector.CreateExampleFeatures(t, deps.subDeps.ExampleMeterID) - examplePlanInput := subscriptiontestutils.GetExamplePlanInput(t) + taxCode := deps.subDeps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + examplePlanInput := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) require.Equal(t, productcatalog.CreditThenInvoiceSettlementMode, examplePlanInput.Plan.SettlementMode, "precondition: plan default must be CreditThenInvoice") plan1 := deps.subDeps.PlanHelper.CreatePlan(t, examplePlanInput) @@ -255,7 +261,9 @@ func TestCreateInlineCustomCurrencyMaterializesManagedIdentity(t *testing.T) { )) require.NoError(t, err) - planInput := subscriptiontestutils.GetExamplePlanInput(t) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + planInput := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) planInput.Plan.Key = "" planInput.Plan.Version = 0 planInput.Plan.Currency = managedCurrency.Reference() @@ -322,7 +330,9 @@ func TestCreateInlineCustomCurrencyGatedByCredits(t *testing.T) { customer := deps.CustomerAdapter.CreateExampleCustomer(t) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - planInput := subscriptiontestutils.GetExamplePlanInput(t) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + planInput := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) planInput.Plan.Key = "" planInput.Plan.Version = 0 planInput.Plan.Currency = currencies.NewCurrencyReference("CREDITS") @@ -377,7 +387,9 @@ func TestCreateInlineEntitlementRateCardResolvesFeatureByID(t *testing.T) { featureIDByKey[f.Key] = f.ID } - planInput := subscriptiontestutils.GetExamplePlanInput(t) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + planInput := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) planInput.Plan.Key = "" planInput.Plan.Version = 0 @@ -430,7 +442,9 @@ func TestCreateInlineCreditOnlyPlanSkipsCurrencyCostBasis(t *testing.T) { )) require.NoError(t, err) - planInput := subscriptiontestutils.GetExamplePlanInput(t) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + planInput := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) planInput.Plan.Key = "" planInput.Plan.Version = 0 planInput.Plan.SettlementMode = productcatalog.CreditOnlySettlementMode diff --git a/openmeter/productcatalog/subscription/service/migrate_test.go b/openmeter/productcatalog/subscription/service/migrate_test.go index 4871aaf070..7d23ee458b 100644 --- a/openmeter/productcatalog/subscription/service/migrate_test.go +++ b/openmeter/productcatalog/subscription/service/migrate_test.go @@ -44,7 +44,9 @@ func TestMigrate(t *testing.T) { t.Run("Should migrate to latest version of plan when none is specified", func(t *testing.T) { withDeps(t, func(t *testing.T, deps tDeps) { - examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t) + taxCode := deps.subDeps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) now := testutils.GetRFC3339Time(t, "2021-01-01T00:01:10Z") clock.SetTime(now) @@ -120,7 +122,9 @@ func TestMigrate(t *testing.T) { t.Run("Should migrate to specific version of plan when provided", func(t *testing.T) { withDeps(t, func(t *testing.T, deps tDeps) { - examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t) + taxCode := deps.subDeps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) now := testutils.GetRFC3339Time(t, "2021-01-01T00:01:10Z") clock.SetTime(now) @@ -194,7 +198,9 @@ func TestMigrate(t *testing.T) { t.Run("Should not allow migrating to same or smaller version", func(t *testing.T) { withDeps(t, func(t *testing.T, deps tDeps) { - examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t) + taxCode := deps.subDeps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) now := testutils.GetRFC3339Time(t, "2021-01-01T00:01:10Z") clock.SetTime(now) @@ -273,7 +279,9 @@ func TestMigrate(t *testing.T) { t.Run("Should replace the subscription when a starting phase is supplied", func(t *testing.T) { withDeps(t, func(t *testing.T, deps tDeps) { - examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t) + taxCode := deps.subDeps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) now := testutils.GetRFC3339Time(t, "2021-01-01T00:01:10Z") clock.SetTime(now) @@ -396,8 +404,10 @@ func TestMigrateReturnsCurrentSnapshotFromUnderLock(t *testing.T) { deps := subscriptiontestutils.NewService(t, db) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} planInput := subscriptiontestutils.BuildTestPlanInput(t).AddPhase(nil, - subscriptiontestutils.ExampleRateCard1.Clone(), + subscriptiontestutils.ExampleRateCard1(taxConfig), ).Build() p1 := deps.PlanHelper.CreatePlan(t, planInput) before := subscriptiontestutils.CreateSubscriptionFromPlan(t, &deps, p1, start) diff --git a/openmeter/productcatalog/subscription/service/plan_test.go b/openmeter/productcatalog/subscription/service/plan_test.go index bfb224f979..6c937deae8 100644 --- a/openmeter/productcatalog/subscription/service/plan_test.go +++ b/openmeter/productcatalog/subscription/service/plan_test.go @@ -7,6 +7,7 @@ import ( "github.com/samber/lo" "github.com/stretchr/testify/require" + "github.com/openmeterio/openmeter/openmeter/productcatalog" plansubscription "github.com/openmeterio/openmeter/openmeter/productcatalog/subscription" "github.com/openmeterio/openmeter/openmeter/subscription" subscriptiontestutils "github.com/openmeterio/openmeter/openmeter/subscription/testutils" @@ -39,8 +40,10 @@ func TestDiscountPersisting(t *testing.T) { t.Run("Should persist discounts", func(t *testing.T) { withDeps(t, func(t *testing.T, deps tDeps) { - examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t) - examplePlanInput1.Phases[0].RateCards[0] = subscriptiontestutils.ExampleRateCardWithDiscounts.Clone() + taxCode := deps.subDeps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) + examplePlanInput1.Phases[0].RateCards[0] = subscriptiontestutils.ExampleRateCardWithDiscounts(taxConfig) ctx := context.Background() diff --git a/openmeter/productcatalog/testutils/plan.go b/openmeter/productcatalog/testutils/plan.go index 47b9036fb2..578efb069a 100644 --- a/openmeter/productcatalog/testutils/plan.go +++ b/openmeter/productcatalog/testutils/plan.go @@ -6,10 +6,12 @@ import ( decimal "github.com/alpacahq/alpacadecimal" "github.com/invopop/gobl/currency" "github.com/samber/lo" + "github.com/stretchr/testify/require" "github.com/openmeterio/openmeter/openmeter/currencies" "github.com/openmeterio/openmeter/openmeter/productcatalog" "github.com/openmeterio/openmeter/openmeter/productcatalog/plan" + "github.com/openmeterio/openmeter/openmeter/taxcode" "github.com/openmeterio/openmeter/pkg/currencyx" "github.com/openmeterio/openmeter/pkg/datetime" "github.com/openmeterio/openmeter/pkg/models" @@ -35,6 +37,31 @@ func WithPlanKey(key string) TransformerFunc[productcatalog.Plan] { } } +// WithRateCardTaxCode points every rate card in the plan at tc by ID, keeping any tax behavior. +// Apply it after WithPlanPhases to cover the replacement phases. +func WithRateCardTaxCode(tc taxcode.TaxCode) TransformerFunc[productcatalog.Plan] { + return func(t *testing.T, plan *productcatalog.Plan) { + t.Helper() + + for _, phase := range plan.Phases { + for _, rc := range phase.RateCards { + require.NoError(t, rc.ChangeMeta(func(m productcatalog.RateCardMeta) (productcatalog.RateCardMeta, error) { + var behavior *productcatalog.TaxBehavior + if m.TaxConfig != nil { + behavior = m.TaxConfig.Behavior + } + + m.TaxConfig = &productcatalog.TaxConfig{TaxCodeID: &tc.ID, Behavior: behavior} + + return m, nil + })) + } + } + } +} + +// NewTestPlan returns a plan input with one untaxed flat-fee rate card; use WithRateCardTaxCode to +// reference a tax code. func NewTestPlan(t *testing.T, namespace string, transformers ...TransformerFunc[productcatalog.Plan]) plan.CreatePlanInput { t.Helper() @@ -73,11 +100,6 @@ func NewTestPlan(t *testing.T, namespace string, transformers ...TransformerFunc Description: lo.ToPtr("API Requests"), Metadata: models.Metadata{"name": "api_requests"}, EntitlementTemplate: nil, - TaxConfig: &productcatalog.TaxConfig{ - Stripe: &productcatalog.StripeTaxConfig{ - Code: "txcd_10000000", - }, - }, Price: productcatalog.NewPriceFrom(productcatalog.FlatPrice{ Amount: decimal.NewFromInt(0), PaymentTerm: productcatalog.InArrearsPaymentTerm, diff --git a/openmeter/subscription/addon/diff/apply_test.go b/openmeter/subscription/addon/diff/apply_test.go index 5e8d312a62..b09f0bd0d9 100644 --- a/openmeter/subscription/addon/diff/apply_test.go +++ b/openmeter/subscription/addon/diff/apply_test.go @@ -12,7 +12,6 @@ import ( "github.com/samber/lo" "github.com/stretchr/testify/require" - "github.com/openmeterio/openmeter/openmeter/app" "github.com/openmeterio/openmeter/openmeter/currencies" currenciestestutils "github.com/openmeterio/openmeter/openmeter/currencies/testutils" "github.com/openmeterio/openmeter/openmeter/productcatalog" @@ -21,7 +20,6 @@ import ( subscriptionaddon "github.com/openmeterio/openmeter/openmeter/subscription/addon" addondiff "github.com/openmeterio/openmeter/openmeter/subscription/addon/diff" subscriptiontestutils "github.com/openmeterio/openmeter/openmeter/subscription/testutils" - "github.com/openmeterio/openmeter/openmeter/taxcode" "github.com/openmeterio/openmeter/pkg/clock" "github.com/openmeterio/openmeter/pkg/currencyx" "github.com/openmeterio/openmeter/pkg/datetime" @@ -33,7 +31,8 @@ var now, _ = time.Parse(time.RFC3339, "2025-04-01T00:00:00Z") func TestApply(t *testing.T) { type tcDeps struct { - deps subscriptiontestutils.SubscriptionDependencies + deps subscriptiontestutils.SubscriptionDependencies + taxConfig productcatalog.TaxConfig } // TODO: we could write purer tests here (without depending on the services) but this is simply more convenient for now @@ -49,8 +48,12 @@ func TestApply(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + fn(t, &tcDeps{ - deps: deps, + deps: deps, + taxConfig: taxConfig, }) } @@ -59,7 +62,7 @@ func TestApply(t *testing.T) { p, a := subscriptiontestutils.CreatePlanWithAddon( t, deps.deps, - subscriptiontestutils.GetExamplePlanInput(t), + subscriptiontestutils.GetExamplePlanInput(t, deps.taxConfig), subscriptiontestutils.GetExampleAddonInput(t, productcatalog.EffectivePeriod{ EffectiveFrom: &now, EffectiveTo: nil, @@ -88,7 +91,7 @@ func TestApply(t *testing.T) { p, a := subscriptiontestutils.CreatePlanWithAddon( t, deps.deps, - subscriptiontestutils.GetExamplePlanInput(t), + subscriptiontestutils.GetExamplePlanInput(t, deps.taxConfig), subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ EffectiveFrom: &now, @@ -148,7 +151,7 @@ func TestApply(t *testing.T) { p, a := subscriptiontestutils.CreatePlanWithAddon( t, deps.deps, - subscriptiontestutils.GetExamplePlanInput(t), + subscriptiontestutils.GetExamplePlanInput(t, deps.taxConfig), subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ EffectiveFrom: &now, @@ -305,7 +308,7 @@ func TestApply(t *testing.T) { p, a := subscriptiontestutils.CreatePlanWithAddon( t, deps.deps, - subscriptiontestutils.GetExamplePlanInput(t), + subscriptiontestutils.GetExamplePlanInput(t, deps.taxConfig), subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ EffectiveFrom: &now, @@ -367,7 +370,7 @@ func TestApply(t *testing.T) { require.Equal(t, int64(300), pr.Amount.IntPart()) // It should have the proper RateCard info, which is price * quantity + bool access - compareRateCardsWithAmountChange(t, withTaxCodeIDAndCurrency(exampleAddonRateCard3, nil, currency.USD), 100*3, item.RateCard, "phase %s", p.PhaseKey) + compareRateCardsWithAmountChange(t, withCurrency(exampleAddonRateCard3, currency.USD), 100*3, item.RateCard, "phase %s", p.PhaseKey) } }) }) @@ -381,7 +384,7 @@ func TestApply(t *testing.T) { p, a := subscriptiontestutils.CreatePlanWithAddon( t, deps.deps, - subscriptiontestutils.GetExamplePlanInput(t), + subscriptiontestutils.GetExamplePlanInput(t, deps.taxConfig), subscriptiontestutils.BuildAddonForTesting(t, effPer, productcatalog.AddonInstanceTypeSingle, @@ -557,8 +560,8 @@ func TestApply(t *testing.T) { t, deps.deps, subscriptiontestutils.BuildTestPlanInput(t). - AddPhase(lo.ToPtr(datetime.MustParseDuration(t, "P1M")), subscriptiontestutils.ExampleRateCard3ForAddons.Clone()). - AddPhase(nil, subscriptiontestutils.ExampleRateCard3ForAddons.Clone()). + AddPhase(lo.ToPtr(datetime.MustParseDuration(t, "P1M")), subscriptiontestutils.ExampleRateCard3ForAddons(deps.taxConfig)). + AddPhase(nil, subscriptiontestutils.ExampleRateCard3ForAddons(deps.taxConfig)). Build(), subscriptiontestutils.BuildAddonForTesting(t, effPer, @@ -569,8 +572,7 @@ func TestApply(t *testing.T) { subView := subscriptiontestutils.CreateSubscriptionFromPlan(t, &deps.deps, p, now) - taxCodeID := lookupTaxCodeID(t, deps.deps, "txcd_10000000") - rc3 := withTaxCodeIDAndCurrency(&subscriptiontestutils.ExampleRateCard3ForAddons, taxCodeID, currency.USD) + rc3 := withCurrency(subscriptiontestutils.ExampleRateCard3ForAddons(deps.taxConfig), currency.USD) subsAdd := subscriptiontestutils.CreateAddonForSubscription(t, &deps.deps, subView.Subscription.NamespacedID, a.NamespacedID, models.CadencedModel{ ActiveFrom: *effPer.EffectiveFrom, @@ -616,8 +618,8 @@ func TestApply(t *testing.T) { t, deps.deps, subscriptiontestutils.BuildTestPlanInput(t). - AddPhase(lo.ToPtr(datetime.MustParseDuration(t, "P1M")), subscriptiontestutils.ExampleRateCard3ForAddons.Clone()). - AddPhase(nil, subscriptiontestutils.ExampleRateCard3ForAddons.Clone()). + AddPhase(lo.ToPtr(datetime.MustParseDuration(t, "P1M")), subscriptiontestutils.ExampleRateCard3ForAddons(deps.taxConfig)). + AddPhase(nil, subscriptiontestutils.ExampleRateCard3ForAddons(deps.taxConfig)). Build(), subscriptiontestutils.BuildAddonForTesting(t, effPer, @@ -628,8 +630,7 @@ func TestApply(t *testing.T) { subView := subscriptiontestutils.CreateSubscriptionFromPlan(t, &deps.deps, p, now) - taxCodeID := lookupTaxCodeID(t, deps.deps, "txcd_10000000") - rc3 := withTaxCodeIDAndCurrency(&subscriptiontestutils.ExampleRateCard3ForAddons, taxCodeID, currency.USD) + rc3 := withCurrency(subscriptiontestutils.ExampleRateCard3ForAddons(deps.taxConfig), currency.USD) subsAdd := subscriptiontestutils.CreateAddonForSubscription(t, &deps.deps, subView.Subscription.NamespacedID, a.NamespacedID, models.CadencedModel{ ActiveFrom: now.AddDate(0, 0, 5), @@ -685,8 +686,8 @@ func TestApply(t *testing.T) { t, deps.deps, subscriptiontestutils.BuildTestPlanInput(t). - AddPhase(lo.ToPtr(datetime.MustParseDuration(t, "P1M")), subscriptiontestutils.ExampleRateCard3ForAddons.Clone()). - AddPhase(nil, subscriptiontestutils.ExampleRateCard3ForAddons.Clone()). + AddPhase(lo.ToPtr(datetime.MustParseDuration(t, "P1M")), subscriptiontestutils.ExampleRateCard3ForAddons(deps.taxConfig)). + AddPhase(nil, subscriptiontestutils.ExampleRateCard3ForAddons(deps.taxConfig)). Build(), subscriptiontestutils.BuildAddonForTesting(t, effPer, @@ -697,8 +698,7 @@ func TestApply(t *testing.T) { subView := subscriptiontestutils.CreateSubscriptionFromPlan(t, &deps.deps, p, now) - taxCodeID := lookupTaxCodeID(t, deps.deps, "txcd_10000000") - rc3 := withTaxCodeIDAndCurrency(&subscriptiontestutils.ExampleRateCard3ForAddons, taxCodeID, currency.USD) + rc3 := withCurrency(subscriptiontestutils.ExampleRateCard3ForAddons(deps.taxConfig), currency.USD) subsAdd := subscriptiontestutils.CreateAddonForSubscription(t, &deps.deps, subView.Subscription.NamespacedID, a.NamespacedID, models.CadencedModel{ ActiveFrom: now.AddDate(0, 0, 5), @@ -799,7 +799,7 @@ func TestApply(t *testing.T) { t, deps.deps, subscriptiontestutils.BuildTestPlanInput(t). - AddPhase(nil, subscriptiontestutils.ExampleRateCard3ForAddons.Clone()). + AddPhase(nil, subscriptiontestutils.ExampleRateCard3ForAddons(deps.taxConfig)). Build(), subscriptiontestutils.BuildAddonForTesting(t, effPer, @@ -821,16 +821,16 @@ func TestApply(t *testing.T) { spec := subView.Spec // Let's just manipulate the spec object directly - ogItem := spec.Phases["test_phase_1"].ItemsByKey[subscriptiontestutils.ExampleRateCard3ForAddons.Key()][0] + ogItem := spec.Phases["test_phase_1"].ItemsByKey[subscriptiontestutils.ExampleFeatureKey2][0] ogRateCard, ok := ogItem.RateCard.(*productcatalog.FlatFeeRateCard) require.True(t, ok) - spec.Phases["test_phase_1"].ItemsByKey[subscriptiontestutils.ExampleRateCard3ForAddons.Key()] = []*subscription.SubscriptionItemSpec{ + spec.Phases["test_phase_1"].ItemsByKey[subscriptiontestutils.ExampleFeatureKey2] = []*subscription.SubscriptionItemSpec{ // First, before gap { CreateSubscriptionItemInput: subscription.CreateSubscriptionItemInput{ CreateSubscriptionItemPlanInput: subscription.CreateSubscriptionItemPlanInput{ PhaseKey: spec.Phases["test_phase_1"].PhaseKey, - ItemKey: subscriptiontestutils.ExampleRateCard3ForAddons.Key(), + ItemKey: subscriptiontestutils.ExampleFeatureKey2, RateCard: ogItem.RateCard.Clone(), }, CreateSubscriptionItemCustomerInput: subscription.CreateSubscriptionItemCustomerInput{ @@ -844,7 +844,7 @@ func TestApply(t *testing.T) { CreateSubscriptionItemInput: subscription.CreateSubscriptionItemInput{ CreateSubscriptionItemPlanInput: subscription.CreateSubscriptionItemPlanInput{ PhaseKey: spec.Phases["test_phase_1"].PhaseKey, - ItemKey: subscriptiontestutils.ExampleRateCard3ForAddons.Key(), + ItemKey: subscriptiontestutils.ExampleFeatureKey2, RateCard: ogItem.RateCard.Clone(), }, CreateSubscriptionItemCustomerInput: subscription.CreateSubscriptionItemCustomerInput{ @@ -859,7 +859,7 @@ func TestApply(t *testing.T) { require.NoError(t, err) // Now let's make sure that we have 5 items: - key := subscriptiontestutils.ExampleRateCard3ForAddons.Key() + key := subscriptiontestutils.ExampleFeatureKey2 phase := spec.GetSortedPhases()[0] pCad, err := spec.GetPhaseCadence(phase.PhaseKey) @@ -882,7 +882,7 @@ func TestApply(t *testing.T) { // [t2-t3]: ExampleAddonRateCard4 require.True(t, items[2].GetCadence(pCad).ActiveFrom.Equal(t2)) require.True(t, items[2].GetCadence(pCad).ActiveTo.Equal(t3)) - compareRateCardsWithAmountChange(t, withTaxCodeIDAndCurrency(subsAdd.RateCards[0].AddonRateCard.RateCard.(*productcatalog.FlatFeeRateCard), nil, currency.USD), 100, items[2].RateCard, "phase %s", phase.PhaseKey) + compareRateCardsWithAmountChange(t, withCurrency(subsAdd.RateCards[0].AddonRateCard.RateCard.(*productcatalog.FlatFeeRateCard), currency.USD), 100, items[2].RateCard, "phase %s", phase.PhaseKey) // [t3-t4]: ExampleRateCard3ForAddons + ExampleAddonRateCard4 require.True(t, items[3].GetCadence(pCad).ActiveFrom.Equal(t3)) @@ -909,7 +909,7 @@ func TestApply(t *testing.T) { t, deps.deps, subscriptiontestutils.BuildTestPlanInput(t). - AddPhase(nil, subscriptiontestutils.ExampleRateCard3ForAddons.Clone()). + AddPhase(nil, subscriptiontestutils.ExampleRateCard3ForAddons(deps.taxConfig)). Build(), subscriptiontestutils.BuildAddonForTesting(t, effPer, @@ -921,8 +921,7 @@ func TestApply(t *testing.T) { subView := subscriptiontestutils.CreateSubscriptionFromPlan(t, &deps.deps, pl, now) - taxCodeID := lookupTaxCodeID(t, deps.deps, "txcd_10000000") - rc3 := withTaxCodeIDAndCurrency(&subscriptiontestutils.ExampleRateCard3ForAddons, taxCodeID, currency.USD) + rc3 := withCurrency(subscriptiontestutils.ExampleRateCard3ForAddons(deps.taxConfig), currency.USD) subAdd := subscriptiontestutils.CreateAddonForSubscription(t, &deps.deps, subView.Subscription.NamespacedID, a.NamespacedID, models.CadencedModel{ ActiveFrom: *effPer.EffectiveFrom, @@ -944,9 +943,9 @@ func TestApply(t *testing.T) { require.NoError(t, err) // Should update ExampleRateCard3ForAddons with ExampleAddonRateCard4 - require.Contains(t, p.ItemsByKey, subscriptiontestutils.ExampleRateCard3ForAddons.Key()) + require.Contains(t, p.ItemsByKey, subscriptiontestutils.ExampleFeatureKey2) - items := p.ItemsByKey[subscriptiontestutils.ExampleRateCard3ForAddons.Key()] + items := p.ItemsByKey[subscriptiontestutils.ExampleFeatureKey2] require.Len(t, items, 1) item := items[0] @@ -967,14 +966,15 @@ func TestApply(t *testing.T) { require.True(t, item.GetCadence(pCad).ActiveFrom.Equal(now)) require.Nil(t, item.GetCadence(pCad).ActiveTo) - compareRateCardsWithAmountChange(t, withTaxCodeIDAndCurrency(&subscriptiontestutils.ExampleAddonRateCard3, nil, currency.USD), 100, item.RateCard, "phase %s", p.PhaseKey) + compareRateCardsWithAmountChange(t, withCurrency(&subscriptiontestutils.ExampleAddonRateCard3, currency.USD), 100, item.RateCard, "phase %s", p.PhaseKey) }) }) } func TestApplyWithMultiInstance(t *testing.T) { type tcDeps struct { - deps subscriptiontestutils.SubscriptionDependencies + deps subscriptiontestutils.SubscriptionDependencies + taxConfig productcatalog.TaxConfig } runWithDeps := func(t *testing.T, fn func(t *testing.T, deps *tcDeps)) { @@ -989,8 +989,12 @@ func TestApplyWithMultiInstance(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + fn(t, &tcDeps{ - deps: deps, + deps: deps, + taxConfig: taxConfig, }) } @@ -1011,7 +1015,7 @@ func TestApplyWithMultiInstance(t *testing.T) { t, deps.deps, subscriptiontestutils.BuildTestPlanInput(t). - AddPhase(nil, subscriptiontestutils.ExampleRateCard3ForAddons.Clone()). + AddPhase(nil, subscriptiontestutils.ExampleRateCard3ForAddons(deps.taxConfig)). Build(), subscriptiontestutils.BuildAddonForTesting(t, effPer, @@ -1022,8 +1026,7 @@ func TestApplyWithMultiInstance(t *testing.T) { subView := subscriptiontestutils.CreateSubscriptionFromPlan(t, &deps.deps, pl, now) - taxCodeID := lookupTaxCodeID(t, deps.deps, "txcd_10000000") - rc3 := withTaxCodeIDAndCurrency(&subscriptiontestutils.ExampleRateCard3ForAddons, taxCodeID, currency.USD) + rc3 := withCurrency(subscriptiontestutils.ExampleRateCard3ForAddons(deps.taxConfig), currency.USD) subAdd := subscriptiontestutils.CreateMultiInstanceAddonForSubscription(t, &deps.deps, subView.Subscription.NamespacedID, a.NamespacedID, []subscriptionaddon.CreateSubscriptionAddonQuantityInput{ { @@ -1075,28 +1078,10 @@ func TestApplyWithMultiInstance(t *testing.T) { }) } -// lookupTaxCodeID resolves the TaxCode entity ID for a given Stripe tax code from the database. -// This is used to set the expected TaxCodeID on test rate cards after plan creation resolves them. -func lookupTaxCodeID(t *testing.T, deps subscriptiontestutils.SubscriptionDependencies, stripeCode string) *string { - t.Helper() - - tc, err := deps.TaxCodeEnv.Service.GetTaxCodeByAppMapping(context.Background(), taxcode.GetTaxCodeByAppMappingInput{ - Namespace: subscriptiontestutils.ExampleNamespace, - AppType: app.AppTypeStripe, - TaxCode: stripeCode, - }) - require.NoError(t, err) - - return &tc.ID -} - -// withTaxCodeIDAndCurrency clones a FlatFeeRateCard and materializes the fields -// resolved when a catalog rate card becomes a subscription item. -func withTaxCodeIDAndCurrency(rc *productcatalog.FlatFeeRateCard, taxCodeID *string, currencyCode currency.Code) *productcatalog.FlatFeeRateCard { +// withCurrency clones a FlatFeeRateCard and materializes the currency resolved when a catalog +// rate card becomes a subscription item. +func withCurrency(rc *productcatalog.FlatFeeRateCard, currencyCode currency.Code) *productcatalog.FlatFeeRateCard { clone := rc.Clone().(*productcatalog.FlatFeeRateCard) - if clone.TaxConfig != nil { - clone.TaxConfig.TaxCodeID = taxCodeID - } currencyReference := currencies.NewCurrencyReference(currencyx.Code(currencyCode)) clone.Currency = ¤cyReference diff --git a/openmeter/subscription/addon/diff/restore_test.go b/openmeter/subscription/addon/diff/restore_test.go index 77580241aa..07fed3db47 100644 --- a/openmeter/subscription/addon/diff/restore_test.go +++ b/openmeter/subscription/addon/diff/restore_test.go @@ -27,7 +27,8 @@ import ( func TestRestore(t *testing.T) { type tcDeps struct { - deps subscriptiontestutils.SubscriptionDependencies + deps subscriptiontestutils.SubscriptionDependencies + taxConfig productcatalog.TaxConfig } withDeps := func(fn func(t *testing.T, deps *tcDeps)) func(t *testing.T) { @@ -43,8 +44,12 @@ func TestRestore(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + fn(t, &tcDeps{ - deps: deps, + deps: deps, + taxConfig: taxConfig, }) } } @@ -114,7 +119,7 @@ func TestRestore(t *testing.T) { env := buildSubAndAddon( t, &deps.deps, - subscriptiontestutils.BuildTestPlanInput(t).AddPhase(nil, subscriptiontestutils.ExampleRateCard1.Clone(), subscriptiontestutils.ExampleRateCard2.Clone()).Build(), + subscriptiontestutils.BuildTestPlanInput(t).AddPhase(nil, subscriptiontestutils.ExampleRateCard1(deps.taxConfig), subscriptiontestutils.ExampleRateCard2.Clone()).Build(), subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ EffectiveFrom: &now, }, productcatalog.AddonInstanceTypeSingle, subscriptiontestutils.ExampleAddonRateCard1.Clone()), @@ -151,7 +156,7 @@ func TestRestore(t *testing.T) { t, &deps.deps, subscriptiontestutils.BuildTestPlanInput(t). - AddPhase(&oneMonth, subscriptiontestutils.ExampleRateCard1.Clone(), subscriptiontestutils.ExampleRateCard2.Clone()). + AddPhase(&oneMonth, subscriptiontestutils.ExampleRateCard1(deps.taxConfig), subscriptiontestutils.ExampleRateCard2.Clone()). AddPhase(nil, subscriptiontestutils.ExampleRateCard2.Clone()). Build(), subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ @@ -182,7 +187,7 @@ func TestRestore(t *testing.T) { t, &deps.deps, subscriptiontestutils.BuildTestPlanInput(t). - AddPhase(nil, subscriptiontestutils.ExampleRateCard1.Clone()). + AddPhase(nil, subscriptiontestutils.ExampleRateCard1(deps.taxConfig)). Build(), subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ EffectiveFrom: &now, @@ -214,7 +219,7 @@ func TestRestore(t *testing.T) { t, &deps.deps, subscriptiontestutils.BuildTestPlanInput(t). - AddPhase(nil, subscriptiontestutils.ExampleRateCard1.Clone()). + AddPhase(nil, subscriptiontestutils.ExampleRateCard1(deps.taxConfig)). Build(), subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ EffectiveFrom: &now, @@ -254,7 +259,7 @@ func TestRestore(t *testing.T) { t, &deps.deps, subscriptiontestutils.BuildTestPlanInput(t). - AddPhase(nil, subscriptiontestutils.ExampleRateCard1.Clone()). + AddPhase(nil, subscriptiontestutils.ExampleRateCard1(deps.taxConfig)). Build(), subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ EffectiveFrom: &now, @@ -311,7 +316,7 @@ func TestRestore(t *testing.T) { t, &deps.deps, subscriptiontestutils.BuildTestPlanInput(t). - AddPhase(nil, subscriptiontestutils.ExampleRateCard1.Clone()). + AddPhase(nil, subscriptiontestutils.ExampleRateCard1(deps.taxConfig)). Build(), subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ EffectiveFrom: &now, @@ -359,7 +364,7 @@ func TestRestore(t *testing.T) { }, SettlementMode: productcatalog.CreditThenInvoiceSettlementMode, }). - AddPhase(nil, subscriptiontestutils.ExampleRateCard1.Clone()). + AddPhase(nil, subscriptiontestutils.ExampleRateCard1(deps.taxConfig)). Build(), subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ EffectiveFrom: &now, @@ -368,7 +373,7 @@ func TestRestore(t *testing.T) { sView := subscriptiontestutils.CreateSubscriptionFromPlan(t, &deps.deps, p, now) - ogItem := sView.Spec.Phases["test_phase_1"].ItemsByKey[subscriptiontestutils.ExampleRateCard1.Key()][0] + ogItem := sView.Spec.Phases["test_phase_1"].ItemsByKey[subscriptiontestutils.ExampleFeatureKey][0] require.NoError(t, ogItem.RateCard.ChangeMeta(func(m productcatalog.RateCardMeta) (productcatalog.RateCardMeta, error) { m.Name = "Different Name for This one" @@ -385,17 +390,17 @@ func TestRestore(t *testing.T) { []subscription.Patch{ patch.PatchRemoveItem{ PhaseKey: "test_phase_1", - ItemKey: subscriptiontestutils.ExampleRateCard1.Key(), + ItemKey: subscriptiontestutils.ExampleFeatureKey, }, patch.PatchAddItem{ PhaseKey: "test_phase_1", - ItemKey: subscriptiontestutils.ExampleRateCard1.Key(), + ItemKey: subscriptiontestutils.ExampleFeatureKey, CreateInput: subscription.SubscriptionItemSpec{ CreateSubscriptionItemInput: subscription.CreateSubscriptionItemInput{ Annotations: ogItem.Annotations, CreateSubscriptionItemPlanInput: subscription.CreateSubscriptionItemPlanInput{ PhaseKey: "test_phase_1", - ItemKey: subscriptiontestutils.ExampleRateCard1.Key(), + ItemKey: subscriptiontestutils.ExampleFeatureKey, RateCard: ogItem.RateCard, }, }, @@ -512,7 +517,7 @@ func TestRestore(t *testing.T) { t, &deps.deps, subscriptiontestutils.BuildTestPlanInput(t). - AddPhase(nil, subscriptiontestutils.ExampleRateCard1.Clone()). + AddPhase(nil, subscriptiontestutils.ExampleRateCard1(deps.taxConfig)). Build(), subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ EffectiveFrom: &now, @@ -572,7 +577,7 @@ func TestRestore(t *testing.T) { deps.deps, subscriptiontestutils.BuildTestPlanInput(t). AddPhase(nil, - subscriptiontestutils.ExampleRateCard1.Clone(), // Flat price + subscriptiontestutils.ExampleRateCard1(deps.taxConfig), // Flat price &productcatalog.UsageBasedRateCard{ // Dynamic price RateCardMeta: productcatalog.RateCardMeta{ Key: subscriptiontestutils.ExampleFeatureKey2, diff --git a/openmeter/subscription/addon/service/change_test.go b/openmeter/subscription/addon/service/change_test.go index 1dbc25524e..d31417a361 100644 --- a/openmeter/subscription/addon/service/change_test.go +++ b/openmeter/subscription/addon/service/change_test.go @@ -75,7 +75,9 @@ func TestAddonServiceChangeQuantity(t *testing.T) { clock.SetTime(now) defer clock.ResetTime() - planInp := subscriptiontestutils.GetExamplePlanInput(t) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + planInp := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) addonInp := subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ EffectiveFrom: lo.ToPtr(now), @@ -187,10 +189,13 @@ func createExampleSubscriptionAddon(t *testing.T, deps subscriptiontestutils.Sub clock.SetTime(now) defer clock.ResetTime() - p, add := createPlanWithAddon( + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + + p, add := subscriptiontestutils.CreatePlanWithAddon( t, deps, - subscriptiontestutils.GetExamplePlanInput(t), + subscriptiontestutils.GetExamplePlanInput(t, taxConfig), subscriptiontestutils.GetExampleAddonInput(t, productcatalog.EffectivePeriod{ EffectiveFrom: lo.ToPtr(now), }), diff --git a/openmeter/subscription/addon/service/create_test.go b/openmeter/subscription/addon/service/create_test.go index 17136ce9f2..e625c5bc38 100644 --- a/openmeter/subscription/addon/service/create_test.go +++ b/openmeter/subscription/addon/service/create_test.go @@ -31,10 +31,13 @@ func TestAddonServiceCreate(t *testing.T) { clock.SetTime(now) defer clock.ResetTime() - p, add := createPlanWithAddon( + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + + p, add := subscriptiontestutils.CreatePlanWithAddon( t, deps, - subscriptiontestutils.GetExamplePlanInput(t), + subscriptiontestutils.GetExamplePlanInput(t, taxConfig), subscriptiontestutils.GetExampleAddonInput(t, productcatalog.EffectivePeriod{ EffectiveFrom: lo.ToPtr(now), }), @@ -77,10 +80,13 @@ func TestAddonServiceCreate(t *testing.T) { clock.SetTime(now) defer clock.ResetTime() - p, _ := createPlanWithAddon( + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + + p, _ := subscriptiontestutils.CreatePlanWithAddon( t, deps, - subscriptiontestutils.GetExamplePlanInput(t), + subscriptiontestutils.GetExamplePlanInput(t, taxConfig), subscriptiontestutils.GetExampleAddonInput(t, productcatalog.EffectivePeriod{ EffectiveFrom: lo.ToPtr(now), }), @@ -150,10 +156,13 @@ func TestAddonServiceCreate(t *testing.T) { clock.SetTime(now) defer clock.ResetTime() - p, add := createPlanWithAddon( + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + + p, add := subscriptiontestutils.CreatePlanWithAddon( t, deps, - subscriptiontestutils.GetExamplePlanInput(t), + subscriptiontestutils.GetExamplePlanInput(t, taxConfig), subscriptiontestutils.GetExampleAddonInput(t, productcatalog.EffectivePeriod{ EffectiveFrom: lo.ToPtr(now), }), @@ -196,10 +205,13 @@ func TestAddonServiceCreate(t *testing.T) { clock.SetTime(now) defer clock.ResetTime() - p, _ := createPlanWithAddon( + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + + p, _ := subscriptiontestutils.CreatePlanWithAddon( t, deps, - subscriptiontestutils.GetExamplePlanInput(t), + subscriptiontestutils.GetExamplePlanInput(t, taxConfig), subscriptiontestutils.GetExampleAddonInput(t, productcatalog.EffectivePeriod{ EffectiveFrom: lo.ToPtr(now), }), @@ -249,7 +261,9 @@ func TestAddonServiceCreate(t *testing.T) { defer clock.ResetTime() // Let's create a plan with addon thats only available in a later phase - planInp := subscriptiontestutils.GetExamplePlanInput(t) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + planInp := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) addonInp := subscriptiontestutils.GetExampleAddonInput(t, productcatalog.EffectivePeriod{ EffectiveFrom: lo.ToPtr(now), }) @@ -325,7 +339,9 @@ func TestAddonServiceCreate(t *testing.T) { defer clock.ResetTime() // Let's create a plan with addon thats only available in a later phase - planInp := subscriptiontestutils.GetExamplePlanInput(t) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + planInp := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) addonInp := subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ EffectiveFrom: lo.ToPtr(now), }, productcatalog.AddonInstanceTypeMultiple, subscriptiontestutils.ExampleAddonRateCard1.Clone()) @@ -404,7 +420,9 @@ func TestAddonServiceCreate(t *testing.T) { // Let's create a subscription without a plan reference cust := deps.CustomerAdapter.CreateExampleCustomer(t) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) spec1, err := subscription.NewSpecFromPlan(plan, subscription.CreateSubscriptionCustomerInput{ CustomerId: cust.ID, @@ -452,10 +470,13 @@ func TestAddonServiceCreate(t *testing.T) { clock.SetTime(now) defer clock.ResetTime() - p, add := createPlanWithAddon( + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + + p, add := subscriptiontestutils.CreatePlanWithAddon( t, deps, - subscriptiontestutils.GetExamplePlanInput(t), + subscriptiontestutils.GetExamplePlanInput(t, taxConfig), subscriptiontestutils.GetExampleAddonInput(t, productcatalog.EffectivePeriod{ EffectiveFrom: lo.ToPtr(now), }), @@ -512,51 +533,12 @@ func TestAddonServiceCreate(t *testing.T) { }) } -func createPlanWithAddon( - t *testing.T, - deps subscriptiontestutils.SubscriptionDependencies, - planInp plan.CreatePlanInput, - addonInp addon.CreateAddonInput, -) (subscription.Plan, addon.Addon) { - t.Helper() - - _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - - p, err := deps.PlanService.CreatePlan(context.Background(), planInp) - require.Nil(t, err) - require.NotNil(t, p) - - add := deps.AddonService.CreateTestAddon(t, addonInp) - - _, err = deps.PlanAddonService.CreatePlanAddon(context.Background(), planaddon.CreatePlanAddonInput{ - NamespacedModel: models.NamespacedModel{ - Namespace: subscriptiontestutils.ExampleNamespace, - }, - PlanID: p.ID, - AddonID: add.ID, - FromPlanPhase: p.Phases[0].Key, - }) - require.Nil(t, err, "received error: %s", err) - - p, err = deps.PlanService.PublishPlan(context.Background(), plan.PublishPlanInput{ - NamespacedID: p.NamespacedID, - EffectivePeriod: productcatalog.EffectivePeriod{ - EffectiveFrom: lo.ToPtr(clock.Now()), - EffectiveTo: lo.ToPtr(testutils.GetRFC3339Time(t, "2099-01-01T00:00:00Z")), - }, - }) - require.Nil(t, err, "received error: %s", err) - - return &plansubscription.Plan{ - Plan: p.AsProductCatalogPlan(), - Ref: &p.NamespacedID, - }, add -} - func createExampleSubscription(t *testing.T, deps subscriptiontestutils.SubscriptionDependencies, currentTime time.Time) subscription.SubscriptionView { cust := deps.CustomerAdapter.CreateExampleCustomer(t) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) spec1, err := subscription.NewSpecFromPlan(plan, subscription.CreateSubscriptionCustomerInput{ CustomerId: cust.ID, diff --git a/openmeter/subscription/addon/service/currency_test.go b/openmeter/subscription/addon/service/currency_test.go index 45f462fba3..58a872740b 100644 --- a/openmeter/subscription/addon/service/currency_test.go +++ b/openmeter/subscription/addon/service/currency_test.go @@ -216,10 +216,13 @@ func createSubscriptionForPlanWithAddon( ) (models.NamespacedID, addon.Addon) { t.Helper() - p, add := createPlanWithAddon( + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + + p, add := subscriptiontestutils.CreatePlanWithAddon( t, deps, - subscriptiontestutils.GetExamplePlanInput(t), + subscriptiontestutils.GetExamplePlanInput(t, taxConfig), addonInput, ) diff --git a/openmeter/subscription/addon/service/list_test.go b/openmeter/subscription/addon/service/list_test.go index 08663bea53..42381ce0ac 100644 --- a/openmeter/subscription/addon/service/list_test.go +++ b/openmeter/subscription/addon/service/list_test.go @@ -28,10 +28,13 @@ func TestAddonServiceGet(t *testing.T) { clock.SetTime(now) defer clock.ResetTime() - p, add := createPlanWithAddon( + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + + p, add := subscriptiontestutils.CreatePlanWithAddon( t, deps, - subscriptiontestutils.GetExamplePlanInput(t), + subscriptiontestutils.GetExamplePlanInput(t, taxConfig), subscriptiontestutils.GetExampleAddonInput(t, productcatalog.EffectivePeriod{ EffectiveFrom: lo.ToPtr(now), }), @@ -101,7 +104,9 @@ func TestAddonServiceList(t *testing.T) { // Let's create a plan - p, err := deps.PlanService.CreatePlan(context.Background(), subscriptiontestutils.GetExamplePlanInput(t)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + p, err := deps.PlanService.CreatePlan(context.Background(), subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) require.Nil(t, err) require.NotNil(t, p) diff --git a/openmeter/subscription/patch/patch_test.go b/openmeter/subscription/patch/patch_test.go index 73a997df88..b1333a5104 100644 --- a/openmeter/subscription/patch/patch_test.go +++ b/openmeter/subscription/patch/patch_test.go @@ -197,7 +197,7 @@ func (ts *testsuite[T]) Run(t *testing.T) { } func getDefaultSpec(t *testing.T, activeFrom time.Time) (*subscription.SubscriptionSpec, *psubs.Plan) { - pInp := subscriptiontestutils.GetExamplePlanInput(t) + pInp := subscriptiontestutils.GetExamplePlanInput(t, productcatalog.TaxConfig{TaxCodeID: lo.ToPtr("example-tax-code"), Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)}) p := &psubs.Plan{ Plan: pInp.Plan, Ref: &models.NamespacedID{Namespace: pInp.Namespace, ID: pInp.Key}, diff --git a/openmeter/subscription/service/listviews_test.go b/openmeter/subscription/service/listviews_test.go index 6551c0b2ed..9b334fa03f 100644 --- a/openmeter/subscription/service/listviews_test.go +++ b/openmeter/subscription/service/listviews_test.go @@ -5,9 +5,11 @@ import ( "testing" "time" + "github.com/samber/lo" "github.com/stretchr/testify/require" "github.com/openmeterio/openmeter/openmeter/customer" + "github.com/openmeterio/openmeter/openmeter/productcatalog" "github.com/openmeterio/openmeter/openmeter/subscription" subscriptiontestutils "github.com/openmeterio/openmeter/openmeter/subscription/testutils" "github.com/openmeterio/openmeter/openmeter/testutils" @@ -34,7 +36,9 @@ func TestListViewsMultiCustomer(t *testing.T) { service := deps.SubscriptionService _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) // given: two distinct customers, each with a subscription from the same plan cust1 := deps.CustomerAdapter.CreateExampleCustomer(t) @@ -87,7 +91,9 @@ func TestGetViewResolvesSoftDeletedCustomer(t *testing.T) { service := deps.SubscriptionService _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) // given: a subscription whose customer is subsequently soft-deleted cust := deps.CustomerAdapter.CreateExampleCustomer(t) diff --git a/openmeter/subscription/service/migration_test.go b/openmeter/subscription/service/migration_test.go index 1fdd17328e..f7b9934f2f 100644 --- a/openmeter/subscription/service/migration_test.go +++ b/openmeter/subscription/service/migration_test.go @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/require" "github.com/openmeterio/openmeter/openmeter/customer" + "github.com/openmeterio/openmeter/openmeter/productcatalog" "github.com/openmeterio/openmeter/openmeter/productcatalog/feature" "github.com/openmeterio/openmeter/openmeter/subscription" subscriptionservice "github.com/openmeterio/openmeter/openmeter/subscription/service" @@ -58,11 +59,13 @@ func TestUpdateRejectsMigrationBetweenReadAndLock(t *testing.T) { defer db.Cleanup(t) deps := subscriptiontestutils.NewService(t, db) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - p1 := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.BuildTestPlanInput(t).AddPhase(nil, subscriptiontestutils.ExampleRateCard1.Clone()).Build()) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + p1 := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.BuildTestPlanInput(t).AddPhase(nil, subscriptiontestutils.ExampleRateCard1(taxConfig)).Build()) before := subscriptiontestutils.CreateSubscriptionFromPlan(t, &deps, p1, start) clock.FreezeTime(start.Add(10 * 24 * time.Hour)) p2 := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.BuildTestPlanInput(t).AddPhase(nil, - subscriptiontestutils.ExampleRateCard1.Clone(), subscriptiontestutils.ExampleRateCard2.Clone()).Build()) + subscriptiontestutils.ExampleRateCard1(taxConfig), subscriptiontestutils.ExampleRateCard2.Clone()).Build()) var migrated subscription.SubscriptionView customerService := &migrateDuringUpdateValidation{Service: deps.CustomerService, migrate: func(ctx context.Context) error { var err error @@ -142,15 +145,17 @@ func TestCancelIncludesMigrationCommittedBeforeLock(t *testing.T) { deps := subscriptiontestutils.NewService(t, db) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} p1 := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.BuildTestPlanInput(t).AddPhase(nil, - subscriptiontestutils.ExampleRateCard1.Clone()).Build()) + subscriptiontestutils.ExampleRateCard1(taxConfig)).Build()) before := subscriptiontestutils.CreateSubscriptionFromPlan(t, &deps, p1, start) clock.FreezeTime(start.Add(10 * 24 * time.Hour)) defer clock.UnFreeze() p2 := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.BuildTestPlanInput(t).AddPhase(nil, - subscriptiontestutils.ExampleRateCard1.Clone(), subscriptiontestutils.ExampleRateCard3ForAddons.Clone()).Build()) + subscriptiontestutils.ExampleRateCard1(taxConfig), subscriptiontestutils.ExampleRateCard3ForAddons(taxConfig)).Build()) var migrated subscription.SubscriptionView features := &migrateBeforeCancelLock{ FeatureConnector: deps.FeatureConnector, diff --git a/openmeter/subscription/service/service_test.go b/openmeter/subscription/service/service_test.go index 4469f5820a..29938cdca4 100644 --- a/openmeter/subscription/service/service_test.go +++ b/openmeter/subscription/service/service_test.go @@ -41,7 +41,9 @@ func TestCreation(t *testing.T) { cust := deps.CustomerAdapter.CreateExampleCustomer(t) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) defaultSpecFromPlan, err := subscription.NewSpecFromPlan(plan, subscription.CreateSubscriptionCustomerInput{ CustomerId: cust.ID, @@ -112,7 +114,9 @@ func TestCreation(t *testing.T) { cust := deps.CustomerAdapter.CreateExampleCustomer(t) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) specWithAnnotations, err := subscription.NewSpecFromPlan(plan, subscription.CreateSubscriptionCustomerInput{ CustomerId: cust.ID, @@ -170,7 +174,9 @@ func TestCreation(t *testing.T) { require.Nil(t, err) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) defaultSpecFromPlan, err := subscription.NewSpecFromPlan(plan, subscription.CreateSubscriptionCustomerInput{ CustomerId: cust.ID, @@ -215,7 +221,9 @@ func TestCreation(t *testing.T) { require.Nil(t, err) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) defaultSpecFromPlan, err := subscription.NewSpecFromPlan(plan, subscription.CreateSubscriptionCustomerInput{ CustomerId: cust.ID, @@ -318,7 +326,9 @@ func TestCancellation(t *testing.T) { cust := deps.CustomerAdapter.CreateExampleCustomer(t) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) // First, let's create a subscription defaultSpecFromPlan, err := subscription.NewSpecFromPlan(plan, subscription.CreateSubscriptionCustomerInput{ @@ -436,7 +446,9 @@ func TestContinuing(t *testing.T) { cust := deps.CustomerAdapter.CreateExampleCustomer(t) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) // First, let's create a subscription defaultSpecFromPlan, err := subscription.NewSpecFromPlan(plan, subscription.CreateSubscriptionCustomerInput{ @@ -523,7 +535,9 @@ func TestContinuing(t *testing.T) { cust := deps.CustomerAdapter.CreateExampleCustomer(t) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) // First, let's create a subscription spec1, err := subscription.NewSpecFromPlan(plan, subscription.CreateSubscriptionCustomerInput{ @@ -631,7 +645,9 @@ func TestList(t *testing.T) { require.Nil(t, err) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) // Let's create some subscriptions: // - One active @@ -815,7 +831,9 @@ func TestList(t *testing.T) { require.Nil(t, err) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) spec1, err := subscription.NewSpecFromPlan(plan, subscription.CreateSubscriptionCustomerInput{ CustomerId: cust1.ID, @@ -911,7 +929,9 @@ func TestSubscriptionChangeTrackingAnnotations(t *testing.T) { cust := deps.CustomerAdapter.CreateExampleCustomer(t) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - plan1 := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + plan1 := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) // Create first subscription sub1, err := workflowService.CreateFromPlan(ctx, subscriptionworkflow.CreateSubscriptionWorkflowInput{ @@ -927,7 +947,7 @@ func TestSubscriptionChangeTrackingAnnotations(t *testing.T) { require.Nil(t, err) // Create second plan - examplePlanInput2 := subscriptiontestutils.GetExamplePlanInput(t) + examplePlanInput2 := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) examplePlanInput2.Key = "example-plan-2" examplePlanInput2.Name = "Example Plan 2" plan2 := deps.PlanHelper.CreatePlan(t, examplePlanInput2) @@ -974,7 +994,9 @@ func TestSubscriptionChangeTrackingAnnotations(t *testing.T) { cust := deps.CustomerAdapter.CreateExampleCustomer(t) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - plan1 := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + plan1 := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) // Create first subscription sub1, err := workflowService.CreateFromPlan(ctx, subscriptionworkflow.CreateSubscriptionWorkflowInput{ @@ -990,7 +1012,7 @@ func TestSubscriptionChangeTrackingAnnotations(t *testing.T) { require.Nil(t, err) // Create second plan - examplePlanInput2 := subscriptiontestutils.GetExamplePlanInput(t) + examplePlanInput2 := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) examplePlanInput2.Key = "example-plan-2" examplePlanInput2.Name = "Example Plan 2" plan2 := deps.PlanHelper.CreatePlan(t, examplePlanInput2) @@ -1038,7 +1060,9 @@ func TestSubscriptionChangeTrackingAnnotations(t *testing.T) { cust := deps.CustomerAdapter.CreateExampleCustomer(t) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - plan1 := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + plan1 := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) // Create first subscription sub1, err := workflowService.CreateFromPlan(ctx, subscriptionworkflow.CreateSubscriptionWorkflowInput{ @@ -1054,7 +1078,7 @@ func TestSubscriptionChangeTrackingAnnotations(t *testing.T) { require.Nil(t, err) // Create second plan - examplePlanInput2 := subscriptiontestutils.GetExamplePlanInput(t) + examplePlanInput2 := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) examplePlanInput2.Key = "example-plan-2" examplePlanInput2.Name = "Example Plan 2" plan2 := deps.PlanHelper.CreatePlan(t, examplePlanInput2) @@ -1102,7 +1126,9 @@ func TestSubscriptionChangeTrackingAnnotations(t *testing.T) { cust := deps.CustomerAdapter.CreateExampleCustomer(t) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - plan1 := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + plan1 := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) // Create standalone scheduled subscription (can be deleted) futureTime := currentTime.AddDate(0, 1, 0) @@ -1144,7 +1170,9 @@ func TestSubscriptionChangeTrackingAnnotations(t *testing.T) { cust := deps.CustomerAdapter.CreateExampleCustomer(t) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - plan1 := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + plan1 := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) // Create scheduled subscription with nil annotations (can be deleted) futureTime := currentTime.AddDate(0, 1, 0) @@ -1173,6 +1201,11 @@ func TestSubscriptionChangeTrackingAnnotations(t *testing.T) { } func TestTaxCodeResolution(t *testing.T) { + // The Stripe-code cases exercise the legacy input: the example plan with its taxed rate cards + // carrying only a Stripe code, which the services resolve to a tax code. + const stripeCode = "txcd_10000000" + stripeTaxConfig := productcatalog.TaxConfig{Stripe: &productcatalog.StripeTaxConfig{Code: stripeCode}} + t.Run("Should resolve and persist TaxCodeID for subscription items with a Stripe tax code", func(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -1188,7 +1221,7 @@ func TestTaxCodeResolution(t *testing.T) { cust := deps.CustomerAdapter.CreateExampleCustomer(t) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t)) + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, stripeTaxConfig)) spec, err := subscription.NewSpecFromPlan(plan, subscription.CreateSubscriptionCustomerInput{ CustomerId: cust.ID, @@ -1206,9 +1239,7 @@ func TestTaxCodeResolution(t *testing.T) { view, err := service.GetView(ctx, models.NamespacedID{ID: sub.ID, Namespace: sub.Namespace}) require.NoError(t, err) - // Look up the TaxCode entity that should have been created during subscription creation. - // ExampleRateCard1 and ExampleRateCard3ForAddons both use Stripe code "txcd_10000000". - const stripeCode = "txcd_10000000" + // Look up the TaxCode entity that should have been created for the Stripe code. tc, err := deps.TaxCodeEnv.Service.GetTaxCodeByAppMapping(ctx, taxcode.GetTaxCodeByAppMappingInput{ Namespace: subscriptiontestutils.ExampleNamespace, AppType: app.AppTypeStripe, @@ -1256,7 +1287,7 @@ func TestTaxCodeResolution(t *testing.T) { cust := deps.CustomerAdapter.CreateExampleCustomer(t) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t)) + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, stripeTaxConfig)) spec, err := subscription.NewSpecFromPlan(plan, subscription.CreateSubscriptionCustomerInput{ CustomerId: cust.ID, @@ -1275,7 +1306,6 @@ func TestTaxCodeResolution(t *testing.T) { view, err := service.GetView(ctx, models.NamespacedID{ID: sub.ID, Namespace: sub.Namespace}) require.NoError(t, err) - const stripeCode = "txcd_10000000" tc, err := deps.TaxCodeEnv.Service.GetTaxCodeByAppMapping(ctx, taxcode.GetTaxCodeByAppMappingInput{ Namespace: subscriptiontestutils.ExampleNamespace, AppType: app.AppTypeStripe, @@ -1509,10 +1539,14 @@ func TestBillingCadenceLegacyCancellation(t *testing.T) { func TestBillingCadenceLegacyFeatureResolution(t *testing.T) { for _, tc := range []struct { name string - rateCard productcatalog.RateCard + rateCard func(productcatalog.TaxConfig) productcatalog.RateCard }{ - {name: "flat fee with item feature", rateCard: subscriptiontestutils.ExampleAddonRateCard4.Clone()}, - {name: "usage based with entitlement feature", rateCard: subscriptiontestutils.ExampleRateCard1.Clone()}, + {name: "flat fee with item feature", rateCard: func(productcatalog.TaxConfig) productcatalog.RateCard { + return subscriptiontestutils.ExampleAddonRateCard4.Clone() + }}, + {name: "usage based with entitlement feature", rateCard: func(taxConfig productcatalog.TaxConfig) productcatalog.RateCard { + return subscriptiontestutils.ExampleRateCard1(taxConfig) + }}, } { t.Run(tc.name, func(t *testing.T) { // given: a persisted weekly subscription whose feature-linked item predates the cadence minimum @@ -1524,7 +1558,10 @@ func TestBillingCadenceLegacyFeatureResolution(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) customer := deps.CustomerAdapter.CreateExampleCustomer(t) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - spec, err := subscriptiontestutils.BuildTestSubscriptionSpec(t).AddPhase(nil, tc.rateCard).Build() + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + rateCard := tc.rateCard(taxConfig) + spec, err := subscriptiontestutils.BuildTestSubscriptionSpec(t).AddPhase(nil, rateCard).Build() require.NoError(t, err) spec.Plan = nil spec.CustomerId = customer.ID @@ -1535,7 +1572,7 @@ func TestBillingCadenceLegacyFeatureResolution(t *testing.T) { require.NoError(t, err) view, err := deps.SubscriptionService.GetView(t.Context(), sub.NamespacedID) require.NoError(t, err) - itemID := view.Phases[0].ItemsByKey[tc.rateCard.Key()][0].SubscriptionItem.ID + itemID := view.Phases[0].ItemsByKey[rateCard.Key()][0].SubscriptionItem.ID _, err = dbDeps.DBClient.SubscriptionItem.UpdateOneID(itemID).SetBillingCadence(datetime.ISODurationString("PT1H")).Save(t.Context()) require.NoError(t, err) @@ -1544,7 +1581,7 @@ func TestBillingCadenceLegacyFeatureResolution(t *testing.T) { // then: reads and cancellation work, but unrelated updates still reject the short cadence require.NoError(t, err) - item := view.Phases[0].ItemsByKey[tc.rateCard.Key()][0] + item := view.Phases[0].ItemsByKey[rateCard.Key()][0] require.NotNil(t, item.Feature) require.True(t, item.Spec.RateCard.AsMeta().Feature.IsResolved()) require.Equal(t, "PT1H", item.Spec.RateCard.GetBillingCadence().String()) diff --git a/openmeter/subscription/service/sync_test.go b/openmeter/subscription/service/sync_test.go index 8304b9b74f..055610c2fe 100644 --- a/openmeter/subscription/service/sync_test.go +++ b/openmeter/subscription/service/sync_test.go @@ -373,7 +373,7 @@ func TestEdit(t *testing.T) { require.True(t, ok) // Let's make sure it has the item we want to change - iKey := subscriptiontestutils.ExampleRateCard1.Key() + iKey := subscriptiontestutils.ExampleFeatureKey v, ok := spec.Phases[pKey].ItemsByKey[iKey] require.True(t, ok) @@ -420,7 +420,9 @@ func TestEdit(t *testing.T) { require.NotNil(t, cust) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) tc.Handler(t, TDeps{ CurrentTime: currentTime, @@ -670,7 +672,9 @@ func TestSyncReconciliation(t *testing.T) { cust := deps.CustomerAdapter.CreateExampleCustomer(t) require.NotNil(t, cust) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) spec, err := subscription.NewSpecFromPlan(plan, subscription.CreateSubscriptionCustomerInput{ Name: "Test", @@ -737,14 +741,16 @@ func TestDeleteScheduledDowngradeCanExpandDeletedSubscriptionForSync(t *testing. deps := subscriptiontestutils.NewService(t, dbDeps) customerEntity := deps.CustomerAdapter.CreateExampleCustomer(t) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} billingAnchor := time.Date(2026, 5, 1, 0, 0, 0, 0, time.UTC) - premiumPlanInput := subscriptiontestutils.GetExamplePlanInput(t) + premiumPlanInput := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) premiumPlanInput.Key = "premium-plan" premiumPlanInput.Name = "Premium" premiumPlan := deps.PlanHelper.CreatePlan(t, premiumPlanInput) - basicPlanInput := subscriptiontestutils.GetExamplePlanInput(t) + basicPlanInput := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) basicPlanInput.Key = "basic-plan" basicPlanInput.Name = "Basic" basicPlan := deps.PlanHelper.CreatePlan(t, basicPlanInput) diff --git a/openmeter/subscription/testutils/compare.go b/openmeter/subscription/testutils/compare.go index a960682351..c7f8c8f011 100644 --- a/openmeter/subscription/testutils/compare.go +++ b/openmeter/subscription/testutils/compare.go @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/require" "github.com/openmeterio/openmeter/openmeter/entitlement" + "github.com/openmeterio/openmeter/openmeter/productcatalog" "github.com/openmeterio/openmeter/openmeter/subscription" subscriptionaddon "github.com/openmeterio/openmeter/openmeter/subscription/addon" "github.com/openmeterio/openmeter/pkg/datetime" @@ -76,25 +77,15 @@ func ValidateSpecAndView(t *testing.T, expected subscription.SubscriptionSpec, f assert.Equal(t, foundPhase.SubscriptionPhase.Key, specItem.PhaseKey) assert.Equal(t, foundPhase.SubscriptionPhase.ID, foundItem.SubscriptionItem.PhaseId) - // Let's validate the RateCard is equal - rc1JSON, _ := json.Marshal(specItem.RateCard) - rc2JSON, _ := json.Marshal(foundItem.SubscriptionItem.RateCard) - - assert.True(t, specItem.RateCard.Equal(foundItem.SubscriptionItem.RateCard), "rate card mismatch for item %s in phase %s: \nspec: %s \n\nview: %s", specItem.ItemKey, specPhase.PhaseKey, rc1JSON, rc2JSON) - - // Let's validate the TaxCodeID - specMeta := specItem.RateCard.AsMeta() - foundMeta := foundItem.SubscriptionItem.RateCard.AsMeta() - if specMeta.TaxConfig != nil && specMeta.TaxConfig.TaxCodeID != nil && *specMeta.TaxConfig.TaxCodeID != "" { - require.NotNil(t, foundMeta.TaxConfig, "TaxConfig must be set for item %s (phase %s) with TaxCodeID %s", specItem.ItemKey, specPhase.PhaseKey, *specMeta.TaxConfig.TaxCodeID) - assert.Equal(t, specMeta.TaxConfig.TaxCodeID, foundMeta.TaxConfig.TaxCodeID, "TaxCodeID mismatch for item %s in phase %s", specItem.ItemKey, specPhase.PhaseKey) - } else if specMeta.TaxConfig != nil && specMeta.TaxConfig.Stripe != nil && specMeta.TaxConfig.Stripe.Code != "" { - require.NotNil(t, foundMeta.TaxConfig, "TaxConfig must be set for item %s (phase %s) with Stripe tax code %s", specItem.ItemKey, specPhase.PhaseKey, specMeta.TaxConfig.Stripe.Code) - require.NotNil(t, foundMeta.TaxConfig.TaxCodeID, "TaxCodeID must be backfilled for item %s (phase %s) with Stripe tax code %s", specItem.ItemKey, specPhase.PhaseKey, specMeta.TaxConfig.Stripe.Code) - assert.Equal(t, specMeta.TaxConfig.TaxCodeID, foundMeta.TaxConfig.TaxCodeID, "TaxCodeID mismatch for item %s in phase %s", specItem.ItemKey, specPhase.PhaseKey) - } else if foundMeta.TaxConfig != nil { - assert.Nil(t, foundMeta.TaxConfig.TaxCodeID, "TaxCodeID must be nil for item %s (phase %s) without a tax code", specItem.ItemKey, specPhase.PhaseKey) - } + // Let's validate the RateCard is equal. Tax is compared by TaxCodeID (and Behavior): + // the Stripe code is a legacy encoding derived from the tax code, not part of the intent. + specRateCard := withoutStripeTaxCode(t, specItem.RateCard) + foundRateCard := withoutStripeTaxCode(t, foundItem.SubscriptionItem.RateCard) + + rc1JSON, _ := json.Marshal(specRateCard) + rc2JSON, _ := json.Marshal(foundRateCard) + + assert.True(t, specRateCard.Equal(foundRateCard), "rate card mismatch for item %s in phase %s: \nspec: %s \n\nview: %s", specItem.ItemKey, specPhase.PhaseKey, rc1JSON, rc2JSON) // Let's validate the Feature linking var expectedFeatureKey, actualFeatureKey *string @@ -233,7 +224,9 @@ func SpecsEqual(t *testing.T, s1, s2 subscription.SubscriptionSpec) { // Let's validate the item properties assert.Equal(t, i1.ItemKey, i2.ItemKey) - assert.True(t, i1.RateCard.Equal(i2.RateCard), "rate card mismatch for item %s in phase %s: \nspec: %+v\n\nview: %+v", itemKey, key, i1.RateCard, i2.RateCard) + rc1 := withoutStripeTaxCode(t, i1.RateCard) + rc2 := withoutStripeTaxCode(t, i2.RateCard) + assert.True(t, rc1.Equal(rc2), "rate card mismatch for item %s in phase %s: \nspec: %+v\n\nview: %+v", itemKey, key, rc1, rc2) assert.Equal(t, i1.PhaseKey, i2.PhaseKey, "phase key mismatch for item %s in phase %s", itemKey, key) // We'll compare the time offsets separately @@ -276,6 +269,35 @@ func SpecsEqual(t *testing.T, s1, s2 subscription.SubscriptionSpec) { } } +// withoutStripeTaxCode returns a copy of rc without the legacy Stripe tax code, so rate cards +// compare by TaxCodeID and Behavior only. +func withoutStripeTaxCode(t *testing.T, rc productcatalog.RateCard) productcatalog.RateCard { + t.Helper() + + out := rc.Clone() + + // Edit the clone's meta directly: ChangeMeta also validates, and a comparison must not fail + // on rate cards the services accepted. + var meta *productcatalog.RateCardMeta + switch v := out.(type) { + case *productcatalog.FlatFeeRateCard: + meta = &v.RateCardMeta + case *productcatalog.UsageBasedRateCard: + meta = &v.RateCardMeta + default: + t.Fatalf("unsupported rate card type %T", out) + } + + if meta.TaxConfig != nil { + meta.TaxConfig.Stripe = nil + if meta.TaxConfig.Behavior == nil && meta.TaxConfig.TaxCodeID == nil { + meta.TaxConfig = nil + } + } + + return out +} + func tsPlusNillableISO(ts time.Time, iso *datetime.ISODuration) *time.Time { if iso == nil { return nil diff --git a/openmeter/subscription/testutils/plan.go b/openmeter/subscription/testutils/plan.go index 11a68ea5cd..18dd8991ca 100644 --- a/openmeter/subscription/testutils/plan.go +++ b/openmeter/subscription/testutils/plan.go @@ -16,12 +16,13 @@ import ( "github.com/openmeterio/openmeter/pkg/datetime" ) -func GetExamplePlanInput(t *testing.T) plan.CreatePlanInput { +// GetExamplePlanInput builds the example plan in ExampleNamespace; its taxed rate cards carry taxConfig. +func GetExamplePlanInput(t *testing.T, taxConfig productcatalog.TaxConfig) plan.CreatePlanInput { b := BuildTestPlanInput(t) - b.AddPhase(lo.ToPtr(datetime.MustParseDuration(t, "P1M")), ExampleRateCard1.Clone()) - b.AddPhase(lo.ToPtr(datetime.MustParseDuration(t, "P2M")), ExampleRateCard1.Clone(), ExampleRateCard2.Clone(), ExampleRateCard3ForAddons.Clone()) - b.AddPhase(nil, ExampleRateCard1.Clone(), ExampleRateCard3ForAddons.Clone()) + b.AddPhase(lo.ToPtr(datetime.MustParseDuration(t, "P1M")), ExampleRateCard1(taxConfig)) + b.AddPhase(lo.ToPtr(datetime.MustParseDuration(t, "P2M")), ExampleRateCard1(taxConfig), ExampleRateCard2.Clone(), ExampleRateCard3ForAddons(taxConfig)) + b.AddPhase(nil, ExampleRateCard1(taxConfig), ExampleRateCard3ForAddons(taxConfig)) return b.Build() } diff --git a/openmeter/subscription/testutils/ratecard.go b/openmeter/subscription/testutils/ratecard.go index 0f808db3af..bd4033f7e8 100644 --- a/openmeter/subscription/testutils/ratecard.go +++ b/openmeter/subscription/testutils/ratecard.go @@ -13,29 +13,8 @@ import ( ) var ( - ExamplePriceAmount int64 = 100 - ExampleRateCard1 productcatalog.UsageBasedRateCard = productcatalog.UsageBasedRateCard{ - RateCardMeta: productcatalog.RateCardMeta{ - Key: ExampleFeatureKey, - Name: "Rate Card 1", - Description: lo.ToPtr("Rate Card 1 Description"), - Feature: productcatalog.NewFeatureReference(nil, lo.ToPtr(ExampleFeatureKey)), - EntitlementTemplate: productcatalog.NewEntitlementTemplateFrom(productcatalog.MeteredEntitlementTemplate{ - IssueAfterReset: lo.ToPtr(100.0), - UsagePeriod: ISOMonth, - }), - TaxConfig: &productcatalog.TaxConfig{ - Stripe: &productcatalog.StripeTaxConfig{ - Code: "txcd_10000000", - }, - }, - Price: productcatalog.NewPriceFrom(productcatalog.UnitPrice{ - Amount: alpacadecimal.NewFromInt(ExamplePriceAmount), - }), - }, - BillingCadence: ISOMonth, - } - ExampleRateCard2 productcatalog.FlatFeeRateCard = productcatalog.FlatFeeRateCard{ + ExamplePriceAmount int64 = 100 + ExampleRateCard2 productcatalog.FlatFeeRateCard = productcatalog.FlatFeeRateCard{ RateCardMeta: productcatalog.RateCardMeta{ Key: "rate-card-2", Name: "Rate Card 2", @@ -47,28 +26,6 @@ var ( }, BillingCadence: &ISOMonth, } - ExampleRateCard3ForAddons productcatalog.FlatFeeRateCard = productcatalog.FlatFeeRateCard{ - RateCardMeta: productcatalog.RateCardMeta{ - Key: ExampleFeatureKey2, - Name: "Rate Card 3 for Addons", - Description: lo.ToPtr("Rate Card 3 Description"), - Feature: productcatalog.NewFeatureReference(nil, lo.ToPtr(ExampleFeatureKey2)), - EntitlementTemplate: productcatalog.NewEntitlementTemplateFrom(productcatalog.MeteredEntitlementTemplate{ - IssueAfterReset: lo.ToPtr(100.0), - UsagePeriod: ISOMonth, - }), - TaxConfig: &productcatalog.TaxConfig{ - Stripe: &productcatalog.StripeTaxConfig{ - Code: "txcd_10000000", - }, - }, - Price: productcatalog.NewPriceFrom(productcatalog.FlatPrice{ - Amount: alpacadecimal.NewFromInt(ExamplePriceAmount), - PaymentTerm: productcatalog.InAdvancePaymentTerm, - }), - }, - BillingCadence: &ISOMonth, - } // Has a boolean entitlement ExampleRateCard4ForAddons productcatalog.FlatFeeRateCard = productcatalog.FlatFeeRateCard{ RateCardMeta: productcatalog.RateCardMeta{ @@ -91,7 +48,14 @@ var ( }, BillingCadence: &ISOMonth, } - ExampleRateCardWithDiscounts productcatalog.FlatFeeRateCard = productcatalog.FlatFeeRateCard{ +) + +// The taxed example rate cards (ExampleRateCard1, ExampleRateCard3ForAddons, +// ExampleRateCardWithDiscounts) carry their own copy of taxConfig, so the plan service resolving +// one rate card's config can't leak into another. Reference the tax code by TaxCodeID; it must +// belong to the namespace the rate card is created in. +func ExampleRateCard1(taxConfig productcatalog.TaxConfig) *productcatalog.UsageBasedRateCard { + return &productcatalog.UsageBasedRateCard{ RateCardMeta: productcatalog.RateCardMeta{ Key: ExampleFeatureKey, Name: "Rate Card 1", @@ -101,11 +65,48 @@ var ( IssueAfterReset: lo.ToPtr(100.0), UsagePeriod: ISOMonth, }), - TaxConfig: &productcatalog.TaxConfig{ - Stripe: &productcatalog.StripeTaxConfig{ - Code: "txcd_10000000", - }, - }, + TaxConfig: lo.ToPtr(taxConfig.Clone()), + Price: productcatalog.NewPriceFrom(productcatalog.UnitPrice{ + Amount: alpacadecimal.NewFromInt(ExamplePriceAmount), + }), + }, + BillingCadence: ISOMonth, + } +} + +func ExampleRateCard3ForAddons(taxConfig productcatalog.TaxConfig) *productcatalog.FlatFeeRateCard { + return &productcatalog.FlatFeeRateCard{ + RateCardMeta: productcatalog.RateCardMeta{ + Key: ExampleFeatureKey2, + Name: "Rate Card 3 for Addons", + Description: lo.ToPtr("Rate Card 3 Description"), + Feature: productcatalog.NewFeatureReference(nil, lo.ToPtr(ExampleFeatureKey2)), + EntitlementTemplate: productcatalog.NewEntitlementTemplateFrom(productcatalog.MeteredEntitlementTemplate{ + IssueAfterReset: lo.ToPtr(100.0), + UsagePeriod: ISOMonth, + }), + TaxConfig: lo.ToPtr(taxConfig.Clone()), + Price: productcatalog.NewPriceFrom(productcatalog.FlatPrice{ + Amount: alpacadecimal.NewFromInt(ExamplePriceAmount), + PaymentTerm: productcatalog.InAdvancePaymentTerm, + }), + }, + BillingCadence: lo.ToPtr(ISOMonth), + } +} + +func ExampleRateCardWithDiscounts(taxConfig productcatalog.TaxConfig) *productcatalog.FlatFeeRateCard { + return &productcatalog.FlatFeeRateCard{ + RateCardMeta: productcatalog.RateCardMeta{ + Key: ExampleFeatureKey, + Name: "Rate Card 1", + Description: lo.ToPtr("Rate Card 1 Description"), + Feature: productcatalog.NewFeatureReference(nil, lo.ToPtr(ExampleFeatureKey)), + EntitlementTemplate: productcatalog.NewEntitlementTemplateFrom(productcatalog.MeteredEntitlementTemplate{ + IssueAfterReset: lo.ToPtr(100.0), + UsagePeriod: ISOMonth, + }), + TaxConfig: lo.ToPtr(taxConfig.Clone()), Price: productcatalog.NewPriceFrom(productcatalog.UnitPrice{ Amount: alpacadecimal.NewFromInt(ExamplePriceAmount), }), @@ -115,9 +116,9 @@ var ( }, }, }, - BillingCadence: &ISOMonth, + BillingCadence: lo.ToPtr(ISOMonth), } -) +} func GetEntitlementTemplateUsagePeriod(t *testing.T, et productcatalog.EntitlementTemplate) *datetime.ISODuration { t.Helper() diff --git a/openmeter/subscription/workflow/service/addon_test.go b/openmeter/subscription/workflow/service/addon_test.go index d58e3ef470..ed676228a7 100644 --- a/openmeter/subscription/workflow/service/addon_test.go +++ b/openmeter/subscription/workflow/service/addon_test.go @@ -52,10 +52,12 @@ func TestAddAddon(t *testing.T) { } t.Run("Should error on invalid input", runWithDeps(func(t *testing.T, deps subscriptiontestutils.SubscriptionDependencies) { + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} p, add := subscriptiontestutils.CreatePlanWithAddon( t, deps, - subscriptiontestutils.GetExamplePlanInput(t), + subscriptiontestutils.GetExamplePlanInput(t, taxConfig), subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ EffectiveFrom: &now, @@ -88,10 +90,12 @@ func TestAddAddon(t *testing.T) { })) t.Run("Should error if the subscription is inactive or in wrong state", runWithDeps(func(t *testing.T, deps subscriptiontestutils.SubscriptionDependencies) { + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} p, add := subscriptiontestutils.CreatePlanWithAddon( t, deps, - subscriptiontestutils.GetExamplePlanInput(t), + subscriptiontestutils.GetExamplePlanInput(t, taxConfig), subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ EffectiveFrom: &now, @@ -131,9 +135,12 @@ func TestAddAddon(t *testing.T) { t.Run("Should add a new addon to a subscription that already has a different addon", runWithDeps(func(t *testing.T, deps subscriptiontestutils.SubscriptionDependencies) { _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + // Let's create a plan p, err := deps.PlanService.CreatePlan(context.Background(), subscriptiontestutils.BuildTestPlanInput(t). - AddPhase(nil, subscriptiontestutils.ExampleRateCard1.Clone()). + AddPhase(nil, subscriptiontestutils.ExampleRateCard1(taxConfig)). Build()) require.Nil(t, err) require.NotNil(t, p) @@ -214,15 +221,17 @@ func TestAddAddon(t *testing.T) { require.NoError(t, err) // And lets validate that both of them updated the entitlement limit - item := subView.Phases[0].ItemsByKey[subscriptiontestutils.ExampleRateCard1.Key()][0] + item := subView.Phases[0].ItemsByKey[subscriptiontestutils.ExampleFeatureKey][0] require.Equal(t, 200.0, *item.Entitlement.Entitlement.IssueAfterReset) })) t.Run("Should sync subscription with new addons contents", runWithDeps(func(t *testing.T, deps subscriptiontestutils.SubscriptionDependencies) { + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} p, add := subscriptiontestutils.CreatePlanWithAddon( t, deps, - subscriptiontestutils.GetExamplePlanInput(t), + subscriptiontestutils.GetExamplePlanInput(t, taxConfig), subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ EffectiveFrom: &now, @@ -276,10 +285,12 @@ func TestAddAddon(t *testing.T) { })) t.Run("Should return conflict error if subscription already has that addon purchased", runWithDeps(func(t *testing.T, deps subscriptiontestutils.SubscriptionDependencies) { + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} p, add := subscriptiontestutils.CreatePlanWithAddon( t, deps, - subscriptiontestutils.GetExamplePlanInput(t), + subscriptiontestutils.GetExamplePlanInput(t, taxConfig), subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ EffectiveFrom: &now, @@ -334,10 +345,12 @@ func TestChangeAddonQuantity(t *testing.T) { } t.Run("Should error if SubscriptionAddon and Subscription are in different namespaces", runWithDeps(func(t *testing.T, deps subscriptiontestutils.SubscriptionDependencies) { + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} p, add := subscriptiontestutils.CreatePlanWithAddon( t, deps, - subscriptiontestutils.GetExamplePlanInput(t), + subscriptiontestutils.GetExamplePlanInput(t, taxConfig), subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ EffectiveFrom: &now, @@ -382,10 +395,12 @@ func TestChangeAddonQuantity(t *testing.T) { })) t.Run("Should error if SubscriptionAddon doesn't belong to Subscription", runWithDeps(func(t *testing.T, deps subscriptiontestutils.SubscriptionDependencies) { + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} p, add := subscriptiontestutils.CreatePlanWithAddon( t, deps, - subscriptiontestutils.GetExamplePlanInput(t), + subscriptiontestutils.GetExamplePlanInput(t, taxConfig), subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ EffectiveFrom: &now, @@ -456,10 +471,12 @@ func TestChangeAddonQuantity(t *testing.T) { })) t.Run("Should error if the subscription is inactive or in wrong state", runWithDeps(func(t *testing.T, deps subscriptiontestutils.SubscriptionDependencies) { + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} p, add := subscriptiontestutils.CreatePlanWithAddon( t, deps, - subscriptiontestutils.GetExamplePlanInput(t), + subscriptiontestutils.GetExamplePlanInput(t, taxConfig), subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ EffectiveFrom: &now, @@ -509,11 +526,13 @@ func TestChangeAddonQuantity(t *testing.T) { })) t.Run("Should update the quantity of the addon", runWithDeps(func(t *testing.T, deps subscriptiontestutils.SubscriptionDependencies) { + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} p, add := subscriptiontestutils.CreatePlanWithAddon( t, deps, subscriptiontestutils.BuildTestPlanInput(t). - AddPhase(nil, subscriptiontestutils.ExampleRateCard1.Clone()). + AddPhase(nil, subscriptiontestutils.ExampleRateCard1(taxConfig)). Build(), subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ @@ -555,7 +574,7 @@ func TestChangeAddonQuantity(t *testing.T) { require.Equal(t, subAdd.Quantities.GetAt(0).GetValue().Quantity, 1) require.Equal(t, subAdd.Quantities.GetAt(1).GetValue().Quantity, 0) - require.Len(t, subView.Phases[0].ItemsByKey[subscriptiontestutils.ExampleRateCard1.Key()], 2) + require.Len(t, subView.Phases[0].ItemsByKey[subscriptiontestutils.ExampleFeatureKey], 2) })) t.Run("Should not combine two subsequent identical items (present due to an edit) when changing the quantity after an addon is already purchased", runWithDeps(func(t *testing.T, deps subscriptiontestutils.SubscriptionDependencies) { @@ -563,6 +582,8 @@ func TestChangeAddonQuantity(t *testing.T) { twoMonthsFromNow, _ := twoMonths.AddTo(now) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} p, add := subscriptiontestutils.CreatePlanWithAddon( t, deps, @@ -579,7 +600,7 @@ func TestChangeAddonQuantity(t *testing.T) { }, SettlementMode: productcatalog.CreditThenInvoiceSettlementMode, }). - AddPhase(nil, subscriptiontestutils.ExampleRateCard1.Clone()). + AddPhase(nil, subscriptiontestutils.ExampleRateCard1(taxConfig)). Build(), subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ @@ -594,7 +615,7 @@ func TestChangeAddonQuantity(t *testing.T) { subView := subscriptiontestutils.CreateSubscriptionFromPlan(t, &deps, p, now) // Now let's edit the sub - ogItem := subView.Phases[0].ItemsByKey[subscriptiontestutils.ExampleRateCard1.Key()][0].Spec + ogItem := subView.Phases[0].ItemsByKey[subscriptiontestutils.ExampleFeatureKey][0].Spec timing := subscription.Timing{ Enum: lo.ToPtr(subscription.TimingNextBillingCycle), @@ -613,7 +634,7 @@ func TestChangeAddonQuantity(t *testing.T) { }, timing) require.NoError(t, err) - require.Len(t, subView.Phases[0].ItemsByKey[subscriptiontestutils.ExampleRateCard1.Key()], 2) + require.Len(t, subView.Phases[0].ItemsByKey[subscriptiontestutils.ExampleFeatureKey], 2) // Now let's add the addon @@ -629,7 +650,7 @@ func TestChangeAddonQuantity(t *testing.T) { require.NoError(t, err) // assert that its still two items - require.Len(t, subView.Phases[0].ItemsByKey[subscriptiontestutils.ExampleRateCard1.Key()], 2) + require.Len(t, subView.Phases[0].ItemsByKey[subscriptiontestutils.ExampleFeatureKey], 2) // Now let's change the quantity of the addon changeInp := subscriptionworkflow.ChangeAddonQuantityWorkflowInput{ @@ -644,7 +665,7 @@ func TestChangeAddonQuantity(t *testing.T) { require.NoError(t, err) // Now it should be three items: original two with addon included + 3rd without the addon after 3 months - require.Len(t, subView.Phases[0].ItemsByKey[subscriptiontestutils.ExampleRateCard1.Key()], 3) + require.Len(t, subView.Phases[0].ItemsByKey[subscriptiontestutils.ExampleFeatureKey], 3) })) } @@ -694,10 +715,13 @@ func TestAddonCombinations(t *testing.T) { } t.Run("Should handle repeated add/remove of single instance addon with dynamic price", runWithDeps(func(t *testing.T, deps subscriptiontestutils.SubscriptionDependencies) { + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + // Create a plan with mixed rate cards planInput := subscriptiontestutils.BuildTestPlanInput(t). AddPhase(nil, - subscriptiontestutils.ExampleRateCard1.Clone(), // Flat price + subscriptiontestutils.ExampleRateCard1(taxConfig), // Flat price &productcatalog.UsageBasedRateCard{ // Dynamic price RateCardMeta: productcatalog.RateCardMeta{ Key: subscriptiontestutils.ExampleFeatureKey2, diff --git a/openmeter/subscription/workflow/service/migrate_test.go b/openmeter/subscription/workflow/service/migrate_test.go index 0a47d61aa4..b92f13e4fe 100644 --- a/openmeter/subscription/workflow/service/migrate_test.go +++ b/openmeter/subscription/workflow/service/migrate_test.go @@ -31,8 +31,10 @@ func TestMigrateToPlanAddons(t *testing.T) { db := subscriptiontestutils.SetupDBDeps(t) defer db.Cleanup(t) deps := subscriptiontestutils.NewService(t, db) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} planInput := subscriptiontestutils.BuildTestPlanInput(t).AddPhase(nil, - subscriptiontestutils.ExampleRateCard3ForAddons.Clone(), subscriptiontestutils.ExampleRateCard2.Clone()).Build() + subscriptiontestutils.ExampleRateCard3ForAddons(taxConfig), subscriptiontestutils.ExampleRateCard2.Clone()).Build() p1, addon := subscriptiontestutils.CreatePlanWithAddon(t, deps, planInput, subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{EffectiveFrom: &start}, productcatalog.AddonInstanceTypeMultiple, subscriptiontestutils.ExampleAddonRateCard4.Clone())) @@ -51,7 +53,7 @@ func TestMigrateToPlanAddons(t *testing.T) { at := start.Add(9 * 24 * time.Hour) clock.FreezeTime(at) nextInput := subscriptiontestutils.BuildTestPlanInput(t).AddPhase(nil, - subscriptiontestutils.ExampleRateCard3ForAddons.Clone(), subscriptiontestutils.ExampleRateCard2.Clone(), subscriptiontestutils.ExampleRateCard1.Clone()).Build() + subscriptiontestutils.ExampleRateCard3ForAddons(taxConfig), subscriptiontestutils.ExampleRateCard2.Clone(), subscriptiontestutils.ExampleRateCard1(taxConfig)).Build() if scenario == "changed base" { require.NoError(t, nextInput.Phases[0].RateCards[0].ChangeMeta(func(meta productcatalog.RateCardMeta) (productcatalog.RateCardMeta, error) { meta.Price = productcatalog.NewPriceFrom(productcatalog.FlatPrice{Amount: alpacadecimal.NewFromInt(200), PaymentTerm: productcatalog.InAdvancePaymentTerm}) diff --git a/openmeter/subscription/workflow/service/subscription_test.go b/openmeter/subscription/workflow/service/subscription_test.go index 73519ccef2..c94e2c2538 100644 --- a/openmeter/subscription/workflow/service/subscription_test.go +++ b/openmeter/subscription/workflow/service/subscription_test.go @@ -111,7 +111,9 @@ func TestCreateFromPlan(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) cust := deps.CustomerAdapter.CreateExampleCustomer(t) require.NotNil(t, cust) @@ -137,8 +139,10 @@ func TestCreateFromPlan(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} p := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.BuildTestPlanInput(t). - AddPhase(nil, subscriptiontestutils.ExampleRateCard3ForAddons.Clone(), subscriptiontestutils.ExampleRateCard4ForAddons.Clone()). + AddPhase(nil, subscriptiontestutils.ExampleRateCard3ForAddons(taxConfig), subscriptiontestutils.ExampleRateCard4ForAddons.Clone()). Build()) cust := deps.CustomerAdapter.CreateExampleCustomer(t) @@ -154,7 +158,7 @@ func TestCreateFromPlan(t *testing.T) { }, p) require.Nil(t, err) - nonBoolItem := subView.Phases[0].ItemsByKey[subscriptiontestutils.ExampleRateCard3ForAddons.Key()][0] + nonBoolItem := subView.Phases[0].ItemsByKey[subscriptiontestutils.ExampleFeatureKey2][0] require.NotNil(t, nonBoolItem) require.Equal(t, 0, subscription.AnnotationParser.GetBooleanEntitlementCount(nonBoolItem.SubscriptionItem.Annotations)) @@ -640,7 +644,9 @@ func TestEditRunning(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) features := deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) cust := deps.CustomerAdapter.CreateExampleCustomer(t) require.NotNil(t, cust) @@ -839,7 +845,9 @@ func TestEditingCurrentPhase(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) cust := deps.CustomerAdapter.CreateExampleCustomer(t) require.NotNil(t, cust) @@ -1079,7 +1087,9 @@ func TestEditingWithTiming(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - planInput := subscriptiontestutils.GetExamplePlanInput(t) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + planInput := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) plan := deps.PlanHelper.CreatePlan(t, planInput) cust := deps.CustomerAdapter.CreateExampleCustomer(t) @@ -1126,9 +1136,29 @@ func TestChangeToPlan(t *testing.T) { withDeps := func(t *testing.T) func(fn func(t *testing.T, deps testCaseDeps)) { return func(fn func(t *testing.T, deps testCaseDeps)) { + tcDeps := testCaseDeps{ + CurrentTime: testutils.GetRFC3339Time(t, "2021-01-01T00:00:00Z"), + } + + clock.SetTime(tcDeps.CurrentTime) + + // Let's build the dependencies + dbDeps := subscriptiontestutils.SetupDBDeps(t) + require.NotNil(t, dbDeps) + defer dbDeps.Cleanup(t) + + deps := subscriptiontestutils.NewService(t, dbDeps) + deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) + + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + // Let's define two plans. One is the example plan, and the second is a slightly modified version of that. // Build them per invocation so plan service mutations (e.g. resolving TaxCodeIDs) don't leak across subtests. - examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t) + examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) + + // Plan 2's new rate cards use a different tax code than the example plan. + plan2TaxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) rc1 := productcatalog.UsageBasedRateCard{ RateCardMeta: productcatalog.RateCardMeta{ @@ -1140,11 +1170,7 @@ func TestChangeToPlan(t *testing.T) { IssueAfterReset: lo.ToPtr(111.0), UsagePeriod: subscriptiontestutils.ISOMonth, }), - TaxConfig: &productcatalog.TaxConfig{ - Stripe: &productcatalog.StripeTaxConfig{ - Code: "txcd_10000001", - }, - }, + TaxConfig: &productcatalog.TaxConfig{TaxCodeID: &plan2TaxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)}, Price: productcatalog.NewPriceFrom(productcatalog.UnitPrice{ Amount: alpacadecimal.NewFromInt(int64(1)), }), @@ -1157,12 +1183,8 @@ func TestChangeToPlan(t *testing.T) { Key: "new-rc-2", Name: "Rate Card 2", Description: lo.ToPtr("Rate Card 2 Description"), - TaxConfig: &productcatalog.TaxConfig{ - Stripe: &productcatalog.StripeTaxConfig{ - Code: "txcd_10000001", - }, - }, - Price: nil, + TaxConfig: &productcatalog.TaxConfig{TaxCodeID: &plan2TaxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)}, + Price: nil, }, BillingCadence: nil, } @@ -1204,7 +1226,7 @@ func TestChangeToPlan(t *testing.T) { Duration: lo.ToPtr(datetime.MustParseDuration(t, "P1M")), }, RateCards: productcatalog.RateCards{ - subscriptiontestutils.ExampleRateCard1.Clone(), + subscriptiontestutils.ExampleRateCard1(taxConfig), &rc2, }, }, @@ -1223,20 +1245,6 @@ func TestChangeToPlan(t *testing.T) { }, } - tcDeps := testCaseDeps{ - CurrentTime: testutils.GetRFC3339Time(t, "2021-01-01T00:00:00Z"), - } - - clock.SetTime(tcDeps.CurrentTime) - - // Let's build the dependencies - dbDeps := subscriptiontestutils.SetupDBDeps(t) - require.NotNil(t, dbDeps) - defer dbDeps.Cleanup(t) - - deps := subscriptiontestutils.NewService(t, dbDeps) - deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - // Let's create the two plans plan1 := deps.PlanHelper.CreatePlan(t, examplePlanInput1) plan2 := deps.PlanHelper.CreatePlan(t, examplePlanInput2) @@ -1319,12 +1327,11 @@ func TestEditCombinations(t *testing.T) { DBDeps *subscriptiontestutils.DBDeps Plan1 subscription.Plan SubsDeps *subscriptiontestutils.SubscriptionDependencies + TaxConfig productcatalog.TaxConfig } withDeps := func(t *testing.T) func(fn func(t *testing.T, deps testCaseDeps)) { return func(fn func(t *testing.T, deps testCaseDeps)) { - examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t) - tcDeps := testCaseDeps{ CurrentTime: testutils.GetRFC3339Time(t, "2021-01-01T00:00:00Z"), } @@ -1339,6 +1346,10 @@ func TestEditCombinations(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) + // Let's create the plan plan1 := deps.PlanHelper.CreatePlan(t, examplePlanInput1) @@ -1351,6 +1362,7 @@ func TestEditCombinations(t *testing.T) { tcDeps.WorkflowService = deps.WorkflowService tcDeps.Plan1 = plan1 tcDeps.SubsDeps = &deps + tcDeps.TaxConfig = taxConfig fn(t, tcDeps) } @@ -1367,11 +1379,13 @@ func TestEditCombinations(t *testing.T) { defer dbDeps.Cleanup(t) deps := subscriptiontestutils.NewService(t, dbDeps) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} p, add := subscriptiontestutils.CreatePlanWithAddon( t, deps, - subscriptiontestutils.GetExamplePlanInput(t), + subscriptiontestutils.GetExamplePlanInput(t, taxConfig), subscriptiontestutils.BuildAddonForTesting( t, productcatalog.EffectivePeriod{ @@ -1417,7 +1431,7 @@ func TestEditCombinations(t *testing.T) { t.Run("Should add boolean entitlement count annotations", func(t *testing.T) { withDeps(t)(func(t *testing.T, deps testCaseDeps) { plan := deps.SubsDeps.PlanHelper.CreatePlan(t, subscriptiontestutils.BuildTestPlanInput(t). - AddPhase(nil, subscriptiontestutils.ExampleRateCard3ForAddons.Clone()). + AddPhase(nil, subscriptiontestutils.ExampleRateCard3ForAddons(deps.TaxConfig)). Build()) timingNow := subscription.Timing{ @@ -1694,8 +1708,6 @@ func TestRestore(t *testing.T) { withDeps := func(t *testing.T) func(fn func(t *testing.T, deps testCaseDeps)) { return func(fn func(t *testing.T, deps testCaseDeps)) { - examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t) - tcDeps := testCaseDeps{ CurrentTime: testutils.GetRFC3339Time(t, "2021-01-01T00:00:00Z"), } @@ -1710,6 +1722,10 @@ func TestRestore(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) + // Let's create the plan plan1 := deps.PlanHelper.CreatePlan(t, examplePlanInput1) @@ -1883,8 +1899,6 @@ func TestMultiSubscription(t *testing.T) { withDeps := func(t *testing.T) func(fn func(t *testing.T, deps testCaseDeps)) { return func(fn func(t *testing.T, deps testCaseDeps)) { - examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t) - tcDeps := testCaseDeps{ CurrentTime: testutils.GetRFC3339Time(t, "2021-01-01T00:00:00Z"), } @@ -1899,6 +1913,10 @@ func TestMultiSubscription(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) + // Let's create the plan plan1 := deps.PlanHelper.CreatePlan(t, examplePlanInput1) @@ -2078,11 +2096,6 @@ func TestSubscriptionChangeTrackingAnnotations(t *testing.T) { withDeps := func(t *testing.T) func(fn func(t *testing.T, deps testCaseDeps)) { return func(fn func(t *testing.T, deps testCaseDeps)) { - examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t) - examplePlanInput2 := subscriptiontestutils.GetExamplePlanInput(t) - examplePlanInput2.Key = "example-plan-2" - examplePlanInput2.Name = "Example Plan 2" - tcDeps := testCaseDeps{ CurrentTime: testutils.GetRFC3339Time(t, "2021-01-01T00:00:00Z"), } @@ -2097,6 +2110,13 @@ func TestSubscriptionChangeTrackingAnnotations(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) + examplePlanInput2 := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) + examplePlanInput2.Key = "example-plan-2" + examplePlanInput2.Name = "Example Plan 2" + // Let's create the two plans plan1 := deps.PlanHelper.CreatePlan(t, examplePlanInput1) plan2 := deps.PlanHelper.CreatePlan(t, examplePlanInput2) @@ -2280,7 +2300,9 @@ func TestSettlementMode(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - p := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + p := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) cust := deps.CustomerAdapter.CreateExampleCustomer(t) subView, err := deps.WorkflowService.CreateFromPlan(context.Background(), subscriptionworkflow.CreateSubscriptionWorkflowInput{ @@ -2311,7 +2333,9 @@ func TestSettlementMode(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - planInput := subscriptiontestutils.GetExamplePlanInput(t) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + planInput := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) planInput.SettlementMode = productcatalog.CreditOnlySettlementMode p := deps.PlanHelper.CreatePlan(t, planInput) cust := deps.CustomerAdapter.CreateExampleCustomer(t) @@ -2345,8 +2369,10 @@ func TestSettlementMode(t *testing.T) { deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) cust := deps.CustomerAdapter.CreateExampleCustomer(t) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} spec, err := subscriptiontestutils.BuildTestSubscriptionSpec(t). - AddPhase(nil, subscriptiontestutils.ExampleRateCard1.Clone()). + AddPhase(nil, subscriptiontestutils.ExampleRateCard1(taxConfig)). Build() require.NoError(t, err) @@ -2383,7 +2409,9 @@ func TestSettlementMode(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - p := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + p := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) cust := deps.CustomerAdapter.CreateExampleCustomer(t) subView, err := deps.WorkflowService.CreateFromPlan(context.Background(), subscriptionworkflow.CreateSubscriptionWorkflowInput{ @@ -2436,7 +2464,9 @@ func TestSettlementMode(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - planInput := subscriptiontestutils.GetExamplePlanInput(t) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + planInput := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) planInput.SettlementMode = productcatalog.CreditOnlySettlementMode p := deps.PlanHelper.CreatePlan(t, planInput) cust := deps.CustomerAdapter.CreateExampleCustomer(t) @@ -2467,7 +2497,9 @@ func TestSettlementMode(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - planInput := subscriptiontestutils.GetExamplePlanInput(t) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + planInput := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) planInput.SettlementMode = productcatalog.CreditOnlySettlementMode p := deps.PlanHelper.CreatePlan(t, planInput) cust := deps.CustomerAdapter.CreateExampleCustomer(t) @@ -2498,9 +2530,11 @@ func TestSettlementMode(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - basePlan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + basePlan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) - creditOnlyPlanInput := subscriptiontestutils.GetExamplePlanInput(t) + creditOnlyPlanInput := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) creditOnlyPlanInput.Key = "credit_only_plan" creditOnlyPlanInput.SettlementMode = productcatalog.CreditOnlySettlementMode creditOnlyPlan := deps.PlanHelper.CreatePlan(t, creditOnlyPlanInput) @@ -2557,12 +2591,15 @@ func TestCreateFromPlanSnapshotsUnitConfig(t *testing.T) { Rounding: productcatalog.UnitConfigRoundingModeCeiling, } + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + // ExampleRateCard1 is usage-based with a UnitPrice, which supports unit_config. - rc := subscriptiontestutils.ExampleRateCard1 + rc := subscriptiontestutils.ExampleRateCard1(taxConfig) rc.UnitConfig = unitConfig p := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.BuildTestPlanInput(t). - AddPhase(nil, &rc). + AddPhase(nil, rc). Build()) cust := deps.CustomerAdapter.CreateExampleCustomer(t) @@ -2581,7 +2618,7 @@ func TestCreateFromPlanSnapshotsUnitConfig(t *testing.T) { reloaded, err := deps.SubscriptionService.GetView(context.Background(), subView.Subscription.NamespacedID) require.NoError(t, err) - items := reloaded.Phases[0].ItemsByKey[subscriptiontestutils.ExampleRateCard1.Key()] + items := reloaded.Phases[0].ItemsByKey[subscriptiontestutils.ExampleFeatureKey] require.Len(t, items, 1) got := items[0].SubscriptionItem.RateCard.AsMeta().UnitConfig diff --git a/test/subscription/migrate_phases_test.go b/test/subscription/migrate_phases_test.go index 08396b29dc..81d58141cc 100644 --- a/test/subscription/migrate_phases_test.go +++ b/test/subscription/migrate_phases_test.go @@ -8,6 +8,7 @@ import ( "github.com/stretchr/testify/require" "github.com/openmeterio/openmeter/openmeter/productcatalog" + "github.com/openmeterio/openmeter/openmeter/productcatalog/plan" plansubscription "github.com/openmeterio/openmeter/openmeter/productcatalog/subscription" "github.com/openmeterio/openmeter/openmeter/subscription" subscriptionaddon "github.com/openmeterio/openmeter/openmeter/subscription/addon" @@ -48,7 +49,7 @@ func TestMigrationStartingPhaseReplacesIncompatibleTimeline(t *testing.T) { // given a single-phase subscription and a target with two phases fixture := newMigrationFixture(t) clock.FreezeTime(start.Add(10 * 24 * time.Hour)) - target := fixture.deps.PlanHelper.CreatePlan(t, migrationPlanWithTwoPhases(t)) + target := fixture.deps.PlanHelper.CreatePlan(t, migrationPlanWithTwoPhases(t, fixture.taxConfig)) clock.FreezeTime(clock.Now().Add(time.Second)) // when the caller selects the target's second phase @@ -70,7 +71,7 @@ func TestMigrationStartingPhaseAtNextCycle(t *testing.T) { // given an incompatible target timeline fixture := newMigrationFixture(t) clock.FreezeTime(start.Add(10 * 24 * time.Hour)) - target := fixture.deps.PlanHelper.CreatePlan(t, migrationPlanWithTwoPhases(t)) + target := fixture.deps.PlanHelper.CreatePlan(t, migrationPlanWithTwoPhases(t, fixture.taxConfig)) clock.FreezeTime(clock.Now().Add(time.Second)) // when replacement is explicitly scheduled for the next cycle @@ -93,7 +94,7 @@ func TestMigrationStartingPhaseWithAnchorAndCustomTime(t *testing.T) { // given an incompatible target timeline and an explicit new anchor fixture := newMigrationFixture(t) clock.FreezeTime(start.Add(10 * 24 * time.Hour)) - target := fixture.deps.PlanHelper.CreatePlan(t, migrationPlanWithTwoPhases(t)) + target := fixture.deps.PlanHelper.CreatePlan(t, migrationPlanWithTwoPhases(t, fixture.taxConfig)) clock.FreezeTime(clock.Now().Add(time.Second)) anchor := start.Add(3 * 24 * time.Hour) @@ -119,7 +120,7 @@ func TestMigrationRejectsChangedPhaseCountWithoutReset(t *testing.T) { // given a target with an additional phase fixture := newMigrationFixture(t) clock.FreezeTime(start.Add(10 * 24 * time.Hour)) - fixture.deps.PlanHelper.CreatePlan(t, migrationPlanWithTwoPhases(t)) + fixture.deps.PlanHelper.CreatePlan(t, migrationPlanWithTwoPhases(t, fixture.taxConfig)) clock.FreezeTime(clock.Now().Add(time.Second)) // when no replacement is requested @@ -149,8 +150,10 @@ func TestMigrationRejectsChangedPhaseStartWithoutReset(t *testing.T) { defer clock.UnFreeze() // given a target whose second phase starts a month later - fixture := newMigrationFixtureWithPlan(t, migrationPlanWithTwoPhases(t)) - next := migrationPlanWithTwoPhases(t) + fixture := newMigrationFixtureWithPlan(t, func(taxConfig productcatalog.TaxConfig) plan.CreatePlanInput { + return migrationPlanWithTwoPhases(t, taxConfig) + }) + next := migrationPlanWithTwoPhases(t, fixture.taxConfig) next.Phases[0].Duration = lo.ToPtr(datetime.MustParseDuration(t, "P2M")) clock.FreezeTime(start.Add(10 * 24 * time.Hour)) fixture.deps.PlanHelper.CreatePlan(t, next) @@ -218,13 +221,15 @@ func TestMigrationStartingPhaseDoesNotTransferAddons(t *testing.T) { deps := setup(t, setupConfig{}) defer deps.cleanup(t) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} input := subscriptiontestutils.BuildTestPlanInput(t).AddPhase(nil, - subscriptiontestutils.ExampleRateCard1.Clone(), subscriptiontestutils.ExampleRateCard2.Clone()).Build() + subscriptiontestutils.ExampleRateCard1(taxConfig), subscriptiontestutils.ExampleRateCard2.Clone()).Build() original, addon := subscriptiontestutils.CreatePlanWithAddon(t, deps.SubscriptionDependencies, input, subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{EffectiveFrom: &start}, productcatalog.AddonInstanceTypeSingle, subscriptiontestutils.ExampleAddonRateCard1.Clone())) before := subscriptiontestutils.CreateSubscriptionFromPlan(t, &deps.SubscriptionDependencies, original, start) - fixture := migrationFixture{t: t, deps: deps, before: before} + fixture := migrationFixture{t: t, deps: deps, taxConfig: taxConfig, before: before} var err error diff --git a/test/subscription/migrate_scheduling_test.go b/test/subscription/migrate_scheduling_test.go index 5e3e3142f1..7541b98900 100644 --- a/test/subscription/migrate_scheduling_test.go +++ b/test/subscription/migrate_scheduling_test.go @@ -24,9 +24,11 @@ func TestMigrationNextCycleAcrossPhaseBoundary(t *testing.T) { defer clock.UnFreeze() // given matching timelines with the next billing cycle in the second phase - fixture := newMigrationFixtureWithPlan(t, migrationPlanWithTwoPhases(t)) + fixture := newMigrationFixtureWithPlan(t, func(taxConfig productcatalog.TaxConfig) plan.CreatePlanInput { + return migrationPlanWithTwoPhases(t, taxConfig) + }) clock.FreezeTime(start.Add(10 * 24 * time.Hour)) - target := fixture.deps.PlanHelper.CreatePlan(t, migrationPlanAddingItemToBothPhases(t)) + target := fixture.deps.PlanHelper.CreatePlan(t, migrationPlanAddingItemToBothPhases(t, fixture.taxConfig)) clock.FreezeTime(clock.Now().Add(time.Second)) // when migration is scheduled for that boundary @@ -46,9 +48,11 @@ func TestMigrationCustomTimeInLaterPhase(t *testing.T) { defer clock.UnFreeze() // given matching timelines and a target that adds an item - fixture := newMigrationFixtureWithPlan(t, migrationPlanWithTwoPhases(t)) + fixture := newMigrationFixtureWithPlan(t, func(taxConfig productcatalog.TaxConfig) plan.CreatePlanInput { + return migrationPlanWithTwoPhases(t, taxConfig) + }) clock.FreezeTime(start.Add(10 * 24 * time.Hour)) - target := fixture.deps.PlanHelper.CreatePlan(t, migrationPlanAddingItemToBothPhases(t)) + target := fixture.deps.PlanHelper.CreatePlan(t, migrationPlanAddingItemToBothPhases(t, fixture.taxConfig)) clock.FreezeTime(clock.Now().Add(time.Second)) // when migration is scheduled beyond the next cycle, inside the second phase @@ -107,20 +111,20 @@ func TestMigrationRejectsPastCustomTime(t *testing.T) { assertMigrationViewUnchanged(t, fixture) } -func migrationPlanWithTwoPhases(t *testing.T) plan.CreatePlanInput { +func migrationPlanWithTwoPhases(t *testing.T, taxConfig productcatalog.TaxConfig) plan.CreatePlanInput { t.Helper() return subscriptiontestutils.BuildTestPlanInput(t). - AddPhase(lo.ToPtr(datetime.MustParseDuration(t, "P1M")), subscriptiontestutils.ExampleRateCard1.Clone()). - AddPhase(nil, subscriptiontestutils.ExampleRateCard1.Clone()).Build() + AddPhase(lo.ToPtr(datetime.MustParseDuration(t, "P1M")), subscriptiontestutils.ExampleRateCard1(taxConfig)). + AddPhase(nil, subscriptiontestutils.ExampleRateCard1(taxConfig)).Build() } -func migrationPlanAddingItemToBothPhases(t *testing.T) plan.CreatePlanInput { +func migrationPlanAddingItemToBothPhases(t *testing.T, taxConfig productcatalog.TaxConfig) plan.CreatePlanInput { t.Helper() - input := migrationPlanWithTwoPhases(t) + input := migrationPlanWithTwoPhases(t, taxConfig) for idx := range input.Phases { - input.Phases[idx].RateCards = append(input.Phases[idx].RateCards, subscriptiontestutils.ExampleRateCard3ForAddons.Clone()) + input.Phases[idx].RateCards = append(input.Phases[idx].RateCards, subscriptiontestutils.ExampleRateCard3ForAddons(taxConfig)) } return input @@ -190,8 +194,10 @@ func TestMigrationScheduledPriceChangeInLaterPhase(t *testing.T) { defer clock.UnFreeze() // given a target that reprices the second phase - fixture := newMigrationFixtureWithPlan(t, migrationPlanWithTwoPhases(t)) - next := migrationPlanWithTwoPhases(t) + fixture := newMigrationFixtureWithPlan(t, func(taxConfig productcatalog.TaxConfig) plan.CreatePlanInput { + return migrationPlanWithTwoPhases(t, taxConfig) + }) + next := migrationPlanWithTwoPhases(t, fixture.taxConfig) require.NoError(t, next.Phases[1].RateCards[0].ChangeMeta(func(meta productcatalog.RateCardMeta) (productcatalog.RateCardMeta, error) { meta.Price = productcatalog.NewPriceFrom(productcatalog.UnitPrice{Amount: alpacadecimal.NewFromInt(50)}) return meta, nil diff --git a/test/subscription/migrate_test.go b/test/subscription/migrate_test.go index eeb44835ea..e9debace16 100644 --- a/test/subscription/migrate_test.go +++ b/test/subscription/migrate_test.go @@ -30,7 +30,7 @@ func TestMigrationAdditionPreservesExistingItems(t *testing.T) { fixture := newMigrationFixture(t) nextPlan := fixture.newPlanVersion() - nextPlan.Phases[0].RateCards = append(nextPlan.Phases[0].RateCards, subscriptiontestutils.ExampleRateCard3ForAddons.Clone()) + nextPlan.Phases[0].RateCards = append(nextPlan.Phases[0].RateCards, subscriptiontestutils.ExampleRateCard3ForAddons(fixture.taxConfig)) clock.FreezeTime(start.Add(24 * time.Hour)) target := fixture.deps.PlanHelper.CreatePlan(t, nextPlan) @@ -158,7 +158,7 @@ func TestMigrationNextCycleAdditionPreservesExistingItems(t *testing.T) { fixture := newMigrationFixture(t) nextPlan := fixture.newPlanVersion() - nextPlan.Phases[0].RateCards = append(nextPlan.Phases[0].RateCards, subscriptiontestutils.ExampleRateCard3ForAddons.Clone()) + nextPlan.Phases[0].RateCards = append(nextPlan.Phases[0].RateCards, subscriptiontestutils.ExampleRateCard3ForAddons(fixture.taxConfig)) clock.FreezeTime(start.Add(24 * time.Hour)) target := fixture.deps.PlanHelper.CreatePlan(t, nextPlan) @@ -307,23 +307,25 @@ func TestMigrationInvalidAnchorLeavesSubscriptionIntact(t *testing.T) { } type migrationFixture struct { - t *testing.T - deps testDeps - before subscription.SubscriptionView + t *testing.T + deps testDeps + taxConfig productcatalog.TaxConfig + before subscription.SubscriptionView } func newMigrationFixture(t *testing.T) migrationFixture { t.Helper() - input := subscriptiontestutils.BuildTestPlanInput(t).AddPhase(nil, - subscriptiontestutils.ExampleRateCard1.Clone(), - subscriptiontestutils.ExampleRateCard2.Clone(), - ).Build() - - return newMigrationFixtureWithPlan(t, input) + return newMigrationFixtureWithPlan(t, func(taxConfig productcatalog.TaxConfig) plan.CreatePlanInput { + return subscriptiontestutils.BuildTestPlanInput(t).AddPhase(nil, + subscriptiontestutils.ExampleRateCard1(taxConfig), + subscriptiontestutils.ExampleRateCard2.Clone(), + ).Build() + }) } -func newMigrationFixtureWithPlan(t *testing.T, input plan.CreatePlanInput) migrationFixture { +// newMigrationFixtureWithPlan builds the plan only after setup, so it can reference the tax code created there. +func newMigrationFixtureWithPlan(t *testing.T, buildPlan func(taxConfig productcatalog.TaxConfig) plan.CreatePlanInput) migrationFixture { t.Helper() deps := setup(t, setupConfig{}) @@ -332,7 +334,9 @@ func newMigrationFixtureWithPlan(t *testing.T, input plan.CreatePlanInput) migra deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) customer := deps.CustomerAdapter.CreateExampleCustomer(t) - original := deps.PlanHelper.CreatePlan(t, input) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + original := deps.PlanHelper.CreatePlan(t, buildPlan(taxConfig)) before, err := deps.WorkflowService.CreateFromPlan(t.Context(), subscriptionworkflow.CreateSubscriptionWorkflowInput{ Namespace: customer.Namespace, @@ -343,14 +347,14 @@ func newMigrationFixtureWithPlan(t *testing.T, input plan.CreatePlanInput) migra }, original) require.NoError(t, err) - return migrationFixture{t: t, deps: deps, before: before} + return migrationFixture{t: t, deps: deps, taxConfig: taxConfig, before: before} } func (f migrationFixture) newPlanVersion() plan.CreatePlanInput { f.t.Helper() return subscriptiontestutils.BuildTestPlanInput(f.t).AddPhase(nil, - subscriptiontestutils.ExampleRateCard1.Clone(), + subscriptiontestutils.ExampleRateCard1(f.taxConfig), subscriptiontestutils.ExampleRateCard2.Clone(), ).Build() } diff --git a/test/subscription/scenario_editaligned_test.go b/test/subscription/scenario_editaligned_test.go index 74b77fc485..d6c602e0c6 100644 --- a/test/subscription/scenario_editaligned_test.go +++ b/test/subscription/scenario_editaligned_test.go @@ -48,6 +48,9 @@ func TestEditingEntitlementOfAlignedSub(t *testing.T) { }) require.NoError(t, err) + taxCode := tDeps.TaxCodeEnv.CreateTaxCode(t, namespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + // 2nd, let's create the plan p, err := tDeps.PlanService.CreatePlan(ctx, plan.CreatePlanInput{ NamespacedModel: models.NamespacedModel{ @@ -80,11 +83,7 @@ func TestEditingEntitlementOfAlignedSub(t *testing.T) { Price: productcatalog.NewPriceFrom(productcatalog.UnitPrice{ Amount: alpacadecimal.NewFromInt(100), }), - TaxConfig: &productcatalog.TaxConfig{ - Stripe: &productcatalog.StripeTaxConfig{ - Code: "txcd_10000000", - }, - }, + TaxConfig: lo.ToPtr(taxConfig.Clone()), EntitlementTemplate: productcatalog.NewEntitlementTemplateFrom(productcatalog.MeteredEntitlementTemplate{ UsagePeriod: datetime.MustParseDuration(t, "P1M"), IssueAfterReset: lo.ToPtr(0.0), // We will change this in the update @@ -177,11 +176,7 @@ func TestEditingEntitlementOfAlignedSub(t *testing.T) { Price: productcatalog.NewPriceFrom(productcatalog.UnitPrice{ Amount: alpacadecimal.NewFromInt(101), }), - TaxConfig: &productcatalog.TaxConfig{ - Stripe: &productcatalog.StripeTaxConfig{ - Code: "txcd_10000000", - }, - }, + TaxConfig: lo.ToPtr(taxConfig.Clone()), }, BillingCadence: datetime.MustParseDuration(t, "P1M"), }, diff --git a/test/subscription/scenario_editcancel_test.go b/test/subscription/scenario_editcancel_test.go index ddc9ad0bb5..f49dab5eea 100644 --- a/test/subscription/scenario_editcancel_test.go +++ b/test/subscription/scenario_editcancel_test.go @@ -49,6 +49,9 @@ func TestEditingAndCanceling(t *testing.T) { }) require.NoError(t, err) + taxCode := tDeps.TaxCodeEnv.CreateTaxCode(t, namespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + // Second, let's create the plan p, err := tDeps.PlanService.CreatePlan(ctx, plan.CreatePlanInput{ NamespacedModel: models.NamespacedModel{ @@ -81,11 +84,7 @@ func TestEditingAndCanceling(t *testing.T) { Price: productcatalog.NewPriceFrom(productcatalog.UnitPrice{ Amount: alpacadecimal.NewFromInt(100), }), - TaxConfig: &productcatalog.TaxConfig{ - Stripe: &productcatalog.StripeTaxConfig{ - Code: "txcd_10000000", - }, - }, + TaxConfig: lo.ToPtr(taxConfig.Clone()), EntitlementTemplate: productcatalog.NewEntitlementTemplateFrom(productcatalog.BooleanEntitlementTemplate{}), }, BillingCadence: datetime.MustParseDuration(t, "P1M"), @@ -202,11 +201,7 @@ func TestEditingAndCanceling(t *testing.T) { Price: productcatalog.NewPriceFrom(productcatalog.UnitPrice{ Amount: alpacadecimal.NewFromInt(101), }), - TaxConfig: &productcatalog.TaxConfig{ - Stripe: &productcatalog.StripeTaxConfig{ - Code: "txcd_10000000", - }, - }, + TaxConfig: lo.ToPtr(taxConfig.Clone()), }, BillingCadence: datetime.MustParseDuration(t, "P1M"), }, diff --git a/test/subscription/scenario_entinnextphase_test.go b/test/subscription/scenario_entinnextphase_test.go index 42e576300e..0216fb45a6 100644 --- a/test/subscription/scenario_entinnextphase_test.go +++ b/test/subscription/scenario_entinnextphase_test.go @@ -41,6 +41,9 @@ func TestSubWithMeteredEntitlement(t *testing.T) { feats := tDeps.FeatureConnector.CreateExampleFeatures(t, tDeps.ExampleMeterID) require.Len(t, feats, 3) + taxCode := tDeps.TaxCodeEnv.CreateTaxCode(t, namespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + // 2nd, let's create the plan p, err := tDeps.PlanService.CreatePlan(ctx, plan.CreatePlanInput{ NamespacedModel: models.NamespacedModel{ @@ -68,14 +71,10 @@ func TestSubWithMeteredEntitlement(t *testing.T) { // Let's have an in-arrears monthly entitlement ratecard &productcatalog.UsageBasedRateCard{ RateCardMeta: productcatalog.RateCardMeta{ - Key: feats[0].Key, - Name: "Test Rate Card", - Feature: productcatalog.NewFeatureReference(lo.ToPtr(feats[0].ID), lo.ToPtr(feats[0].Key)), - TaxConfig: &productcatalog.TaxConfig{ - Stripe: &productcatalog.StripeTaxConfig{ - Code: "txcd_10000000", - }, - }, + Key: feats[0].Key, + Name: "Test Rate Card", + Feature: productcatalog.NewFeatureReference(lo.ToPtr(feats[0].ID), lo.ToPtr(feats[0].Key)), + TaxConfig: lo.ToPtr(taxConfig.Clone()), EntitlementTemplate: productcatalog.NewEntitlementTemplateFrom(productcatalog.MeteredEntitlementTemplate{ UsagePeriod: datetime.MustParseDuration(t, "P1M"), // compatible with the billing cadence IssueAfterReset: lo.ToPtr(10.0), @@ -100,11 +99,7 @@ func TestSubWithMeteredEntitlement(t *testing.T) { Price: productcatalog.NewPriceFrom(productcatalog.UnitPrice{ Amount: alpacadecimal.NewFromInt(100), }), - TaxConfig: &productcatalog.TaxConfig{ - Stripe: &productcatalog.StripeTaxConfig{ - Code: "txcd_10000000", - }, - }, + TaxConfig: lo.ToPtr(taxConfig.Clone()), EntitlementTemplate: productcatalog.NewEntitlementTemplateFrom(productcatalog.MeteredEntitlementTemplate{ UsagePeriod: datetime.MustParseDuration(t, "P1M"), // compatible with the billing cadence IssueAfterReset: lo.ToPtr(100.0), diff --git a/test/subscription/scenario_firstofmonth_test.go b/test/subscription/scenario_firstofmonth_test.go index af6adbef17..98ad38a368 100644 --- a/test/subscription/scenario_firstofmonth_test.go +++ b/test/subscription/scenario_firstofmonth_test.go @@ -46,6 +46,9 @@ func TestBillingOnFirstOfMonth(t *testing.T) { feats := tDeps.FeatureConnector.CreateExampleFeatures(t, tDeps.ExampleMeterID) require.Len(t, feats, 3) + taxCode := tDeps.TaxCodeEnv.CreateTaxCode(t, namespace) + taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + // 2nd, let's create the plan p, err := tDeps.PlanService.CreatePlan(ctx, plan.CreatePlanInput{ NamespacedModel: models.NamespacedModel{ @@ -79,11 +82,7 @@ func TestBillingOnFirstOfMonth(t *testing.T) { Price: productcatalog.NewPriceFrom(productcatalog.UnitPrice{ Amount: alpacadecimal.NewFromInt(100), }), - TaxConfig: &productcatalog.TaxConfig{ - Stripe: &productcatalog.StripeTaxConfig{ - Code: "txcd_10000000", - }, - }, + TaxConfig: lo.ToPtr(taxConfig.Clone()), EntitlementTemplate: productcatalog.NewEntitlementTemplateFrom(productcatalog.MeteredEntitlementTemplate{ UsagePeriod: datetime.MustParseDuration(t, "P1M"), // compatible with the billing cadence IssueAfterReset: lo.ToPtr(10.0), @@ -101,11 +100,7 @@ func TestBillingOnFirstOfMonth(t *testing.T) { Amount: alpacadecimal.NewFromInt(10), PaymentTerm: productcatalog.InAdvancePaymentTerm, }), - TaxConfig: &productcatalog.TaxConfig{ - Stripe: &productcatalog.StripeTaxConfig{ - Code: "txcd_10000000", - }, - }, + TaxConfig: lo.ToPtr(taxConfig.Clone()), }, BillingCadence: lo.ToPtr(datetime.MustParseDuration(t, "P1M")), }, @@ -118,11 +113,7 @@ func TestBillingOnFirstOfMonth(t *testing.T) { Price: productcatalog.NewPriceFrom(productcatalog.UnitPrice{ Amount: alpacadecimal.NewFromInt(1), }), - TaxConfig: &productcatalog.TaxConfig{ - Stripe: &productcatalog.StripeTaxConfig{ - Code: "txcd_10000000", - }, - }, + TaxConfig: lo.ToPtr(taxConfig.Clone()), EntitlementTemplate: productcatalog.NewEntitlementTemplateFrom(productcatalog.MeteredEntitlementTemplate{ UsagePeriod: datetime.MustParseDuration(t, "P1D"), // compatible with the billing cadence IssueAfterReset: lo.ToPtr(10.0), From 22465a8451f227eb97450521112887938da66d36 Mon Sep 17 00:00:00 2001 From: Robert Borbely Date: Tue, 27 Oct 2026 15:52:09 +0100 Subject: [PATCH 2/8] refactor(test): default subscription example plans to a shared example tax code --- api/v3/handlers/subscriptions/convert_test.go | 6 +- api/v3/handlers/subscriptions/migrate_test.go | 4 +- .../subscription/service/change_test.go | 29 +++---- .../subscription/service/create_test.go | 28 ++----- .../subscription/service/migrate_test.go | 19 ++--- .../subscription/service/plan_test.go | 6 +- .../subscription/addon/diff/apply_test.go | 30 ++++--- .../subscription/addon/diff/restore_test.go | 3 +- .../subscription/addon/service/change_test.go | 9 +-- .../subscription/addon/service/create_test.go | 41 +++------- .../addon/service/currency_test.go | 5 +- .../subscription/addon/service/list_test.go | 9 +-- openmeter/subscription/patch/patch_test.go | 2 +- .../subscription/service/listviews_test.go | 10 +-- .../subscription/service/migration_test.go | 7 +- .../subscription/service/service_test.go | 69 +++++----------- openmeter/subscription/service/sync_test.go | 14 +--- openmeter/subscription/testutils/plan.go | 32 +++++++- openmeter/subscription/testutils/taxcode.go | 49 ++++++++++++ .../workflow/service/addon_test.go | 40 +++------- .../workflow/service/migrate_test.go | 3 +- .../workflow/service/subscription_test.go | 79 ++++++------------- test/subscription/migrate_phases_test.go | 3 +- test/subscription/migrate_test.go | 3 +- .../subscription/scenario_editaligned_test.go | 4 +- test/subscription/scenario_editcancel_test.go | 4 +- .../scenario_entinnextphase_test.go | 4 +- .../scenario_firstofmonth_test.go | 4 +- 28 files changed, 215 insertions(+), 301 deletions(-) create mode 100644 openmeter/subscription/testutils/taxcode.go diff --git a/api/v3/handlers/subscriptions/convert_test.go b/api/v3/handlers/subscriptions/convert_test.go index aebaf872e6..e38a7f69c8 100644 --- a/api/v3/handlers/subscriptions/convert_test.go +++ b/api/v3/handlers/subscriptions/convert_test.go @@ -4,13 +4,11 @@ import ( "encoding/json" "testing" - "github.com/samber/lo" "github.com/stretchr/testify/require" api "github.com/openmeterio/openmeter/api/v3" "github.com/openmeterio/openmeter/openmeter/currencies" "github.com/openmeterio/openmeter/openmeter/customer" - "github.com/openmeterio/openmeter/openmeter/productcatalog" "github.com/openmeterio/openmeter/openmeter/subscription" subscriptiontestutils "github.com/openmeterio/openmeter/openmeter/subscription/testutils" "github.com/openmeterio/openmeter/openmeter/testutils" @@ -139,9 +137,7 @@ func TestToAPIBillingSubscriptionViewRoundtrip(t *testing.T) { // given: a subscription created from the example plan, which has phases and rate cards cust := deps.CustomerAdapter.CreateExampleCustomer(t) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv)) spec, err := subscription.NewSpecFromPlan(plan, subscription.CreateSubscriptionCustomerInput{ CustomerId: cust.ID, diff --git a/api/v3/handlers/subscriptions/migrate_test.go b/api/v3/handlers/subscriptions/migrate_test.go index dcd56e43d7..9c86da3cda 100644 --- a/api/v3/handlers/subscriptions/migrate_test.go +++ b/api/v3/handlers/subscriptions/migrate_test.go @@ -13,7 +13,6 @@ import ( "github.com/stretchr/testify/require" api "github.com/openmeterio/openmeter/api/v3" - "github.com/openmeterio/openmeter/openmeter/productcatalog" "github.com/openmeterio/openmeter/openmeter/productcatalog/featureresolver" plansubscription "github.com/openmeterio/openmeter/openmeter/productcatalog/subscription" pcservice "github.com/openmeterio/openmeter/openmeter/productcatalog/subscription/service" @@ -69,8 +68,7 @@ func TestMigrateSubscriptionHandler(t *testing.T) { defer db.Cleanup(t) deps := subscriptiontestutils.NewService(t, db) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + taxConfig := subscriptiontestutils.ExampleTaxConfig(t, deps.TaxCodeEnv) plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.BuildTestPlanInput(t). AddPhase(nil, subscriptiontestutils.ExampleRateCard1(taxConfig)).Build()) before := subscriptiontestutils.CreateSubscriptionFromPlan(t, &deps, plan, start) diff --git a/openmeter/productcatalog/subscription/service/change_test.go b/openmeter/productcatalog/subscription/service/change_test.go index 0570490789..92e38ea972 100644 --- a/openmeter/productcatalog/subscription/service/change_test.go +++ b/openmeter/productcatalog/subscription/service/change_test.go @@ -46,9 +46,8 @@ func TestChange(t *testing.T) { t.Run("Should change to different plan", func(t *testing.T) { withDeps(t, func(t *testing.T, deps tDeps) { - taxCode := deps.subDeps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) + taxConfig := subscriptiontestutils.ExampleTaxConfig(t, deps.subDeps.TaxCodeEnv) + examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, deps.subDeps.TaxCodeEnv) now := testutils.GetRFC3339Time(t, "2021-01-01T00:01:10Z") clock.SetTime(now) @@ -148,9 +147,8 @@ func TestChange(t *testing.T) { t.Run("Should change to different plan starting from specific phase", func(t *testing.T) { withDeps(t, func(t *testing.T, deps tDeps) { - taxCode := deps.subDeps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) + taxConfig := subscriptiontestutils.ExampleTaxConfig(t, deps.subDeps.TaxCodeEnv) + examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, deps.subDeps.TaxCodeEnv) now := testutils.GetRFC3339Time(t, "2021-01-01T00:01:10Z") clock.SetTime(now) @@ -272,9 +270,8 @@ func TestChange(t *testing.T) { t.Run("Should not allow changing to inactive plan", func(t *testing.T) { withDeps(t, func(t *testing.T, deps tDeps) { - taxCode := deps.subDeps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) + taxConfig := subscriptiontestutils.ExampleTaxConfig(t, deps.subDeps.TaxCodeEnv) + examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, deps.subDeps.TaxCodeEnv) now := testutils.GetRFC3339Time(t, "2021-01-01T00:01:10Z") clock.SetTime(now) @@ -392,9 +389,7 @@ func TestChange(t *testing.T) { t.Run("Should apply the settlement mode override when creating from a plan reference", func(t *testing.T) { withDeps(t, func(t *testing.T, deps tDeps) { - taxCode := deps.subDeps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - examplePlanInput := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) + examplePlanInput := subscriptiontestutils.GetExamplePlanInput(t, deps.subDeps.TaxCodeEnv) require.Equal(t, productcatalog.CreditThenInvoiceSettlementMode, examplePlanInput.Plan.SettlementMode) now := testutils.GetRFC3339Time(t, "2021-01-01T00:01:10Z") @@ -438,9 +433,7 @@ func TestChange(t *testing.T) { t.Run("Should apply the settlement mode override when changing to a plan reference", func(t *testing.T) { withDeps(t, func(t *testing.T, deps tDeps) { - taxCode := deps.subDeps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) + examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, deps.subDeps.TaxCodeEnv) now := testutils.GetRFC3339Time(t, "2021-01-01T00:01:10Z") clock.SetTime(now) @@ -542,9 +535,7 @@ func TestChangeInlineCustomPlanRejectsMissingFeature(t *testing.T) { customer := deps.CustomerAdapter.CreateExampleCustomer(t) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - currentPlanInput := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) + currentPlanInput := subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv) currentPlanInput.Plan.Key = "" currentPlanInput.Plan.Version = 0 currentPlan := plansubscription.PlanInput{} @@ -564,7 +555,7 @@ func TestChangeInlineCustomPlanRejectsMissingFeature(t *testing.T) { require.NoError(t, err) const missingFeatureKey = "missing-change-feature" - replacementPlanInput := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) + replacementPlanInput := subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv) replacementPlanInput.Plan.Key = "" replacementPlanInput.Plan.Version = 0 require.NoError(t, replacementPlanInput.Plan.Phases[0].RateCards[0].ChangeMeta(func(meta productcatalog.RateCardMeta) (productcatalog.RateCardMeta, error) { diff --git a/openmeter/productcatalog/subscription/service/create_test.go b/openmeter/productcatalog/subscription/service/create_test.go index 4e0587bf45..1439a2e244 100644 --- a/openmeter/productcatalog/subscription/service/create_test.go +++ b/openmeter/productcatalog/subscription/service/create_test.go @@ -79,9 +79,7 @@ func TestCreateInlineCustomPlanRejectsMissingFeature(t *testing.T) { deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) const missingFeatureKey = "missing-feature" - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - planInput := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) + planInput := subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv) planInput.Plan.Key = "" planInput.Plan.Version = 0 require.NoError(t, planInput.Plan.Phases[0].RateCards[0].ChangeMeta(func(meta productcatalog.RateCardMeta) (productcatalog.RateCardMeta, error) { @@ -153,10 +151,8 @@ func TestCreateSettlementModeOverride(t *testing.T) { cust := deps.subDeps.CustomerAdapter.CreateExampleCustomer(t) deps.subDeps.FeatureConnector.CreateExampleFeatures(t, deps.subDeps.ExampleMeterID) - taxCode := deps.subDeps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} // Build a custom plan input; clear Key/Version so PlanFromPlanInput accepts it. - planInput := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) + planInput := subscriptiontestutils.GetExamplePlanInput(t, deps.subDeps.TaxCodeEnv) require.Equal(t, productcatalog.CreditThenInvoiceSettlementMode, planInput.Plan.SettlementMode, "precondition: plan default must be CreditThenInvoice") planInput.Plan.Key = "" planInput.Plan.Version = 0 @@ -202,9 +198,7 @@ func TestCreateSettlementModeOverride(t *testing.T) { cust := deps.subDeps.CustomerAdapter.CreateExampleCustomer(t) deps.subDeps.FeatureConnector.CreateExampleFeatures(t, deps.subDeps.ExampleMeterID) - taxCode := deps.subDeps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - examplePlanInput := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) + examplePlanInput := subscriptiontestutils.GetExamplePlanInput(t, deps.subDeps.TaxCodeEnv) require.Equal(t, productcatalog.CreditThenInvoiceSettlementMode, examplePlanInput.Plan.SettlementMode, "precondition: plan default must be CreditThenInvoice") plan1 := deps.subDeps.PlanHelper.CreatePlan(t, examplePlanInput) @@ -261,9 +255,7 @@ func TestCreateInlineCustomCurrencyMaterializesManagedIdentity(t *testing.T) { )) require.NoError(t, err) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - planInput := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) + planInput := subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv) planInput.Plan.Key = "" planInput.Plan.Version = 0 planInput.Plan.Currency = managedCurrency.Reference() @@ -330,9 +322,7 @@ func TestCreateInlineCustomCurrencyGatedByCredits(t *testing.T) { customer := deps.CustomerAdapter.CreateExampleCustomer(t) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - planInput := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) + planInput := subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv) planInput.Plan.Key = "" planInput.Plan.Version = 0 planInput.Plan.Currency = currencies.NewCurrencyReference("CREDITS") @@ -387,9 +377,7 @@ func TestCreateInlineEntitlementRateCardResolvesFeatureByID(t *testing.T) { featureIDByKey[f.Key] = f.ID } - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - planInput := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) + planInput := subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv) planInput.Plan.Key = "" planInput.Plan.Version = 0 @@ -442,9 +430,7 @@ func TestCreateInlineCreditOnlyPlanSkipsCurrencyCostBasis(t *testing.T) { )) require.NoError(t, err) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - planInput := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) + planInput := subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv) planInput.Plan.Key = "" planInput.Plan.Version = 0 planInput.Plan.SettlementMode = productcatalog.CreditOnlySettlementMode diff --git a/openmeter/productcatalog/subscription/service/migrate_test.go b/openmeter/productcatalog/subscription/service/migrate_test.go index 7d23ee458b..8dc48a7bf3 100644 --- a/openmeter/productcatalog/subscription/service/migrate_test.go +++ b/openmeter/productcatalog/subscription/service/migrate_test.go @@ -44,9 +44,7 @@ func TestMigrate(t *testing.T) { t.Run("Should migrate to latest version of plan when none is specified", func(t *testing.T) { withDeps(t, func(t *testing.T, deps tDeps) { - taxCode := deps.subDeps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) + examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, deps.subDeps.TaxCodeEnv) now := testutils.GetRFC3339Time(t, "2021-01-01T00:01:10Z") clock.SetTime(now) @@ -122,9 +120,7 @@ func TestMigrate(t *testing.T) { t.Run("Should migrate to specific version of plan when provided", func(t *testing.T) { withDeps(t, func(t *testing.T, deps tDeps) { - taxCode := deps.subDeps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) + examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, deps.subDeps.TaxCodeEnv) now := testutils.GetRFC3339Time(t, "2021-01-01T00:01:10Z") clock.SetTime(now) @@ -198,9 +194,7 @@ func TestMigrate(t *testing.T) { t.Run("Should not allow migrating to same or smaller version", func(t *testing.T) { withDeps(t, func(t *testing.T, deps tDeps) { - taxCode := deps.subDeps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) + examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, deps.subDeps.TaxCodeEnv) now := testutils.GetRFC3339Time(t, "2021-01-01T00:01:10Z") clock.SetTime(now) @@ -279,9 +273,7 @@ func TestMigrate(t *testing.T) { t.Run("Should replace the subscription when a starting phase is supplied", func(t *testing.T) { withDeps(t, func(t *testing.T, deps tDeps) { - taxCode := deps.subDeps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) + examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, deps.subDeps.TaxCodeEnv) now := testutils.GetRFC3339Time(t, "2021-01-01T00:01:10Z") clock.SetTime(now) @@ -404,8 +396,7 @@ func TestMigrateReturnsCurrentSnapshotFromUnderLock(t *testing.T) { deps := subscriptiontestutils.NewService(t, db) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + taxConfig := subscriptiontestutils.ExampleTaxConfig(t, deps.TaxCodeEnv) planInput := subscriptiontestutils.BuildTestPlanInput(t).AddPhase(nil, subscriptiontestutils.ExampleRateCard1(taxConfig), ).Build() diff --git a/openmeter/productcatalog/subscription/service/plan_test.go b/openmeter/productcatalog/subscription/service/plan_test.go index 6c937deae8..d1fe0b2ee3 100644 --- a/openmeter/productcatalog/subscription/service/plan_test.go +++ b/openmeter/productcatalog/subscription/service/plan_test.go @@ -7,7 +7,6 @@ import ( "github.com/samber/lo" "github.com/stretchr/testify/require" - "github.com/openmeterio/openmeter/openmeter/productcatalog" plansubscription "github.com/openmeterio/openmeter/openmeter/productcatalog/subscription" "github.com/openmeterio/openmeter/openmeter/subscription" subscriptiontestutils "github.com/openmeterio/openmeter/openmeter/subscription/testutils" @@ -40,9 +39,8 @@ func TestDiscountPersisting(t *testing.T) { t.Run("Should persist discounts", func(t *testing.T) { withDeps(t, func(t *testing.T, deps tDeps) { - taxCode := deps.subDeps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) + taxConfig := subscriptiontestutils.ExampleTaxConfig(t, deps.subDeps.TaxCodeEnv) + examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, deps.subDeps.TaxCodeEnv) examplePlanInput1.Phases[0].RateCards[0] = subscriptiontestutils.ExampleRateCardWithDiscounts(taxConfig) ctx := context.Background() diff --git a/openmeter/subscription/addon/diff/apply_test.go b/openmeter/subscription/addon/diff/apply_test.go index b09f0bd0d9..f0bd9016af 100644 --- a/openmeter/subscription/addon/diff/apply_test.go +++ b/openmeter/subscription/addon/diff/apply_test.go @@ -48,8 +48,7 @@ func TestApply(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + taxConfig := subscriptiontestutils.ExampleTaxConfig(t, deps.TaxCodeEnv) fn(t, &tcDeps{ deps: deps, @@ -62,7 +61,7 @@ func TestApply(t *testing.T) { p, a := subscriptiontestutils.CreatePlanWithAddon( t, deps.deps, - subscriptiontestutils.GetExamplePlanInput(t, deps.taxConfig), + subscriptiontestutils.GetExamplePlanInput(t, deps.deps.TaxCodeEnv), subscriptiontestutils.GetExampleAddonInput(t, productcatalog.EffectivePeriod{ EffectiveFrom: &now, EffectiveTo: nil, @@ -91,7 +90,7 @@ func TestApply(t *testing.T) { p, a := subscriptiontestutils.CreatePlanWithAddon( t, deps.deps, - subscriptiontestutils.GetExamplePlanInput(t, deps.taxConfig), + subscriptiontestutils.GetExamplePlanInput(t, deps.deps.TaxCodeEnv), subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ EffectiveFrom: &now, @@ -151,7 +150,7 @@ func TestApply(t *testing.T) { p, a := subscriptiontestutils.CreatePlanWithAddon( t, deps.deps, - subscriptiontestutils.GetExamplePlanInput(t, deps.taxConfig), + subscriptiontestutils.GetExamplePlanInput(t, deps.deps.TaxCodeEnv), subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ EffectiveFrom: &now, @@ -308,7 +307,7 @@ func TestApply(t *testing.T) { p, a := subscriptiontestutils.CreatePlanWithAddon( t, deps.deps, - subscriptiontestutils.GetExamplePlanInput(t, deps.taxConfig), + subscriptiontestutils.GetExamplePlanInput(t, deps.deps.TaxCodeEnv), subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ EffectiveFrom: &now, @@ -384,7 +383,7 @@ func TestApply(t *testing.T) { p, a := subscriptiontestutils.CreatePlanWithAddon( t, deps.deps, - subscriptiontestutils.GetExamplePlanInput(t, deps.taxConfig), + subscriptiontestutils.GetExamplePlanInput(t, deps.deps.TaxCodeEnv), subscriptiontestutils.BuildAddonForTesting(t, effPer, productcatalog.AddonInstanceTypeSingle, @@ -989,8 +988,7 @@ func TestApplyWithMultiInstance(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + taxConfig := subscriptiontestutils.ExampleTaxConfig(t, deps.TaxCodeEnv) fn(t, &tcDeps{ deps: deps, @@ -1101,6 +1099,18 @@ func featureReferenceWithoutID(meta productcatalog.RateCardMeta) (productcatalog return meta, nil } +// The services fill in the Stripe code from the tax code's app mapping, so expected rate cards +// built from a TaxCodeID-only config compare by TaxCodeID and Behavior. +func withoutStripeTaxCode(meta productcatalog.RateCardMeta) (productcatalog.RateCardMeta, error) { + if meta.TaxConfig != nil { + taxConfig := meta.TaxConfig.Clone() + taxConfig.Stripe = nil + meta.TaxConfig = &taxConfig + } + + return meta, nil +} + func compareRateCardsWithAmountChange(t *testing.T, baseTarget *productcatalog.FlatFeeRateCard, targetAmount int, value productcatalog.RateCard, msgAndArgs ...interface{}) { t.Helper() @@ -1123,9 +1133,11 @@ func compareRateCardsWithAmountChange(t *testing.T, baseTarget *productcatalog.F left := target.Clone() require.NoError(t, left.ChangeMeta(featureReferenceWithoutID)) + require.NoError(t, left.ChangeMeta(withoutStripeTaxCode)) right := value.Clone() require.NoError(t, right.ChangeMeta(featureReferenceWithoutID)) + require.NoError(t, right.ChangeMeta(withoutStripeTaxCode)) if len(msgAndArgs) > 0 { customMsg := fmt.Sprintf(msgAndArgs[0].(string), msgAndArgs[1:]...) diff --git a/openmeter/subscription/addon/diff/restore_test.go b/openmeter/subscription/addon/diff/restore_test.go index 07fed3db47..4115d74578 100644 --- a/openmeter/subscription/addon/diff/restore_test.go +++ b/openmeter/subscription/addon/diff/restore_test.go @@ -44,8 +44,7 @@ func TestRestore(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + taxConfig := subscriptiontestutils.ExampleTaxConfig(t, deps.TaxCodeEnv) fn(t, &tcDeps{ deps: deps, diff --git a/openmeter/subscription/addon/service/change_test.go b/openmeter/subscription/addon/service/change_test.go index d31417a361..a6d5d275ab 100644 --- a/openmeter/subscription/addon/service/change_test.go +++ b/openmeter/subscription/addon/service/change_test.go @@ -75,9 +75,7 @@ func TestAddonServiceChangeQuantity(t *testing.T) { clock.SetTime(now) defer clock.ResetTime() - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - planInp := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) + planInp := subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv) addonInp := subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ EffectiveFrom: lo.ToPtr(now), @@ -189,13 +187,10 @@ func createExampleSubscriptionAddon(t *testing.T, deps subscriptiontestutils.Sub clock.SetTime(now) defer clock.ResetTime() - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - p, add := subscriptiontestutils.CreatePlanWithAddon( t, deps, - subscriptiontestutils.GetExamplePlanInput(t, taxConfig), + subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv), subscriptiontestutils.GetExampleAddonInput(t, productcatalog.EffectivePeriod{ EffectiveFrom: lo.ToPtr(now), }), diff --git a/openmeter/subscription/addon/service/create_test.go b/openmeter/subscription/addon/service/create_test.go index e625c5bc38..1febf60b0b 100644 --- a/openmeter/subscription/addon/service/create_test.go +++ b/openmeter/subscription/addon/service/create_test.go @@ -31,13 +31,10 @@ func TestAddonServiceCreate(t *testing.T) { clock.SetTime(now) defer clock.ResetTime() - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - p, add := subscriptiontestutils.CreatePlanWithAddon( t, deps, - subscriptiontestutils.GetExamplePlanInput(t, taxConfig), + subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv), subscriptiontestutils.GetExampleAddonInput(t, productcatalog.EffectivePeriod{ EffectiveFrom: lo.ToPtr(now), }), @@ -80,13 +77,10 @@ func TestAddonServiceCreate(t *testing.T) { clock.SetTime(now) defer clock.ResetTime() - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - p, _ := subscriptiontestutils.CreatePlanWithAddon( t, deps, - subscriptiontestutils.GetExamplePlanInput(t, taxConfig), + subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv), subscriptiontestutils.GetExampleAddonInput(t, productcatalog.EffectivePeriod{ EffectiveFrom: lo.ToPtr(now), }), @@ -156,13 +150,10 @@ func TestAddonServiceCreate(t *testing.T) { clock.SetTime(now) defer clock.ResetTime() - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - p, add := subscriptiontestutils.CreatePlanWithAddon( t, deps, - subscriptiontestutils.GetExamplePlanInput(t, taxConfig), + subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv), subscriptiontestutils.GetExampleAddonInput(t, productcatalog.EffectivePeriod{ EffectiveFrom: lo.ToPtr(now), }), @@ -205,13 +196,10 @@ func TestAddonServiceCreate(t *testing.T) { clock.SetTime(now) defer clock.ResetTime() - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - p, _ := subscriptiontestutils.CreatePlanWithAddon( t, deps, - subscriptiontestutils.GetExamplePlanInput(t, taxConfig), + subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv), subscriptiontestutils.GetExampleAddonInput(t, productcatalog.EffectivePeriod{ EffectiveFrom: lo.ToPtr(now), }), @@ -261,9 +249,7 @@ func TestAddonServiceCreate(t *testing.T) { defer clock.ResetTime() // Let's create a plan with addon thats only available in a later phase - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - planInp := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) + planInp := subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv) addonInp := subscriptiontestutils.GetExampleAddonInput(t, productcatalog.EffectivePeriod{ EffectiveFrom: lo.ToPtr(now), }) @@ -339,9 +325,7 @@ func TestAddonServiceCreate(t *testing.T) { defer clock.ResetTime() // Let's create a plan with addon thats only available in a later phase - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - planInp := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) + planInp := subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv) addonInp := subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ EffectiveFrom: lo.ToPtr(now), }, productcatalog.AddonInstanceTypeMultiple, subscriptiontestutils.ExampleAddonRateCard1.Clone()) @@ -420,9 +404,7 @@ func TestAddonServiceCreate(t *testing.T) { // Let's create a subscription without a plan reference cust := deps.CustomerAdapter.CreateExampleCustomer(t) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv)) spec1, err := subscription.NewSpecFromPlan(plan, subscription.CreateSubscriptionCustomerInput{ CustomerId: cust.ID, @@ -470,13 +452,10 @@ func TestAddonServiceCreate(t *testing.T) { clock.SetTime(now) defer clock.ResetTime() - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - p, add := subscriptiontestutils.CreatePlanWithAddon( t, deps, - subscriptiontestutils.GetExamplePlanInput(t, taxConfig), + subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv), subscriptiontestutils.GetExampleAddonInput(t, productcatalog.EffectivePeriod{ EffectiveFrom: lo.ToPtr(now), }), @@ -536,9 +515,7 @@ func TestAddonServiceCreate(t *testing.T) { func createExampleSubscription(t *testing.T, deps subscriptiontestutils.SubscriptionDependencies, currentTime time.Time) subscription.SubscriptionView { cust := deps.CustomerAdapter.CreateExampleCustomer(t) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv)) spec1, err := subscription.NewSpecFromPlan(plan, subscription.CreateSubscriptionCustomerInput{ CustomerId: cust.ID, diff --git a/openmeter/subscription/addon/service/currency_test.go b/openmeter/subscription/addon/service/currency_test.go index 58a872740b..9e7f6380ea 100644 --- a/openmeter/subscription/addon/service/currency_test.go +++ b/openmeter/subscription/addon/service/currency_test.go @@ -216,13 +216,10 @@ func createSubscriptionForPlanWithAddon( ) (models.NamespacedID, addon.Addon) { t.Helper() - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - p, add := subscriptiontestutils.CreatePlanWithAddon( t, deps, - subscriptiontestutils.GetExamplePlanInput(t, taxConfig), + subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv), addonInput, ) diff --git a/openmeter/subscription/addon/service/list_test.go b/openmeter/subscription/addon/service/list_test.go index 42381ce0ac..784cd0ad3e 100644 --- a/openmeter/subscription/addon/service/list_test.go +++ b/openmeter/subscription/addon/service/list_test.go @@ -28,13 +28,10 @@ func TestAddonServiceGet(t *testing.T) { clock.SetTime(now) defer clock.ResetTime() - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - p, add := subscriptiontestutils.CreatePlanWithAddon( t, deps, - subscriptiontestutils.GetExamplePlanInput(t, taxConfig), + subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv), subscriptiontestutils.GetExampleAddonInput(t, productcatalog.EffectivePeriod{ EffectiveFrom: lo.ToPtr(now), }), @@ -104,9 +101,7 @@ func TestAddonServiceList(t *testing.T) { // Let's create a plan - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - p, err := deps.PlanService.CreatePlan(context.Background(), subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) + p, err := deps.PlanService.CreatePlan(context.Background(), subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv)) require.Nil(t, err) require.NotNil(t, p) diff --git a/openmeter/subscription/patch/patch_test.go b/openmeter/subscription/patch/patch_test.go index b1333a5104..e394f9a546 100644 --- a/openmeter/subscription/patch/patch_test.go +++ b/openmeter/subscription/patch/patch_test.go @@ -197,7 +197,7 @@ func (ts *testsuite[T]) Run(t *testing.T) { } func getDefaultSpec(t *testing.T, activeFrom time.Time) (*subscription.SubscriptionSpec, *psubs.Plan) { - pInp := subscriptiontestutils.GetExamplePlanInput(t, productcatalog.TaxConfig{TaxCodeID: lo.ToPtr("example-tax-code"), Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)}) + pInp := subscriptiontestutils.GetExamplePlanInput(t, nil, subscriptiontestutils.WithTaxConfig(productcatalog.TaxConfig{TaxCodeID: lo.ToPtr("example-tax-code"), Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)})) p := &psubs.Plan{ Plan: pInp.Plan, Ref: &models.NamespacedID{Namespace: pInp.Namespace, ID: pInp.Key}, diff --git a/openmeter/subscription/service/listviews_test.go b/openmeter/subscription/service/listviews_test.go index 9b334fa03f..21ffed790d 100644 --- a/openmeter/subscription/service/listviews_test.go +++ b/openmeter/subscription/service/listviews_test.go @@ -5,11 +5,9 @@ import ( "testing" "time" - "github.com/samber/lo" "github.com/stretchr/testify/require" "github.com/openmeterio/openmeter/openmeter/customer" - "github.com/openmeterio/openmeter/openmeter/productcatalog" "github.com/openmeterio/openmeter/openmeter/subscription" subscriptiontestutils "github.com/openmeterio/openmeter/openmeter/subscription/testutils" "github.com/openmeterio/openmeter/openmeter/testutils" @@ -36,9 +34,7 @@ func TestListViewsMultiCustomer(t *testing.T) { service := deps.SubscriptionService _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv)) // given: two distinct customers, each with a subscription from the same plan cust1 := deps.CustomerAdapter.CreateExampleCustomer(t) @@ -91,9 +87,7 @@ func TestGetViewResolvesSoftDeletedCustomer(t *testing.T) { service := deps.SubscriptionService _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv)) // given: a subscription whose customer is subsequently soft-deleted cust := deps.CustomerAdapter.CreateExampleCustomer(t) diff --git a/openmeter/subscription/service/migration_test.go b/openmeter/subscription/service/migration_test.go index f7b9934f2f..691dc45bba 100644 --- a/openmeter/subscription/service/migration_test.go +++ b/openmeter/subscription/service/migration_test.go @@ -9,7 +9,6 @@ import ( "github.com/stretchr/testify/require" "github.com/openmeterio/openmeter/openmeter/customer" - "github.com/openmeterio/openmeter/openmeter/productcatalog" "github.com/openmeterio/openmeter/openmeter/productcatalog/feature" "github.com/openmeterio/openmeter/openmeter/subscription" subscriptionservice "github.com/openmeterio/openmeter/openmeter/subscription/service" @@ -59,8 +58,7 @@ func TestUpdateRejectsMigrationBetweenReadAndLock(t *testing.T) { defer db.Cleanup(t) deps := subscriptiontestutils.NewService(t, db) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + taxConfig := subscriptiontestutils.ExampleTaxConfig(t, deps.TaxCodeEnv) p1 := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.BuildTestPlanInput(t).AddPhase(nil, subscriptiontestutils.ExampleRateCard1(taxConfig)).Build()) before := subscriptiontestutils.CreateSubscriptionFromPlan(t, &deps, p1, start) clock.FreezeTime(start.Add(10 * 24 * time.Hour)) @@ -145,8 +143,7 @@ func TestCancelIncludesMigrationCommittedBeforeLock(t *testing.T) { deps := subscriptiontestutils.NewService(t, db) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + taxConfig := subscriptiontestutils.ExampleTaxConfig(t, deps.TaxCodeEnv) p1 := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.BuildTestPlanInput(t).AddPhase(nil, subscriptiontestutils.ExampleRateCard1(taxConfig)).Build()) before := subscriptiontestutils.CreateSubscriptionFromPlan(t, &deps, p1, start) diff --git a/openmeter/subscription/service/service_test.go b/openmeter/subscription/service/service_test.go index 29938cdca4..34751115b0 100644 --- a/openmeter/subscription/service/service_test.go +++ b/openmeter/subscription/service/service_test.go @@ -41,9 +41,7 @@ func TestCreation(t *testing.T) { cust := deps.CustomerAdapter.CreateExampleCustomer(t) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv)) defaultSpecFromPlan, err := subscription.NewSpecFromPlan(plan, subscription.CreateSubscriptionCustomerInput{ CustomerId: cust.ID, @@ -114,9 +112,7 @@ func TestCreation(t *testing.T) { cust := deps.CustomerAdapter.CreateExampleCustomer(t) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv)) specWithAnnotations, err := subscription.NewSpecFromPlan(plan, subscription.CreateSubscriptionCustomerInput{ CustomerId: cust.ID, @@ -174,9 +170,7 @@ func TestCreation(t *testing.T) { require.Nil(t, err) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv)) defaultSpecFromPlan, err := subscription.NewSpecFromPlan(plan, subscription.CreateSubscriptionCustomerInput{ CustomerId: cust.ID, @@ -221,9 +215,7 @@ func TestCreation(t *testing.T) { require.Nil(t, err) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv)) defaultSpecFromPlan, err := subscription.NewSpecFromPlan(plan, subscription.CreateSubscriptionCustomerInput{ CustomerId: cust.ID, @@ -326,9 +318,7 @@ func TestCancellation(t *testing.T) { cust := deps.CustomerAdapter.CreateExampleCustomer(t) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv)) // First, let's create a subscription defaultSpecFromPlan, err := subscription.NewSpecFromPlan(plan, subscription.CreateSubscriptionCustomerInput{ @@ -446,9 +436,7 @@ func TestContinuing(t *testing.T) { cust := deps.CustomerAdapter.CreateExampleCustomer(t) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv)) // First, let's create a subscription defaultSpecFromPlan, err := subscription.NewSpecFromPlan(plan, subscription.CreateSubscriptionCustomerInput{ @@ -535,9 +523,7 @@ func TestContinuing(t *testing.T) { cust := deps.CustomerAdapter.CreateExampleCustomer(t) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv)) // First, let's create a subscription spec1, err := subscription.NewSpecFromPlan(plan, subscription.CreateSubscriptionCustomerInput{ @@ -645,9 +631,7 @@ func TestList(t *testing.T) { require.Nil(t, err) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv)) // Let's create some subscriptions: // - One active @@ -831,9 +815,7 @@ func TestList(t *testing.T) { require.Nil(t, err) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv)) spec1, err := subscription.NewSpecFromPlan(plan, subscription.CreateSubscriptionCustomerInput{ CustomerId: cust1.ID, @@ -929,9 +911,7 @@ func TestSubscriptionChangeTrackingAnnotations(t *testing.T) { cust := deps.CustomerAdapter.CreateExampleCustomer(t) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - plan1 := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) + plan1 := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv)) // Create first subscription sub1, err := workflowService.CreateFromPlan(ctx, subscriptionworkflow.CreateSubscriptionWorkflowInput{ @@ -947,7 +927,7 @@ func TestSubscriptionChangeTrackingAnnotations(t *testing.T) { require.Nil(t, err) // Create second plan - examplePlanInput2 := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) + examplePlanInput2 := subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv) examplePlanInput2.Key = "example-plan-2" examplePlanInput2.Name = "Example Plan 2" plan2 := deps.PlanHelper.CreatePlan(t, examplePlanInput2) @@ -994,9 +974,7 @@ func TestSubscriptionChangeTrackingAnnotations(t *testing.T) { cust := deps.CustomerAdapter.CreateExampleCustomer(t) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - plan1 := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) + plan1 := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv)) // Create first subscription sub1, err := workflowService.CreateFromPlan(ctx, subscriptionworkflow.CreateSubscriptionWorkflowInput{ @@ -1012,7 +990,7 @@ func TestSubscriptionChangeTrackingAnnotations(t *testing.T) { require.Nil(t, err) // Create second plan - examplePlanInput2 := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) + examplePlanInput2 := subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv) examplePlanInput2.Key = "example-plan-2" examplePlanInput2.Name = "Example Plan 2" plan2 := deps.PlanHelper.CreatePlan(t, examplePlanInput2) @@ -1060,9 +1038,7 @@ func TestSubscriptionChangeTrackingAnnotations(t *testing.T) { cust := deps.CustomerAdapter.CreateExampleCustomer(t) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - plan1 := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) + plan1 := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv)) // Create first subscription sub1, err := workflowService.CreateFromPlan(ctx, subscriptionworkflow.CreateSubscriptionWorkflowInput{ @@ -1078,7 +1054,7 @@ func TestSubscriptionChangeTrackingAnnotations(t *testing.T) { require.Nil(t, err) // Create second plan - examplePlanInput2 := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) + examplePlanInput2 := subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv) examplePlanInput2.Key = "example-plan-2" examplePlanInput2.Name = "Example Plan 2" plan2 := deps.PlanHelper.CreatePlan(t, examplePlanInput2) @@ -1126,9 +1102,7 @@ func TestSubscriptionChangeTrackingAnnotations(t *testing.T) { cust := deps.CustomerAdapter.CreateExampleCustomer(t) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - plan1 := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) + plan1 := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv)) // Create standalone scheduled subscription (can be deleted) futureTime := currentTime.AddDate(0, 1, 0) @@ -1170,9 +1144,7 @@ func TestSubscriptionChangeTrackingAnnotations(t *testing.T) { cust := deps.CustomerAdapter.CreateExampleCustomer(t) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - plan1 := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) + plan1 := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv)) // Create scheduled subscription with nil annotations (can be deleted) futureTime := currentTime.AddDate(0, 1, 0) @@ -1221,7 +1193,7 @@ func TestTaxCodeResolution(t *testing.T) { cust := deps.CustomerAdapter.CreateExampleCustomer(t) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, stripeTaxConfig)) + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, nil, subscriptiontestutils.WithTaxConfig(stripeTaxConfig))) spec, err := subscription.NewSpecFromPlan(plan, subscription.CreateSubscriptionCustomerInput{ CustomerId: cust.ID, @@ -1287,7 +1259,7 @@ func TestTaxCodeResolution(t *testing.T) { cust := deps.CustomerAdapter.CreateExampleCustomer(t) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, stripeTaxConfig)) + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, nil, subscriptiontestutils.WithTaxConfig(stripeTaxConfig))) spec, err := subscription.NewSpecFromPlan(plan, subscription.CreateSubscriptionCustomerInput{ CustomerId: cust.ID, @@ -1558,8 +1530,7 @@ func TestBillingCadenceLegacyFeatureResolution(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) customer := deps.CustomerAdapter.CreateExampleCustomer(t) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + taxConfig := subscriptiontestutils.ExampleTaxConfig(t, deps.TaxCodeEnv) rateCard := tc.rateCard(taxConfig) spec, err := subscriptiontestutils.BuildTestSubscriptionSpec(t).AddPhase(nil, rateCard).Build() require.NoError(t, err) diff --git a/openmeter/subscription/service/sync_test.go b/openmeter/subscription/service/sync_test.go index 055610c2fe..a40a1bb2a0 100644 --- a/openmeter/subscription/service/sync_test.go +++ b/openmeter/subscription/service/sync_test.go @@ -420,9 +420,7 @@ func TestEdit(t *testing.T) { require.NotNil(t, cust) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv)) tc.Handler(t, TDeps{ CurrentTime: currentTime, @@ -672,9 +670,7 @@ func TestSyncReconciliation(t *testing.T) { cust := deps.CustomerAdapter.CreateExampleCustomer(t) require.NotNil(t, cust) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv)) spec, err := subscription.NewSpecFromPlan(plan, subscription.CreateSubscriptionCustomerInput{ Name: "Test", @@ -741,16 +737,14 @@ func TestDeleteScheduledDowngradeCanExpandDeletedSubscriptionForSync(t *testing. deps := subscriptiontestutils.NewService(t, dbDeps) customerEntity := deps.CustomerAdapter.CreateExampleCustomer(t) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} billingAnchor := time.Date(2026, 5, 1, 0, 0, 0, 0, time.UTC) - premiumPlanInput := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) + premiumPlanInput := subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv) premiumPlanInput.Key = "premium-plan" premiumPlanInput.Name = "Premium" premiumPlan := deps.PlanHelper.CreatePlan(t, premiumPlanInput) - basicPlanInput := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) + basicPlanInput := subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv) basicPlanInput.Key = "basic-plan" basicPlanInput.Name = "Basic" basicPlan := deps.PlanHelper.CreatePlan(t, basicPlanInput) diff --git a/openmeter/subscription/testutils/plan.go b/openmeter/subscription/testutils/plan.go index 18dd8991ca..f49584a8ae 100644 --- a/openmeter/subscription/testutils/plan.go +++ b/openmeter/subscription/testutils/plan.go @@ -11,13 +11,41 @@ import ( "github.com/openmeterio/openmeter/openmeter/productcatalog/plan" plansubscription "github.com/openmeterio/openmeter/openmeter/productcatalog/subscription" "github.com/openmeterio/openmeter/openmeter/subscription" + taxcodetestutils "github.com/openmeterio/openmeter/openmeter/taxcode/testutils" "github.com/openmeterio/openmeter/openmeter/testutils" "github.com/openmeterio/openmeter/pkg/clock" "github.com/openmeterio/openmeter/pkg/datetime" ) -// GetExamplePlanInput builds the example plan in ExampleNamespace; its taxed rate cards carry taxConfig. -func GetExamplePlanInput(t *testing.T, taxConfig productcatalog.TaxConfig) plan.CreatePlanInput { +type examplePlanOptions struct { + taxConfig *productcatalog.TaxConfig +} + +type ExamplePlanOption func(*examplePlanOptions) + +// WithTaxConfig replaces the shared example tax config, for tests that assert on their own tax +// code, the legacy Stripe-only input, or in-memory tests without a tax code env. +func WithTaxConfig(taxConfig productcatalog.TaxConfig) ExamplePlanOption { + return func(o *examplePlanOptions) { + o.taxConfig = &taxConfig + } +} + +// GetExamplePlanInput builds the example plan in ExampleNamespace. Its taxed rate cards use the +// shared example tax code (ExampleTaxConfig) unless WithTaxConfig is given; env may be nil then. +func GetExamplePlanInput(t *testing.T, env *taxcodetestutils.TestEnv, opts ...ExamplePlanOption) plan.CreatePlanInput { + t.Helper() + + var o examplePlanOptions + for _, opt := range opts { + opt(&o) + } + + taxConfig := lo.FromPtr(o.taxConfig) + if o.taxConfig == nil { + taxConfig = ExampleTaxConfig(t, env) + } + b := BuildTestPlanInput(t) b.AddPhase(lo.ToPtr(datetime.MustParseDuration(t, "P1M")), ExampleRateCard1(taxConfig)) diff --git a/openmeter/subscription/testutils/taxcode.go b/openmeter/subscription/testutils/taxcode.go new file mode 100644 index 0000000000..3584585c75 --- /dev/null +++ b/openmeter/subscription/testutils/taxcode.go @@ -0,0 +1,49 @@ +package subscriptiontestutils + +import ( + "testing" + + "github.com/samber/lo" + "github.com/stretchr/testify/require" + + "github.com/openmeterio/openmeter/openmeter/app" + "github.com/openmeterio/openmeter/openmeter/productcatalog" + "github.com/openmeterio/openmeter/openmeter/taxcode" + taxcodetestutils "github.com/openmeterio/openmeter/openmeter/taxcode/testutils" +) + +const ( + ExampleTaxCodeKey = "example" + // ExampleStripeTaxCode is the Stripe code the example rate cards carried before they referenced + // tax codes by ID, so the legacy Stripe path resolves to the same tax code. + ExampleStripeTaxCode = "txcd_10000000" +) + +// ExampleTaxConfig returns the tax config of the example rate cards. Every call in a namespace +// shares one tax code: plan versions built from separate calls must compare equal, otherwise +// migrations would split every taxed item. +func ExampleTaxConfig(t *testing.T, env *taxcodetestutils.TestEnv) productcatalog.TaxConfig { + t.Helper() + require.NotNil(t, env, "the example tax code needs a tax code env; pass WithTaxConfig to build without one") + + tc, err := env.Service.GetTaxCodeByKey(t.Context(), taxcode.GetTaxCodeByKeyInput{ + Namespace: ExampleNamespace, + Key: ExampleTaxCodeKey, + }) + if err != nil { + require.True(t, taxcode.IsTaxCodeNotFoundError(err), "getting example tax code: %v", err) + + tc = env.CreateTaxCode(t, ExampleNamespace, taxcode.CreateTaxCodeInput{ + Key: ExampleTaxCodeKey, + Name: "Example", + AppMappings: taxcode.TaxCodeAppMappings{ + {AppType: app.AppTypeStripe, TaxCode: ExampleStripeTaxCode}, + }, + }) + } + + return productcatalog.TaxConfig{ + TaxCodeID: lo.ToPtr(tc.ID), + Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior), + } +} diff --git a/openmeter/subscription/workflow/service/addon_test.go b/openmeter/subscription/workflow/service/addon_test.go index ed676228a7..b8ba32b3b2 100644 --- a/openmeter/subscription/workflow/service/addon_test.go +++ b/openmeter/subscription/workflow/service/addon_test.go @@ -52,12 +52,10 @@ func TestAddAddon(t *testing.T) { } t.Run("Should error on invalid input", runWithDeps(func(t *testing.T, deps subscriptiontestutils.SubscriptionDependencies) { - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} p, add := subscriptiontestutils.CreatePlanWithAddon( t, deps, - subscriptiontestutils.GetExamplePlanInput(t, taxConfig), + subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv), subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ EffectiveFrom: &now, @@ -90,12 +88,10 @@ func TestAddAddon(t *testing.T) { })) t.Run("Should error if the subscription is inactive or in wrong state", runWithDeps(func(t *testing.T, deps subscriptiontestutils.SubscriptionDependencies) { - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} p, add := subscriptiontestutils.CreatePlanWithAddon( t, deps, - subscriptiontestutils.GetExamplePlanInput(t, taxConfig), + subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv), subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ EffectiveFrom: &now, @@ -135,8 +131,7 @@ func TestAddAddon(t *testing.T) { t.Run("Should add a new addon to a subscription that already has a different addon", runWithDeps(func(t *testing.T, deps subscriptiontestutils.SubscriptionDependencies) { _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + taxConfig := subscriptiontestutils.ExampleTaxConfig(t, deps.TaxCodeEnv) // Let's create a plan p, err := deps.PlanService.CreatePlan(context.Background(), subscriptiontestutils.BuildTestPlanInput(t). @@ -226,12 +221,10 @@ func TestAddAddon(t *testing.T) { })) t.Run("Should sync subscription with new addons contents", runWithDeps(func(t *testing.T, deps subscriptiontestutils.SubscriptionDependencies) { - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} p, add := subscriptiontestutils.CreatePlanWithAddon( t, deps, - subscriptiontestutils.GetExamplePlanInput(t, taxConfig), + subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv), subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ EffectiveFrom: &now, @@ -285,12 +278,10 @@ func TestAddAddon(t *testing.T) { })) t.Run("Should return conflict error if subscription already has that addon purchased", runWithDeps(func(t *testing.T, deps subscriptiontestutils.SubscriptionDependencies) { - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} p, add := subscriptiontestutils.CreatePlanWithAddon( t, deps, - subscriptiontestutils.GetExamplePlanInput(t, taxConfig), + subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv), subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ EffectiveFrom: &now, @@ -345,12 +336,10 @@ func TestChangeAddonQuantity(t *testing.T) { } t.Run("Should error if SubscriptionAddon and Subscription are in different namespaces", runWithDeps(func(t *testing.T, deps subscriptiontestutils.SubscriptionDependencies) { - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} p, add := subscriptiontestutils.CreatePlanWithAddon( t, deps, - subscriptiontestutils.GetExamplePlanInput(t, taxConfig), + subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv), subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ EffectiveFrom: &now, @@ -395,12 +384,10 @@ func TestChangeAddonQuantity(t *testing.T) { })) t.Run("Should error if SubscriptionAddon doesn't belong to Subscription", runWithDeps(func(t *testing.T, deps subscriptiontestutils.SubscriptionDependencies) { - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} p, add := subscriptiontestutils.CreatePlanWithAddon( t, deps, - subscriptiontestutils.GetExamplePlanInput(t, taxConfig), + subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv), subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ EffectiveFrom: &now, @@ -471,12 +458,10 @@ func TestChangeAddonQuantity(t *testing.T) { })) t.Run("Should error if the subscription is inactive or in wrong state", runWithDeps(func(t *testing.T, deps subscriptiontestutils.SubscriptionDependencies) { - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} p, add := subscriptiontestutils.CreatePlanWithAddon( t, deps, - subscriptiontestutils.GetExamplePlanInput(t, taxConfig), + subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv), subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ EffectiveFrom: &now, @@ -526,8 +511,7 @@ func TestChangeAddonQuantity(t *testing.T) { })) t.Run("Should update the quantity of the addon", runWithDeps(func(t *testing.T, deps subscriptiontestutils.SubscriptionDependencies) { - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + taxConfig := subscriptiontestutils.ExampleTaxConfig(t, deps.TaxCodeEnv) p, add := subscriptiontestutils.CreatePlanWithAddon( t, deps, @@ -582,8 +566,7 @@ func TestChangeAddonQuantity(t *testing.T) { twoMonthsFromNow, _ := twoMonths.AddTo(now) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + taxConfig := subscriptiontestutils.ExampleTaxConfig(t, deps.TaxCodeEnv) p, add := subscriptiontestutils.CreatePlanWithAddon( t, deps, @@ -715,8 +698,7 @@ func TestAddonCombinations(t *testing.T) { } t.Run("Should handle repeated add/remove of single instance addon with dynamic price", runWithDeps(func(t *testing.T, deps subscriptiontestutils.SubscriptionDependencies) { - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + taxConfig := subscriptiontestutils.ExampleTaxConfig(t, deps.TaxCodeEnv) // Create a plan with mixed rate cards planInput := subscriptiontestutils.BuildTestPlanInput(t). diff --git a/openmeter/subscription/workflow/service/migrate_test.go b/openmeter/subscription/workflow/service/migrate_test.go index b92f13e4fe..9dc8103305 100644 --- a/openmeter/subscription/workflow/service/migrate_test.go +++ b/openmeter/subscription/workflow/service/migrate_test.go @@ -31,8 +31,7 @@ func TestMigrateToPlanAddons(t *testing.T) { db := subscriptiontestutils.SetupDBDeps(t) defer db.Cleanup(t) deps := subscriptiontestutils.NewService(t, db) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + taxConfig := subscriptiontestutils.ExampleTaxConfig(t, deps.TaxCodeEnv) planInput := subscriptiontestutils.BuildTestPlanInput(t).AddPhase(nil, subscriptiontestutils.ExampleRateCard3ForAddons(taxConfig), subscriptiontestutils.ExampleRateCard2.Clone()).Build() p1, addon := subscriptiontestutils.CreatePlanWithAddon(t, deps, planInput, diff --git a/openmeter/subscription/workflow/service/subscription_test.go b/openmeter/subscription/workflow/service/subscription_test.go index c94e2c2538..147577c8b8 100644 --- a/openmeter/subscription/workflow/service/subscription_test.go +++ b/openmeter/subscription/workflow/service/subscription_test.go @@ -111,9 +111,7 @@ func TestCreateFromPlan(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv)) cust := deps.CustomerAdapter.CreateExampleCustomer(t) require.NotNil(t, cust) @@ -139,8 +137,7 @@ func TestCreateFromPlan(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + taxConfig := subscriptiontestutils.ExampleTaxConfig(t, deps.TaxCodeEnv) p := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.BuildTestPlanInput(t). AddPhase(nil, subscriptiontestutils.ExampleRateCard3ForAddons(taxConfig), subscriptiontestutils.ExampleRateCard4ForAddons.Clone()). Build()) @@ -644,9 +641,7 @@ func TestEditRunning(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) features := deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv)) cust := deps.CustomerAdapter.CreateExampleCustomer(t) require.NotNil(t, cust) @@ -845,9 +840,7 @@ func TestEditingCurrentPhase(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv)) cust := deps.CustomerAdapter.CreateExampleCustomer(t) require.NotNil(t, cust) @@ -1087,9 +1080,7 @@ func TestEditingWithTiming(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - planInput := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) + planInput := subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv) plan := deps.PlanHelper.CreatePlan(t, planInput) cust := deps.CustomerAdapter.CreateExampleCustomer(t) @@ -1150,12 +1141,11 @@ func TestChangeToPlan(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + taxConfig := subscriptiontestutils.ExampleTaxConfig(t, deps.TaxCodeEnv) // Let's define two plans. One is the example plan, and the second is a slightly modified version of that. // Build them per invocation so plan service mutations (e.g. resolving TaxCodeIDs) don't leak across subtests. - examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) + examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv) // Plan 2's new rate cards use a different tax code than the example plan. plan2TaxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) @@ -1346,9 +1336,8 @@ func TestEditCombinations(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) + taxConfig := subscriptiontestutils.ExampleTaxConfig(t, deps.TaxCodeEnv) + examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv) // Let's create the plan plan1 := deps.PlanHelper.CreatePlan(t, examplePlanInput1) @@ -1379,13 +1368,11 @@ func TestEditCombinations(t *testing.T) { defer dbDeps.Cleanup(t) deps := subscriptiontestutils.NewService(t, dbDeps) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} p, add := subscriptiontestutils.CreatePlanWithAddon( t, deps, - subscriptiontestutils.GetExamplePlanInput(t, taxConfig), + subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv), subscriptiontestutils.BuildAddonForTesting( t, productcatalog.EffectivePeriod{ @@ -1722,9 +1709,7 @@ func TestRestore(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) + examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv) // Let's create the plan plan1 := deps.PlanHelper.CreatePlan(t, examplePlanInput1) @@ -1913,9 +1898,7 @@ func TestMultiSubscription(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) + examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv) // Let's create the plan plan1 := deps.PlanHelper.CreatePlan(t, examplePlanInput1) @@ -2110,10 +2093,8 @@ func TestSubscriptionChangeTrackingAnnotations(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) - examplePlanInput2 := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) + examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv) + examplePlanInput2 := subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv) examplePlanInput2.Key = "example-plan-2" examplePlanInput2.Name = "Example Plan 2" @@ -2300,9 +2281,7 @@ func TestSettlementMode(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - p := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) + p := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv)) cust := deps.CustomerAdapter.CreateExampleCustomer(t) subView, err := deps.WorkflowService.CreateFromPlan(context.Background(), subscriptionworkflow.CreateSubscriptionWorkflowInput{ @@ -2333,9 +2312,7 @@ func TestSettlementMode(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - planInput := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) + planInput := subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv) planInput.SettlementMode = productcatalog.CreditOnlySettlementMode p := deps.PlanHelper.CreatePlan(t, planInput) cust := deps.CustomerAdapter.CreateExampleCustomer(t) @@ -2369,8 +2346,7 @@ func TestSettlementMode(t *testing.T) { deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) cust := deps.CustomerAdapter.CreateExampleCustomer(t) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + taxConfig := subscriptiontestutils.ExampleTaxConfig(t, deps.TaxCodeEnv) spec, err := subscriptiontestutils.BuildTestSubscriptionSpec(t). AddPhase(nil, subscriptiontestutils.ExampleRateCard1(taxConfig)). Build() @@ -2409,9 +2385,7 @@ func TestSettlementMode(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - p := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) + p := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv)) cust := deps.CustomerAdapter.CreateExampleCustomer(t) subView, err := deps.WorkflowService.CreateFromPlan(context.Background(), subscriptionworkflow.CreateSubscriptionWorkflowInput{ @@ -2464,9 +2438,7 @@ func TestSettlementMode(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - planInput := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) + planInput := subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv) planInput.SettlementMode = productcatalog.CreditOnlySettlementMode p := deps.PlanHelper.CreatePlan(t, planInput) cust := deps.CustomerAdapter.CreateExampleCustomer(t) @@ -2497,9 +2469,7 @@ func TestSettlementMode(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - planInput := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) + planInput := subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv) planInput.SettlementMode = productcatalog.CreditOnlySettlementMode p := deps.PlanHelper.CreatePlan(t, planInput) cust := deps.CustomerAdapter.CreateExampleCustomer(t) @@ -2530,11 +2500,9 @@ func TestSettlementMode(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} - basePlan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) + basePlan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv)) - creditOnlyPlanInput := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) + creditOnlyPlanInput := subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv) creditOnlyPlanInput.Key = "credit_only_plan" creditOnlyPlanInput.SettlementMode = productcatalog.CreditOnlySettlementMode creditOnlyPlan := deps.PlanHelper.CreatePlan(t, creditOnlyPlanInput) @@ -2591,8 +2559,7 @@ func TestCreateFromPlanSnapshotsUnitConfig(t *testing.T) { Rounding: productcatalog.UnitConfigRoundingModeCeiling, } - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + taxConfig := subscriptiontestutils.ExampleTaxConfig(t, deps.TaxCodeEnv) // ExampleRateCard1 is usage-based with a UnitPrice, which supports unit_config. rc := subscriptiontestutils.ExampleRateCard1(taxConfig) diff --git a/test/subscription/migrate_phases_test.go b/test/subscription/migrate_phases_test.go index 81d58141cc..3dfbb0072d 100644 --- a/test/subscription/migrate_phases_test.go +++ b/test/subscription/migrate_phases_test.go @@ -221,8 +221,7 @@ func TestMigrationStartingPhaseDoesNotTransferAddons(t *testing.T) { deps := setup(t, setupConfig{}) defer deps.cleanup(t) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + taxConfig := subscriptiontestutils.ExampleTaxConfig(t, deps.TaxCodeEnv) input := subscriptiontestutils.BuildTestPlanInput(t).AddPhase(nil, subscriptiontestutils.ExampleRateCard1(taxConfig), subscriptiontestutils.ExampleRateCard2.Clone()).Build() original, addon := subscriptiontestutils.CreatePlanWithAddon(t, deps.SubscriptionDependencies, input, diff --git a/test/subscription/migrate_test.go b/test/subscription/migrate_test.go index e9debace16..2ac694264d 100644 --- a/test/subscription/migrate_test.go +++ b/test/subscription/migrate_test.go @@ -334,8 +334,7 @@ func newMigrationFixtureWithPlan(t *testing.T, buildPlan func(taxConfig productc deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) customer := deps.CustomerAdapter.CreateExampleCustomer(t) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + taxConfig := subscriptiontestutils.ExampleTaxConfig(t, deps.TaxCodeEnv) original := deps.PlanHelper.CreatePlan(t, buildPlan(taxConfig)) before, err := deps.WorkflowService.CreateFromPlan(t.Context(), subscriptionworkflow.CreateSubscriptionWorkflowInput{ diff --git a/test/subscription/scenario_editaligned_test.go b/test/subscription/scenario_editaligned_test.go index d6c602e0c6..29dbed989f 100644 --- a/test/subscription/scenario_editaligned_test.go +++ b/test/subscription/scenario_editaligned_test.go @@ -17,6 +17,7 @@ import ( pcsubscription "github.com/openmeterio/openmeter/openmeter/productcatalog/subscription" "github.com/openmeterio/openmeter/openmeter/subscription" "github.com/openmeterio/openmeter/openmeter/subscription/patch" + subscriptiontestutils "github.com/openmeterio/openmeter/openmeter/subscription/testutils" subscriptionworkflow "github.com/openmeterio/openmeter/openmeter/subscription/workflow" "github.com/openmeterio/openmeter/openmeter/testutils" "github.com/openmeterio/openmeter/pkg/clock" @@ -48,8 +49,7 @@ func TestEditingEntitlementOfAlignedSub(t *testing.T) { }) require.NoError(t, err) - taxCode := tDeps.TaxCodeEnv.CreateTaxCode(t, namespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + taxConfig := subscriptiontestutils.ExampleTaxConfig(t, tDeps.TaxCodeEnv) // 2nd, let's create the plan p, err := tDeps.PlanService.CreatePlan(ctx, plan.CreatePlanInput{ diff --git a/test/subscription/scenario_editcancel_test.go b/test/subscription/scenario_editcancel_test.go index f49dab5eea..c3b882cfa1 100644 --- a/test/subscription/scenario_editcancel_test.go +++ b/test/subscription/scenario_editcancel_test.go @@ -18,6 +18,7 @@ import ( pcsubscription "github.com/openmeterio/openmeter/openmeter/productcatalog/subscription" "github.com/openmeterio/openmeter/openmeter/subscription" "github.com/openmeterio/openmeter/openmeter/subscription/patch" + subscriptiontestutils "github.com/openmeterio/openmeter/openmeter/subscription/testutils" subscriptionworkflow "github.com/openmeterio/openmeter/openmeter/subscription/workflow" "github.com/openmeterio/openmeter/openmeter/testutils" "github.com/openmeterio/openmeter/pkg/clock" @@ -49,8 +50,7 @@ func TestEditingAndCanceling(t *testing.T) { }) require.NoError(t, err) - taxCode := tDeps.TaxCodeEnv.CreateTaxCode(t, namespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + taxConfig := subscriptiontestutils.ExampleTaxConfig(t, tDeps.TaxCodeEnv) // Second, let's create the plan p, err := tDeps.PlanService.CreatePlan(ctx, plan.CreatePlanInput{ diff --git a/test/subscription/scenario_entinnextphase_test.go b/test/subscription/scenario_entinnextphase_test.go index 0216fb45a6..eb0ca01d8d 100644 --- a/test/subscription/scenario_entinnextphase_test.go +++ b/test/subscription/scenario_entinnextphase_test.go @@ -14,6 +14,7 @@ import ( "github.com/openmeterio/openmeter/openmeter/productcatalog/plan" pcsubscription "github.com/openmeterio/openmeter/openmeter/productcatalog/subscription" subscription "github.com/openmeterio/openmeter/openmeter/subscription" + subscriptiontestutils "github.com/openmeterio/openmeter/openmeter/subscription/testutils" subscriptionworkflow "github.com/openmeterio/openmeter/openmeter/subscription/workflow" "github.com/openmeterio/openmeter/openmeter/testutils" "github.com/openmeterio/openmeter/pkg/clock" @@ -41,8 +42,7 @@ func TestSubWithMeteredEntitlement(t *testing.T) { feats := tDeps.FeatureConnector.CreateExampleFeatures(t, tDeps.ExampleMeterID) require.Len(t, feats, 3) - taxCode := tDeps.TaxCodeEnv.CreateTaxCode(t, namespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + taxConfig := subscriptiontestutils.ExampleTaxConfig(t, tDeps.TaxCodeEnv) // 2nd, let's create the plan p, err := tDeps.PlanService.CreatePlan(ctx, plan.CreatePlanInput{ diff --git a/test/subscription/scenario_firstofmonth_test.go b/test/subscription/scenario_firstofmonth_test.go index 98ad38a368..7a728eab98 100644 --- a/test/subscription/scenario_firstofmonth_test.go +++ b/test/subscription/scenario_firstofmonth_test.go @@ -18,6 +18,7 @@ import ( "github.com/openmeterio/openmeter/openmeter/productcatalog/plan" pcsubscription "github.com/openmeterio/openmeter/openmeter/productcatalog/subscription" subscription "github.com/openmeterio/openmeter/openmeter/subscription" + subscriptiontestutils "github.com/openmeterio/openmeter/openmeter/subscription/testutils" subscriptionworkflow "github.com/openmeterio/openmeter/openmeter/subscription/workflow" "github.com/openmeterio/openmeter/openmeter/testutils" "github.com/openmeterio/openmeter/pkg/clock" @@ -46,8 +47,7 @@ func TestBillingOnFirstOfMonth(t *testing.T) { feats := tDeps.FeatureConnector.CreateExampleFeatures(t, tDeps.ExampleMeterID) require.Len(t, feats, 3) - taxCode := tDeps.TaxCodeEnv.CreateTaxCode(t, namespace) - taxConfig := productcatalog.TaxConfig{TaxCodeID: &taxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)} + taxConfig := subscriptiontestutils.ExampleTaxConfig(t, tDeps.TaxCodeEnv) // 2nd, let's create the plan p, err := tDeps.PlanService.CreatePlan(ctx, plan.CreatePlanInput{ From 294790c7db641087e8bb845b80cb0c50d3b7f411 Mon Sep 17 00:00:00 2001 From: Robert Borbely Date: Wed, 28 Oct 2026 11:28:28 +0100 Subject: [PATCH 3/8] refactor(test): separate example tax code setup from subscription plan builders Tests create the example tax code once with TaxCodeEnv.CreateTaxCode and GetExampleTaxCodeInput, then pass ExampleTaxConfig(taxCode) to the pure GetExamplePlanInput and rate card builders. The builders no longer read or write the database. --- api/v3/handlers/subscriptions/convert_test.go | 4 +- api/v3/handlers/subscriptions/migrate_test.go | 3 +- .../subscription/service/change_test.go | 29 ++++--- .../subscription/service/create_test.go | 28 +++++-- .../subscription/service/migrate_test.go | 19 +++-- .../subscription/service/plan_test.go | 5 +- .../subscription/addon/diff/apply_test.go | 16 ++-- .../subscription/addon/diff/restore_test.go | 3 +- .../subscription/addon/service/change_test.go | 9 ++- .../subscription/addon/service/create_test.go | 41 +++++++--- .../addon/service/currency_test.go | 5 +- .../subscription/addon/service/list_test.go | 9 ++- openmeter/subscription/patch/patch_test.go | 2 +- .../subscription/service/listviews_test.go | 8 +- .../subscription/service/migration_test.go | 6 +- .../subscription/service/service_test.go | 69 +++++++++++----- openmeter/subscription/service/sync_test.go | 14 +++- openmeter/subscription/testutils/plan.go | 32 +------- openmeter/subscription/testutils/taxcode.go | 42 +++------- .../workflow/service/addon_test.go | 40 +++++++--- .../workflow/service/migrate_test.go | 3 +- .../workflow/service/subscription_test.go | 79 +++++++++++++------ test/subscription/migrate_phases_test.go | 3 +- test/subscription/migrate_test.go | 3 +- .../subscription/scenario_editaligned_test.go | 3 +- test/subscription/scenario_editcancel_test.go | 3 +- .../scenario_entinnextphase_test.go | 3 +- .../scenario_firstofmonth_test.go | 3 +- 28 files changed, 304 insertions(+), 180 deletions(-) diff --git a/api/v3/handlers/subscriptions/convert_test.go b/api/v3/handlers/subscriptions/convert_test.go index e38a7f69c8..f1d2c45cf4 100644 --- a/api/v3/handlers/subscriptions/convert_test.go +++ b/api/v3/handlers/subscriptions/convert_test.go @@ -137,7 +137,9 @@ func TestToAPIBillingSubscriptionViewRoundtrip(t *testing.T) { // given: a subscription created from the example plan, which has phases and rate cards cust := deps.CustomerAdapter.CreateExampleCustomer(t) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) spec, err := subscription.NewSpecFromPlan(plan, subscription.CreateSubscriptionCustomerInput{ CustomerId: cust.ID, diff --git a/api/v3/handlers/subscriptions/migrate_test.go b/api/v3/handlers/subscriptions/migrate_test.go index 9c86da3cda..6a3fda388a 100644 --- a/api/v3/handlers/subscriptions/migrate_test.go +++ b/api/v3/handlers/subscriptions/migrate_test.go @@ -68,7 +68,8 @@ func TestMigrateSubscriptionHandler(t *testing.T) { defer db.Cleanup(t) deps := subscriptiontestutils.NewService(t, db) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - taxConfig := subscriptiontestutils.ExampleTaxConfig(t, deps.TaxCodeEnv) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.BuildTestPlanInput(t). AddPhase(nil, subscriptiontestutils.ExampleRateCard1(taxConfig)).Build()) before := subscriptiontestutils.CreateSubscriptionFromPlan(t, &deps, plan, start) diff --git a/openmeter/productcatalog/subscription/service/change_test.go b/openmeter/productcatalog/subscription/service/change_test.go index 92e38ea972..1e431c7222 100644 --- a/openmeter/productcatalog/subscription/service/change_test.go +++ b/openmeter/productcatalog/subscription/service/change_test.go @@ -46,8 +46,9 @@ func TestChange(t *testing.T) { t.Run("Should change to different plan", func(t *testing.T) { withDeps(t, func(t *testing.T, deps tDeps) { - taxConfig := subscriptiontestutils.ExampleTaxConfig(t, deps.subDeps.TaxCodeEnv) - examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, deps.subDeps.TaxCodeEnv) + taxCode := deps.subDeps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) now := testutils.GetRFC3339Time(t, "2021-01-01T00:01:10Z") clock.SetTime(now) @@ -147,8 +148,9 @@ func TestChange(t *testing.T) { t.Run("Should change to different plan starting from specific phase", func(t *testing.T) { withDeps(t, func(t *testing.T, deps tDeps) { - taxConfig := subscriptiontestutils.ExampleTaxConfig(t, deps.subDeps.TaxCodeEnv) - examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, deps.subDeps.TaxCodeEnv) + taxCode := deps.subDeps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) now := testutils.GetRFC3339Time(t, "2021-01-01T00:01:10Z") clock.SetTime(now) @@ -270,8 +272,9 @@ func TestChange(t *testing.T) { t.Run("Should not allow changing to inactive plan", func(t *testing.T) { withDeps(t, func(t *testing.T, deps tDeps) { - taxConfig := subscriptiontestutils.ExampleTaxConfig(t, deps.subDeps.TaxCodeEnv) - examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, deps.subDeps.TaxCodeEnv) + taxCode := deps.subDeps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) now := testutils.GetRFC3339Time(t, "2021-01-01T00:01:10Z") clock.SetTime(now) @@ -389,7 +392,9 @@ func TestChange(t *testing.T) { t.Run("Should apply the settlement mode override when creating from a plan reference", func(t *testing.T) { withDeps(t, func(t *testing.T, deps tDeps) { - examplePlanInput := subscriptiontestutils.GetExamplePlanInput(t, deps.subDeps.TaxCodeEnv) + taxCode := deps.subDeps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + examplePlanInput := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) require.Equal(t, productcatalog.CreditThenInvoiceSettlementMode, examplePlanInput.Plan.SettlementMode) now := testutils.GetRFC3339Time(t, "2021-01-01T00:01:10Z") @@ -433,7 +438,9 @@ func TestChange(t *testing.T) { t.Run("Should apply the settlement mode override when changing to a plan reference", func(t *testing.T) { withDeps(t, func(t *testing.T, deps tDeps) { - examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, deps.subDeps.TaxCodeEnv) + taxCode := deps.subDeps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) now := testutils.GetRFC3339Time(t, "2021-01-01T00:01:10Z") clock.SetTime(now) @@ -535,7 +542,9 @@ func TestChangeInlineCustomPlanRejectsMissingFeature(t *testing.T) { customer := deps.CustomerAdapter.CreateExampleCustomer(t) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - currentPlanInput := subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + currentPlanInput := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) currentPlanInput.Plan.Key = "" currentPlanInput.Plan.Version = 0 currentPlan := plansubscription.PlanInput{} @@ -555,7 +564,7 @@ func TestChangeInlineCustomPlanRejectsMissingFeature(t *testing.T) { require.NoError(t, err) const missingFeatureKey = "missing-change-feature" - replacementPlanInput := subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv) + replacementPlanInput := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) replacementPlanInput.Plan.Key = "" replacementPlanInput.Plan.Version = 0 require.NoError(t, replacementPlanInput.Plan.Phases[0].RateCards[0].ChangeMeta(func(meta productcatalog.RateCardMeta) (productcatalog.RateCardMeta, error) { diff --git a/openmeter/productcatalog/subscription/service/create_test.go b/openmeter/productcatalog/subscription/service/create_test.go index 1439a2e244..3d07261057 100644 --- a/openmeter/productcatalog/subscription/service/create_test.go +++ b/openmeter/productcatalog/subscription/service/create_test.go @@ -79,7 +79,9 @@ func TestCreateInlineCustomPlanRejectsMissingFeature(t *testing.T) { deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) const missingFeatureKey = "missing-feature" - planInput := subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + planInput := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) planInput.Plan.Key = "" planInput.Plan.Version = 0 require.NoError(t, planInput.Plan.Phases[0].RateCards[0].ChangeMeta(func(meta productcatalog.RateCardMeta) (productcatalog.RateCardMeta, error) { @@ -151,8 +153,10 @@ func TestCreateSettlementModeOverride(t *testing.T) { cust := deps.subDeps.CustomerAdapter.CreateExampleCustomer(t) deps.subDeps.FeatureConnector.CreateExampleFeatures(t, deps.subDeps.ExampleMeterID) + taxCode := deps.subDeps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) // Build a custom plan input; clear Key/Version so PlanFromPlanInput accepts it. - planInput := subscriptiontestutils.GetExamplePlanInput(t, deps.subDeps.TaxCodeEnv) + planInput := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) require.Equal(t, productcatalog.CreditThenInvoiceSettlementMode, planInput.Plan.SettlementMode, "precondition: plan default must be CreditThenInvoice") planInput.Plan.Key = "" planInput.Plan.Version = 0 @@ -198,7 +202,9 @@ func TestCreateSettlementModeOverride(t *testing.T) { cust := deps.subDeps.CustomerAdapter.CreateExampleCustomer(t) deps.subDeps.FeatureConnector.CreateExampleFeatures(t, deps.subDeps.ExampleMeterID) - examplePlanInput := subscriptiontestutils.GetExamplePlanInput(t, deps.subDeps.TaxCodeEnv) + taxCode := deps.subDeps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + examplePlanInput := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) require.Equal(t, productcatalog.CreditThenInvoiceSettlementMode, examplePlanInput.Plan.SettlementMode, "precondition: plan default must be CreditThenInvoice") plan1 := deps.subDeps.PlanHelper.CreatePlan(t, examplePlanInput) @@ -255,7 +261,9 @@ func TestCreateInlineCustomCurrencyMaterializesManagedIdentity(t *testing.T) { )) require.NoError(t, err) - planInput := subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + planInput := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) planInput.Plan.Key = "" planInput.Plan.Version = 0 planInput.Plan.Currency = managedCurrency.Reference() @@ -322,7 +330,9 @@ func TestCreateInlineCustomCurrencyGatedByCredits(t *testing.T) { customer := deps.CustomerAdapter.CreateExampleCustomer(t) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - planInput := subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + planInput := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) planInput.Plan.Key = "" planInput.Plan.Version = 0 planInput.Plan.Currency = currencies.NewCurrencyReference("CREDITS") @@ -377,7 +387,9 @@ func TestCreateInlineEntitlementRateCardResolvesFeatureByID(t *testing.T) { featureIDByKey[f.Key] = f.ID } - planInput := subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + planInput := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) planInput.Plan.Key = "" planInput.Plan.Version = 0 @@ -430,7 +442,9 @@ func TestCreateInlineCreditOnlyPlanSkipsCurrencyCostBasis(t *testing.T) { )) require.NoError(t, err) - planInput := subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + planInput := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) planInput.Plan.Key = "" planInput.Plan.Version = 0 planInput.Plan.SettlementMode = productcatalog.CreditOnlySettlementMode diff --git a/openmeter/productcatalog/subscription/service/migrate_test.go b/openmeter/productcatalog/subscription/service/migrate_test.go index 8dc48a7bf3..252e0927cb 100644 --- a/openmeter/productcatalog/subscription/service/migrate_test.go +++ b/openmeter/productcatalog/subscription/service/migrate_test.go @@ -44,7 +44,9 @@ func TestMigrate(t *testing.T) { t.Run("Should migrate to latest version of plan when none is specified", func(t *testing.T) { withDeps(t, func(t *testing.T, deps tDeps) { - examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, deps.subDeps.TaxCodeEnv) + taxCode := deps.subDeps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) now := testutils.GetRFC3339Time(t, "2021-01-01T00:01:10Z") clock.SetTime(now) @@ -120,7 +122,9 @@ func TestMigrate(t *testing.T) { t.Run("Should migrate to specific version of plan when provided", func(t *testing.T) { withDeps(t, func(t *testing.T, deps tDeps) { - examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, deps.subDeps.TaxCodeEnv) + taxCode := deps.subDeps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) now := testutils.GetRFC3339Time(t, "2021-01-01T00:01:10Z") clock.SetTime(now) @@ -194,7 +198,9 @@ func TestMigrate(t *testing.T) { t.Run("Should not allow migrating to same or smaller version", func(t *testing.T) { withDeps(t, func(t *testing.T, deps tDeps) { - examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, deps.subDeps.TaxCodeEnv) + taxCode := deps.subDeps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) now := testutils.GetRFC3339Time(t, "2021-01-01T00:01:10Z") clock.SetTime(now) @@ -273,7 +279,9 @@ func TestMigrate(t *testing.T) { t.Run("Should replace the subscription when a starting phase is supplied", func(t *testing.T) { withDeps(t, func(t *testing.T, deps tDeps) { - examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, deps.subDeps.TaxCodeEnv) + taxCode := deps.subDeps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) now := testutils.GetRFC3339Time(t, "2021-01-01T00:01:10Z") clock.SetTime(now) @@ -396,7 +404,8 @@ func TestMigrateReturnsCurrentSnapshotFromUnderLock(t *testing.T) { deps := subscriptiontestutils.NewService(t, db) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - taxConfig := subscriptiontestutils.ExampleTaxConfig(t, deps.TaxCodeEnv) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) planInput := subscriptiontestutils.BuildTestPlanInput(t).AddPhase(nil, subscriptiontestutils.ExampleRateCard1(taxConfig), ).Build() diff --git a/openmeter/productcatalog/subscription/service/plan_test.go b/openmeter/productcatalog/subscription/service/plan_test.go index d1fe0b2ee3..ddc54c74b1 100644 --- a/openmeter/productcatalog/subscription/service/plan_test.go +++ b/openmeter/productcatalog/subscription/service/plan_test.go @@ -39,8 +39,9 @@ func TestDiscountPersisting(t *testing.T) { t.Run("Should persist discounts", func(t *testing.T) { withDeps(t, func(t *testing.T, deps tDeps) { - taxConfig := subscriptiontestutils.ExampleTaxConfig(t, deps.subDeps.TaxCodeEnv) - examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, deps.subDeps.TaxCodeEnv) + taxCode := deps.subDeps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) examplePlanInput1.Phases[0].RateCards[0] = subscriptiontestutils.ExampleRateCardWithDiscounts(taxConfig) ctx := context.Background() diff --git a/openmeter/subscription/addon/diff/apply_test.go b/openmeter/subscription/addon/diff/apply_test.go index f0bd9016af..8fb7755db4 100644 --- a/openmeter/subscription/addon/diff/apply_test.go +++ b/openmeter/subscription/addon/diff/apply_test.go @@ -48,7 +48,8 @@ func TestApply(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) - taxConfig := subscriptiontestutils.ExampleTaxConfig(t, deps.TaxCodeEnv) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) fn(t, &tcDeps{ deps: deps, @@ -61,7 +62,7 @@ func TestApply(t *testing.T) { p, a := subscriptiontestutils.CreatePlanWithAddon( t, deps.deps, - subscriptiontestutils.GetExamplePlanInput(t, deps.deps.TaxCodeEnv), + subscriptiontestutils.GetExamplePlanInput(t, deps.taxConfig), subscriptiontestutils.GetExampleAddonInput(t, productcatalog.EffectivePeriod{ EffectiveFrom: &now, EffectiveTo: nil, @@ -90,7 +91,7 @@ func TestApply(t *testing.T) { p, a := subscriptiontestutils.CreatePlanWithAddon( t, deps.deps, - subscriptiontestutils.GetExamplePlanInput(t, deps.deps.TaxCodeEnv), + subscriptiontestutils.GetExamplePlanInput(t, deps.taxConfig), subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ EffectiveFrom: &now, @@ -150,7 +151,7 @@ func TestApply(t *testing.T) { p, a := subscriptiontestutils.CreatePlanWithAddon( t, deps.deps, - subscriptiontestutils.GetExamplePlanInput(t, deps.deps.TaxCodeEnv), + subscriptiontestutils.GetExamplePlanInput(t, deps.taxConfig), subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ EffectiveFrom: &now, @@ -307,7 +308,7 @@ func TestApply(t *testing.T) { p, a := subscriptiontestutils.CreatePlanWithAddon( t, deps.deps, - subscriptiontestutils.GetExamplePlanInput(t, deps.deps.TaxCodeEnv), + subscriptiontestutils.GetExamplePlanInput(t, deps.taxConfig), subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ EffectiveFrom: &now, @@ -383,7 +384,7 @@ func TestApply(t *testing.T) { p, a := subscriptiontestutils.CreatePlanWithAddon( t, deps.deps, - subscriptiontestutils.GetExamplePlanInput(t, deps.deps.TaxCodeEnv), + subscriptiontestutils.GetExamplePlanInput(t, deps.taxConfig), subscriptiontestutils.BuildAddonForTesting(t, effPer, productcatalog.AddonInstanceTypeSingle, @@ -988,7 +989,8 @@ func TestApplyWithMultiInstance(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) - taxConfig := subscriptiontestutils.ExampleTaxConfig(t, deps.TaxCodeEnv) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) fn(t, &tcDeps{ deps: deps, diff --git a/openmeter/subscription/addon/diff/restore_test.go b/openmeter/subscription/addon/diff/restore_test.go index 4115d74578..eb53058a9b 100644 --- a/openmeter/subscription/addon/diff/restore_test.go +++ b/openmeter/subscription/addon/diff/restore_test.go @@ -44,7 +44,8 @@ func TestRestore(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) - taxConfig := subscriptiontestutils.ExampleTaxConfig(t, deps.TaxCodeEnv) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) fn(t, &tcDeps{ deps: deps, diff --git a/openmeter/subscription/addon/service/change_test.go b/openmeter/subscription/addon/service/change_test.go index a6d5d275ab..06e7efd2aa 100644 --- a/openmeter/subscription/addon/service/change_test.go +++ b/openmeter/subscription/addon/service/change_test.go @@ -75,7 +75,9 @@ func TestAddonServiceChangeQuantity(t *testing.T) { clock.SetTime(now) defer clock.ResetTime() - planInp := subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + planInp := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) addonInp := subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ EffectiveFrom: lo.ToPtr(now), @@ -187,10 +189,13 @@ func createExampleSubscriptionAddon(t *testing.T, deps subscriptiontestutils.Sub clock.SetTime(now) defer clock.ResetTime() + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + p, add := subscriptiontestutils.CreatePlanWithAddon( t, deps, - subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv), + subscriptiontestutils.GetExamplePlanInput(t, taxConfig), subscriptiontestutils.GetExampleAddonInput(t, productcatalog.EffectivePeriod{ EffectiveFrom: lo.ToPtr(now), }), diff --git a/openmeter/subscription/addon/service/create_test.go b/openmeter/subscription/addon/service/create_test.go index 1febf60b0b..5386304561 100644 --- a/openmeter/subscription/addon/service/create_test.go +++ b/openmeter/subscription/addon/service/create_test.go @@ -31,10 +31,13 @@ func TestAddonServiceCreate(t *testing.T) { clock.SetTime(now) defer clock.ResetTime() + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + p, add := subscriptiontestutils.CreatePlanWithAddon( t, deps, - subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv), + subscriptiontestutils.GetExamplePlanInput(t, taxConfig), subscriptiontestutils.GetExampleAddonInput(t, productcatalog.EffectivePeriod{ EffectiveFrom: lo.ToPtr(now), }), @@ -77,10 +80,13 @@ func TestAddonServiceCreate(t *testing.T) { clock.SetTime(now) defer clock.ResetTime() + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + p, _ := subscriptiontestutils.CreatePlanWithAddon( t, deps, - subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv), + subscriptiontestutils.GetExamplePlanInput(t, taxConfig), subscriptiontestutils.GetExampleAddonInput(t, productcatalog.EffectivePeriod{ EffectiveFrom: lo.ToPtr(now), }), @@ -150,10 +156,13 @@ func TestAddonServiceCreate(t *testing.T) { clock.SetTime(now) defer clock.ResetTime() + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + p, add := subscriptiontestutils.CreatePlanWithAddon( t, deps, - subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv), + subscriptiontestutils.GetExamplePlanInput(t, taxConfig), subscriptiontestutils.GetExampleAddonInput(t, productcatalog.EffectivePeriod{ EffectiveFrom: lo.ToPtr(now), }), @@ -196,10 +205,13 @@ func TestAddonServiceCreate(t *testing.T) { clock.SetTime(now) defer clock.ResetTime() + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + p, _ := subscriptiontestutils.CreatePlanWithAddon( t, deps, - subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv), + subscriptiontestutils.GetExamplePlanInput(t, taxConfig), subscriptiontestutils.GetExampleAddonInput(t, productcatalog.EffectivePeriod{ EffectiveFrom: lo.ToPtr(now), }), @@ -249,7 +261,9 @@ func TestAddonServiceCreate(t *testing.T) { defer clock.ResetTime() // Let's create a plan with addon thats only available in a later phase - planInp := subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + planInp := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) addonInp := subscriptiontestutils.GetExampleAddonInput(t, productcatalog.EffectivePeriod{ EffectiveFrom: lo.ToPtr(now), }) @@ -325,7 +339,9 @@ func TestAddonServiceCreate(t *testing.T) { defer clock.ResetTime() // Let's create a plan with addon thats only available in a later phase - planInp := subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + planInp := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) addonInp := subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ EffectiveFrom: lo.ToPtr(now), }, productcatalog.AddonInstanceTypeMultiple, subscriptiontestutils.ExampleAddonRateCard1.Clone()) @@ -404,7 +420,9 @@ func TestAddonServiceCreate(t *testing.T) { // Let's create a subscription without a plan reference cust := deps.CustomerAdapter.CreateExampleCustomer(t) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) spec1, err := subscription.NewSpecFromPlan(plan, subscription.CreateSubscriptionCustomerInput{ CustomerId: cust.ID, @@ -452,10 +470,13 @@ func TestAddonServiceCreate(t *testing.T) { clock.SetTime(now) defer clock.ResetTime() + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + p, add := subscriptiontestutils.CreatePlanWithAddon( t, deps, - subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv), + subscriptiontestutils.GetExamplePlanInput(t, taxConfig), subscriptiontestutils.GetExampleAddonInput(t, productcatalog.EffectivePeriod{ EffectiveFrom: lo.ToPtr(now), }), @@ -515,7 +536,9 @@ func TestAddonServiceCreate(t *testing.T) { func createExampleSubscription(t *testing.T, deps subscriptiontestutils.SubscriptionDependencies, currentTime time.Time) subscription.SubscriptionView { cust := deps.CustomerAdapter.CreateExampleCustomer(t) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) spec1, err := subscription.NewSpecFromPlan(plan, subscription.CreateSubscriptionCustomerInput{ CustomerId: cust.ID, diff --git a/openmeter/subscription/addon/service/currency_test.go b/openmeter/subscription/addon/service/currency_test.go index 9e7f6380ea..38086c6231 100644 --- a/openmeter/subscription/addon/service/currency_test.go +++ b/openmeter/subscription/addon/service/currency_test.go @@ -216,10 +216,13 @@ func createSubscriptionForPlanWithAddon( ) (models.NamespacedID, addon.Addon) { t.Helper() + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + p, add := subscriptiontestutils.CreatePlanWithAddon( t, deps, - subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv), + subscriptiontestutils.GetExamplePlanInput(t, taxConfig), addonInput, ) diff --git a/openmeter/subscription/addon/service/list_test.go b/openmeter/subscription/addon/service/list_test.go index 784cd0ad3e..56b8cd91f4 100644 --- a/openmeter/subscription/addon/service/list_test.go +++ b/openmeter/subscription/addon/service/list_test.go @@ -28,10 +28,13 @@ func TestAddonServiceGet(t *testing.T) { clock.SetTime(now) defer clock.ResetTime() + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + p, add := subscriptiontestutils.CreatePlanWithAddon( t, deps, - subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv), + subscriptiontestutils.GetExamplePlanInput(t, taxConfig), subscriptiontestutils.GetExampleAddonInput(t, productcatalog.EffectivePeriod{ EffectiveFrom: lo.ToPtr(now), }), @@ -101,7 +104,9 @@ func TestAddonServiceList(t *testing.T) { // Let's create a plan - p, err := deps.PlanService.CreatePlan(context.Background(), subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + p, err := deps.PlanService.CreatePlan(context.Background(), subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) require.Nil(t, err) require.NotNil(t, p) diff --git a/openmeter/subscription/patch/patch_test.go b/openmeter/subscription/patch/patch_test.go index e394f9a546..b1333a5104 100644 --- a/openmeter/subscription/patch/patch_test.go +++ b/openmeter/subscription/patch/patch_test.go @@ -197,7 +197,7 @@ func (ts *testsuite[T]) Run(t *testing.T) { } func getDefaultSpec(t *testing.T, activeFrom time.Time) (*subscription.SubscriptionSpec, *psubs.Plan) { - pInp := subscriptiontestutils.GetExamplePlanInput(t, nil, subscriptiontestutils.WithTaxConfig(productcatalog.TaxConfig{TaxCodeID: lo.ToPtr("example-tax-code"), Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)})) + pInp := subscriptiontestutils.GetExamplePlanInput(t, productcatalog.TaxConfig{TaxCodeID: lo.ToPtr("example-tax-code"), Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)}) p := &psubs.Plan{ Plan: pInp.Plan, Ref: &models.NamespacedID{Namespace: pInp.Namespace, ID: pInp.Key}, diff --git a/openmeter/subscription/service/listviews_test.go b/openmeter/subscription/service/listviews_test.go index 21ffed790d..f8d59ac843 100644 --- a/openmeter/subscription/service/listviews_test.go +++ b/openmeter/subscription/service/listviews_test.go @@ -34,7 +34,9 @@ func TestListViewsMultiCustomer(t *testing.T) { service := deps.SubscriptionService _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) // given: two distinct customers, each with a subscription from the same plan cust1 := deps.CustomerAdapter.CreateExampleCustomer(t) @@ -87,7 +89,9 @@ func TestGetViewResolvesSoftDeletedCustomer(t *testing.T) { service := deps.SubscriptionService _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) // given: a subscription whose customer is subsequently soft-deleted cust := deps.CustomerAdapter.CreateExampleCustomer(t) diff --git a/openmeter/subscription/service/migration_test.go b/openmeter/subscription/service/migration_test.go index 691dc45bba..573ae6ce79 100644 --- a/openmeter/subscription/service/migration_test.go +++ b/openmeter/subscription/service/migration_test.go @@ -58,7 +58,8 @@ func TestUpdateRejectsMigrationBetweenReadAndLock(t *testing.T) { defer db.Cleanup(t) deps := subscriptiontestutils.NewService(t, db) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - taxConfig := subscriptiontestutils.ExampleTaxConfig(t, deps.TaxCodeEnv) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) p1 := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.BuildTestPlanInput(t).AddPhase(nil, subscriptiontestutils.ExampleRateCard1(taxConfig)).Build()) before := subscriptiontestutils.CreateSubscriptionFromPlan(t, &deps, p1, start) clock.FreezeTime(start.Add(10 * 24 * time.Hour)) @@ -143,7 +144,8 @@ func TestCancelIncludesMigrationCommittedBeforeLock(t *testing.T) { deps := subscriptiontestutils.NewService(t, db) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - taxConfig := subscriptiontestutils.ExampleTaxConfig(t, deps.TaxCodeEnv) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) p1 := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.BuildTestPlanInput(t).AddPhase(nil, subscriptiontestutils.ExampleRateCard1(taxConfig)).Build()) before := subscriptiontestutils.CreateSubscriptionFromPlan(t, &deps, p1, start) diff --git a/openmeter/subscription/service/service_test.go b/openmeter/subscription/service/service_test.go index 34751115b0..6c74691998 100644 --- a/openmeter/subscription/service/service_test.go +++ b/openmeter/subscription/service/service_test.go @@ -41,7 +41,9 @@ func TestCreation(t *testing.T) { cust := deps.CustomerAdapter.CreateExampleCustomer(t) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) defaultSpecFromPlan, err := subscription.NewSpecFromPlan(plan, subscription.CreateSubscriptionCustomerInput{ CustomerId: cust.ID, @@ -112,7 +114,9 @@ func TestCreation(t *testing.T) { cust := deps.CustomerAdapter.CreateExampleCustomer(t) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) specWithAnnotations, err := subscription.NewSpecFromPlan(plan, subscription.CreateSubscriptionCustomerInput{ CustomerId: cust.ID, @@ -170,7 +174,9 @@ func TestCreation(t *testing.T) { require.Nil(t, err) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) defaultSpecFromPlan, err := subscription.NewSpecFromPlan(plan, subscription.CreateSubscriptionCustomerInput{ CustomerId: cust.ID, @@ -215,7 +221,9 @@ func TestCreation(t *testing.T) { require.Nil(t, err) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) defaultSpecFromPlan, err := subscription.NewSpecFromPlan(plan, subscription.CreateSubscriptionCustomerInput{ CustomerId: cust.ID, @@ -318,7 +326,9 @@ func TestCancellation(t *testing.T) { cust := deps.CustomerAdapter.CreateExampleCustomer(t) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) // First, let's create a subscription defaultSpecFromPlan, err := subscription.NewSpecFromPlan(plan, subscription.CreateSubscriptionCustomerInput{ @@ -436,7 +446,9 @@ func TestContinuing(t *testing.T) { cust := deps.CustomerAdapter.CreateExampleCustomer(t) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) // First, let's create a subscription defaultSpecFromPlan, err := subscription.NewSpecFromPlan(plan, subscription.CreateSubscriptionCustomerInput{ @@ -523,7 +535,9 @@ func TestContinuing(t *testing.T) { cust := deps.CustomerAdapter.CreateExampleCustomer(t) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) // First, let's create a subscription spec1, err := subscription.NewSpecFromPlan(plan, subscription.CreateSubscriptionCustomerInput{ @@ -631,7 +645,9 @@ func TestList(t *testing.T) { require.Nil(t, err) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) // Let's create some subscriptions: // - One active @@ -815,7 +831,9 @@ func TestList(t *testing.T) { require.Nil(t, err) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) spec1, err := subscription.NewSpecFromPlan(plan, subscription.CreateSubscriptionCustomerInput{ CustomerId: cust1.ID, @@ -911,7 +929,9 @@ func TestSubscriptionChangeTrackingAnnotations(t *testing.T) { cust := deps.CustomerAdapter.CreateExampleCustomer(t) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - plan1 := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + plan1 := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) // Create first subscription sub1, err := workflowService.CreateFromPlan(ctx, subscriptionworkflow.CreateSubscriptionWorkflowInput{ @@ -927,7 +947,7 @@ func TestSubscriptionChangeTrackingAnnotations(t *testing.T) { require.Nil(t, err) // Create second plan - examplePlanInput2 := subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv) + examplePlanInput2 := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) examplePlanInput2.Key = "example-plan-2" examplePlanInput2.Name = "Example Plan 2" plan2 := deps.PlanHelper.CreatePlan(t, examplePlanInput2) @@ -974,7 +994,9 @@ func TestSubscriptionChangeTrackingAnnotations(t *testing.T) { cust := deps.CustomerAdapter.CreateExampleCustomer(t) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - plan1 := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + plan1 := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) // Create first subscription sub1, err := workflowService.CreateFromPlan(ctx, subscriptionworkflow.CreateSubscriptionWorkflowInput{ @@ -990,7 +1012,7 @@ func TestSubscriptionChangeTrackingAnnotations(t *testing.T) { require.Nil(t, err) // Create second plan - examplePlanInput2 := subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv) + examplePlanInput2 := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) examplePlanInput2.Key = "example-plan-2" examplePlanInput2.Name = "Example Plan 2" plan2 := deps.PlanHelper.CreatePlan(t, examplePlanInput2) @@ -1038,7 +1060,9 @@ func TestSubscriptionChangeTrackingAnnotations(t *testing.T) { cust := deps.CustomerAdapter.CreateExampleCustomer(t) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - plan1 := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + plan1 := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) // Create first subscription sub1, err := workflowService.CreateFromPlan(ctx, subscriptionworkflow.CreateSubscriptionWorkflowInput{ @@ -1054,7 +1078,7 @@ func TestSubscriptionChangeTrackingAnnotations(t *testing.T) { require.Nil(t, err) // Create second plan - examplePlanInput2 := subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv) + examplePlanInput2 := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) examplePlanInput2.Key = "example-plan-2" examplePlanInput2.Name = "Example Plan 2" plan2 := deps.PlanHelper.CreatePlan(t, examplePlanInput2) @@ -1102,7 +1126,9 @@ func TestSubscriptionChangeTrackingAnnotations(t *testing.T) { cust := deps.CustomerAdapter.CreateExampleCustomer(t) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - plan1 := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + plan1 := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) // Create standalone scheduled subscription (can be deleted) futureTime := currentTime.AddDate(0, 1, 0) @@ -1144,7 +1170,9 @@ func TestSubscriptionChangeTrackingAnnotations(t *testing.T) { cust := deps.CustomerAdapter.CreateExampleCustomer(t) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - plan1 := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + plan1 := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) // Create scheduled subscription with nil annotations (can be deleted) futureTime := currentTime.AddDate(0, 1, 0) @@ -1193,7 +1221,7 @@ func TestTaxCodeResolution(t *testing.T) { cust := deps.CustomerAdapter.CreateExampleCustomer(t) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, nil, subscriptiontestutils.WithTaxConfig(stripeTaxConfig))) + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, stripeTaxConfig)) spec, err := subscription.NewSpecFromPlan(plan, subscription.CreateSubscriptionCustomerInput{ CustomerId: cust.ID, @@ -1259,7 +1287,7 @@ func TestTaxCodeResolution(t *testing.T) { cust := deps.CustomerAdapter.CreateExampleCustomer(t) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, nil, subscriptiontestutils.WithTaxConfig(stripeTaxConfig))) + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, stripeTaxConfig)) spec, err := subscription.NewSpecFromPlan(plan, subscription.CreateSubscriptionCustomerInput{ CustomerId: cust.ID, @@ -1530,7 +1558,8 @@ func TestBillingCadenceLegacyFeatureResolution(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) customer := deps.CustomerAdapter.CreateExampleCustomer(t) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - taxConfig := subscriptiontestutils.ExampleTaxConfig(t, deps.TaxCodeEnv) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) rateCard := tc.rateCard(taxConfig) spec, err := subscriptiontestutils.BuildTestSubscriptionSpec(t).AddPhase(nil, rateCard).Build() require.NoError(t, err) diff --git a/openmeter/subscription/service/sync_test.go b/openmeter/subscription/service/sync_test.go index a40a1bb2a0..46692ceeea 100644 --- a/openmeter/subscription/service/sync_test.go +++ b/openmeter/subscription/service/sync_test.go @@ -420,7 +420,9 @@ func TestEdit(t *testing.T) { require.NotNil(t, cust) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) tc.Handler(t, TDeps{ CurrentTime: currentTime, @@ -670,7 +672,9 @@ func TestSyncReconciliation(t *testing.T) { cust := deps.CustomerAdapter.CreateExampleCustomer(t) require.NotNil(t, cust) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) spec, err := subscription.NewSpecFromPlan(plan, subscription.CreateSubscriptionCustomerInput{ Name: "Test", @@ -737,14 +741,16 @@ func TestDeleteScheduledDowngradeCanExpandDeletedSubscriptionForSync(t *testing. deps := subscriptiontestutils.NewService(t, dbDeps) customerEntity := deps.CustomerAdapter.CreateExampleCustomer(t) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) billingAnchor := time.Date(2026, 5, 1, 0, 0, 0, 0, time.UTC) - premiumPlanInput := subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv) + premiumPlanInput := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) premiumPlanInput.Key = "premium-plan" premiumPlanInput.Name = "Premium" premiumPlan := deps.PlanHelper.CreatePlan(t, premiumPlanInput) - basicPlanInput := subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv) + basicPlanInput := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) basicPlanInput.Key = "basic-plan" basicPlanInput.Name = "Basic" basicPlan := deps.PlanHelper.CreatePlan(t, basicPlanInput) diff --git a/openmeter/subscription/testutils/plan.go b/openmeter/subscription/testutils/plan.go index f49584a8ae..18dd8991ca 100644 --- a/openmeter/subscription/testutils/plan.go +++ b/openmeter/subscription/testutils/plan.go @@ -11,41 +11,13 @@ import ( "github.com/openmeterio/openmeter/openmeter/productcatalog/plan" plansubscription "github.com/openmeterio/openmeter/openmeter/productcatalog/subscription" "github.com/openmeterio/openmeter/openmeter/subscription" - taxcodetestutils "github.com/openmeterio/openmeter/openmeter/taxcode/testutils" "github.com/openmeterio/openmeter/openmeter/testutils" "github.com/openmeterio/openmeter/pkg/clock" "github.com/openmeterio/openmeter/pkg/datetime" ) -type examplePlanOptions struct { - taxConfig *productcatalog.TaxConfig -} - -type ExamplePlanOption func(*examplePlanOptions) - -// WithTaxConfig replaces the shared example tax config, for tests that assert on their own tax -// code, the legacy Stripe-only input, or in-memory tests without a tax code env. -func WithTaxConfig(taxConfig productcatalog.TaxConfig) ExamplePlanOption { - return func(o *examplePlanOptions) { - o.taxConfig = &taxConfig - } -} - -// GetExamplePlanInput builds the example plan in ExampleNamespace. Its taxed rate cards use the -// shared example tax code (ExampleTaxConfig) unless WithTaxConfig is given; env may be nil then. -func GetExamplePlanInput(t *testing.T, env *taxcodetestutils.TestEnv, opts ...ExamplePlanOption) plan.CreatePlanInput { - t.Helper() - - var o examplePlanOptions - for _, opt := range opts { - opt(&o) - } - - taxConfig := lo.FromPtr(o.taxConfig) - if o.taxConfig == nil { - taxConfig = ExampleTaxConfig(t, env) - } - +// GetExamplePlanInput builds the example plan in ExampleNamespace; its taxed rate cards carry taxConfig. +func GetExamplePlanInput(t *testing.T, taxConfig productcatalog.TaxConfig) plan.CreatePlanInput { b := BuildTestPlanInput(t) b.AddPhase(lo.ToPtr(datetime.MustParseDuration(t, "P1M")), ExampleRateCard1(taxConfig)) diff --git a/openmeter/subscription/testutils/taxcode.go b/openmeter/subscription/testutils/taxcode.go index 3584585c75..168626f1ef 100644 --- a/openmeter/subscription/testutils/taxcode.go +++ b/openmeter/subscription/testutils/taxcode.go @@ -1,47 +1,25 @@ package subscriptiontestutils import ( - "testing" - "github.com/samber/lo" - "github.com/stretchr/testify/require" "github.com/openmeterio/openmeter/openmeter/app" "github.com/openmeterio/openmeter/openmeter/productcatalog" "github.com/openmeterio/openmeter/openmeter/taxcode" - taxcodetestutils "github.com/openmeterio/openmeter/openmeter/taxcode/testutils" -) - -const ( - ExampleTaxCodeKey = "example" - // ExampleStripeTaxCode is the Stripe code the example rate cards carried before they referenced - // tax codes by ID, so the legacy Stripe path resolves to the same tax code. - ExampleStripeTaxCode = "txcd_10000000" ) -// ExampleTaxConfig returns the tax config of the example rate cards. Every call in a namespace -// shares one tax code: plan versions built from separate calls must compare equal, otherwise -// migrations would split every taxed item. -func ExampleTaxConfig(t *testing.T, env *taxcodetestutils.TestEnv) productcatalog.TaxConfig { - t.Helper() - require.NotNil(t, env, "the example tax code needs a tax code env; pass WithTaxConfig to build without one") - - tc, err := env.Service.GetTaxCodeByKey(t.Context(), taxcode.GetTaxCodeByKeyInput{ - Namespace: ExampleNamespace, - Key: ExampleTaxCodeKey, - }) - if err != nil { - require.True(t, taxcode.IsTaxCodeNotFoundError(err), "getting example tax code: %v", err) - - tc = env.CreateTaxCode(t, ExampleNamespace, taxcode.CreateTaxCodeInput{ - Key: ExampleTaxCodeKey, - Name: "Example", - AppMappings: taxcode.TaxCodeAppMappings{ - {AppType: app.AppTypeStripe, TaxCode: ExampleStripeTaxCode}, - }, - }) +// GetExampleTaxCodeInput is passed to TaxCodeEnv.CreateTaxCode for the example rate cards' tax code. +// The Stripe mapping is the code those rate cards carried before they referenced tax codes by ID. +func GetExampleTaxCodeInput() taxcode.CreateTaxCodeInput { + return taxcode.CreateTaxCodeInput{ + AppMappings: taxcode.TaxCodeAppMappings{ + {AppType: app.AppTypeStripe, TaxCode: "txcd_10000000"}, + }, } +} +// ExampleTaxConfig points rate cards at tc with exclusive tax behavior. +func ExampleTaxConfig(tc taxcode.TaxCode) productcatalog.TaxConfig { return productcatalog.TaxConfig{ TaxCodeID: lo.ToPtr(tc.ID), Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior), diff --git a/openmeter/subscription/workflow/service/addon_test.go b/openmeter/subscription/workflow/service/addon_test.go index b8ba32b3b2..047f02c0b8 100644 --- a/openmeter/subscription/workflow/service/addon_test.go +++ b/openmeter/subscription/workflow/service/addon_test.go @@ -52,10 +52,12 @@ func TestAddAddon(t *testing.T) { } t.Run("Should error on invalid input", runWithDeps(func(t *testing.T, deps subscriptiontestutils.SubscriptionDependencies) { + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) p, add := subscriptiontestutils.CreatePlanWithAddon( t, deps, - subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv), + subscriptiontestutils.GetExamplePlanInput(t, taxConfig), subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ EffectiveFrom: &now, @@ -88,10 +90,12 @@ func TestAddAddon(t *testing.T) { })) t.Run("Should error if the subscription is inactive or in wrong state", runWithDeps(func(t *testing.T, deps subscriptiontestutils.SubscriptionDependencies) { + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) p, add := subscriptiontestutils.CreatePlanWithAddon( t, deps, - subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv), + subscriptiontestutils.GetExamplePlanInput(t, taxConfig), subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ EffectiveFrom: &now, @@ -131,7 +135,8 @@ func TestAddAddon(t *testing.T) { t.Run("Should add a new addon to a subscription that already has a different addon", runWithDeps(func(t *testing.T, deps subscriptiontestutils.SubscriptionDependencies) { _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - taxConfig := subscriptiontestutils.ExampleTaxConfig(t, deps.TaxCodeEnv) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) // Let's create a plan p, err := deps.PlanService.CreatePlan(context.Background(), subscriptiontestutils.BuildTestPlanInput(t). @@ -221,10 +226,12 @@ func TestAddAddon(t *testing.T) { })) t.Run("Should sync subscription with new addons contents", runWithDeps(func(t *testing.T, deps subscriptiontestutils.SubscriptionDependencies) { + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) p, add := subscriptiontestutils.CreatePlanWithAddon( t, deps, - subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv), + subscriptiontestutils.GetExamplePlanInput(t, taxConfig), subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ EffectiveFrom: &now, @@ -278,10 +285,12 @@ func TestAddAddon(t *testing.T) { })) t.Run("Should return conflict error if subscription already has that addon purchased", runWithDeps(func(t *testing.T, deps subscriptiontestutils.SubscriptionDependencies) { + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) p, add := subscriptiontestutils.CreatePlanWithAddon( t, deps, - subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv), + subscriptiontestutils.GetExamplePlanInput(t, taxConfig), subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ EffectiveFrom: &now, @@ -336,10 +345,12 @@ func TestChangeAddonQuantity(t *testing.T) { } t.Run("Should error if SubscriptionAddon and Subscription are in different namespaces", runWithDeps(func(t *testing.T, deps subscriptiontestutils.SubscriptionDependencies) { + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) p, add := subscriptiontestutils.CreatePlanWithAddon( t, deps, - subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv), + subscriptiontestutils.GetExamplePlanInput(t, taxConfig), subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ EffectiveFrom: &now, @@ -384,10 +395,12 @@ func TestChangeAddonQuantity(t *testing.T) { })) t.Run("Should error if SubscriptionAddon doesn't belong to Subscription", runWithDeps(func(t *testing.T, deps subscriptiontestutils.SubscriptionDependencies) { + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) p, add := subscriptiontestutils.CreatePlanWithAddon( t, deps, - subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv), + subscriptiontestutils.GetExamplePlanInput(t, taxConfig), subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ EffectiveFrom: &now, @@ -458,10 +471,12 @@ func TestChangeAddonQuantity(t *testing.T) { })) t.Run("Should error if the subscription is inactive or in wrong state", runWithDeps(func(t *testing.T, deps subscriptiontestutils.SubscriptionDependencies) { + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) p, add := subscriptiontestutils.CreatePlanWithAddon( t, deps, - subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv), + subscriptiontestutils.GetExamplePlanInput(t, taxConfig), subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ EffectiveFrom: &now, @@ -511,7 +526,8 @@ func TestChangeAddonQuantity(t *testing.T) { })) t.Run("Should update the quantity of the addon", runWithDeps(func(t *testing.T, deps subscriptiontestutils.SubscriptionDependencies) { - taxConfig := subscriptiontestutils.ExampleTaxConfig(t, deps.TaxCodeEnv) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) p, add := subscriptiontestutils.CreatePlanWithAddon( t, deps, @@ -566,7 +582,8 @@ func TestChangeAddonQuantity(t *testing.T) { twoMonthsFromNow, _ := twoMonths.AddTo(now) - taxConfig := subscriptiontestutils.ExampleTaxConfig(t, deps.TaxCodeEnv) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) p, add := subscriptiontestutils.CreatePlanWithAddon( t, deps, @@ -698,7 +715,8 @@ func TestAddonCombinations(t *testing.T) { } t.Run("Should handle repeated add/remove of single instance addon with dynamic price", runWithDeps(func(t *testing.T, deps subscriptiontestutils.SubscriptionDependencies) { - taxConfig := subscriptiontestutils.ExampleTaxConfig(t, deps.TaxCodeEnv) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) // Create a plan with mixed rate cards planInput := subscriptiontestutils.BuildTestPlanInput(t). diff --git a/openmeter/subscription/workflow/service/migrate_test.go b/openmeter/subscription/workflow/service/migrate_test.go index 9dc8103305..80fa214bf5 100644 --- a/openmeter/subscription/workflow/service/migrate_test.go +++ b/openmeter/subscription/workflow/service/migrate_test.go @@ -31,7 +31,8 @@ func TestMigrateToPlanAddons(t *testing.T) { db := subscriptiontestutils.SetupDBDeps(t) defer db.Cleanup(t) deps := subscriptiontestutils.NewService(t, db) - taxConfig := subscriptiontestutils.ExampleTaxConfig(t, deps.TaxCodeEnv) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) planInput := subscriptiontestutils.BuildTestPlanInput(t).AddPhase(nil, subscriptiontestutils.ExampleRateCard3ForAddons(taxConfig), subscriptiontestutils.ExampleRateCard2.Clone()).Build() p1, addon := subscriptiontestutils.CreatePlanWithAddon(t, deps, planInput, diff --git a/openmeter/subscription/workflow/service/subscription_test.go b/openmeter/subscription/workflow/service/subscription_test.go index 147577c8b8..6bc28b3349 100644 --- a/openmeter/subscription/workflow/service/subscription_test.go +++ b/openmeter/subscription/workflow/service/subscription_test.go @@ -111,7 +111,9 @@ func TestCreateFromPlan(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) cust := deps.CustomerAdapter.CreateExampleCustomer(t) require.NotNil(t, cust) @@ -137,7 +139,8 @@ func TestCreateFromPlan(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - taxConfig := subscriptiontestutils.ExampleTaxConfig(t, deps.TaxCodeEnv) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) p := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.BuildTestPlanInput(t). AddPhase(nil, subscriptiontestutils.ExampleRateCard3ForAddons(taxConfig), subscriptiontestutils.ExampleRateCard4ForAddons.Clone()). Build()) @@ -641,7 +644,9 @@ func TestEditRunning(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) features := deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) cust := deps.CustomerAdapter.CreateExampleCustomer(t) require.NotNil(t, cust) @@ -840,7 +845,9 @@ func TestEditingCurrentPhase(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) cust := deps.CustomerAdapter.CreateExampleCustomer(t) require.NotNil(t, cust) @@ -1080,7 +1087,9 @@ func TestEditingWithTiming(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - planInput := subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + planInput := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) plan := deps.PlanHelper.CreatePlan(t, planInput) cust := deps.CustomerAdapter.CreateExampleCustomer(t) @@ -1141,11 +1150,12 @@ func TestChangeToPlan(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - taxConfig := subscriptiontestutils.ExampleTaxConfig(t, deps.TaxCodeEnv) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) // Let's define two plans. One is the example plan, and the second is a slightly modified version of that. // Build them per invocation so plan service mutations (e.g. resolving TaxCodeIDs) don't leak across subtests. - examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv) + examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) // Plan 2's new rate cards use a different tax code than the example plan. plan2TaxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace) @@ -1336,8 +1346,9 @@ func TestEditCombinations(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - taxConfig := subscriptiontestutils.ExampleTaxConfig(t, deps.TaxCodeEnv) - examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) // Let's create the plan plan1 := deps.PlanHelper.CreatePlan(t, examplePlanInput1) @@ -1368,11 +1379,13 @@ func TestEditCombinations(t *testing.T) { defer dbDeps.Cleanup(t) deps := subscriptiontestutils.NewService(t, dbDeps) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) p, add := subscriptiontestutils.CreatePlanWithAddon( t, deps, - subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv), + subscriptiontestutils.GetExamplePlanInput(t, taxConfig), subscriptiontestutils.BuildAddonForTesting( t, productcatalog.EffectivePeriod{ @@ -1709,7 +1722,9 @@ func TestRestore(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) // Let's create the plan plan1 := deps.PlanHelper.CreatePlan(t, examplePlanInput1) @@ -1898,7 +1913,9 @@ func TestMultiSubscription(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) // Let's create the plan plan1 := deps.PlanHelper.CreatePlan(t, examplePlanInput1) @@ -2093,8 +2110,10 @@ func TestSubscriptionChangeTrackingAnnotations(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv) - examplePlanInput2 := subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + examplePlanInput1 := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) + examplePlanInput2 := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) examplePlanInput2.Key = "example-plan-2" examplePlanInput2.Name = "Example Plan 2" @@ -2281,7 +2300,9 @@ func TestSettlementMode(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - p := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + p := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) cust := deps.CustomerAdapter.CreateExampleCustomer(t) subView, err := deps.WorkflowService.CreateFromPlan(context.Background(), subscriptionworkflow.CreateSubscriptionWorkflowInput{ @@ -2312,7 +2333,9 @@ func TestSettlementMode(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - planInput := subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + planInput := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) planInput.SettlementMode = productcatalog.CreditOnlySettlementMode p := deps.PlanHelper.CreatePlan(t, planInput) cust := deps.CustomerAdapter.CreateExampleCustomer(t) @@ -2346,7 +2369,8 @@ func TestSettlementMode(t *testing.T) { deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) cust := deps.CustomerAdapter.CreateExampleCustomer(t) - taxConfig := subscriptiontestutils.ExampleTaxConfig(t, deps.TaxCodeEnv) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) spec, err := subscriptiontestutils.BuildTestSubscriptionSpec(t). AddPhase(nil, subscriptiontestutils.ExampleRateCard1(taxConfig)). Build() @@ -2385,7 +2409,9 @@ func TestSettlementMode(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - p := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + p := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) cust := deps.CustomerAdapter.CreateExampleCustomer(t) subView, err := deps.WorkflowService.CreateFromPlan(context.Background(), subscriptionworkflow.CreateSubscriptionWorkflowInput{ @@ -2438,7 +2464,9 @@ func TestSettlementMode(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - planInput := subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + planInput := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) planInput.SettlementMode = productcatalog.CreditOnlySettlementMode p := deps.PlanHelper.CreatePlan(t, planInput) cust := deps.CustomerAdapter.CreateExampleCustomer(t) @@ -2469,7 +2497,9 @@ func TestSettlementMode(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - planInput := subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + planInput := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) planInput.SettlementMode = productcatalog.CreditOnlySettlementMode p := deps.PlanHelper.CreatePlan(t, planInput) cust := deps.CustomerAdapter.CreateExampleCustomer(t) @@ -2500,9 +2530,11 @@ func TestSettlementMode(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - basePlan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + basePlan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, taxConfig)) - creditOnlyPlanInput := subscriptiontestutils.GetExamplePlanInput(t, deps.TaxCodeEnv) + creditOnlyPlanInput := subscriptiontestutils.GetExamplePlanInput(t, taxConfig) creditOnlyPlanInput.Key = "credit_only_plan" creditOnlyPlanInput.SettlementMode = productcatalog.CreditOnlySettlementMode creditOnlyPlan := deps.PlanHelper.CreatePlan(t, creditOnlyPlanInput) @@ -2559,7 +2591,8 @@ func TestCreateFromPlanSnapshotsUnitConfig(t *testing.T) { Rounding: productcatalog.UnitConfigRoundingModeCeiling, } - taxConfig := subscriptiontestutils.ExampleTaxConfig(t, deps.TaxCodeEnv) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) // ExampleRateCard1 is usage-based with a UnitPrice, which supports unit_config. rc := subscriptiontestutils.ExampleRateCard1(taxConfig) diff --git a/test/subscription/migrate_phases_test.go b/test/subscription/migrate_phases_test.go index 3dfbb0072d..03710db570 100644 --- a/test/subscription/migrate_phases_test.go +++ b/test/subscription/migrate_phases_test.go @@ -221,7 +221,8 @@ func TestMigrationStartingPhaseDoesNotTransferAddons(t *testing.T) { deps := setup(t, setupConfig{}) defer deps.cleanup(t) - taxConfig := subscriptiontestutils.ExampleTaxConfig(t, deps.TaxCodeEnv) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) input := subscriptiontestutils.BuildTestPlanInput(t).AddPhase(nil, subscriptiontestutils.ExampleRateCard1(taxConfig), subscriptiontestutils.ExampleRateCard2.Clone()).Build() original, addon := subscriptiontestutils.CreatePlanWithAddon(t, deps.SubscriptionDependencies, input, diff --git a/test/subscription/migrate_test.go b/test/subscription/migrate_test.go index 2ac694264d..7d0a8224be 100644 --- a/test/subscription/migrate_test.go +++ b/test/subscription/migrate_test.go @@ -334,7 +334,8 @@ func newMigrationFixtureWithPlan(t *testing.T, buildPlan func(taxConfig productc deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) customer := deps.CustomerAdapter.CreateExampleCustomer(t) - taxConfig := subscriptiontestutils.ExampleTaxConfig(t, deps.TaxCodeEnv) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) original := deps.PlanHelper.CreatePlan(t, buildPlan(taxConfig)) before, err := deps.WorkflowService.CreateFromPlan(t.Context(), subscriptionworkflow.CreateSubscriptionWorkflowInput{ diff --git a/test/subscription/scenario_editaligned_test.go b/test/subscription/scenario_editaligned_test.go index 29dbed989f..2da2f421e1 100644 --- a/test/subscription/scenario_editaligned_test.go +++ b/test/subscription/scenario_editaligned_test.go @@ -49,7 +49,8 @@ func TestEditingEntitlementOfAlignedSub(t *testing.T) { }) require.NoError(t, err) - taxConfig := subscriptiontestutils.ExampleTaxConfig(t, tDeps.TaxCodeEnv) + taxCode := tDeps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) // 2nd, let's create the plan p, err := tDeps.PlanService.CreatePlan(ctx, plan.CreatePlanInput{ diff --git a/test/subscription/scenario_editcancel_test.go b/test/subscription/scenario_editcancel_test.go index c3b882cfa1..c6c15870e6 100644 --- a/test/subscription/scenario_editcancel_test.go +++ b/test/subscription/scenario_editcancel_test.go @@ -50,7 +50,8 @@ func TestEditingAndCanceling(t *testing.T) { }) require.NoError(t, err) - taxConfig := subscriptiontestutils.ExampleTaxConfig(t, tDeps.TaxCodeEnv) + taxCode := tDeps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) // Second, let's create the plan p, err := tDeps.PlanService.CreatePlan(ctx, plan.CreatePlanInput{ diff --git a/test/subscription/scenario_entinnextphase_test.go b/test/subscription/scenario_entinnextphase_test.go index eb0ca01d8d..17578b329d 100644 --- a/test/subscription/scenario_entinnextphase_test.go +++ b/test/subscription/scenario_entinnextphase_test.go @@ -42,7 +42,8 @@ func TestSubWithMeteredEntitlement(t *testing.T) { feats := tDeps.FeatureConnector.CreateExampleFeatures(t, tDeps.ExampleMeterID) require.Len(t, feats, 3) - taxConfig := subscriptiontestutils.ExampleTaxConfig(t, tDeps.TaxCodeEnv) + taxCode := tDeps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) // 2nd, let's create the plan p, err := tDeps.PlanService.CreatePlan(ctx, plan.CreatePlanInput{ diff --git a/test/subscription/scenario_firstofmonth_test.go b/test/subscription/scenario_firstofmonth_test.go index 7a728eab98..f488c1dd5f 100644 --- a/test/subscription/scenario_firstofmonth_test.go +++ b/test/subscription/scenario_firstofmonth_test.go @@ -47,7 +47,8 @@ func TestBillingOnFirstOfMonth(t *testing.T) { feats := tDeps.FeatureConnector.CreateExampleFeatures(t, tDeps.ExampleMeterID) require.Len(t, feats, 3) - taxConfig := subscriptiontestutils.ExampleTaxConfig(t, tDeps.TaxCodeEnv) + taxCode := tDeps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) // 2nd, let's create the plan p, err := tDeps.PlanService.CreatePlan(ctx, plan.CreatePlanInput{ From 3a7135380ac1ee4798028565e2f8e4bc7fd92774 Mon Sep 17 00:00:00 2001 From: Robert Borbely Date: Wed, 28 Oct 2026 12:03:11 +0100 Subject: [PATCH 4/8] refactor(test): create example tax codes inside addon diff subtests Each subtest sets up its own data, so the tax code is created where the taxed rate cards are built instead of in the shared tcDeps wrapper. --- .../subscription/addon/diff/apply_test.go | 89 ++++++++++++------- .../subscription/addon/diff/restore_test.go | 54 +++++++---- 2 files changed, 94 insertions(+), 49 deletions(-) diff --git a/openmeter/subscription/addon/diff/apply_test.go b/openmeter/subscription/addon/diff/apply_test.go index 8fb7755db4..5e98ac2981 100644 --- a/openmeter/subscription/addon/diff/apply_test.go +++ b/openmeter/subscription/addon/diff/apply_test.go @@ -31,8 +31,7 @@ var now, _ = time.Parse(time.RFC3339, "2025-04-01T00:00:00Z") func TestApply(t *testing.T) { type tcDeps struct { - deps subscriptiontestutils.SubscriptionDependencies - taxConfig productcatalog.TaxConfig + deps subscriptiontestutils.SubscriptionDependencies } // TODO: we could write purer tests here (without depending on the services) but this is simply more convenient for now @@ -48,21 +47,20 @@ func TestApply(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) - taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) - fn(t, &tcDeps{ - deps: deps, - taxConfig: taxConfig, + deps: deps, }) } t.Run("Should return nil when there's no quantities listed", func(t *testing.T) { runWithDeps(t, func(t *testing.T, deps *tcDeps) { + taxCode := deps.deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + p, a := subscriptiontestutils.CreatePlanWithAddon( t, deps.deps, - subscriptiontestutils.GetExamplePlanInput(t, deps.taxConfig), + subscriptiontestutils.GetExamplePlanInput(t, taxConfig), subscriptiontestutils.GetExampleAddonInput(t, productcatalog.EffectivePeriod{ EffectiveFrom: &now, EffectiveTo: nil, @@ -88,10 +86,13 @@ func TestApply(t *testing.T) { t.Run("Should add the new item to the subscription", func(t *testing.T) { runWithDeps(t, func(t *testing.T, deps *tcDeps) { + taxCode := deps.deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + p, a := subscriptiontestutils.CreatePlanWithAddon( t, deps.deps, - subscriptiontestutils.GetExamplePlanInput(t, deps.taxConfig), + subscriptiontestutils.GetExamplePlanInput(t, taxConfig), subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ EffectiveFrom: &now, @@ -148,10 +149,13 @@ func TestApply(t *testing.T) { t.Run("Should materialize the addon currency on new priced items", func(t *testing.T) { runWithDeps(t, func(t *testing.T, deps *tcDeps) { + taxCode := deps.deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + p, a := subscriptiontestutils.CreatePlanWithAddon( t, deps.deps, - subscriptiontestutils.GetExamplePlanInput(t, deps.taxConfig), + subscriptiontestutils.GetExamplePlanInput(t, taxConfig), subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ EffectiveFrom: &now, @@ -302,13 +306,16 @@ func TestApply(t *testing.T) { t.Run("Should add multiple instances of new item to the subscription", func(t *testing.T) { runWithDeps(t, func(t *testing.T, deps *tcDeps) { + taxCode := deps.deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + exampleAddonRateCard3, ok := subscriptiontestutils.ExampleAddonRateCard3.Clone().(*productcatalog.FlatFeeRateCard) require.True(t, ok, "expected FlatFeeRateCard, got %T", exampleAddonRateCard3) p, a := subscriptiontestutils.CreatePlanWithAddon( t, deps.deps, - subscriptiontestutils.GetExamplePlanInput(t, deps.taxConfig), + subscriptiontestutils.GetExamplePlanInput(t, taxConfig), subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ EffectiveFrom: &now, @@ -377,6 +384,9 @@ func TestApply(t *testing.T) { t.Run("Should add item for defined cadence of the addon", func(t *testing.T) { runWithDeps(t, func(t *testing.T, deps *tcDeps) { + taxCode := deps.deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + effPer := productcatalog.EffectivePeriod{ EffectiveFrom: lo.ToPtr(now), } @@ -384,7 +394,7 @@ func TestApply(t *testing.T) { p, a := subscriptiontestutils.CreatePlanWithAddon( t, deps.deps, - subscriptiontestutils.GetExamplePlanInput(t, deps.taxConfig), + subscriptiontestutils.GetExamplePlanInput(t, taxConfig), subscriptiontestutils.BuildAddonForTesting(t, effPer, productcatalog.AddonInstanceTypeSingle, @@ -551,6 +561,9 @@ func TestApply(t *testing.T) { t.Run("Should update an existing Item that fills its entire phase", func(t *testing.T) { runWithDeps(t, func(t *testing.T, deps *tcDeps) { + taxCode := deps.deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + effPer := productcatalog.EffectivePeriod{ EffectiveFrom: lo.ToPtr(now.AddDate(0, 0, 0)), EffectiveTo: nil, @@ -560,8 +573,8 @@ func TestApply(t *testing.T) { t, deps.deps, subscriptiontestutils.BuildTestPlanInput(t). - AddPhase(lo.ToPtr(datetime.MustParseDuration(t, "P1M")), subscriptiontestutils.ExampleRateCard3ForAddons(deps.taxConfig)). - AddPhase(nil, subscriptiontestutils.ExampleRateCard3ForAddons(deps.taxConfig)). + AddPhase(lo.ToPtr(datetime.MustParseDuration(t, "P1M")), subscriptiontestutils.ExampleRateCard3ForAddons(taxConfig)). + AddPhase(nil, subscriptiontestutils.ExampleRateCard3ForAddons(taxConfig)). Build(), subscriptiontestutils.BuildAddonForTesting(t, effPer, @@ -572,7 +585,7 @@ func TestApply(t *testing.T) { subView := subscriptiontestutils.CreateSubscriptionFromPlan(t, &deps.deps, p, now) - rc3 := withCurrency(subscriptiontestutils.ExampleRateCard3ForAddons(deps.taxConfig), currency.USD) + rc3 := withCurrency(subscriptiontestutils.ExampleRateCard3ForAddons(taxConfig), currency.USD) subsAdd := subscriptiontestutils.CreateAddonForSubscription(t, &deps.deps, subView.Subscription.NamespacedID, a.NamespacedID, models.CadencedModel{ ActiveFrom: *effPer.EffectiveFrom, @@ -609,6 +622,9 @@ func TestApply(t *testing.T) { t.Run("Should partially update an existing item in accordance with the cadence", func(t *testing.T) { runWithDeps(t, func(t *testing.T, deps *tcDeps) { + taxCode := deps.deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + effPer := productcatalog.EffectivePeriod{ EffectiveFrom: lo.ToPtr(now), EffectiveTo: nil, @@ -618,8 +634,8 @@ func TestApply(t *testing.T) { t, deps.deps, subscriptiontestutils.BuildTestPlanInput(t). - AddPhase(lo.ToPtr(datetime.MustParseDuration(t, "P1M")), subscriptiontestutils.ExampleRateCard3ForAddons(deps.taxConfig)). - AddPhase(nil, subscriptiontestutils.ExampleRateCard3ForAddons(deps.taxConfig)). + AddPhase(lo.ToPtr(datetime.MustParseDuration(t, "P1M")), subscriptiontestutils.ExampleRateCard3ForAddons(taxConfig)). + AddPhase(nil, subscriptiontestutils.ExampleRateCard3ForAddons(taxConfig)). Build(), subscriptiontestutils.BuildAddonForTesting(t, effPer, @@ -630,7 +646,7 @@ func TestApply(t *testing.T) { subView := subscriptiontestutils.CreateSubscriptionFromPlan(t, &deps.deps, p, now) - rc3 := withCurrency(subscriptiontestutils.ExampleRateCard3ForAddons(deps.taxConfig), currency.USD) + rc3 := withCurrency(subscriptiontestutils.ExampleRateCard3ForAddons(taxConfig), currency.USD) subsAdd := subscriptiontestutils.CreateAddonForSubscription(t, &deps.deps, subView.Subscription.NamespacedID, a.NamespacedID, models.CadencedModel{ ActiveFrom: now.AddDate(0, 0, 5), @@ -677,6 +693,9 @@ func TestApply(t *testing.T) { t.Run("Should partially update an existing item in accordance with the cadence - but for multi instance", func(t *testing.T) { runWithDeps(t, func(t *testing.T, deps *tcDeps) { + taxCode := deps.deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + effPer := productcatalog.EffectivePeriod{ EffectiveFrom: lo.ToPtr(now), EffectiveTo: nil, @@ -686,8 +705,8 @@ func TestApply(t *testing.T) { t, deps.deps, subscriptiontestutils.BuildTestPlanInput(t). - AddPhase(lo.ToPtr(datetime.MustParseDuration(t, "P1M")), subscriptiontestutils.ExampleRateCard3ForAddons(deps.taxConfig)). - AddPhase(nil, subscriptiontestutils.ExampleRateCard3ForAddons(deps.taxConfig)). + AddPhase(lo.ToPtr(datetime.MustParseDuration(t, "P1M")), subscriptiontestutils.ExampleRateCard3ForAddons(taxConfig)). + AddPhase(nil, subscriptiontestutils.ExampleRateCard3ForAddons(taxConfig)). Build(), subscriptiontestutils.BuildAddonForTesting(t, effPer, @@ -698,7 +717,7 @@ func TestApply(t *testing.T) { subView := subscriptiontestutils.CreateSubscriptionFromPlan(t, &deps.deps, p, now) - rc3 := withCurrency(subscriptiontestutils.ExampleRateCard3ForAddons(deps.taxConfig), currency.USD) + rc3 := withCurrency(subscriptiontestutils.ExampleRateCard3ForAddons(taxConfig), currency.USD) subsAdd := subscriptiontestutils.CreateAddonForSubscription(t, &deps.deps, subView.Subscription.NamespacedID, a.NamespacedID, models.CadencedModel{ ActiveFrom: now.AddDate(0, 0, 5), @@ -773,6 +792,9 @@ func TestApply(t *testing.T) { t.Run("Should guarantee access is continuous across changing items", func(t *testing.T) { runWithDeps(t, func(t *testing.T, deps *tcDeps) { + taxCode := deps.deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + t0 := now clock.FreezeTime(t0.Add(time.Millisecond)) // Addons are written so that effective period is exclusive on both ends :) @@ -799,7 +821,7 @@ func TestApply(t *testing.T) { t, deps.deps, subscriptiontestutils.BuildTestPlanInput(t). - AddPhase(nil, subscriptiontestutils.ExampleRateCard3ForAddons(deps.taxConfig)). + AddPhase(nil, subscriptiontestutils.ExampleRateCard3ForAddons(taxConfig)). Build(), subscriptiontestutils.BuildAddonForTesting(t, effPer, @@ -899,6 +921,9 @@ func TestApply(t *testing.T) { t.Run("Should create multiple rate cards in the addon", func(t *testing.T) { runWithDeps(t, func(t *testing.T, deps *tcDeps) { + taxCode := deps.deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + // we'll reuse this for subsadd cadence too effPer := productcatalog.EffectivePeriod{ EffectiveFrom: lo.ToPtr(now), @@ -909,7 +934,7 @@ func TestApply(t *testing.T) { t, deps.deps, subscriptiontestutils.BuildTestPlanInput(t). - AddPhase(nil, subscriptiontestutils.ExampleRateCard3ForAddons(deps.taxConfig)). + AddPhase(nil, subscriptiontestutils.ExampleRateCard3ForAddons(taxConfig)). Build(), subscriptiontestutils.BuildAddonForTesting(t, effPer, @@ -921,7 +946,7 @@ func TestApply(t *testing.T) { subView := subscriptiontestutils.CreateSubscriptionFromPlan(t, &deps.deps, pl, now) - rc3 := withCurrency(subscriptiontestutils.ExampleRateCard3ForAddons(deps.taxConfig), currency.USD) + rc3 := withCurrency(subscriptiontestutils.ExampleRateCard3ForAddons(taxConfig), currency.USD) subAdd := subscriptiontestutils.CreateAddonForSubscription(t, &deps.deps, subView.Subscription.NamespacedID, a.NamespacedID, models.CadencedModel{ ActiveFrom: *effPer.EffectiveFrom, @@ -973,8 +998,7 @@ func TestApply(t *testing.T) { func TestApplyWithMultiInstance(t *testing.T) { type tcDeps struct { - deps subscriptiontestutils.SubscriptionDependencies - taxConfig productcatalog.TaxConfig + deps subscriptiontestutils.SubscriptionDependencies } runWithDeps := func(t *testing.T, fn func(t *testing.T, deps *tcDeps)) { @@ -989,17 +1013,16 @@ func TestApplyWithMultiInstance(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) - taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) - fn(t, &tcDeps{ - deps: deps, - taxConfig: taxConfig, + deps: deps, }) } t.Run("Should create items in phase according to quantities", func(t *testing.T) { runWithDeps(t, func(t *testing.T, deps *tcDeps) { + taxCode := deps.deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + t0 := now t1 := t0.AddDate(0, 0, 1) @@ -1015,7 +1038,7 @@ func TestApplyWithMultiInstance(t *testing.T) { t, deps.deps, subscriptiontestutils.BuildTestPlanInput(t). - AddPhase(nil, subscriptiontestutils.ExampleRateCard3ForAddons(deps.taxConfig)). + AddPhase(nil, subscriptiontestutils.ExampleRateCard3ForAddons(taxConfig)). Build(), subscriptiontestutils.BuildAddonForTesting(t, effPer, @@ -1026,7 +1049,7 @@ func TestApplyWithMultiInstance(t *testing.T) { subView := subscriptiontestutils.CreateSubscriptionFromPlan(t, &deps.deps, pl, now) - rc3 := withCurrency(subscriptiontestutils.ExampleRateCard3ForAddons(deps.taxConfig), currency.USD) + rc3 := withCurrency(subscriptiontestutils.ExampleRateCard3ForAddons(taxConfig), currency.USD) subAdd := subscriptiontestutils.CreateMultiInstanceAddonForSubscription(t, &deps.deps, subView.Subscription.NamespacedID, a.NamespacedID, []subscriptionaddon.CreateSubscriptionAddonQuantityInput{ { diff --git a/openmeter/subscription/addon/diff/restore_test.go b/openmeter/subscription/addon/diff/restore_test.go index eb53058a9b..526102fcad 100644 --- a/openmeter/subscription/addon/diff/restore_test.go +++ b/openmeter/subscription/addon/diff/restore_test.go @@ -27,8 +27,7 @@ import ( func TestRestore(t *testing.T) { type tcDeps struct { - deps subscriptiontestutils.SubscriptionDependencies - taxConfig productcatalog.TaxConfig + deps subscriptiontestutils.SubscriptionDependencies } withDeps := func(fn func(t *testing.T, deps *tcDeps)) func(t *testing.T) { @@ -44,12 +43,8 @@ func TestRestore(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) - taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) - taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) - fn(t, &tcDeps{ - deps: deps, - taxConfig: taxConfig, + deps: deps, }) } } @@ -112,6 +107,9 @@ func TestRestore(t *testing.T) { })) t.Run("Should delete a single RateCard that was created by the addon and leave in place the RateCard with the same key as that was part of the subscription", withDeps(func(t *testing.T, deps *tcDeps) { + taxCode := deps.deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + oneMonth := datetime.MustParseDuration(t, "P1M") oneMonthLater, _ := oneMonth.AddTo(now) @@ -119,7 +117,7 @@ func TestRestore(t *testing.T) { env := buildSubAndAddon( t, &deps.deps, - subscriptiontestutils.BuildTestPlanInput(t).AddPhase(nil, subscriptiontestutils.ExampleRateCard1(deps.taxConfig), subscriptiontestutils.ExampleRateCard2.Clone()).Build(), + subscriptiontestutils.BuildTestPlanInput(t).AddPhase(nil, subscriptiontestutils.ExampleRateCard1(taxConfig), subscriptiontestutils.ExampleRateCard2.Clone()).Build(), subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ EffectiveFrom: &now, }, productcatalog.AddonInstanceTypeSingle, subscriptiontestutils.ExampleAddonRateCard1.Clone()), @@ -148,6 +146,9 @@ func TestRestore(t *testing.T) { })) t.Run("Should delete a single RateCard from a phase where it was created by the addon but leave RateCard with same key in another phase where it was already present", withDeps(func(t *testing.T, deps *tcDeps) { + taxCode := deps.deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + oneMonth := datetime.MustParseDuration(t, "P1M") oneMonthLater, _ := oneMonth.AddTo(now) @@ -156,7 +157,7 @@ func TestRestore(t *testing.T) { t, &deps.deps, subscriptiontestutils.BuildTestPlanInput(t). - AddPhase(&oneMonth, subscriptiontestutils.ExampleRateCard1(deps.taxConfig), subscriptiontestutils.ExampleRateCard2.Clone()). + AddPhase(&oneMonth, subscriptiontestutils.ExampleRateCard1(taxConfig), subscriptiontestutils.ExampleRateCard2.Clone()). AddPhase(nil, subscriptiontestutils.ExampleRateCard2.Clone()). Build(), subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ @@ -183,11 +184,14 @@ func TestRestore(t *testing.T) { })) t.Run("Should restore a single RateCard by undoing the effects of the addon RateCard restoring original entitlement template", withDeps(func(t *testing.T, deps *tcDeps) { + taxCode := deps.deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + env := buildSubAndAddon( t, &deps.deps, subscriptiontestutils.BuildTestPlanInput(t). - AddPhase(nil, subscriptiontestutils.ExampleRateCard1(deps.taxConfig)). + AddPhase(nil, subscriptiontestutils.ExampleRateCard1(taxConfig)). Build(), subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ EffectiveFrom: &now, @@ -213,13 +217,16 @@ func TestRestore(t *testing.T) { })) t.Run("Should restore a single RateCard and delete subsequent created RateCards", withDeps(func(t *testing.T, deps *tcDeps) { + taxCode := deps.deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + oneMonth := datetime.MustParseDuration(t, "P1M") env := buildSubAndAddon( t, &deps.deps, subscriptiontestutils.BuildTestPlanInput(t). - AddPhase(nil, subscriptiontestutils.ExampleRateCard1(deps.taxConfig)). + AddPhase(nil, subscriptiontestutils.ExampleRateCard1(taxConfig)). Build(), subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ EffectiveFrom: &now, @@ -249,6 +256,9 @@ func TestRestore(t *testing.T) { })) t.Run("Should restore a single RateCard and then delete it in the later step", withDeps(func(t *testing.T, deps *tcDeps) { + taxCode := deps.deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + // First we add apply an AddonRateCard once, // then twice, // then remove it once, (which should leave the first addition in place) @@ -259,7 +269,7 @@ func TestRestore(t *testing.T) { t, &deps.deps, subscriptiontestutils.BuildTestPlanInput(t). - AddPhase(nil, subscriptiontestutils.ExampleRateCard1(deps.taxConfig)). + AddPhase(nil, subscriptiontestutils.ExampleRateCard1(taxConfig)). Build(), subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ EffectiveFrom: &now, @@ -308,6 +318,9 @@ func TestRestore(t *testing.T) { })) t.Run("Should re-combine single split item when restoring", withDeps(func(t *testing.T, deps *tcDeps) { + taxCode := deps.deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + oneMonth := datetime.MustParseDuration(t, "P1M") oneMonthLater, _ := oneMonth.AddTo(now) @@ -316,7 +329,7 @@ func TestRestore(t *testing.T) { t, &deps.deps, subscriptiontestutils.BuildTestPlanInput(t). - AddPhase(nil, subscriptiontestutils.ExampleRateCard1(deps.taxConfig)). + AddPhase(nil, subscriptiontestutils.ExampleRateCard1(taxConfig)). Build(), subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ EffectiveFrom: &now, @@ -343,6 +356,9 @@ func TestRestore(t *testing.T) { })) t.Run("Should not recombine different original items into one", withDeps(func(t *testing.T, deps *tcDeps) { + taxCode := deps.deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + twoMonths := datetime.MustParseDuration(t, "P2M") twoMonthsLater, _ := twoMonths.AddTo(now) @@ -364,7 +380,7 @@ func TestRestore(t *testing.T) { }, SettlementMode: productcatalog.CreditThenInvoiceSettlementMode, }). - AddPhase(nil, subscriptiontestutils.ExampleRateCard1(deps.taxConfig)). + AddPhase(nil, subscriptiontestutils.ExampleRateCard1(taxConfig)). Build(), subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ EffectiveFrom: &now, @@ -513,11 +529,14 @@ func TestRestore(t *testing.T) { }) t.Run("Should respect addon quantity when restoring", withDeps(func(t *testing.T, deps *tcDeps) { + taxCode := deps.deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + env := buildSubAndMultiInstanceAddon( t, &deps.deps, subscriptiontestutils.BuildTestPlanInput(t). - AddPhase(nil, subscriptiontestutils.ExampleRateCard1(deps.taxConfig)). + AddPhase(nil, subscriptiontestutils.ExampleRateCard1(taxConfig)). Build(), subscriptiontestutils.BuildAddonForTesting(t, productcatalog.EffectivePeriod{ EffectiveFrom: &now, @@ -559,6 +578,9 @@ func TestRestore(t *testing.T) { })) t.Run("Should apply and remove same single instance addon 4 times in a row with slightly progressive times", withDeps(func(t *testing.T, deps *tcDeps) { + taxCode := deps.deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + taxConfig := subscriptiontestutils.ExampleTaxConfig(taxCode) + // We will set up a subscriptionAddon which has a series of quantities set: // 1st, single quantity with 1 at t1 // 2nd, two quantities, second with 0 at t2 @@ -577,7 +599,7 @@ func TestRestore(t *testing.T) { deps.deps, subscriptiontestutils.BuildTestPlanInput(t). AddPhase(nil, - subscriptiontestutils.ExampleRateCard1(deps.taxConfig), // Flat price + subscriptiontestutils.ExampleRateCard1(taxConfig), // Flat price &productcatalog.UsageBasedRateCard{ // Dynamic price RateCardMeta: productcatalog.RateCardMeta{ Key: subscriptiontestutils.ExampleFeatureKey2, From bc5f5a6b176b4d445c7a2178e930e1e03d48b781 Mon Sep 17 00:00:00 2001 From: Robert Borbely Date: Fri, 30 Oct 2026 12:35:30 +0100 Subject: [PATCH 5/8] test(subscription): compare stored Stripe tax codes when the expected spec has one --- .../subscription/addon/diff/apply_test.go | 18 +---- openmeter/subscription/testutils/compare.go | 72 ++++++++++--------- openmeter/subscription/testutils/ratecard.go | 4 ++ 3 files changed, 45 insertions(+), 49 deletions(-) diff --git a/openmeter/subscription/addon/diff/apply_test.go b/openmeter/subscription/addon/diff/apply_test.go index 5e98ac2981..096a96a2c1 100644 --- a/openmeter/subscription/addon/diff/apply_test.go +++ b/openmeter/subscription/addon/diff/apply_test.go @@ -1124,18 +1124,6 @@ func featureReferenceWithoutID(meta productcatalog.RateCardMeta) (productcatalog return meta, nil } -// The services fill in the Stripe code from the tax code's app mapping, so expected rate cards -// built from a TaxCodeID-only config compare by TaxCodeID and Behavior. -func withoutStripeTaxCode(meta productcatalog.RateCardMeta) (productcatalog.RateCardMeta, error) { - if meta.TaxConfig != nil { - taxConfig := meta.TaxConfig.Clone() - taxConfig.Stripe = nil - meta.TaxConfig = &taxConfig - } - - return meta, nil -} - func compareRateCardsWithAmountChange(t *testing.T, baseTarget *productcatalog.FlatFeeRateCard, targetAmount int, value productcatalog.RateCard, msgAndArgs ...interface{}) { t.Helper() @@ -1158,16 +1146,14 @@ func compareRateCardsWithAmountChange(t *testing.T, baseTarget *productcatalog.F left := target.Clone() require.NoError(t, left.ChangeMeta(featureReferenceWithoutID)) - require.NoError(t, left.ChangeMeta(withoutStripeTaxCode)) right := value.Clone() require.NoError(t, right.ChangeMeta(featureReferenceWithoutID)) - require.NoError(t, right.ChangeMeta(withoutStripeTaxCode)) if len(msgAndArgs) > 0 { customMsg := fmt.Sprintf(msgAndArgs[0].(string), msgAndArgs[1:]...) - require.True(t, left.Equal(right), "%s: %s", customMsg, msgX) + require.True(t, subscriptiontestutils.RateCardsEqual(left, right), "%s: %s", customMsg, msgX) } else { - require.True(t, left.Equal(right), msgX) + require.True(t, subscriptiontestutils.RateCardsEqual(left, right), msgX) } } diff --git a/openmeter/subscription/testutils/compare.go b/openmeter/subscription/testutils/compare.go index c7f8c8f011..522513205f 100644 --- a/openmeter/subscription/testutils/compare.go +++ b/openmeter/subscription/testutils/compare.go @@ -77,15 +77,11 @@ func ValidateSpecAndView(t *testing.T, expected subscription.SubscriptionSpec, f assert.Equal(t, foundPhase.SubscriptionPhase.Key, specItem.PhaseKey) assert.Equal(t, foundPhase.SubscriptionPhase.ID, foundItem.SubscriptionItem.PhaseId) - // Let's validate the RateCard is equal. Tax is compared by TaxCodeID (and Behavior): - // the Stripe code is a legacy encoding derived from the tax code, not part of the intent. - specRateCard := withoutStripeTaxCode(t, specItem.RateCard) - foundRateCard := withoutStripeTaxCode(t, foundItem.SubscriptionItem.RateCard) + // Let's validate the RateCard is equal + rc1JSON, _ := json.Marshal(specItem.RateCard) + rc2JSON, _ := json.Marshal(foundItem.SubscriptionItem.RateCard) - rc1JSON, _ := json.Marshal(specRateCard) - rc2JSON, _ := json.Marshal(foundRateCard) - - assert.True(t, specRateCard.Equal(foundRateCard), "rate card mismatch for item %s in phase %s: \nspec: %s \n\nview: %s", specItem.ItemKey, specPhase.PhaseKey, rc1JSON, rc2JSON) + assert.True(t, RateCardsEqual(specItem.RateCard, foundItem.SubscriptionItem.RateCard), "rate card mismatch for item %s in phase %s: \nspec: %s \n\nview: %s", specItem.ItemKey, specPhase.PhaseKey, rc1JSON, rc2JSON) // Let's validate the Feature linking var expectedFeatureKey, actualFeatureKey *string @@ -161,6 +157,7 @@ func ValidateSpecAndView(t *testing.T, expected subscription.SubscriptionSpec, f } } +// SpecsEqual treats s1 as the expected spec; see RateCardsEqual. func SpecsEqual(t *testing.T, s1, s2 subscription.SubscriptionSpec) { t.Helper() @@ -224,9 +221,7 @@ func SpecsEqual(t *testing.T, s1, s2 subscription.SubscriptionSpec) { // Let's validate the item properties assert.Equal(t, i1.ItemKey, i2.ItemKey) - rc1 := withoutStripeTaxCode(t, i1.RateCard) - rc2 := withoutStripeTaxCode(t, i2.RateCard) - assert.True(t, rc1.Equal(rc2), "rate card mismatch for item %s in phase %s: \nspec: %+v\n\nview: %+v", itemKey, key, rc1, rc2) + assert.True(t, RateCardsEqual(i1.RateCard, i2.RateCard), "rate card mismatch for item %s in phase %s: \nspec: %+v\n\nview: %+v", itemKey, key, i1.RateCard, i2.RateCard) assert.Equal(t, i1.PhaseKey, i2.PhaseKey, "phase key mismatch for item %s in phase %s", itemKey, key) // We'll compare the time offsets separately @@ -269,33 +264,44 @@ func SpecsEqual(t *testing.T, s1, s2 subscription.SubscriptionSpec) { } } -// withoutStripeTaxCode returns a copy of rc without the legacy Stripe tax code, so rate cards -// compare by TaxCodeID and Behavior only. -func withoutStripeTaxCode(t *testing.T, rc productcatalog.RateCard) productcatalog.RateCard { - t.Helper() +// RateCardsEqual is RateCard.Equal, except that found's Stripe tax code is ignored when expected +// has none. The services fill in the Stripe code from the tax code's mapping, so a spec built +// from a TaxCodeID-only config can't know it. When expected has a Stripe code, like specs built +// from plans read back from the service, it's compared, so a wrong or stale code still fails. +func RateCardsEqual(expected, found productcatalog.RateCard) bool { + if expected.Type() != found.Type() { + return false + } - out := rc.Clone() - - // Edit the clone's meta directly: ChangeMeta also validates, and a comparison must not fail - // on rate cards the services accepted. - var meta *productcatalog.RateCardMeta - switch v := out.(type) { - case *productcatalog.FlatFeeRateCard: - meta = &v.RateCardMeta - case *productcatalog.UsageBasedRateCard: - meta = &v.RateCardMeta - default: - t.Fatalf("unsupported rate card type %T", out) + if lo.FromPtr(expected.GetBillingCadence()).ISOString() != lo.FromPtr(found.GetBillingCadence()).ISOString() { + return false } - if meta.TaxConfig != nil { - meta.TaxConfig.Stripe = nil - if meta.TaxConfig.Behavior == nil && meta.TaxConfig.TaxCodeID == nil { - meta.TaxConfig = nil - } + // AsMeta returns copies, so adjusting TaxConfig here doesn't touch the rate cards. + expectedMeta := expected.AsMeta() + foundMeta := found.AsMeta() + + if expectedMeta.TaxConfig == nil || expectedMeta.TaxConfig.Stripe == nil { + foundMeta.TaxConfig = withoutStripeTaxCode(foundMeta.TaxConfig) } - return out + return expectedMeta.Equal(foundMeta) +} + +// withoutStripeTaxCode returns a copy of c without the Stripe code, or nil if nothing else is set. +func withoutStripeTaxCode(c *productcatalog.TaxConfig) *productcatalog.TaxConfig { + if c == nil { + return nil + } + + out := c.Clone() + out.Stripe = nil + + if out.Behavior == nil && out.TaxCodeID == nil { + return nil + } + + return &out } func tsPlusNillableISO(ts time.Time, iso *datetime.ISODuration) *time.Time { diff --git a/openmeter/subscription/testutils/ratecard.go b/openmeter/subscription/testutils/ratecard.go index bd4033f7e8..c6ef153983 100644 --- a/openmeter/subscription/testutils/ratecard.go +++ b/openmeter/subscription/testutils/ratecard.go @@ -54,6 +54,8 @@ var ( // ExampleRateCardWithDiscounts) carry their own copy of taxConfig, so the plan service resolving // one rate card's config can't leak into another. Reference the tax code by TaxCodeID; it must // belong to the namespace the rate card is created in. + +// ExampleRateCard1 returns a new taxed usage-based rate card for the example feature. func ExampleRateCard1(taxConfig productcatalog.TaxConfig) *productcatalog.UsageBasedRateCard { return &productcatalog.UsageBasedRateCard{ RateCardMeta: productcatalog.RateCardMeta{ @@ -74,6 +76,7 @@ func ExampleRateCard1(taxConfig productcatalog.TaxConfig) *productcatalog.UsageB } } +// ExampleRateCard3ForAddons returns a new taxed flat-fee rate card for addon tests. func ExampleRateCard3ForAddons(taxConfig productcatalog.TaxConfig) *productcatalog.FlatFeeRateCard { return &productcatalog.FlatFeeRateCard{ RateCardMeta: productcatalog.RateCardMeta{ @@ -95,6 +98,7 @@ func ExampleRateCard3ForAddons(taxConfig productcatalog.TaxConfig) *productcatal } } +// ExampleRateCardWithDiscounts returns a new taxed flat-fee rate card with discounts. func ExampleRateCardWithDiscounts(taxConfig productcatalog.TaxConfig) *productcatalog.FlatFeeRateCard { return &productcatalog.FlatFeeRateCard{ RateCardMeta: productcatalog.RateCardMeta{ From 251e3e67054c4c6ab4ff1cd0b7180ef5eb6768a8 Mon Sep 17 00:00:00 2001 From: Robert Borbely Date: Fri, 30 Oct 2026 12:40:38 +0100 Subject: [PATCH 6/8] test(subscription): leave example tax behavior nil so it comes from the billing profile --- openmeter/subscription/patch/patch_test.go | 2 +- openmeter/subscription/testutils/taxcode.go | 4 ++-- openmeter/subscription/workflow/service/subscription_test.go | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/openmeter/subscription/patch/patch_test.go b/openmeter/subscription/patch/patch_test.go index b1333a5104..8bf553216e 100644 --- a/openmeter/subscription/patch/patch_test.go +++ b/openmeter/subscription/patch/patch_test.go @@ -197,7 +197,7 @@ func (ts *testsuite[T]) Run(t *testing.T) { } func getDefaultSpec(t *testing.T, activeFrom time.Time) (*subscription.SubscriptionSpec, *psubs.Plan) { - pInp := subscriptiontestutils.GetExamplePlanInput(t, productcatalog.TaxConfig{TaxCodeID: lo.ToPtr("example-tax-code"), Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)}) + pInp := subscriptiontestutils.GetExamplePlanInput(t, productcatalog.TaxConfig{TaxCodeID: lo.ToPtr("example-tax-code")}) p := &psubs.Plan{ Plan: pInp.Plan, Ref: &models.NamespacedID{Namespace: pInp.Namespace, ID: pInp.Key}, diff --git a/openmeter/subscription/testutils/taxcode.go b/openmeter/subscription/testutils/taxcode.go index 168626f1ef..d8a26bbf92 100644 --- a/openmeter/subscription/testutils/taxcode.go +++ b/openmeter/subscription/testutils/taxcode.go @@ -18,10 +18,10 @@ func GetExampleTaxCodeInput() taxcode.CreateTaxCodeInput { } } -// ExampleTaxConfig points rate cards at tc with exclusive tax behavior. +// ExampleTaxConfig points rate cards at tc. Behavior is left nil, so it comes from the billing +// profile; set it on the result if a test needs one. func ExampleTaxConfig(tc taxcode.TaxCode) productcatalog.TaxConfig { return productcatalog.TaxConfig{ TaxCodeID: lo.ToPtr(tc.ID), - Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior), } } diff --git a/openmeter/subscription/workflow/service/subscription_test.go b/openmeter/subscription/workflow/service/subscription_test.go index 6bc28b3349..3ffd808a5c 100644 --- a/openmeter/subscription/workflow/service/subscription_test.go +++ b/openmeter/subscription/workflow/service/subscription_test.go @@ -1170,7 +1170,7 @@ func TestChangeToPlan(t *testing.T) { IssueAfterReset: lo.ToPtr(111.0), UsagePeriod: subscriptiontestutils.ISOMonth, }), - TaxConfig: &productcatalog.TaxConfig{TaxCodeID: &plan2TaxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)}, + TaxConfig: &productcatalog.TaxConfig{TaxCodeID: &plan2TaxCode.ID}, Price: productcatalog.NewPriceFrom(productcatalog.UnitPrice{ Amount: alpacadecimal.NewFromInt(int64(1)), }), @@ -1183,7 +1183,7 @@ func TestChangeToPlan(t *testing.T) { Key: "new-rc-2", Name: "Rate Card 2", Description: lo.ToPtr("Rate Card 2 Description"), - TaxConfig: &productcatalog.TaxConfig{TaxCodeID: &plan2TaxCode.ID, Behavior: lo.ToPtr(productcatalog.ExclusiveTaxBehavior)}, + TaxConfig: &productcatalog.TaxConfig{TaxCodeID: &plan2TaxCode.ID}, Price: nil, }, BillingCadence: nil, From 0fc33851201fecc478d0ce9bb0a3dbf45b19f1c3 Mon Sep 17 00:00:00 2001 From: Robert Borbely Date: Tue, 3 Nov 2026 12:23:04 +0100 Subject: [PATCH 7/8] test(subscription): strip stored Stripe tax code only for TaxCodeID-only expectations --- openmeter/subscription/testutils/compare.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/openmeter/subscription/testutils/compare.go b/openmeter/subscription/testutils/compare.go index 522513205f..c41fb9c86e 100644 --- a/openmeter/subscription/testutils/compare.go +++ b/openmeter/subscription/testutils/compare.go @@ -265,9 +265,10 @@ func SpecsEqual(t *testing.T, s1, s2 subscription.SubscriptionSpec) { } // RateCardsEqual is RateCard.Equal, except that found's Stripe tax code is ignored when expected -// has none. The services fill in the Stripe code from the tax code's mapping, so a spec built -// from a TaxCodeID-only config can't know it. When expected has a Stripe code, like specs built -// from plans read back from the service, it's compared, so a wrong or stale code still fails. +// identifies the tax code by TaxCodeID alone. The services fill in the Stripe code from the tax +// code's mapping, so a spec built from a TaxCodeID-only config can't know it. Otherwise the Stripe +// code is compared, so a wrong or stale code still fails, and an expectation without a tax config +// doesn't match a taxed card. func RateCardsEqual(expected, found productcatalog.RateCard) bool { if expected.Type() != found.Type() { return false @@ -281,7 +282,7 @@ func RateCardsEqual(expected, found productcatalog.RateCard) bool { expectedMeta := expected.AsMeta() foundMeta := found.AsMeta() - if expectedMeta.TaxConfig == nil || expectedMeta.TaxConfig.Stripe == nil { + if c := expectedMeta.TaxConfig; c != nil && c.TaxCodeID != nil && c.Stripe == nil { foundMeta.TaxConfig = withoutStripeTaxCode(foundMeta.TaxConfig) } From e996963691cc63677e4137ce9235c52f4b6d3417 Mon Sep 17 00:00:00 2001 From: Robert Borbely Date: Tue, 3 Nov 2026 18:01:16 +0100 Subject: [PATCH 8/8] test(subscription): create example tax code for entitlement adapter plan --- openmeter/subscription/entitlement/adapter_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openmeter/subscription/entitlement/adapter_test.go b/openmeter/subscription/entitlement/adapter_test.go index 2acc4ed129..3eb9b489e2 100644 --- a/openmeter/subscription/entitlement/adapter_test.go +++ b/openmeter/subscription/entitlement/adapter_test.go @@ -27,7 +27,8 @@ func TestGetForItemsAt(t *testing.T) { deps := subscriptiontestutils.NewService(t, dbDeps) _ = deps.FeatureConnector.CreateExampleFeatures(t, deps.ExampleMeterID) - plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t)) + taxCode := deps.TaxCodeEnv.CreateTaxCode(t, subscriptiontestutils.ExampleNamespace, subscriptiontestutils.GetExampleTaxCodeInput()) + plan := deps.PlanHelper.CreatePlan(t, subscriptiontestutils.GetExamplePlanInput(t, subscriptiontestutils.ExampleTaxConfig(taxCode))) cust := deps.CustomerAdapter.CreateExampleCustomer(t) spec, err := subscription.NewSpecFromPlan(plan, subscription.CreateSubscriptionCustomerInput{