Skip to content

Commit a847433

Browse files
tothandrasborosr
authored andcommitted
chore: update
Signed-off-by: Andras Toth <4157749+tothandras@users.noreply.github.com>
1 parent 6fe14dd commit a847433

6 files changed

Lines changed: 23 additions & 16 deletions

File tree

api/v3/handlers/subscriptions/subscriptionaddons/convert.go

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,27 +20,25 @@ import (
2020
"github.com/openmeterio/openmeter/pkg/timeutil"
2121
)
2222

23-
func mapCreateSubscriptionAddonRequestToInput(req apiv3.CreateSubscriptionAddonRequest) (subscriptionworkflow.AddAddonWorkflowInput, error) {
23+
func FromAPICreateSubscriptionAddonRequest(req apiv3.CreateSubscriptionAddonRequest) (subscriptionworkflow.AddAddonWorkflowInput, error) {
2424
timing, err := subscriptions.FromAPIBillingSubscriptionEditTiming(req.Timing)
2525
if err != nil {
26-
return subscriptionworkflow.AddAddonWorkflowInput{}, fmt.Errorf("failed to cast Timing: %w", err)
26+
return subscriptionworkflow.AddAddonWorkflowInput{}, fmt.Errorf("failed to convert timing: %w", err)
2727
}
2828

2929
meta, err := labels.ToMetadata(req.Labels)
3030
if err != nil {
3131
return subscriptionworkflow.AddAddonWorkflowInput{}, err
3232
}
3333

34-
r := subscriptionworkflow.AddAddonWorkflowInput{
34+
return subscriptionworkflow.AddAddonWorkflowInput{
3535
AddonID: req.Addon.Id,
3636
InitialQuantity: req.Quantity,
3737
Timing: timing,
3838
MetadataModel: models.MetadataModel{
3939
Metadata: meta,
4040
},
41-
}
42-
43-
return r, nil
41+
}, nil
4442
}
4543

4644
func toAPISubscriptionAddon(view subscription.SubscriptionView, addon subscriptionaddon.SubscriptionAddon) (apiv3.SubscriptionAddon, error) {
@@ -66,9 +64,10 @@ func toAPISubscriptionAddon(view subscription.SubscriptionView, addon subscripti
6664
rateCards, err := slicesx.MapWithErr(addon.RateCards, func(r subscriptionaddon.SubscriptionAddonRateCard) (apiv3.SubscriptionAddonRateCard, error) {
6765
rc, err := plans.ToAPIBillingRateCard(r.AddonRateCard.RateCard)
6866
if err != nil {
69-
return apiv3.SubscriptionAddonRateCard{}, fmt.Errorf("failed to cast RateCard: %w", err)
67+
return apiv3.SubscriptionAddonRateCard{}, fmt.Errorf("failed to convert rate card: %w", err)
7068
}
7169

70+
// JSON encoders should emit [] not null when no items are affected.
7271
ids := affectedMap[r.AddonRateCard.RateCard.Key()]
7372
if ids == nil {
7473
ids = []string{}
@@ -80,7 +79,12 @@ func toAPISubscriptionAddon(view subscription.SubscriptionView, addon subscripti
8079
}, nil
8180
})
8281
if err != nil {
83-
return apiv3.SubscriptionAddon{}, fmt.Errorf("failed to cast RateCards: %w", err)
82+
return apiv3.SubscriptionAddon{}, fmt.Errorf("failed to convert rate cards: %w", err)
83+
}
84+
85+
// Addons with no rate cards leave RateCards nil; emit [] so the response satisfies the array schema.
86+
if rateCards == nil {
87+
rateCards = []apiv3.SubscriptionAddonRateCard{}
8488
}
8589

8690
return apiv3.SubscriptionAddon{

api/v3/handlers/subscriptions/subscriptionaddons/convert_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import (
1616
"github.com/openmeterio/openmeter/pkg/timeutil"
1717
)
1818

19-
func TestMapCreateSubscriptionAddonRequestToInput(t *testing.T) {
19+
func TestFromAPICreateSubscriptionAddonRequest(t *testing.T) {
2020
t.Run("maps immediate timing and labels", func(t *testing.T) {
2121
var timing apiv3.BillingSubscriptionEditTiming
2222
require.NoError(t, timing.FromBillingSubscriptionEditTimingEnum(apiv3.BillingSubscriptionEditTimingEnum("immediate")))
@@ -29,7 +29,7 @@ func TestMapCreateSubscriptionAddonRequestToInput(t *testing.T) {
2929
Timing: timing,
3030
}
3131

32-
input, err := mapCreateSubscriptionAddonRequestToInput(req)
32+
input, err := FromAPICreateSubscriptionAddonRequest(req)
3333
require.NoError(t, err)
3434

3535
assert.Equal(t, "01J8GFKQ0000000000000000", input.AddonID)
@@ -49,7 +49,7 @@ func TestMapCreateSubscriptionAddonRequestToInput(t *testing.T) {
4949
Timing: timing,
5050
}
5151

52-
input, err := mapCreateSubscriptionAddonRequestToInput(req)
52+
input, err := FromAPICreateSubscriptionAddonRequest(req)
5353
require.NoError(t, err)
5454
require.NotNil(t, input.Timing.Enum)
5555
assert.Equal(t, subscription.TimingNextBillingCycle, *input.Timing.Enum)
@@ -66,7 +66,7 @@ func TestMapCreateSubscriptionAddonRequestToInput(t *testing.T) {
6666
Timing: timing,
6767
}
6868

69-
_, err := mapCreateSubscriptionAddonRequestToInput(req)
69+
_, err := FromAPICreateSubscriptionAddonRequest(req)
7070
require.Error(t, err)
7171
})
7272
}

api/v3/handlers/subscriptions/subscriptionaddons/create.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ func (h *handler) CreateSubscriptionAddon() CreateSubscriptionAddonHandler {
3636
return CreateSubscriptionAddonRequest{}, err
3737
}
3838

39-
addonInput, err := mapCreateSubscriptionAddonRequestToInput(body)
39+
addonInput, err := FromAPICreateSubscriptionAddonRequest(body)
4040
if err != nil {
4141
return CreateSubscriptionAddonRequest{}, err
4242
}

openmeter/subscription/addon/repo/subscriptionaddon.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,11 @@ func (r *subscriptionAddonRepo) Create(ctx context.Context, namespace string, in
4242
if err != nil {
4343
// Surface the partial unique index on (namespace, subscription_id, addon_id)
4444
// as a conflict so concurrent creators see the same error as the in-tx duplicate check.
45+
// Keep the user-visible message generic so it does not echo addon/subscription IDs;
46+
// the workflow's pre-Create validation already establishes that both exist.
4547
if db.IsConstraintError(err) {
4648
return nil, models.NewGenericConflictError(
47-
fmt.Errorf("subscription %s already has addon %s", input.SubscriptionID, input.AddonID),
49+
fmt.Errorf("addon is already attached to subscription"),
4850
)
4951
}
5052

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
-- create index "subscriptionaddon_namespace_subscription_id_addon_id" to table: "subscription_addons"
2+
-- atlas:nolint MF101
23
CREATE UNIQUE INDEX "subscriptionaddon_namespace_subscription_id_addon_id" ON "subscription_addons" ("namespace", "subscription_id", "addon_id") WHERE (deleted_at IS NULL);

tools/migrate/migrations/atlas.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
h1:ULIR3dgkcW7H3/qnsKJy/sVY6eDQELwJP3vRKYDfzfs=
1+
h1:ZIgAIFY3zNI+/e+OgVKSfmAp5T0MACyAwS/u2R0f6Ms=
22
20240826120919_init.up.sql h1:tc1V91/smlmaeJGQ8h+MzTEeFjjnrrFDbDAjOYJK91o=
33
20240903155435_entitlement-expired-index.up.sql h1:Hp8u5uckmLXc1cRvWU0AtVnnK8ShlpzZNp8pbiJLhac=
44
20240917172257_billing-entities.up.sql h1:Q1dAMo0Vjiit76OybClNfYPGC5nmvov2/M2W1ioi4Kw=
@@ -214,4 +214,4 @@ h1:ULIR3dgkcW7H3/qnsKJy/sVY6eDQELwJP3vRKYDfzfs=
214214
20260623101013_add_billing_profile_subscription_end_proration_mode.up.sql h1:XtiMtYP8QL7Z5Lt04VCZ3mf3gMbqZOuu9/EMOnn21Sk=
215215
20260624043300_charge_intent_override_ddl.up.sql h1:IQckC6jS1yadEgZqiGkOgn51lhdwTt7d2IVDsIWipts=
216216
20260624135146_remove_deprecated_ent_fields.up.sql h1:x5paHYKtNbRUBkY9UEHdc+fCkdIxIMt3tqfkMDEtfUM=
217-
20260625085650_add_subscription_addon_unique_index.up.sql h1:Ap4QS5LHFuoqa3sr48E8DcX9TgrQgZPVmxyR/IE0PU8=
217+
20260625085650_add_subscription_addon_unique_index.up.sql h1:w2/eQq5S2F4L1w1Z459uJg8d7i6Ebr3P37bqaVnYWqk=

0 commit comments

Comments
 (0)