收口审计治理与套餐任务进展
Constraint: 在线热修前必须保存当前迭代分支全部有效代码进展 Confidence: medium Scope-risk: broad Directive: 后续修改需保持审计事件与业务事务边界一致 Tested: git diff --cached --check Not-tested: 未运行全量测试,提交用于切换分支前保存既有工作
This commit is contained in:
@@ -7,6 +7,7 @@ import (
|
||||
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/break/junhong_cmp_fiber/internal/infrastructure/audit"
|
||||
"github.com/break/junhong_cmp_fiber/internal/model"
|
||||
"github.com/break/junhong_cmp_fiber/internal/model/dto"
|
||||
"github.com/break/junhong_cmp_fiber/internal/service/packageprice"
|
||||
@@ -18,10 +19,12 @@ import (
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
db *gorm.DB
|
||||
packageStore *postgres.PackageStore
|
||||
packageSeriesStore *postgres.PackageSeriesStore
|
||||
packageAllocationStore *postgres.ShopPackageAllocationStore
|
||||
shopSeriesAllocationStore *postgres.ShopSeriesAllocationStore
|
||||
auditWriter *audit.Writer
|
||||
}
|
||||
|
||||
func New(
|
||||
@@ -38,7 +41,7 @@ func New(
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Service) Create(ctx context.Context, req *dto.CreatePackageRequest) (*dto.PackageResponse, error) {
|
||||
func (s *Service) Create(ctx context.Context, req *dto.CreatePackageRequest) (_ *dto.PackageResponse, retErr error) {
|
||||
currentUserID := middleware.GetUserIDFromContext(ctx)
|
||||
if currentUserID == 0 {
|
||||
return nil, errors.New(errors.CodeUnauthorized, "未授权访问")
|
||||
@@ -114,6 +117,13 @@ func (s *Service) Create(ctx context.Context, req *dto.CreatePackageRequest) (*d
|
||||
Status: constants.StatusEnabled,
|
||||
ShelfStatus: 2,
|
||||
}
|
||||
defer func() {
|
||||
if retErr != nil {
|
||||
failedPackage := *pkg
|
||||
failedPackage.ID = 0
|
||||
s.recordPackageFailure(ctx, constants.AuditActionPackageCreated, "创建套餐商品失败 "+pkg.PackageCode, &failedPackage, nil, retErr)
|
||||
}
|
||||
}()
|
||||
if req.SeriesID != nil {
|
||||
pkg.SeriesID = *req.SeriesID
|
||||
}
|
||||
@@ -140,8 +150,13 @@ func (s *Service) Create(ctx context.Context, req *dto.CreatePackageRequest) (*d
|
||||
pkg.VirtualRatio = calculateVirtualRatio(pkg.EnableVirtualData, pkg.RealDataMB, pkg.VirtualDataMB)
|
||||
pkg.Creator = currentUserID
|
||||
|
||||
if err := s.packageStore.Create(ctx, pkg); err != nil {
|
||||
return nil, errors.Wrap(errors.CodeInternalError, err, "创建套餐失败")
|
||||
if err := s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||
if err := postgres.NewPackageStore(tx).Create(ctx, pkg); err != nil {
|
||||
return errors.Wrap(errors.CodeInternalError, err, "创建套餐失败")
|
||||
}
|
||||
return s.appendPackageAudit(ctx, tx, constants.AuditActionPackageCreated, "创建套餐商品 "+pkg.PackageCode, pkg, nil, packageData(pkg))
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp := s.toResponse(ctx, pkg)
|
||||
@@ -157,7 +172,6 @@ func (s *Service) Get(ctx context.Context, id uint) (*dto.PackageResponse, error
|
||||
}
|
||||
return nil, errors.Wrap(errors.CodeInternalError, err, "获取套餐失败")
|
||||
}
|
||||
|
||||
resp := s.toResponse(ctx, pkg)
|
||||
// 查询系列名称
|
||||
if pkg.SeriesID > 0 {
|
||||
@@ -191,7 +205,7 @@ func (s *Service) Get(ctx context.Context, id uint) (*dto.PackageResponse, error
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (s *Service) Update(ctx context.Context, id uint, req *dto.UpdatePackageRequest) (*dto.PackageResponse, error) {
|
||||
func (s *Service) Update(ctx context.Context, id uint, req *dto.UpdatePackageRequest) (_ *dto.PackageResponse, retErr error) {
|
||||
currentUserID := middleware.GetUserIDFromContext(ctx)
|
||||
if currentUserID == 0 {
|
||||
return nil, errors.New(errors.CodeUnauthorized, "未授权访问")
|
||||
@@ -204,6 +218,12 @@ func (s *Service) Update(ctx context.Context, id uint, req *dto.UpdatePackageReq
|
||||
}
|
||||
return nil, errors.Wrap(errors.CodeInternalError, err, "获取套餐失败")
|
||||
}
|
||||
before := *pkg
|
||||
defer func() {
|
||||
if retErr != nil {
|
||||
s.recordPackageFailure(ctx, constants.AuditActionPackageUpdated, "更新套餐商品失败 "+before.PackageCode, &before, packageData(&before), retErr)
|
||||
}
|
||||
}()
|
||||
|
||||
var seriesName *string
|
||||
if req.SeriesID != nil && *req.SeriesID > 0 {
|
||||
@@ -305,8 +325,13 @@ func (s *Service) Update(ctx context.Context, id uint, req *dto.UpdatePackageReq
|
||||
pkg.VirtualRatio = calculateVirtualRatio(pkg.EnableVirtualData, pkg.RealDataMB, pkg.VirtualDataMB)
|
||||
pkg.Updater = currentUserID
|
||||
|
||||
if err := s.packageStore.Update(ctx, pkg); err != nil {
|
||||
return nil, errors.Wrap(errors.CodeInternalError, err, "更新套餐失败")
|
||||
if err := s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||
if err := postgres.NewPackageStore(tx).Update(ctx, pkg); err != nil {
|
||||
return errors.Wrap(errors.CodeInternalError, err, "更新套餐失败")
|
||||
}
|
||||
return s.appendPackageAudit(ctx, tx, constants.AuditActionPackageUpdated, "更新套餐商品 "+pkg.PackageCode, pkg, packageData(&before), packageData(pkg))
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp := s.toResponse(ctx, pkg)
|
||||
@@ -314,20 +339,26 @@ func (s *Service) Update(ctx context.Context, id uint, req *dto.UpdatePackageReq
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (s *Service) Delete(ctx context.Context, id uint) error {
|
||||
_, err := s.packageStore.GetByID(ctx, id)
|
||||
func (s *Service) Delete(ctx context.Context, id uint) (retErr error) {
|
||||
pkg, err := s.packageStore.GetByID(ctx, id)
|
||||
if err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return errors.New(errors.CodeNotFound, "套餐不存在")
|
||||
}
|
||||
return errors.Wrap(errors.CodeInternalError, err, "获取套餐失败")
|
||||
}
|
||||
defer func() {
|
||||
if retErr != nil {
|
||||
s.recordPackageFailure(ctx, constants.AuditActionPackageDeleted, "删除套餐商品失败 "+pkg.PackageCode, pkg, packageData(pkg), retErr)
|
||||
}
|
||||
}()
|
||||
|
||||
if err := s.packageStore.Delete(ctx, id); err != nil {
|
||||
return errors.Wrap(errors.CodeInternalError, err, "删除套餐失败")
|
||||
}
|
||||
|
||||
return nil
|
||||
return s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||
if err := postgres.NewPackageStore(tx).Delete(ctx, id); err != nil {
|
||||
return errors.Wrap(errors.CodeInternalError, err, "删除套餐失败")
|
||||
}
|
||||
return s.appendPackageAudit(ctx, tx, constants.AuditActionPackageDeleted, "删除套餐商品 "+pkg.PackageCode, pkg, packageData(pkg), map[string]any{"deleted": true})
|
||||
})
|
||||
}
|
||||
|
||||
func (s *Service) List(ctx context.Context, req *dto.PackageListRequest) ([]*dto.PackageResponse, int64, error) {
|
||||
@@ -444,7 +475,7 @@ func (s *Service) batchGetSeriesAllocationsForShop(ctx context.Context, shopID u
|
||||
return result
|
||||
}
|
||||
|
||||
func (s *Service) UpdateStatus(ctx context.Context, id uint, status int) error {
|
||||
func (s *Service) UpdateStatus(ctx context.Context, id uint, status int) (retErr error) {
|
||||
currentUserID := middleware.GetUserIDFromContext(ctx)
|
||||
if currentUserID == 0 {
|
||||
return errors.New(errors.CodeUnauthorized, "未授权访问")
|
||||
@@ -457,6 +488,12 @@ func (s *Service) UpdateStatus(ctx context.Context, id uint, status int) error {
|
||||
}
|
||||
return errors.Wrap(errors.CodeInternalError, err, "获取套餐失败")
|
||||
}
|
||||
before := *pkg
|
||||
defer func() {
|
||||
if retErr != nil {
|
||||
s.recordPackageFailure(ctx, constants.AuditActionPackageStatusUpdated, "更新套餐商品状态失败 "+before.PackageCode, &before, map[string]any{"status": before.Status, "shelf_status": before.ShelfStatus}, retErr)
|
||||
}
|
||||
}()
|
||||
|
||||
pkg.Status = status
|
||||
pkg.Updater = currentUserID
|
||||
@@ -465,14 +502,16 @@ func (s *Service) UpdateStatus(ctx context.Context, id uint, status int) error {
|
||||
pkg.ShelfStatus = 2
|
||||
}
|
||||
|
||||
if err := s.packageStore.Update(ctx, pkg); err != nil {
|
||||
return errors.Wrap(errors.CodeInternalError, err, "更新套餐状态失败")
|
||||
}
|
||||
|
||||
return nil
|
||||
return s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||
if err := postgres.NewPackageStore(tx).Update(ctx, pkg); err != nil {
|
||||
return errors.Wrap(errors.CodeInternalError, err, "更新套餐状态失败")
|
||||
}
|
||||
return s.appendPackageAudit(ctx, tx, constants.AuditActionPackageStatusUpdated, "更新套餐商品状态 "+pkg.PackageCode, pkg,
|
||||
map[string]any{"status": before.Status, "shelf_status": before.ShelfStatus}, map[string]any{"status": pkg.Status, "shelf_status": pkg.ShelfStatus})
|
||||
})
|
||||
}
|
||||
|
||||
func (s *Service) UpdateShelfStatus(ctx context.Context, id uint, shelfStatus int) error {
|
||||
func (s *Service) UpdateShelfStatus(ctx context.Context, id uint, shelfStatus int) (retErr error) {
|
||||
currentUserID := middleware.GetUserIDFromContext(ctx)
|
||||
if currentUserID == 0 {
|
||||
return errors.New(errors.CodeUnauthorized, "未授权访问")
|
||||
@@ -493,6 +532,12 @@ func (s *Service) UpdateShelfStatus(ctx context.Context, id uint, shelfStatus in
|
||||
}
|
||||
return errors.Wrap(errors.CodeInternalError, err, "获取套餐失败")
|
||||
}
|
||||
before := *pkg
|
||||
defer func() {
|
||||
if retErr != nil {
|
||||
s.recordPackageFailure(ctx, constants.AuditActionPackageShelfStatusUpdated, "更新套餐上架状态失败 "+before.PackageCode, &before, map[string]any{"shelf_status": before.ShelfStatus}, retErr)
|
||||
}
|
||||
}()
|
||||
|
||||
if shelfStatus == constants.ShelfStatusOn && pkg.Status == constants.StatusDisabled {
|
||||
return errors.New(errors.CodeInvalidStatus, "禁用的套餐不能上架,请先启用")
|
||||
@@ -501,15 +546,17 @@ func (s *Service) UpdateShelfStatus(ctx context.Context, id uint, shelfStatus in
|
||||
pkg.ShelfStatus = shelfStatus
|
||||
pkg.Updater = currentUserID
|
||||
|
||||
if err := s.packageStore.Update(ctx, pkg); err != nil {
|
||||
return errors.Wrap(errors.CodeInternalError, err, "更新套餐上架状态失败")
|
||||
}
|
||||
|
||||
return nil
|
||||
return s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||
if err := postgres.NewPackageStore(tx).Update(ctx, pkg); err != nil {
|
||||
return errors.Wrap(errors.CodeInternalError, err, "更新套餐上架状态失败")
|
||||
}
|
||||
return s.appendPackageAudit(ctx, tx, constants.AuditActionPackageShelfStatusUpdated, "更新套餐上架状态 "+pkg.PackageCode, pkg,
|
||||
map[string]any{"shelf_status": before.ShelfStatus}, map[string]any{"shelf_status": pkg.ShelfStatus})
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateRetailPrice 代理修改自己店铺的套餐零售价
|
||||
func (s *Service) UpdateRetailPrice(ctx context.Context, packageID uint, retailPrice int64) error {
|
||||
func (s *Service) UpdateRetailPrice(ctx context.Context, packageID uint, retailPrice int64) (retErr error) {
|
||||
currentUserID := middleware.GetUserIDFromContext(ctx)
|
||||
if currentUserID == 0 {
|
||||
return errors.New(errors.CodeUnauthorized, "未授权访问")
|
||||
@@ -540,6 +587,14 @@ func (s *Service) UpdateRetailPrice(ctx context.Context, packageID uint, retailP
|
||||
}
|
||||
return errors.Wrap(errors.CodeInternalError, err, "获取套餐失败")
|
||||
}
|
||||
beforePrice, beforeStatus := allocation.RetailPrice, allocation.RetailPriceConfigStatus
|
||||
beforeAllocation := *allocation
|
||||
defer func() {
|
||||
if retErr != nil {
|
||||
s.recordAllocationFailure(ctx, constants.AuditActionPackageRetailPriceUpdated, "更新店铺套餐零售价失败 "+pkg.PackageCode, &beforeAllocation, pkg,
|
||||
map[string]any{"retail_price": beforePrice, "retail_price_config_status": beforeStatus}, retErr)
|
||||
}
|
||||
}()
|
||||
if pkg.IsGift {
|
||||
return errors.New(errors.CodeForbidden, "赠送套餐不允许代理修改零售价")
|
||||
}
|
||||
@@ -550,16 +605,19 @@ func (s *Service) UpdateRetailPrice(ctx context.Context, packageID uint, retailP
|
||||
if retailPrice < allocation.CostPrice {
|
||||
return errors.New(errors.CodeInvalidParam, "零售价不能低于成本价")
|
||||
}
|
||||
|
||||
if err := s.packageAllocationStore.UpdateRetailPrice(ctx, allocation.ID, storedRetailPrice, priceConfigStatus, currentUserID); err != nil {
|
||||
return errors.Wrap(errors.CodeInternalError, err, "更新零售价失败")
|
||||
}
|
||||
|
||||
return nil
|
||||
return s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||
if err := postgres.NewShopPackageAllocationStore(tx).UpdateRetailPrice(ctx, allocation.ID, storedRetailPrice, priceConfigStatus, currentUserID); err != nil {
|
||||
return errors.Wrap(errors.CodeInternalError, err, "更新零售价失败")
|
||||
}
|
||||
allocation.RetailPrice, allocation.RetailPriceConfigStatus = storedRetailPrice, priceConfigStatus
|
||||
return s.appendAllocationAudit(ctx, tx, constants.AuditActionPackageRetailPriceUpdated, "更新店铺套餐零售价 "+pkg.PackageCode, allocation, pkg,
|
||||
map[string]any{"retail_price": beforePrice, "retail_price_config_status": beforeStatus},
|
||||
map[string]any{"retail_price": storedRetailPrice, "retail_price_config_status": priceConfigStatus})
|
||||
})
|
||||
}
|
||||
|
||||
// updateAgentShelfStatus 代理上下架路径:更新分配记录的 shelf_status
|
||||
func (s *Service) updateAgentShelfStatus(ctx context.Context, packageID uint, shelfStatus int, updaterID uint) error {
|
||||
func (s *Service) updateAgentShelfStatus(ctx context.Context, packageID uint, shelfStatus int, updaterID uint) (retErr error) {
|
||||
shopID := middleware.GetShopIDFromContext(ctx)
|
||||
if shopID == 0 {
|
||||
return errors.New(errors.CodeUnauthorized, "当前用户不属于任何店铺")
|
||||
@@ -573,26 +631,34 @@ func (s *Service) updateAgentShelfStatus(ctx context.Context, packageID uint, sh
|
||||
}
|
||||
return errors.Wrap(errors.CodeInternalError, err, "获取分配记录失败")
|
||||
}
|
||||
beforeShelfStatus := allocation.ShelfStatus
|
||||
beforeAllocation := *allocation
|
||||
pkg, err := s.packageStore.GetByID(ctx, packageID)
|
||||
if err != nil {
|
||||
return errors.New(errors.CodeNotFound, "套餐不存在")
|
||||
}
|
||||
defer func() {
|
||||
if retErr != nil {
|
||||
s.recordAllocationFailure(ctx, constants.AuditActionShopPackageShelfStatusUpdated, "更新店铺套餐上架状态失败 "+pkg.PackageCode, &beforeAllocation, pkg,
|
||||
map[string]any{"shelf_status": beforeShelfStatus}, retErr)
|
||||
}
|
||||
}()
|
||||
|
||||
// 上架时检查套餐全局禁用状态
|
||||
if shelfStatus == constants.ShelfStatusOn {
|
||||
pkg, err := s.packageStore.GetByID(ctx, packageID)
|
||||
if err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return errors.New(errors.CodeNotFound, "套餐不存在")
|
||||
}
|
||||
return errors.Wrap(errors.CodeInternalError, err, "获取套餐失败")
|
||||
}
|
||||
if pkg.Status == constants.StatusDisabled {
|
||||
return errors.New(errors.CodeInvalidStatus, "套餐已禁用,无法上架")
|
||||
}
|
||||
}
|
||||
|
||||
if err := s.packageAllocationStore.UpdateShelfStatus(ctx, allocation.ID, shelfStatus, updaterID); err != nil {
|
||||
return errors.Wrap(errors.CodeInternalError, err, "更新上下架状态失败")
|
||||
}
|
||||
|
||||
return nil
|
||||
return s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||
if err := postgres.NewShopPackageAllocationStore(tx).UpdateShelfStatus(ctx, allocation.ID, shelfStatus, updaterID); err != nil {
|
||||
return errors.Wrap(errors.CodeInternalError, err, "更新上下架状态失败")
|
||||
}
|
||||
allocation.ShelfStatus = shelfStatus
|
||||
return s.appendAllocationAudit(ctx, tx, constants.AuditActionShopPackageShelfStatusUpdated, "更新店铺套餐上架状态 "+pkg.PackageCode, allocation, pkg,
|
||||
map[string]any{"shelf_status": beforeShelfStatus}, map[string]any{"shelf_status": shelfStatus})
|
||||
})
|
||||
}
|
||||
|
||||
func (s *Service) toResponse(ctx context.Context, pkg *model.Package) *dto.PackageResponse {
|
||||
@@ -607,29 +673,29 @@ 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,
|
||||
IsGift: pkg.IsGift,
|
||||
DurationMonths: pkg.DurationMonths,
|
||||
RealDataMB: pkg.RealDataMB,
|
||||
VirtualDataMB: pkg.VirtualDataMB,
|
||||
EnableVirtualData: pkg.EnableVirtualData,
|
||||
VirtualRatio: calculateVirtualRatio(pkg.EnableVirtualData, pkg.RealDataMB, pkg.VirtualDataMB),
|
||||
CostPrice: pkg.CostPrice,
|
||||
SuggestedRetailPrice: packageprice.PackageRawSuggestedRetailPrice(pkg),
|
||||
PriceConfigStatus: pkg.PriceConfigStatus,
|
||||
PriceConfigStatusName: packagePriceConfigStatusName(pkg.PriceConfigStatus),
|
||||
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),
|
||||
ID: pkg.ID,
|
||||
PackageCode: pkg.PackageCode,
|
||||
PackageName: pkg.PackageName,
|
||||
SeriesID: seriesID,
|
||||
PackageType: pkg.PackageType,
|
||||
IsGift: pkg.IsGift,
|
||||
DurationMonths: pkg.DurationMonths,
|
||||
RealDataMB: pkg.RealDataMB,
|
||||
VirtualDataMB: pkg.VirtualDataMB,
|
||||
EnableVirtualData: pkg.EnableVirtualData,
|
||||
VirtualRatio: calculateVirtualRatio(pkg.EnableVirtualData, pkg.RealDataMB, pkg.VirtualDataMB),
|
||||
CostPrice: pkg.CostPrice,
|
||||
SuggestedRetailPrice: packageprice.PackageRawSuggestedRetailPrice(pkg),
|
||||
PriceConfigStatus: pkg.PriceConfigStatus,
|
||||
PriceConfigStatusName: packagePriceConfigStatusName(pkg.PriceConfigStatus),
|
||||
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),
|
||||
}
|
||||
initPackageExpiryBaseFields(resp, pkg)
|
||||
|
||||
@@ -686,29 +752,29 @@ 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,
|
||||
IsGift: pkg.IsGift,
|
||||
DurationMonths: pkg.DurationMonths,
|
||||
RealDataMB: pkg.RealDataMB,
|
||||
VirtualDataMB: pkg.VirtualDataMB,
|
||||
EnableVirtualData: pkg.EnableVirtualData,
|
||||
VirtualRatio: calculateVirtualRatio(pkg.EnableVirtualData, pkg.RealDataMB, pkg.VirtualDataMB),
|
||||
CostPrice: pkg.CostPrice,
|
||||
SuggestedRetailPrice: packageprice.PackageRawSuggestedRetailPrice(pkg),
|
||||
PriceConfigStatus: pkg.PriceConfigStatus,
|
||||
PriceConfigStatusName: packagePriceConfigStatusName(pkg.PriceConfigStatus),
|
||||
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),
|
||||
ID: pkg.ID,
|
||||
PackageCode: pkg.PackageCode,
|
||||
PackageName: pkg.PackageName,
|
||||
SeriesID: seriesID,
|
||||
PackageType: pkg.PackageType,
|
||||
IsGift: pkg.IsGift,
|
||||
DurationMonths: pkg.DurationMonths,
|
||||
RealDataMB: pkg.RealDataMB,
|
||||
VirtualDataMB: pkg.VirtualDataMB,
|
||||
EnableVirtualData: pkg.EnableVirtualData,
|
||||
VirtualRatio: calculateVirtualRatio(pkg.EnableVirtualData, pkg.RealDataMB, pkg.VirtualDataMB),
|
||||
CostPrice: pkg.CostPrice,
|
||||
SuggestedRetailPrice: packageprice.PackageRawSuggestedRetailPrice(pkg),
|
||||
PriceConfigStatus: pkg.PriceConfigStatus,
|
||||
PriceConfigStatusName: packagePriceConfigStatusName(pkg.PriceConfigStatus),
|
||||
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),
|
||||
}
|
||||
initPackageExpiryBaseFields(resp, pkg)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user