chore: 并入 iotlcm-admin-svr 历史到 admin-svr/(原提交 49818c6)
This commit is contained in:
@@ -0,0 +1,353 @@
|
||||
package addpackage
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/consts"
|
||||
"git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/dao"
|
||||
"git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/library/batchimport"
|
||||
"git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/library/xgorm/handler"
|
||||
"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/os/gtime"
|
||||
)
|
||||
|
||||
type cardTarget struct {
|
||||
Iccid string `orm:"iccid"`
|
||||
CurrentPackageCode string `orm:"current_package_code"`
|
||||
PackageStatus int `orm:"package_status"`
|
||||
}
|
||||
|
||||
type cardLatestBindTarget struct {
|
||||
Iccid string `orm:"iccid"`
|
||||
PackageCode string `orm:"package_code"`
|
||||
EffectiveStatus int `orm:"effective_status"`
|
||||
ExpectedExpireTime *gtime.Time `orm:"expected_expire_time"`
|
||||
}
|
||||
|
||||
type poolTarget struct {
|
||||
FlowPoolCode string `orm:"flow_pool_code"`
|
||||
PoolPackageCode int64 `orm:"pool_package_code"`
|
||||
PoolStatus int `orm:"pool_status"`
|
||||
}
|
||||
|
||||
func (p *Processor) PrepareRows(ctx context.Context, rows []batchimport.Row) error {
|
||||
if p.config.Operation == OperationPool {
|
||||
return p.preparePoolRows(ctx, rows)
|
||||
}
|
||||
return p.prepareCardRows(ctx, rows)
|
||||
}
|
||||
|
||||
func (p *Processor) prepareCardRows(ctx context.Context, rows []batchimport.Row) error {
|
||||
typedRows, targetCodes, err := collectTypedRows(rows)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(targetCodes) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var cards []*cardTarget
|
||||
cardColumns := dao.TSimCardInfo.Columns()
|
||||
if err = handler.Model(dao.TSimCardInfo.Ctx(ctx), &handler.Option{FilterTenant: true, FilterAuth: true}).
|
||||
Fields(cardColumns.Iccid, cardColumns.CurrentPackageCode, cardColumns.PackageStatus, cardColumns.TenantId, cardColumns.DeptId, cardColumns.CreatedDept, cardColumns.CreatedBy).
|
||||
WhereIn(cardColumns.Iccid, targetCodes).
|
||||
Scan(&cards); err != nil {
|
||||
return gerror.Wrap(err, "查询加油包卡信息失败")
|
||||
}
|
||||
|
||||
cardMap := make(map[string]*cardTarget, len(cards))
|
||||
for _, card := range cards {
|
||||
if card == nil {
|
||||
continue
|
||||
}
|
||||
iccid := strings.TrimSpace(card.Iccid)
|
||||
if iccid == "" {
|
||||
continue
|
||||
}
|
||||
cardMap[iccid] = card
|
||||
}
|
||||
|
||||
latestBinds, err := p.loadLatestCardBaseBinds(ctx, targetCodes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
latestBindMap := make(map[string]*cardLatestBindTarget, len(latestBinds))
|
||||
for _, bind := range latestBinds {
|
||||
if bind == nil {
|
||||
continue
|
||||
}
|
||||
iccid := strings.TrimSpace(bind.Iccid)
|
||||
if iccid == "" || latestBindMap[iccid] != nil {
|
||||
continue
|
||||
}
|
||||
latestBindMap[iccid] = bind
|
||||
}
|
||||
|
||||
basePackageCodes := make([]string, 0, len(latestBindMap))
|
||||
for _, bind := range latestBindMap {
|
||||
if bind == nil {
|
||||
continue
|
||||
}
|
||||
basePackageCodes = append(basePackageCodes, bind.PackageCode)
|
||||
}
|
||||
|
||||
packages, err := p.loadPackageMap(ctx, append(basePackageCodes, rowPackageCodes(typedRows)...))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
now := gtime.Now()
|
||||
for _, row := range typedRows {
|
||||
card := cardMap[row.TargetCode]
|
||||
if card == nil {
|
||||
row.AddErrorReason("ICCID不存在或无权限")
|
||||
continue
|
||||
}
|
||||
latestBind := latestBindMap[row.TargetCode]
|
||||
if latestBind == nil || strings.TrimSpace(latestBind.PackageCode) == "" {
|
||||
row.AddErrorReason("当前卡订购记录不存在")
|
||||
continue
|
||||
}
|
||||
row.Authorized = true
|
||||
if card.PackageStatus != consts.PackageStatusEffective {
|
||||
row.AddErrorReason("当前卡套餐未生效,不能订购加油包")
|
||||
continue
|
||||
}
|
||||
if bindExpired(latestBind, now) {
|
||||
row.AddErrorReason("当前卡基础套餐已到期,不能订购加油包")
|
||||
continue
|
||||
}
|
||||
if err := p.validateTargetPackage(row, packages, 103); err != nil {
|
||||
row.AddErrorReason(err.Error())
|
||||
continue
|
||||
}
|
||||
basePackage := packages[strings.TrimSpace(latestBind.PackageCode)]
|
||||
if basePackage == nil {
|
||||
row.AddErrorReason("当前卡基础套餐不存在")
|
||||
continue
|
||||
}
|
||||
if !containsString(packageCodesFromJSON(basePackage.TopupPackageCodes), row.PackageCode) {
|
||||
row.AddErrorReason("当前卡基础套餐不允许订购该加油包")
|
||||
continue
|
||||
}
|
||||
}
|
||||
return rowsValidationError(rows, "加油包卡信息校验失败")
|
||||
}
|
||||
|
||||
func (p *Processor) preparePoolRows(ctx context.Context, rows []batchimport.Row) error {
|
||||
typedRows, targetCodes, err := collectTypedRows(rows)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(targetCodes) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var pools []*poolTarget
|
||||
poolColumns := dao.TSimFlowPool.Columns()
|
||||
if err = handler.Model(dao.TSimFlowPool.Ctx(ctx), &handler.Option{FilterTenant: true, FilterAuth: true}).
|
||||
Fields(poolColumns.FlowPoolCode, poolColumns.PoolPackageCode, poolColumns.PoolStatus, poolColumns.TenantId, poolColumns.DeptId, poolColumns.CreatedDept, poolColumns.CreatedBy).
|
||||
WhereIn(poolColumns.FlowPoolCode, targetCodes).
|
||||
Scan(&pools); err != nil {
|
||||
return gerror.Wrap(err, "查询流量池信息失败")
|
||||
}
|
||||
poolMap := make(map[string]*poolTarget, len(pools))
|
||||
for _, pool := range pools {
|
||||
if pool == nil {
|
||||
continue
|
||||
}
|
||||
code := strings.TrimSpace(pool.FlowPoolCode)
|
||||
poolMap[code] = pool
|
||||
}
|
||||
|
||||
packages, err := p.loadPackageMap(ctx, rowPackageCodes(typedRows))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, row := range typedRows {
|
||||
pool := poolMap[row.TargetCode]
|
||||
if pool == nil {
|
||||
row.AddErrorReason("流量池编号不存在或无权限")
|
||||
continue
|
||||
}
|
||||
row.Authorized = true
|
||||
if pool.PoolStatus != 0 {
|
||||
row.AddErrorReason("流量池状态异常,不能订购加油包")
|
||||
continue
|
||||
}
|
||||
if err := p.validateTargetPackage(row, packages, 104); err != nil {
|
||||
row.AddErrorReason(err.Error())
|
||||
continue
|
||||
}
|
||||
targetPackage := packages[row.PackageCode]
|
||||
if targetPackage == nil {
|
||||
row.AddErrorReason("加油包不存在")
|
||||
continue
|
||||
}
|
||||
if targetPackage.PoolPackageCode != pool.PoolPackageCode {
|
||||
row.AddErrorReason("加油包不属于当前流量池套餐")
|
||||
continue
|
||||
}
|
||||
}
|
||||
return rowsValidationError(rows, "流量池加油包校验失败")
|
||||
}
|
||||
|
||||
func (p *Processor) loadLatestCardBaseBinds(ctx context.Context, iccids []string) ([]*cardLatestBindTarget, error) {
|
||||
iccids = uniqueStrings(iccids)
|
||||
if len(iccids) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var binds []*cardLatestBindTarget
|
||||
if err := handler.Model(dao.TSimCardBindPkg.Ctx(ctx), &handler.Option{FilterTenant: true, FilterAuth: true}).
|
||||
Fields(
|
||||
dao.TSimCardBindPkg.Columns().Iccid,
|
||||
dao.TSimCardBindPkg.Columns().PackageCode,
|
||||
dao.TSimCardBindPkg.Columns().EffectiveStatus,
|
||||
dao.TSimCardBindPkg.Columns().ExpectedExpireTime,
|
||||
dao.TSimCardBindPkg.Columns().TenantId,
|
||||
dao.TSimCardBindPkg.Columns().DeptId,
|
||||
dao.TSimCardBindPkg.Columns().CreatedDept,
|
||||
dao.TSimCardBindPkg.Columns().CreatedBy,
|
||||
).
|
||||
WhereIn(dao.TSimCardBindPkg.Columns().Iccid, iccids).
|
||||
WhereIn(dao.TSimCardBindPkg.Columns().PackageType, []int{101, 102}).
|
||||
Where(dao.TSimCardBindPkg.Columns().EffectiveStatus, consts.EffectiveStatusEffective).
|
||||
OrderDesc(dao.TSimCardBindPkg.Columns().ExpectedExpireTime).
|
||||
OrderDesc(dao.TSimCardBindPkg.Columns().Id).
|
||||
Scan(&binds); err != nil {
|
||||
return nil, gerror.Wrap(err, "查询卡最新订购记录失败")
|
||||
}
|
||||
return binds, nil
|
||||
}
|
||||
|
||||
func bindExpired(bind *cardLatestBindTarget, now *gtime.Time) bool {
|
||||
if bind == nil {
|
||||
return true
|
||||
}
|
||||
if bind.EffectiveStatus == consts.EffectiveStatusExpired {
|
||||
return true
|
||||
}
|
||||
if bind.ExpectedExpireTime == nil || now == nil {
|
||||
return false
|
||||
}
|
||||
return !bind.ExpectedExpireTime.After(now)
|
||||
}
|
||||
|
||||
func (p *Processor) validateTargetPackage(row *Row, packages map[string]*entity.TSimFlowPackageInfo, packageType int) error {
|
||||
if row == nil {
|
||||
return nil
|
||||
}
|
||||
pkg := packages[row.PackageCode]
|
||||
if pkg == nil {
|
||||
return gerror.New("加油包不存在")
|
||||
}
|
||||
if pkg.Enabled != 1 {
|
||||
return gerror.New("加油包未启用")
|
||||
}
|
||||
if pkg.PackageType != packageType {
|
||||
return gerror.Newf("加油包类型错误,应为%d", packageType)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Processor) loadPackageMap(ctx context.Context, codes []string) (map[string]*entity.TSimFlowPackageInfo, error) {
|
||||
out := make(map[string]*entity.TSimFlowPackageInfo)
|
||||
codes = uniqueStrings(codes)
|
||||
if len(codes) == 0 {
|
||||
return out, nil
|
||||
}
|
||||
var packages []*entity.TSimFlowPackageInfo
|
||||
columns := dao.TSimFlowPackageInfo.Columns()
|
||||
if err := handler.Model(dao.TSimFlowPackageInfo.Ctx(ctx), &handler.Option{FilterTenant: true, FilterAuth: false}).
|
||||
WhereIn(columns.PackageCode, codes).
|
||||
Scan(&packages); err != nil {
|
||||
return nil, gerror.Wrap(err, "查询加油包套餐信息失败")
|
||||
}
|
||||
for _, pkg := range packages {
|
||||
if pkg == nil {
|
||||
continue
|
||||
}
|
||||
out[strings.TrimSpace(pkg.PackageCode)] = pkg
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func collectTypedRows(rows []batchimport.Row) ([]*Row, []string, error) {
|
||||
typedRows := make([]*Row, 0, len(rows))
|
||||
targetCodes := make([]string, 0, len(rows))
|
||||
for _, item := range rows {
|
||||
row, ok := item.(*Row)
|
||||
if !ok || row == nil {
|
||||
return nil, nil, gerror.New("加油包批次行类型错误")
|
||||
}
|
||||
typedRows = append(typedRows, row)
|
||||
if row.TargetCode != "" {
|
||||
targetCodes = append(targetCodes, row.TargetCode)
|
||||
}
|
||||
}
|
||||
return typedRows, uniqueStrings(targetCodes), nil
|
||||
}
|
||||
|
||||
func rowPackageCodes(rows []*Row) []string {
|
||||
codes := make([]string, 0, len(rows))
|
||||
for _, row := range rows {
|
||||
if row != nil {
|
||||
codes = append(codes, row.PackageCode)
|
||||
}
|
||||
}
|
||||
return codes
|
||||
}
|
||||
|
||||
func packageCodesFromJSON(jsonValue *gjson.Json) []string {
|
||||
if jsonValue == nil || jsonValue.IsNil() {
|
||||
return nil
|
||||
}
|
||||
values := jsonValue.Interfaces()
|
||||
out := make([]string, 0, len(values))
|
||||
for _, raw := range values {
|
||||
code := strings.TrimSpace(fmt.Sprint(raw))
|
||||
if code != "" {
|
||||
out = append(out, code)
|
||||
}
|
||||
}
|
||||
return uniqueStrings(out)
|
||||
}
|
||||
|
||||
func containsString(values []string, target string) bool {
|
||||
target = strings.TrimSpace(target)
|
||||
if target == "" {
|
||||
return false
|
||||
}
|
||||
for _, value := range values {
|
||||
if strings.TrimSpace(value) == target {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func uniqueStrings(in []string) []string {
|
||||
if len(in) == 0 {
|
||||
return nil
|
||||
}
|
||||
seen := make(map[string]struct{}, len(in))
|
||||
out := make([]string, 0, len(in))
|
||||
for _, value := range in {
|
||||
value = strings.TrimSpace(value)
|
||||
if value == "" {
|
||||
continue
|
||||
}
|
||||
if _, ok := seen[value]; ok {
|
||||
continue
|
||||
}
|
||||
seen[value] = struct{}{}
|
||||
out = append(out, value)
|
||||
}
|
||||
return out
|
||||
}
|
||||
Reference in New Issue
Block a user