add subscription tiers

This commit is contained in:
KS Jannette
2026-03-10 15:22:48 -04:00
parent 7b45c5b2ab
commit f9fa7def2b
26 changed files with 944 additions and 160 deletions

View File

@@ -6,29 +6,40 @@ import (
"time"
"github.com/kjannette/koin-ping/backend/internal/config"
"github.com/kjannette/koin-ping/backend/internal/domain"
"github.com/kjannette/koin-ping/backend/internal/middleware"
"github.com/kjannette/koin-ping/backend/internal/models"
)
type AccountHandler struct {
users *models.UserModel
cfg *config.Config
users *models.UserModel
addresses *models.AddressModel
cfg *config.Config
}
func NewAccountHandler(users *models.UserModel, cfg *config.Config) *AccountHandler {
return &AccountHandler{users: users, cfg: cfg}
func NewAccountHandler(users *models.UserModel, addresses *models.AddressModel, cfg *config.Config) *AccountHandler {
return &AccountHandler{users: users, addresses: addresses, cfg: cfg}
}
type accountResponse struct {
UserID string `json:"user_id"`
Email string `json:"email"`
UserName string `json:"user_name"`
SubscriptionStatus string `json:"subscription_status"`
SubscriptionPlan string `json:"subscription_plan"`
MemberSince *string `json:"member_since,omitempty"`
NextBillingDate *string `json:"next_billing_date,omitempty"`
CancelAtPeriodEnd bool `json:"cancel_at_period_end"`
PeriodEndDate *string `json:"period_end_date,omitempty"`
UserID string `json:"user_id"`
Email string `json:"email"`
UserName string `json:"user_name"`
SubscriptionStatus string `json:"subscription_status"`
SubscriptionTier string `json:"subscription_tier"`
SubscriptionPlan string `json:"subscription_plan"`
TierLimits domain.TierLimits `json:"tier_limits"`
AddressCount int `json:"address_count"`
MemberSince *string `json:"member_since,omitempty"`
NextBillingDate *string `json:"next_billing_date,omitempty"`
CancelAtPeriodEnd bool `json:"cancel_at_period_end"`
PeriodEndDate *string `json:"period_end_date,omitempty"`
}
var tierPlanLabels = map[domain.SubscriptionTier]string{ //nolint:gochecknoglobals
domain.TierFree: "Free Trial",
domain.TierPremium: "Premium / $1.99 mo",
domain.TierPro: "Pro / $11.99 mo",
}
func (h *AccountHandler) GetAccount(w http.ResponseWriter, r *http.Request) {
@@ -42,12 +53,26 @@ func (h *AccountHandler) GetAccount(w http.ResponseWriter, r *http.Request) {
return
}
addrCount, err := h.addresses.CountByUser(r.Context(), userID)
if err != nil {
log.Printf("Account: failed to count addresses for %s: %v", userID, err)
addrCount = 0
}
planLabel := tierPlanLabels[user.SubscriptionTier]
if planLabel == "" {
planLabel = "Free Trial"
}
resp := accountResponse{
UserID: user.ID,
Email: email,
UserName: email,
SubscriptionStatus: user.SubscriptionStatus,
SubscriptionPlan: "monthly/$1.99",
SubscriptionTier: string(user.SubscriptionTier),
SubscriptionPlan: planLabel,
TierLimits: domain.GetTierLimits(user.SubscriptionTier),
AddressCount: addrCount,
}
if user.SubscriptionCreatedAt != nil {
@@ -55,9 +80,6 @@ func (h *AccountHandler) GetAccount(w http.ResponseWriter, r *http.Request) {
resp.MemberSince = &t
}
// MOCKED: NextBillingDate, CancelAtPeriodEnd, PeriodEndDate.
// TODO: stripe-go v82 removed Subscription.CurrentPeriodEnd / CancelAtPeriodEnd.
// Research SubscriptionItem.CurrentPeriodEnd or use Stripe REST API directly.
resp.NextBillingDate = nil
resp.CancelAtPeriodEnd = false
resp.PeriodEndDate = nil