From 244a2742c12b0d5cc53031eba6cfc8c25cf874df Mon Sep 17 00:00:00 2001 From: huang Date: Sat, 28 Mar 2026 10:37:51 +0800 Subject: [PATCH] =?UTF-8?q?fix(realname):=20DTO=20=E6=9B=B4=E6=96=B0=20exp?= =?UTF-8?q?iry=5Fbase=20=E6=9B=BF=E6=8D=A2=20enable=5Frealname=5Factivatio?= =?UTF-8?q?n=20REALNAME-05?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - package_dto.go: CreatePackageRequest/UpdatePackageRequest/PackageResponse 三处替换 - service.go: 同步更新 DTO 映射逻辑使用 ExpiryBase --- internal/model/dto/package_dto.go | 106 ++++++++++++++-------------- internal/service/package/service.go | 90 +++++++++++------------ 2 files changed, 98 insertions(+), 98 deletions(-) diff --git a/internal/model/dto/package_dto.go b/internal/model/dto/package_dto.go index 810b501..8bdc2c5 100644 --- a/internal/model/dto/package_dto.go +++ b/internal/model/dto/package_dto.go @@ -2,37 +2,37 @@ package dto // CreatePackageRequest 创建套餐请求 type CreatePackageRequest struct { - PackageCode string `json:"package_code" validate:"required,min=1,max=100" required:"true" minLength:"1" maxLength:"100" description:"套餐编码"` - PackageName string `json:"package_name" validate:"required,min=1,max=255" required:"true" minLength:"1" maxLength:"255" description:"套餐名称"` - SeriesID *uint `json:"series_id" validate:"omitempty" description:"套餐系列ID"` - PackageType string `json:"package_type" validate:"required,oneof=formal addon" required:"true" description:"套餐类型 (formal:正式套餐, addon:附加套餐)"` - DurationMonths int `json:"duration_months" validate:"required,min=1,max=120" required:"true" minimum:"1" maximum:"120" description:"套餐时长(月数)"` - RealDataMB *int64 `json:"real_data_mb" validate:"omitempty,min=0" minimum:"0" description:"真流量额度(MB)"` - VirtualDataMB *int64 `json:"virtual_data_mb" validate:"omitempty,min=0" minimum:"0" description:"虚流量额度(MB)"` - EnableVirtualData bool `json:"enable_virtual_data" description:"是否启用虚流量"` - SuggestedRetailPrice *int64 `json:"suggested_retail_price" validate:"omitempty,min=0" minimum:"0" description:"建议售价(分)"` - CostPrice int64 `json:"cost_price" validate:"required,min=0" required:"true" minimum:"0" description:"成本价(分)"` - CalendarType *string `json:"calendar_type" validate:"omitempty,oneof=natural_month by_day" description:"套餐周期类型 (natural_month:自然月, by_day:按天)"` - DurationDays *int `json:"duration_days" validate:"omitempty,min=1,max=3650" minimum:"1" maximum:"3650" description:"套餐天数(calendar_type=by_day时必填)"` - DataResetCycle *string `json:"data_reset_cycle" validate:"omitempty,oneof=daily monthly yearly none" description:"流量重置周期 (daily:每日, monthly:每月, yearly:每年, none:不重置)"` - EnableRealnameActivation *bool `json:"enable_realname_activation" description:"是否启用实名激活 (true:需实名后激活, false:立即激活)"` + PackageCode string `json:"package_code" validate:"required,min=1,max=100" required:"true" minLength:"1" maxLength:"100" description:"套餐编码"` + PackageName string `json:"package_name" validate:"required,min=1,max=255" required:"true" minLength:"1" maxLength:"255" description:"套餐名称"` + SeriesID *uint `json:"series_id" validate:"omitempty" description:"套餐系列ID"` + PackageType string `json:"package_type" validate:"required,oneof=formal addon" required:"true" description:"套餐类型 (formal:正式套餐, addon:附加套餐)"` + DurationMonths int `json:"duration_months" validate:"required,min=1,max=120" required:"true" minimum:"1" maximum:"120" description:"套餐时长(月数)"` + RealDataMB *int64 `json:"real_data_mb" validate:"omitempty,min=0" minimum:"0" description:"真流量额度(MB)"` + VirtualDataMB *int64 `json:"virtual_data_mb" validate:"omitempty,min=0" minimum:"0" description:"虚流量额度(MB)"` + EnableVirtualData bool `json:"enable_virtual_data" description:"是否启用虚流量"` + SuggestedRetailPrice *int64 `json:"suggested_retail_price" validate:"omitempty,min=0" minimum:"0" description:"建议售价(分)"` + CostPrice int64 `json:"cost_price" validate:"required,min=0" required:"true" minimum:"0" description:"成本价(分)"` + CalendarType *string `json:"calendar_type" validate:"omitempty,oneof=natural_month by_day" description:"套餐周期类型 (natural_month:自然月, by_day:按天)"` + DurationDays *int `json:"duration_days" validate:"omitempty,min=1,max=3650" minimum:"1" maximum:"3650" description:"套餐天数(calendar_type=by_day时必填)"` + DataResetCycle *string `json:"data_reset_cycle" validate:"omitempty,oneof=daily monthly yearly none" description:"流量重置周期 (daily:每日, monthly:每月, yearly:每年, none:不重置)"` + ExpiryBase string `json:"expiry_base" validate:"omitempty,oneof=from_activation from_purchase" description:"到期时间基准 (from_activation:实名激活时起算, from_purchase:购买时起算)" example:"from_activation"` } // UpdatePackageRequest 更新套餐请求 type UpdatePackageRequest struct { - PackageName *string `json:"package_name" validate:"omitempty,min=1,max=255" minLength:"1" maxLength:"255" description:"套餐名称"` - SeriesID *uint `json:"series_id" validate:"omitempty" description:"套餐系列ID"` - PackageType *string `json:"package_type" validate:"omitempty,oneof=formal addon" description:"套餐类型 (formal:正式套餐, addon:附加套餐)"` - DurationMonths *int `json:"duration_months" validate:"omitempty,min=1,max=120" minimum:"1" maximum:"120" description:"套餐时长(月数)"` - RealDataMB *int64 `json:"real_data_mb" validate:"omitempty,min=0" minimum:"0" description:"真流量额度(MB)"` - VirtualDataMB *int64 `json:"virtual_data_mb" validate:"omitempty,min=0" minimum:"0" description:"虚流量额度(MB)"` - EnableVirtualData *bool `json:"enable_virtual_data" description:"是否启用虚流量"` - SuggestedRetailPrice *int64 `json:"suggested_retail_price" validate:"omitempty,min=0" minimum:"0" description:"建议售价(分)"` - CostPrice *int64 `json:"cost_price" validate:"omitempty,min=0" minimum:"0" description:"成本价(分)"` - CalendarType *string `json:"calendar_type" validate:"omitempty,oneof=natural_month by_day" description:"套餐周期类型 (natural_month:自然月, by_day:按天)"` - DurationDays *int `json:"duration_days" validate:"omitempty,min=1,max=3650" minimum:"1" maximum:"3650" description:"套餐天数(calendar_type=by_day时必填)"` - DataResetCycle *string `json:"data_reset_cycle" validate:"omitempty,oneof=daily monthly yearly none" description:"流量重置周期 (daily:每日, monthly:每月, yearly:每年, none:不重置)"` - EnableRealnameActivation *bool `json:"enable_realname_activation" description:"是否启用实名激活 (true:需实名后激活, false:立即激活)"` + PackageName *string `json:"package_name" validate:"omitempty,min=1,max=255" minLength:"1" maxLength:"255" description:"套餐名称"` + SeriesID *uint `json:"series_id" validate:"omitempty" description:"套餐系列ID"` + PackageType *string `json:"package_type" validate:"omitempty,oneof=formal addon" description:"套餐类型 (formal:正式套餐, addon:附加套餐)"` + DurationMonths *int `json:"duration_months" validate:"omitempty,min=1,max=120" minimum:"1" maximum:"120" description:"套餐时长(月数)"` + RealDataMB *int64 `json:"real_data_mb" validate:"omitempty,min=0" minimum:"0" description:"真流量额度(MB)"` + VirtualDataMB *int64 `json:"virtual_data_mb" validate:"omitempty,min=0" minimum:"0" description:"虚流量额度(MB)"` + EnableVirtualData *bool `json:"enable_virtual_data" description:"是否启用虚流量"` + SuggestedRetailPrice *int64 `json:"suggested_retail_price" validate:"omitempty,min=0" minimum:"0" description:"建议售价(分)"` + CostPrice *int64 `json:"cost_price" validate:"omitempty,min=0" minimum:"0" description:"成本价(分)"` + CalendarType *string `json:"calendar_type" validate:"omitempty,oneof=natural_month by_day" description:"套餐周期类型 (natural_month:自然月, by_day:按天)"` + DurationDays *int `json:"duration_days" validate:"omitempty,min=1,max=3650" minimum:"1" maximum:"3650" description:"套餐天数(calendar_type=by_day时必填)"` + DataResetCycle *string `json:"data_reset_cycle" validate:"omitempty,oneof=daily monthly yearly none" description:"流量重置周期 (daily:每日, monthly:每月, yearly:每年, none:不重置)"` + ExpiryBase *string `json:"expiry_base" validate:"omitempty,oneof=from_activation from_purchase" description:"到期时间基准 (from_activation:实名激活时起算, from_purchase:购买时起算)"` } // PackageListRequest 套餐列表请求 @@ -70,32 +70,32 @@ type CommissionTierInfo struct { // PackageResponse 套餐响应 type PackageResponse struct { - ID uint `json:"id" description:"套餐ID"` - PackageCode string `json:"package_code" description:"套餐编码"` - PackageName string `json:"package_name" description:"套餐名称"` - SeriesID *uint `json:"series_id" description:"套餐系列ID"` - SeriesName *string `json:"series_name" description:"套餐系列名称"` - PackageType string `json:"package_type" description:"套餐类型 (formal:正式套餐, addon:附加套餐)"` - DurationMonths int `json:"duration_months" description:"套餐时长(月数)"` - RealDataMB int64 `json:"real_data_mb" description:"真流量额度(MB)"` - VirtualDataMB int64 `json:"virtual_data_mb" description:"虚流量额度(MB)"` - EnableVirtualData bool `json:"enable_virtual_data" description:"是否启用虚流量"` - VirtualRatio float64 `json:"virtual_ratio" description:"虚流量比例(real_data_mb/virtual_data_mb),启用虚流量时计算,否则为1.0"` - SuggestedRetailPrice int64 `json:"suggested_retail_price" description:"建议售价(分)"` - CostPrice int64 `json:"cost_price" description:"成本价(分)"` - OneTimeCommissionAmount *int64 `json:"one_time_commission_amount,omitempty" description:"一次性佣金金额(分,代理视角)"` - Status int `json:"status" description:"状态 (1:启用, 2:禁用)"` - ShelfStatus int `json:"shelf_status" description:"上架状态 (1:上架, 2:下架)"` - CreatedAt string `json:"created_at" description:"创建时间"` - UpdatedAt string `json:"updated_at" description:"更新时间"` - RetailPrice *int64 `json:"retail_price,omitempty" description:"代理零售价(分),仅代理用户可见"` - ProfitMargin *int64 `json:"profit_margin,omitempty" description:"利润空间(分,仅代理用户可见)"` - CurrentCommissionRate string `json:"current_commission_rate,omitempty" description:"当前返佣比例(仅代理用户可见)"` - TierInfo *CommissionTierInfo `json:"tier_info,omitempty" description:"梯度返佣信息(仅代理用户可见)"` - CalendarType string `json:"calendar_type" description:"套餐周期类型 (natural_month:自然月, by_day:按天)"` - DurationDays *int `json:"duration_days,omitempty" description:"套餐天数(calendar_type=by_day时有值)"` - DataResetCycle string `json:"data_reset_cycle" description:"流量重置周期 (daily:每日, monthly:每月, yearly:每年, none:不重置)"` - EnableRealnameActivation bool `json:"enable_realname_activation" description:"是否启用实名激活 (true:需实名后激活, false:立即激活)"` + ID uint `json:"id" description:"套餐ID"` + PackageCode string `json:"package_code" description:"套餐编码"` + PackageName string `json:"package_name" description:"套餐名称"` + SeriesID *uint `json:"series_id" description:"套餐系列ID"` + SeriesName *string `json:"series_name" description:"套餐系列名称"` + PackageType string `json:"package_type" description:"套餐类型 (formal:正式套餐, addon:附加套餐)"` + DurationMonths int `json:"duration_months" description:"套餐时长(月数)"` + RealDataMB int64 `json:"real_data_mb" description:"真流量额度(MB)"` + VirtualDataMB int64 `json:"virtual_data_mb" description:"虚流量额度(MB)"` + EnableVirtualData bool `json:"enable_virtual_data" description:"是否启用虚流量"` + VirtualRatio float64 `json:"virtual_ratio" description:"虚流量比例(real_data_mb/virtual_data_mb),启用虚流量时计算,否则为1.0"` + SuggestedRetailPrice int64 `json:"suggested_retail_price" description:"建议售价(分)"` + CostPrice int64 `json:"cost_price" description:"成本价(分)"` + OneTimeCommissionAmount *int64 `json:"one_time_commission_amount,omitempty" description:"一次性佣金金额(分,代理视角)"` + Status int `json:"status" description:"状态 (1:启用, 2:禁用)"` + ShelfStatus int `json:"shelf_status" description:"上架状态 (1:上架, 2:下架)"` + CreatedAt string `json:"created_at" description:"创建时间"` + UpdatedAt string `json:"updated_at" description:"更新时间"` + RetailPrice *int64 `json:"retail_price,omitempty" description:"代理零售价(分),仅代理用户可见"` + ProfitMargin *int64 `json:"profit_margin,omitempty" description:"利润空间(分,仅代理用户可见)"` + CurrentCommissionRate string `json:"current_commission_rate,omitempty" description:"当前返佣比例(仅代理用户可见)"` + TierInfo *CommissionTierInfo `json:"tier_info,omitempty" description:"梯度返佣信息(仅代理用户可见)"` + CalendarType string `json:"calendar_type" description:"套餐周期类型 (natural_month:自然月, by_day:按天)"` + DurationDays *int `json:"duration_days,omitempty" description:"套餐天数(calendar_type=by_day时有值)"` + DataResetCycle string `json:"data_reset_cycle" description:"流量重置周期 (daily:每日, monthly:每月, yearly:每年, none:不重置)"` + ExpiryBase string `json:"expiry_base" description:"到期时间基准 (from_activation:实名激活时起算, from_purchase:购买时起算)"` } // UpdatePackageParams 更新套餐聚合参数 diff --git a/internal/service/package/service.go b/internal/service/package/service.go index 3c2eff3..9860c01 100644 --- a/internal/service/package/service.go +++ b/internal/service/package/service.go @@ -123,10 +123,10 @@ func (s *Service) Create(ctx context.Context, req *dto.CreatePackageRequest) (*d // 默认月重置 pkg.DataResetCycle = constants.PackageDataResetMonthly } - if req.EnableRealnameActivation != nil { - pkg.EnableRealnameActivation = *req.EnableRealnameActivation + if req.ExpiryBase != "" { + pkg.ExpiryBase = req.ExpiryBase } else { - pkg.EnableRealnameActivation = true + pkg.ExpiryBase = "from_activation" } pkg.VirtualRatio = calculateVirtualRatio(pkg.EnableVirtualData, pkg.RealDataMB, pkg.VirtualDataMB) pkg.Creator = currentUserID @@ -225,8 +225,8 @@ func (s *Service) Update(ctx context.Context, id uint, req *dto.UpdatePackageReq if req.DataResetCycle != nil { pkg.DataResetCycle = *req.DataResetCycle } - if req.EnableRealnameActivation != nil { - pkg.EnableRealnameActivation = *req.EnableRealnameActivation + if req.ExpiryBase != nil { + pkg.ExpiryBase = *req.ExpiryBase } // 校验套餐周期类型和时长配置 @@ -541,26 +541,26 @@ func (s *Service) toResponse(ctx context.Context, pkg *model.Package) *dto.Packa } resp := &dto.PackageResponse{ - ID: pkg.ID, - PackageCode: pkg.PackageCode, - PackageName: pkg.PackageName, - SeriesID: seriesID, - PackageType: pkg.PackageType, - DurationMonths: pkg.DurationMonths, - RealDataMB: pkg.RealDataMB, - VirtualDataMB: pkg.VirtualDataMB, - EnableVirtualData: pkg.EnableVirtualData, - VirtualRatio: calculateVirtualRatio(pkg.EnableVirtualData, pkg.RealDataMB, pkg.VirtualDataMB), - CostPrice: pkg.CostPrice, - SuggestedRetailPrice: pkg.SuggestedRetailPrice, - CalendarType: pkg.CalendarType, - DurationDays: durationDays, - DataResetCycle: pkg.DataResetCycle, - EnableRealnameActivation: pkg.EnableRealnameActivation, - Status: pkg.Status, - ShelfStatus: pkg.ShelfStatus, - CreatedAt: pkg.CreatedAt.Format(time.RFC3339), - UpdatedAt: pkg.UpdatedAt.Format(time.RFC3339), + ID: pkg.ID, + PackageCode: pkg.PackageCode, + PackageName: pkg.PackageName, + SeriesID: seriesID, + PackageType: pkg.PackageType, + DurationMonths: pkg.DurationMonths, + RealDataMB: pkg.RealDataMB, + VirtualDataMB: pkg.VirtualDataMB, + EnableVirtualData: pkg.EnableVirtualData, + VirtualRatio: calculateVirtualRatio(pkg.EnableVirtualData, pkg.RealDataMB, pkg.VirtualDataMB), + CostPrice: pkg.CostPrice, + SuggestedRetailPrice: pkg.SuggestedRetailPrice, + CalendarType: pkg.CalendarType, + DurationDays: durationDays, + DataResetCycle: pkg.DataResetCycle, + ExpiryBase: pkg.ExpiryBase, + Status: pkg.Status, + ShelfStatus: pkg.ShelfStatus, + CreatedAt: pkg.CreatedAt.Format(time.RFC3339), + UpdatedAt: pkg.UpdatedAt.Format(time.RFC3339), } userType := middleware.GetUserTypeFromContext(ctx) @@ -606,26 +606,26 @@ func (s *Service) toResponseWithAllocation(_ context.Context, pkg *model.Package } resp := &dto.PackageResponse{ - ID: pkg.ID, - PackageCode: pkg.PackageCode, - PackageName: pkg.PackageName, - SeriesID: seriesID, - PackageType: pkg.PackageType, - DurationMonths: pkg.DurationMonths, - RealDataMB: pkg.RealDataMB, - VirtualDataMB: pkg.VirtualDataMB, - EnableVirtualData: pkg.EnableVirtualData, - VirtualRatio: calculateVirtualRatio(pkg.EnableVirtualData, pkg.RealDataMB, pkg.VirtualDataMB), - CostPrice: pkg.CostPrice, - SuggestedRetailPrice: pkg.SuggestedRetailPrice, - CalendarType: pkg.CalendarType, - DurationDays: durationDays, - DataResetCycle: pkg.DataResetCycle, - EnableRealnameActivation: pkg.EnableRealnameActivation, - Status: pkg.Status, - ShelfStatus: pkg.ShelfStatus, - CreatedAt: pkg.CreatedAt.Format(time.RFC3339), - UpdatedAt: pkg.UpdatedAt.Format(time.RFC3339), + ID: pkg.ID, + PackageCode: pkg.PackageCode, + PackageName: pkg.PackageName, + SeriesID: seriesID, + PackageType: pkg.PackageType, + DurationMonths: pkg.DurationMonths, + RealDataMB: pkg.RealDataMB, + VirtualDataMB: pkg.VirtualDataMB, + EnableVirtualData: pkg.EnableVirtualData, + VirtualRatio: calculateVirtualRatio(pkg.EnableVirtualData, pkg.RealDataMB, pkg.VirtualDataMB), + CostPrice: pkg.CostPrice, + SuggestedRetailPrice: pkg.SuggestedRetailPrice, + CalendarType: pkg.CalendarType, + DurationDays: durationDays, + DataResetCycle: pkg.DataResetCycle, + ExpiryBase: pkg.ExpiryBase, + Status: pkg.Status, + ShelfStatus: pkg.ShelfStatus, + CreatedAt: pkg.CreatedAt.Format(time.RFC3339), + UpdatedAt: pkg.UpdatedAt.Format(time.RFC3339), } if allocationMap != nil {