Skip to content
This repository has been archived by the owner on Jan 2, 2024. It is now read-only.

Commit

Permalink
api: add support for decimal unit prices (#260)
Browse files Browse the repository at this point in the history
This commit adds support for fractional unit amounts for the base price
of a licensed feature.

Closes #223
  • Loading branch information
bmizerany committed Feb 23, 2023
1 parent 9a456f5 commit b80919a
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 12 deletions.
12 changes: 6 additions & 6 deletions api/apitypes/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,12 @@ func (t *Tier) UnmarshalJSON(data []byte) error {
}

type Feature struct {
Title string `json:"title,omitempty"`
Base int `json:"base,omitempty"`
Mode string `json:"mode,omitempty"`
Aggregate string `json:"aggregate,omitempty"`
Tiers []Tier `json:"tiers,omitempty"`
PermLink string `json:"permLink,omitempty"`
Title string `json:"title,omitempty"`
Base float64 `json:"base,omitempty"`
Mode string `json:"mode,omitempty"`
Aggregate string `json:"aggregate,omitempty"`
Tiers []Tier `json:"tiers,omitempty"`
PermLink string `json:"permLink,omitempty"`
}

type Plan struct {
Expand Down
2 changes: 1 addition & 1 deletion cmd/tier/tier.go
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ func runTier(cmd string, args []string) (err error) {

for plan, p := range m.Plans {
for feature, f := range p.Features {
fmt.Fprintf(tw, "%s\t%s\t%s\t%s\t%d\n",
fmt.Fprintf(tw, "%s\t%s\t%s\t%s\t%f\n",
plan,
feature,
f.Mode,
Expand Down
10 changes: 5 additions & 5 deletions control/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ type Feature struct {

// Base is the base price for the feature. If Tiers is not empty, then Base
// is ignored.
Base int
Base float64

// Mode specifies the billing mode for use with Tiers.
//
Expand Down Expand Up @@ -280,7 +280,7 @@ func (c *Client) pushFeature(ctx context.Context, f Feature) (providerID string,
if len(f.Tiers) == 0 {
data.Set("recurring", "usage_type", "licensed")
data.Set("billing_scheme", "per_unit")
data.Set("unit_amount", f.Base)
data.Set("unit_amount_decimal", f.Base)
} else {
data.Set("recurring", "usage_type", "metered")
data.Set("billing_scheme", "tiered")
Expand Down Expand Up @@ -336,9 +336,9 @@ type stripePrice struct {
UsageType string `json:"usage_type"`
AggregateUsage string `json:"aggregate_usage"`
}
BillingScheme string `json:"billing_scheme"`
TiersMode string `json:"tiers_mode"`
UnitAmount int `json:"unit_amount"`
BillingScheme string `json:"billing_scheme"`
TiersMode string `json:"tiers_mode"`
UnitAmount float64 `json:"unit_amount_decimal,string"`
Tiers []struct {
Upto int `json:"up_to"`
Price float64 `json:"unit_amount"`
Expand Down
12 changes: 12 additions & 0 deletions control/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ func TestRoundTrip(t *testing.T) {
ctx := context.Background()

want := []Feature{
{
FeaturePlan: refs.MustParseFeaturePlan("feature:decimal@fractionalBase"),
Interval: "@daily",
Currency: "eur",
Base: 0.1,
},
{
FeaturePlan: refs.MustParseFeaturePlan("feature:test@plan:free@3"),
Interval: "@daily",
Expand All @@ -65,6 +71,12 @@ func TestRoundTrip(t *testing.T) {
},
}

if !slices.IsSortedFunc(want, func(a, b Feature) bool {
return a.Less(b.FeaturePlan)
}) {
t.Fatal("want must be sorted")
}

if err := tc.Push(ctx, want, pushLogger(t)); err != nil {
t.Fatal(err)
}
Expand Down

0 comments on commit b80919a

Please sign in to comment.