实现套餐生效条件覆盖与购买快照

This commit is contained in:
2026-07-22 20:51:12 +09:00
parent c7f8b4c702
commit 9818537239
30 changed files with 1092 additions and 149 deletions

View File

@@ -0,0 +1,65 @@
// Package package 提供套餐生命周期领域规则。
package packagedomain
import (
"github.com/break/junhong_cmp_fiber/internal/model"
"github.com/break/junhong_cmp_fiber/pkg/constants"
"github.com/break/junhong_cmp_fiber/pkg/errors"
)
// TermsSnapshot 套餐购买时不可变计时条款。
type TermsSnapshot struct {
ExpiryBase string
CalendarType string
DurationMonths int
DurationDays int
}
// ResolveTermsSnapshot 解析并校验套餐购买时计时条款。
func ResolveTermsSnapshot(pkg *model.Package, allocation *model.ShopPackageAllocation) (TermsSnapshot, error) {
if pkg == nil {
return TermsSnapshot{}, errors.New(errors.CodeInvalidParam, "套餐计时条款缺失")
}
expiryBase := pkg.ExpiryBase
if allocation != nil && allocation.ExpiryBaseOverride != nil {
expiryBase = *allocation.ExpiryBaseOverride
}
if expiryBase != constants.PackageExpiryBaseFromActivation && expiryBase != constants.PackageExpiryBaseFromPurchase {
return TermsSnapshot{}, errors.New(errors.CodeInvalidParam, "套餐生效条件无效")
}
if pkg.CalendarType == constants.PackageCalendarTypeNaturalMonth {
if pkg.DurationMonths <= 0 {
return TermsSnapshot{}, errors.New(errors.CodeInvalidParam, "套餐自然月时长无效")
}
return TermsSnapshot{ExpiryBase: expiryBase, CalendarType: pkg.CalendarType, DurationMonths: pkg.DurationMonths}, nil
}
if pkg.CalendarType == constants.PackageCalendarTypeByDay && pkg.DurationDays > 0 {
return TermsSnapshot{ExpiryBase: expiryBase, CalendarType: pkg.CalendarType, DurationDays: pkg.DurationDays}, nil
}
return TermsSnapshot{}, errors.New(errors.CodeInvalidParam, "套餐按天时长无效")
}
// Apply 将计时条款写入套餐使用记录。
func (s TermsSnapshot) Apply(usage *model.PackageUsage) {
usage.ExpiryBaseSnapshot = s.ExpiryBase
usage.CalendarTypeSnapshot = s.CalendarType
usage.DurationMonthsSnapshot = s.DurationMonths
usage.DurationDaysSnapshot = s.DurationDays
}
// IsValid 判断快照是否完整有效。
func (s TermsSnapshot) IsValid() bool {
if s.ExpiryBase != constants.PackageExpiryBaseFromActivation && s.ExpiryBase != constants.PackageExpiryBaseFromPurchase {
return false
}
return (s.CalendarType == constants.PackageCalendarTypeNaturalMonth && s.DurationMonths > 0) ||
(s.CalendarType == constants.PackageCalendarTypeByDay && s.DurationDays > 0)
}
// TermsSnapshotFromUsage 从使用记录读取计时条款。
func TermsSnapshotFromUsage(usage *model.PackageUsage) TermsSnapshot {
return TermsSnapshot{
ExpiryBase: usage.ExpiryBaseSnapshot, CalendarType: usage.CalendarTypeSnapshot,
DurationMonths: usage.DurationMonthsSnapshot, DurationDays: usage.DurationDaysSnapshot,
}
}