From 5277f33155fb467d11f28732116ace72883b3099 Mon Sep 17 00:00:00 2001 From: erio Date: Mon, 13 Apr 2026 18:08:06 +0800 Subject: [PATCH] fix(plans): subscription plan page validation, sorting, and toFixed error - Fix toFixed crash when price is undefined - Remove sort_order field, order by created_at instead - Fix group selector showing blank when nothing selected - Add required field markers (*) and backend validation - Add i18n groupRequired key for both zh/en --- backend/cmd/server/VERSION | 2 +- .../internal/service/payment_config_plans.go | 28 +++++++++++++- frontend/src/i18n/locales/en.ts | 1 + frontend/src/i18n/locales/zh.ts | 1 + .../admin/orders/AdminPaymentPlansView.vue | 38 +++++++++---------- 5 files changed, 48 insertions(+), 22 deletions(-) diff --git a/backend/cmd/server/VERSION b/backend/cmd/server/VERSION index 01eddd222f..9a57afb880 100644 --- a/backend/cmd/server/VERSION +++ b/backend/cmd/server/VERSION @@ -1 +1 @@ -0.1.110.34 +0.1.110.35 diff --git a/backend/internal/service/payment_config_plans.go b/backend/internal/service/payment_config_plans.go index 8a3e2950cc..ca8b32d270 100644 --- a/backend/internal/service/payment_config_plans.go +++ b/backend/internal/service/payment_config_plans.go @@ -3,6 +3,7 @@ package service import ( "context" "fmt" + "strings" dbent "github.com/Wei-Shaw/sub2api/ent" "github.com/Wei-Shaw/sub2api/ent/group" @@ -10,6 +11,26 @@ import ( infraerrors "github.com/Wei-Shaw/sub2api/internal/pkg/errors" ) +// validatePlanRequired checks that all required fields for a plan are provided. +func validatePlanRequired(name string, groupID int64, price float64, validityDays int, validityUnit string) error { + if strings.TrimSpace(name) == "" { + return infraerrors.BadRequest("PLAN_NAME_REQUIRED", "plan name is required") + } + if groupID <= 0 { + return infraerrors.BadRequest("PLAN_GROUP_REQUIRED", "group is required") + } + if price < 0 { + return infraerrors.BadRequest("PLAN_PRICE_INVALID", "price must be >= 0") + } + if validityDays <= 0 { + return infraerrors.BadRequest("PLAN_VALIDITY_REQUIRED", "validity days must be > 0") + } + if strings.TrimSpace(validityUnit) == "" { + return infraerrors.BadRequest("PLAN_VALIDITY_UNIT_REQUIRED", "validity unit is required") + } + return nil +} + // --- Plan CRUD --- // PlanGroupInfo holds the group details needed for subscription plan display. @@ -66,14 +87,17 @@ func (s *PaymentConfigService) GetGroupInfoMap(ctx context.Context, plans []*dbe } func (s *PaymentConfigService) ListPlans(ctx context.Context) ([]*dbent.SubscriptionPlan, error) { - return s.entClient.SubscriptionPlan.Query().Order(subscriptionplan.BySortOrder()).All(ctx) + return s.entClient.SubscriptionPlan.Query().Order(subscriptionplan.ByCreatedAt()).All(ctx) } func (s *PaymentConfigService) ListPlansForSale(ctx context.Context) ([]*dbent.SubscriptionPlan, error) { - return s.entClient.SubscriptionPlan.Query().Where(subscriptionplan.ForSaleEQ(true)).Order(subscriptionplan.BySortOrder()).All(ctx) + return s.entClient.SubscriptionPlan.Query().Where(subscriptionplan.ForSaleEQ(true)).Order(subscriptionplan.ByCreatedAt()).All(ctx) } func (s *PaymentConfigService) CreatePlan(ctx context.Context, req CreatePlanRequest) (*dbent.SubscriptionPlan, error) { + if err := validatePlanRequired(req.Name, req.GroupID, req.Price, req.ValidityDays, req.ValidityUnit); err != nil { + return nil, err + } b := s.entClient.SubscriptionPlan.Create(). SetGroupID(req.GroupID).SetName(req.Name).SetDescription(req.Description). SetPrice(req.Price).SetValidityDays(req.ValidityDays).SetValidityUnit(req.ValidityUnit). diff --git a/frontend/src/i18n/locales/en.ts b/frontend/src/i18n/locales/en.ts index a21082690f..9986c42260 100644 --- a/frontend/src/i18n/locales/en.ts +++ b/frontend/src/i18n/locales/en.ts @@ -5412,6 +5412,7 @@ export default { tabPlanConfig: 'Plan Configuration', tabUserSubs: 'User Subscriptions', selectGroup: 'Select a group', + groupRequired: 'Please select a subscription group', groupMissing: 'Missing', groupInfo: 'Group Info', platform: 'Platform', diff --git a/frontend/src/i18n/locales/zh.ts b/frontend/src/i18n/locales/zh.ts index f8d6b8588f..60bc6b1dc1 100644 --- a/frontend/src/i18n/locales/zh.ts +++ b/frontend/src/i18n/locales/zh.ts @@ -5607,6 +5607,7 @@ export default { tabPlanConfig: '套餐配置', tabUserSubs: '用户订阅', selectGroup: '请选择分组', + groupRequired: '请选择订阅分组', groupMissing: '缺失', groupInfo: '分组信息', platform: '平台', diff --git a/frontend/src/views/admin/orders/AdminPaymentPlansView.vue b/frontend/src/views/admin/orders/AdminPaymentPlansView.vue index 639b4f666e..fc7bff44aa 100644 --- a/frontend/src/views/admin/orders/AdminPaymentPlansView.vue +++ b/frontend/src/views/admin/orders/AdminPaymentPlansView.vue @@ -29,7 +29,7 @@ @@ -71,12 +71,12 @@
- +
- -