diff --git a/internal/controllers/subscriptions.go b/internal/controllers/subscriptions.go index 6fa7b5c..fdbc7c6 100644 --- a/internal/controllers/subscriptions.go +++ b/internal/controllers/subscriptions.go @@ -113,8 +113,13 @@ func (sa *SubscriptionAdder) AddSubscription(tx *gorm.DB, req model.Subscription return sa.subscriptionError(*username, err.Error()) } + // Define the subscription options. + opts := &model.SubscriptionOptions{ + Paid: paid, + } + // Add the subscription. - sub, err := db.SubscribeUserToPlan(sa.cfg.Ctx, tx, user, plan, *paid) + sub, err := db.SubscribeUserToPlan(sa.cfg.Ctx, tx, user, plan, opts) if err != nil { log.Error(err) return sa.subscriptionError(*username, err.Error()) diff --git a/internal/controllers/users.go b/internal/controllers/users.go index 1566f55..3696f83 100644 --- a/internal/controllers/users.go +++ b/internal/controllers/users.go @@ -402,8 +402,13 @@ func (s Server) UpdateSubscription(ctx echo.Context) error { log.Debug("deactivated all active plans for the user") + // Define the subscription options. + opts := &model.SubscriptionOptions{ + Paid: &paid, + } + // Subscribe the user to the plan. - subscription, err := db.SubscribeUserToPlan(context, tx, user, plan, paid) + subscription, err := db.SubscribeUserToPlan(context, tx, user, plan, opts) if err != nil { return model.Error(ctx, err.Error(), http.StatusInternalServerError) } diff --git a/internal/db/subscriptions.go b/internal/db/subscriptions.go index 58fdc0a..3c73f01 100644 --- a/internal/db/subscriptions.go +++ b/internal/db/subscriptions.go @@ -14,11 +14,15 @@ import ( // QuotasFromPlan generates a set of quotas from the plan quota defaults in a plan. This function assumes that the // given plan already contains the plan quota defaults. -func QuotasFromPlan(plan *model.Plan) []model.Quota { +func QuotasFromPlan(plan *model.Plan, periods int32) []model.Quota { result := make([]model.Quota, len(plan.PlanQuotaDefaults)) for i, quotaDefault := range plan.PlanQuotaDefaults { + quotaValue := quotaDefault.QuotaValue + if quotaDefault.ResourceType.Consumable { + quotaValue *= float64(periods) + } result[i] = model.Quota{ - Quota: quotaDefault.QuotaValue, + Quota: quotaValue, ResourceTypeID: quotaDefault.ResourceTypeID, } } @@ -27,21 +31,21 @@ func QuotasFromPlan(plan *model.Plan) []model.Quota { // SubscribeUserToPlan subscribes the given user to the given plan. func SubscribeUserToPlan( - ctx context.Context, db *gorm.DB, user *model.User, plan *model.Plan, paid bool, + ctx context.Context, db *gorm.DB, user *model.User, plan *model.Plan, opts *model.SubscriptionOptions, ) (*model.Subscription, error) { wrapMsg := "unable to add user plan" var err error // Define the user plan. effectiveStartDate := time.Now() - effectiveEndDate := effectiveStartDate.AddDate(1, 0, 0) + effectiveEndDate := opts.GetEndDate(effectiveStartDate) subscription := model.Subscription{ EffectiveStartDate: &effectiveStartDate, EffectiveEndDate: &effectiveEndDate, UserID: user.ID, PlanID: plan.ID, - Quotas: QuotasFromPlan(plan), - Paid: paid, + Quotas: QuotasFromPlan(plan, opts.GetPeriods()), + Paid: opts.IsPaid(), } err = db.WithContext(ctx).Create(&subscription).Error if err != nil { @@ -69,7 +73,7 @@ func SubscribeUserToDefaultPlan(ctx context.Context, db *gorm.DB, username strin } // Subscribe the user to the plan. - return SubscribeUserToPlan(ctx, db, user, plan, false) + return SubscribeUserToPlan(ctx, db, user, plan, &model.SubscriptionOptions{}) } // GetActiveSubscription retrieves the user plan record that is currently active for the user. The effective start diff --git a/internal/model/subscriptions.go b/internal/model/subscriptions.go index ee17ecb..f116cb8 100644 --- a/internal/model/subscriptions.go +++ b/internal/model/subscriptions.go @@ -1,5 +1,48 @@ package model +import "time" + +// SubscriptionOptions represents options that can be applied to a new subscription. +// +// swagger: model +type SubscriptionOptions struct { + // True if the user paid for the subscription. + Paid *bool `json:"paid"` + + // The number of periods included in the subscription. + Periods *int32 `json:"periods"` + + // The effective end date of the subscription. + EndDate *time.Time `json:"end_date"` +} + +// Return the appropriate paid flag for the subscription options. +func (o *SubscriptionOptions) IsPaid() bool { + if o.Paid == nil { + return false + } else { + return *o.Paid + } +} + +// Return the number of periods for the subscription options. +func (o *SubscriptionOptions) GetPeriods() int32 { + if o.Periods == nil { + return 1 + } else { + return *o.Periods + } +} + +// Return the effective end date for the subscription options. +func (o *SubscriptionOptions) GetEndDate(startDate time.Time) time.Time { + if o.EndDate == nil { + return startDate.AddDate(int(o.GetPeriods()), 0, 0) + } else { + return *o.EndDate + } +} + // SubscriptionRequest represents a request for a single subscription. // // swagger: model