package packageduration import ( "sort" "strconv" "git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/consts" "git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/model/entity" "github.com/gogf/gf/v2/encoding/gjson" "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/util/gconv" ) const ( FlowCycleUnitMonth = "month" RenewUnitYear = "year" ) // Policy is the normalized duration contract used by package-related business. // The database keeps the existing fields; this type separates their meanings. type Policy struct { FlowCycleUnit string RenewUnit string RenewableYears []int ChangeMonths []int } func FromPackage(pkg *entity.TSimFlowPackageInfo) (*Policy, error) { if pkg == nil { return nil, gerror.New("package information is empty") } years, err := RenewableYears(pkg) if err != nil { return nil, err } months, err := ChangeMonths(pkg) if err != nil { return nil, err } return &Policy{ FlowCycleUnit: FlowCycleUnitMonth, RenewUnit: RenewUnitYear, RenewableYears: years, ChangeMonths: months, }, nil } func MonthBillingMethodValue() string { return strconv.Itoa(consts.BillingMethodMonth) } func RenewableYears(pkg *entity.TSimFlowPackageInfo) ([]int, error) { if pkg == nil { return nil, gerror.New("package information is empty") } return renewableYearsFromConfig(pkg.RenewableDurationConfig) } func ChangeMonths(pkg *entity.TSimFlowPackageInfo) ([]int, error) { if pkg == nil { return nil, gerror.New("package information is empty") } values, legacyMonthConfig, err := rawDurationValues(pkg.RenewableDurationConfig) if err != nil { return nil, err } if legacyMonthConfig { return uniqueSorted(values), nil } months := make([]int, 0, len(values)) for _, year := range values { if year <= 0 { continue } months = append(months, year*12) } months = uniqueSorted(months) if len(months) == 0 { return nil, gerror.New("package has no valid change duration options") } return months, nil } // NormalizeRenewableDurationConfig converts legacy month values such as // [12,24,36] into the new year values [1,2,3] before saving a package. func NormalizeRenewableDurationConfig(config *gjson.Json) (*gjson.Json, error) { values, legacyMonthConfig, err := rawDurationValues(config) if err != nil { return nil, err } if legacyMonthConfig { years := make([]int, 0, len(values)) for _, month := range values { if month > 0 && month%12 == 0 { years = append(years, month/12) } } years = uniqueSorted(years) if len(years) == 0 { return nil, gerror.New("package has no valid renewable duration options") } return gjson.New(years), nil } return gjson.New(uniqueSorted(values)), nil } func NormalizeRenewableYears(values []int) []int { values = uniqueSorted(values) if len(values) == 0 { return nil } legacyMonthConfig := true for _, value := range values { if value < 12 || value%12 != 0 { legacyMonthConfig = false break } } if !legacyMonthConfig { return values } years := make([]int, 0, len(values)) for _, month := range values { if month > 0 && month%12 == 0 { years = append(years, month/12) } } return uniqueSorted(years) } func RenewMonths(years int) int { if years <= 0 { return 0 } return years * 12 } func renewableYearsFromConfig(config *gjson.Json) ([]int, error) { values, legacyMonthConfig, err := rawDurationValues(config) if err != nil { return nil, err } years := make([]int, 0, len(values)) for _, value := range values { if value <= 0 { continue } if legacyMonthConfig { if value%12 != 0 { continue } value /= 12 } years = append(years, value) } years = uniqueSorted(years) if len(years) == 0 { return nil, gerror.New("package has no valid renewable duration options") } return years, nil } func rawDurationValues(config *gjson.Json) ([]int, bool, error) { if config == nil || config.IsNil() { return nil, false, gerror.New("package has no renewable duration config") } values := config.Interfaces() if len(values) == 0 { return nil, false, gerror.New("package has no renewable duration config") } result := make([]int, 0, len(values)) for _, value := range values { parsed := gconv.Int(value) if parsed > 0 { result = append(result, parsed) } } result = uniqueSorted(result) if len(result) == 0 { return nil, false, gerror.New("package has no valid renewable duration options") } legacyMonthConfig := true for _, value := range result { if value < 12 || value%12 != 0 { legacyMonthConfig = false break } } return result, legacyMonthConfig, nil } func uniqueSorted(values []int) []int { if len(values) == 0 { return nil } seen := make(map[int]struct{}, len(values)) result := make([]int, 0, len(values)) for _, value := range values { if value <= 0 { continue } if _, exists := seen[value]; exists { continue } seen[value] = struct{}{} result = append(result, value) } sort.Ints(result) return result }