215 lines
4.9 KiB
Go
215 lines
4.9 KiB
Go
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
|
|
}
|