Skip to content

Commit

Permalink
Merge pull request #1824 from openmeterio/feat/plan-api-impl
Browse files Browse the repository at this point in the history
fix: multiple issues in Plan API
  • Loading branch information
chrisgacsal authored Nov 11, 2024
2 parents b32bc7f + 6496000 commit 97d78fa
Show file tree
Hide file tree
Showing 16 changed files with 962 additions and 131 deletions.
4 changes: 2 additions & 2 deletions openmeter/billing/httpdriver/invoiceline.go
Original file line number Diff line number Diff line change
Expand Up @@ -386,14 +386,14 @@ func mapTieredPriceToAPI(p plan.TieredPrice) (api.RateCardUsageBasedPrice, error
if t.FlatPrice != nil {
res.FlatPrice = &api.FlatPrice{
Amount: t.FlatPrice.Amount.String(),
Type: api.FlatPriceType(t.FlatPrice.Type),
Type: api.FlatPriceType(plan.FlatPriceType),
}
}

if t.UnitPrice != nil {
res.UnitPrice = &api.UnitPrice{
Amount: t.UnitPrice.Amount.String(),
Type: api.UnitPriceType(t.UnitPrice.Type),
Type: api.UnitPriceType(plan.UnitPriceType),
}
}
return res
Expand Down
2 changes: 1 addition & 1 deletion openmeter/productcatalog/plan/adapter/adapter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ func TestPostgresAdapter(t *testing.T) {
Namespace: namespace,
ID: planV1.ID,
},
EffectivePeriod: &plan.EffectivePeriod{
EffectivePeriod: plan.EffectivePeriod{
EffectiveFrom: lo.ToPtr(now.UTC()),
EffectiveTo: lo.ToPtr(now.Add(30 * 24 * time.Hour).UTC()),
},
Expand Down
3 changes: 3 additions & 0 deletions openmeter/productcatalog/plan/adapter/mapping.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,9 @@ func asPlanRateCardRow(r plan.RateCard) (entdb.PlanRateCard, error) {
}

ratecard := entdb.PlanRateCard{
Namespace: meta.Namespace,
ID: meta.ID,
PhaseID: meta.PhaseID,
Key: meta.Key,
Metadata: meta.Metadata,
Name: meta.Name,
Expand Down
7 changes: 5 additions & 2 deletions openmeter/productcatalog/plan/adapter/phase.go
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ func (a *adapter) UpdatePhase(ctx context.Context, params plan.UpdatePhaseInput)
PlanID: params.PlanID,
})
if err != nil {
return nil, fmt.Errorf("failed to get Plan: %w", err)
return nil, fmt.Errorf("failed to get PlanPhase: %w", err)
}

if !params.Equal(*p) {
Expand All @@ -371,7 +371,7 @@ func (a *adapter) UpdatePhase(ctx context.Context, params plan.UpdatePhaseInput)
p.Metadata = *params.Metadata
}

if params.Metadata != nil {
if params.StartAfter != nil {
query = query.SetStartAfter(params.StartAfter.ISOString())
p.StartAfter = *params.StartAfter
}
Expand Down Expand Up @@ -529,6 +529,9 @@ func rateCardsDiff(inputs, rateCards []plan.RateCard) (rateCardsDiffResult, erro
}

if !match {
input.Namespace = rateCard.Namespace
input.ID = rateCard.ID
input.PhaseID = rateCard.PhaseID
result.Update = append(result.Update, input)

rateCardsVisited[rateCardKey] = struct{}{}
Expand Down
38 changes: 24 additions & 14 deletions openmeter/productcatalog/plan/adapter/plan.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,14 +121,18 @@ func (a *adapter) CreatePlan(ctx context.Context, params plan.CreatePlanInput) (

// Create plan

if params.Version == 0 {
params.Version = 1
}

planRow, err := a.db.Plan.Create().
SetKey(params.Key).
SetNamespace(params.Namespace).
SetName(params.Name).
SetNillableDescription(params.Description).
SetCurrency(params.Currency.String()).
SetMetadata(params.Metadata).
SetVersion(1).
SetVersion(params.Version).
Save(ctx)
if err != nil {
return nil, fmt.Errorf("failed to create Plan: %w", err)
Expand Down Expand Up @@ -317,6 +321,7 @@ func (a *adapter) GetPlan(ctx context.Context, params plan.GetPlanInput) (*plan.
plandb.EffectiveToGT(now),
plandb.EffectiveToIsNil(),
),
plandb.DeletedAtIsNil(),
))
}
} else { // get Plan by Key and Version
Expand Down Expand Up @@ -381,27 +386,32 @@ func (a *adapter) UpdatePlan(ctx context.Context, params plan.UpdatePlanInput) (
}

if !params.Equal(*p) {
query := a.db.Plan.UpdateOneID(p.ID).Where(plandb.Namespace(params.Namespace))

if params.Name != nil {
query = query.SetName(*params.Name)
p.Name = *params.Name
}

if params.Description != nil {
query = query.SetDescription(*params.Description)
p.Description = params.Description
}
query := a.db.Plan.UpdateOneID(p.ID).
Where(plandb.Namespace(params.Namespace)).
SetNillableName(params.Name).
SetNillableDescription(params.Description).
SetNillableEffectiveFrom(params.EffectiveFrom).
SetNillableEffectiveTo(params.EffectiveTo)

if params.Metadata != nil {
query = query.SetMetadata(*params.Metadata)
p.Metadata = *params.Metadata
}

err = query.Exec(ctx)
if err != nil {
return nil, fmt.Errorf("failed to update Plan: %w", err)
}

// Plan needs to be refetched after updated in order to populate all subresources
p, err = a.GetPlan(ctx, plan.GetPlanInput{
NamespacedID: models.NamespacedID{
Namespace: params.Namespace,
ID: params.ID,
},
})
if err != nil {
return nil, fmt.Errorf("failed to get updated Plan: %w", err)
}
}

if params.Phases != nil {
Expand Down Expand Up @@ -437,7 +447,7 @@ func (a *adapter) UpdatePlan(ctx context.Context, params plan.UpdatePlanInput) (

phase, err := a.UpdatePhase(ctx, updateInput)
if err != nil {
return nil, fmt.Errorf("failed to update PlanPhasee: %w", err)
return nil, fmt.Errorf("failed to update PlanPhase: %w", err)
}

phases = append(phases, *phase)
Expand Down
9 changes: 9 additions & 0 deletions openmeter/productcatalog/plan/errors.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package plan

import (
"errors"
"fmt"

"github.com/openmeterio/openmeter/pkg/models"
Expand All @@ -16,6 +17,14 @@ func (e NotFoundError) Error() string {
return fmt.Sprintf("resource not found in %s namespace", e.Namespace)
}

func IsNotFound(err error) bool {
if err == nil {
return false
}
var e NotFoundError
return errors.As(err, &e)
}

type genericError struct {
Err error
}
Expand Down
6 changes: 0 additions & 6 deletions openmeter/productcatalog/plan/httpdriver/mapping.go
Original file line number Diff line number Diff line change
Expand Up @@ -677,9 +677,6 @@ func AsPriceTier(t api.PriceTier) (plan.PriceTier, error) {
}

tier.FlatPrice = &plan.PriceTierFlatPrice{
PriceMeta: plan.PriceMeta{
Type: plan.FlatPriceType,
},
Amount: amount,
}
}
Expand All @@ -691,9 +688,6 @@ func AsPriceTier(t api.PriceTier) (plan.PriceTier, error) {
}

tier.UnitPrice = &plan.PriceTierUnitPrice{
PriceMeta: plan.PriceMeta{
Type: plan.UnitPriceType,
},
Amount: amount,
}
}
Expand Down
12 changes: 8 additions & 4 deletions openmeter/productcatalog/plan/plan.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"time"

"github.com/invopop/gobl/currency"
"github.com/samber/lo"

"github.com/openmeterio/openmeter/pkg/datex"
"github.com/openmeterio/openmeter/pkg/models"
Expand Down Expand Up @@ -120,25 +121,28 @@ func (p EffectivePeriod) Status() PlanStatus {

// StatusAt returns the plan status relative to time t.
func (p EffectivePeriod) StatusAt(t time.Time) PlanStatus {
from := lo.FromPtrOr(p.EffectiveFrom, time.Time{})
to := lo.FromPtrOr(p.EffectiveTo, time.Time{})

// Plan has DraftStatus if neither the EffectiveFrom nor EffectiveTo are set
if p.EffectiveFrom == nil && p.EffectiveTo == nil {
if from.IsZero() && to.IsZero() {
return DraftStatus
}

// Plan has ArchivedStatus if EffectiveTo is in the past relative to time t.
if p.EffectiveFrom != nil && p.EffectiveFrom.Before(t) && p.EffectiveTo != nil && p.EffectiveTo.Before(t) && p.EffectiveFrom.Before(*p.EffectiveTo) {
if from.Before(t) && (to.Before(t) && from.Before(to)) {
return ArchivedStatus
}

// Plan has ActiveStatus if EffectiveFrom is set in the past relative to time t and EffectiveTo is not set
// or in the future relative to time t.
if p.EffectiveFrom != nil && p.EffectiveFrom.Before(t) && (p.EffectiveTo == nil || p.EffectiveTo.After(t)) {
if from.Before(t) && (to.IsZero() || to.After(t)) {
return ActiveStatus
}

// Plan is ScheduledForActiveStatus if EffectiveFrom is set in the future relative to time t and EffectiveTo is not set
// or in the future relative to time t.
if p.EffectiveFrom != nil && p.EffectiveFrom.After(t) && (p.EffectiveTo == nil || p.EffectiveTo.After(t)) {
if from.After(t) && (to.IsZero() || to.After(from)) {
return ScheduledStatus
}

Expand Down
12 changes: 10 additions & 2 deletions openmeter/productcatalog/plan/plan_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,20 @@ func TestPlanStatus(t *testing.T) {
Expected: InvalidStatus,
},
{
Name: "Invalid with missing start",
Name: "Invalid with no start with end in the past",
Effective: EffectivePeriod{
EffectiveFrom: nil,
EffectiveTo: lo.ToPtr(now.Add(-24 * time.Hour)),
},
Expected: InvalidStatus,
Expected: ArchivedStatus,
},
{
Name: "Invalid with no start with end in the future",
Effective: EffectivePeriod{
EffectiveFrom: nil,
EffectiveTo: lo.ToPtr(now.Add(24 * time.Hour)),
},
Expected: ActiveStatus,
},
}

Expand Down
4 changes: 0 additions & 4 deletions openmeter/productcatalog/plan/price.go
Original file line number Diff line number Diff line change
Expand Up @@ -450,8 +450,6 @@ func (p PriceTier) Validate() error {
var _ Validator = (*PriceTierFlatPrice)(nil)

type PriceTierFlatPrice struct {
PriceMeta

// Amount of the flat price.
Amount decimal.Decimal `json:"amount"`
}
Expand All @@ -467,8 +465,6 @@ func (f PriceTierFlatPrice) Validate() error {
var _ Validator = (*PriceTierUnitPrice)(nil)

type PriceTierUnitPrice struct {
PriceMeta

// Amount of the flat price.
Amount decimal.Decimal `json:"amount"`
}
Expand Down
48 changes: 0 additions & 48 deletions openmeter/productcatalog/plan/price_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,30 +142,18 @@ func TestTieredPrice(t *testing.T) {
{
UpToAmount: lo.ToPtr(decimal.NewFromInt(1000)),
FlatPrice: &PriceTierFlatPrice{
PriceMeta: PriceMeta{
Type: FlatPriceType,
},
Amount: decimal.NewFromInt(5),
},
UnitPrice: &PriceTierUnitPrice{
PriceMeta: PriceMeta{
Type: UnitPriceType,
},
Amount: decimal.NewFromInt(5),
},
},
{
UpToAmount: lo.ToPtr(decimal.NewFromInt(2500)),
FlatPrice: &PriceTierFlatPrice{
PriceMeta: PriceMeta{
Type: FlatPriceType,
},
Amount: decimal.NewFromInt(3),
},
UnitPrice: &PriceTierUnitPrice{
PriceMeta: PriceMeta{
Type: UnitPriceType,
},
Amount: decimal.NewFromInt(1),
},
},
Expand All @@ -186,30 +174,18 @@ func TestTieredPrice(t *testing.T) {
{
UpToAmount: lo.ToPtr(decimal.NewFromInt(1000)),
FlatPrice: &PriceTierFlatPrice{
PriceMeta: PriceMeta{
Type: FlatPriceType,
},
Amount: decimal.NewFromInt(5),
},
UnitPrice: &PriceTierUnitPrice{
PriceMeta: PriceMeta{
Type: UnitPriceType,
},
Amount: decimal.NewFromInt(5),
},
},
{
UpToAmount: lo.ToPtr(decimal.NewFromInt(2500)),
FlatPrice: &PriceTierFlatPrice{
PriceMeta: PriceMeta{
Type: FlatPriceType,
},
Amount: decimal.NewFromInt(3),
},
UnitPrice: &PriceTierUnitPrice{
PriceMeta: PriceMeta{
Type: UnitPriceType,
},
Amount: decimal.NewFromInt(1),
},
},
Expand All @@ -230,30 +206,18 @@ func TestTieredPrice(t *testing.T) {
{
UpToAmount: lo.ToPtr(decimal.NewFromInt(1000)),
FlatPrice: &PriceTierFlatPrice{
PriceMeta: PriceMeta{
Type: FlatPriceType,
},
Amount: decimal.NewFromInt(5),
},
UnitPrice: &PriceTierUnitPrice{
PriceMeta: PriceMeta{
Type: UnitPriceType,
},
Amount: decimal.NewFromInt(5),
},
},
{
UpToAmount: lo.ToPtr(decimal.NewFromInt(2500)),
FlatPrice: &PriceTierFlatPrice{
PriceMeta: PriceMeta{
Type: FlatPriceType,
},
Amount: decimal.NewFromInt(3),
},
UnitPrice: &PriceTierUnitPrice{
PriceMeta: PriceMeta{
Type: UnitPriceType,
},
Amount: decimal.NewFromInt(1),
},
},
Expand All @@ -274,30 +238,18 @@ func TestTieredPrice(t *testing.T) {
{
UpToAmount: lo.ToPtr(decimal.NewFromInt(-1000)),
FlatPrice: &PriceTierFlatPrice{
PriceMeta: PriceMeta{
Type: FlatPriceType,
},
Amount: decimal.NewFromInt(-5),
},
UnitPrice: &PriceTierUnitPrice{
PriceMeta: PriceMeta{
Type: UnitPriceType,
},
Amount: decimal.NewFromInt(-5),
},
},
{
UpToAmount: lo.ToPtr(decimal.NewFromInt(-1000)),
FlatPrice: &PriceTierFlatPrice{
PriceMeta: PriceMeta{
Type: FlatPriceType,
},
Amount: decimal.NewFromInt(-3),
},
UnitPrice: &PriceTierUnitPrice{
PriceMeta: PriceMeta{
Type: UnitPriceType,
},
Amount: decimal.NewFromInt(-1),
},
},
Expand Down
Loading

0 comments on commit 97d78fa

Please sign in to comment.