package app import ( "context" "strings" "git.5iot.com/iotlcm-public/iotlcm-app/internal/dao" "git.5iot.com/iotlcm-public/iotlcm-app/internal/library/contexts" "git.5iot.com/iotlcm-public/iotlcm-app/internal/model" "git.5iot.com/iotlcm-public/iotlcm-app/internal/model/entity" "github.com/gogf/gf/v2/database/gdb" "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/os/gtime" ) // 查询当前登录用户可见的套餐订购记录。 func (s *sAppCard) PackageList(ctx context.Context, param *model.AppPackageListParam) (items []*model.AppPackageModel, total int, err error) { user, err := appCurrentUser(ctx) if err != nil { return nil, 0, err } mod := s.visiblePackageModel(ctx, user) mod = s.applyPackageFilters(mod, param) if param.Page <= 0 { param.Page = 1 } if param.PageSize <= 0 { param.PageSize = 10 } var rows []*appPackageQueryRow err = mod.OrderDesc(dao.TSimCardBindPkg.Table()+"."+dao.TSimCardBindPkg.Columns().Id). Page(param.Page, param.PageSize). ScanAndCount(&rows, &total, false) if err != nil { return nil, 0, gerror.Wrap(err, "查询套餐列表失败,请稍后重试") } ownerType := s.ownerType(ctx, user) items = make([]*model.AppPackageModel, 0, len(rows)) for _, row := range rows { items = append(items, s.packageRowToModel(row, ownerType, s.canOperatePackageRow(ctx, user, row))) } return items, total, nil } // 查询卡片当前套餐详情。 // 核心规则是“卡主表 current_package_code -> 套餐表 package_code”,订购记录只做详情兜底, // 避免卡主表与订购表不同步时前端报“套餐信息不存在”。 func (s *sAppCard) PublicPackageDetail(ctx context.Context, param *model.AppPackagePublicDetailParam) (res *model.AppPackageModel, err error) { if param == nil { param = &model.AppPackagePublicDetailParam{} } card, err := s.findPublicCard(ctx, param.TenantId, param.CardValue) if err != nil { return nil, err } if card == nil { return nil, gerror.New("卡信息不存在,请确认查询号码是否正确") } ownerType := appCardOwnerPublic canBusiness := false displayCard := card if userId := contexts.GetUserId(ctx); userId > 0 { user, userErr := appCurrentUser(ctx) if userErr == nil && user != nil { visibleCard, visibleErr := s.findVisibleCard(ctx, user, param.CardValue) if visibleErr == nil && visibleCard != nil && strings.TrimSpace(visibleCard.Iccid) == strings.TrimSpace(card.Iccid) && strings.TrimSpace(visibleCard.TenantId) == strings.TrimSpace(card.TenantId) { displayCard = visibleCard ownerType = s.ownerType(ctx, user) canBusiness = s.canOperateCard(ctx, user, visibleCard) } } } var subscriptionBind *entity.TSimCardBindPkg if strings.TrimSpace(param.SubscriptionNo) != "" { subscriptionBind, err = s.loadRenewSubscription(ctx, card, param.SubscriptionNo) if err != nil { return nil, err } } latestBind, err := s.loadLatestRenewBind(ctx, card) if err != nil { return nil, err } candidates := appPublicPackageCandidates(displayCard, subscriptionBind, latestBind, param.PackageCode) if len(candidates) == 0 { return nil, gerror.New("当前卡片没有套餐信息") } for _, packageCode := range candidates { pkg, err := s.loadPublicPackageInfo(ctx, card.TenantId, packageCode) if err != nil { return nil, err } if pkg == nil { continue } result := s.publicPackageRowToModel(displayCard, pkg) result.OwnerType = ownerType result.CanBusiness = canBusiness if subscriptionBind != nil && strings.TrimSpace(subscriptionBind.PackageCode) == strings.TrimSpace(pkg.PackageCode) { appFillPublicPackageFromBind(result, subscriptionBind) } else if latestBind != nil && strings.TrimSpace(latestBind.PackageCode) == strings.TrimSpace(pkg.PackageCode) { appFillPublicPackageFromBind(result, latestBind) } if ownerType == appCardOwnerPublic { result = appSanitizePublicPackageModel(result, param.CardValue) } return result, nil } return nil, gerror.Newf("当前卡片套餐编码 %s 未配置套餐信息", strings.Join(candidates, "、")) } func appPublicPackageCandidates(card *appCardQueryRow, subscriptionBind *entity.TSimCardBindPkg, latestBind *entity.TSimCardBindPkg, requestedPackageCode string) []string { var candidates []string addCandidate := func(value string) { value = strings.TrimSpace(value) if value == "" { return } for _, item := range candidates { if item == value { return } } candidates = append(candidates, value) } if subscriptionBind != nil { addCandidate(subscriptionBind.PackageCode) } currentPackageCode := "" if card != nil { currentPackageCode = appCardCurrentPackageCode(card) addCandidate(currentPackageCode) } if latestBind != nil && currentPackageCode == "" { addCandidate(latestBind.PackageCode) } if appPublicPackageCodeAllowed(requestedPackageCode, card, subscriptionBind, latestBind) { addCandidate(requestedPackageCode) } return candidates } func appPublicPackageCodeAllowed(packageCode string, card *appCardQueryRow, subscriptionBind *entity.TSimCardBindPkg, latestBind *entity.TSimCardBindPkg) bool { packageCode = strings.TrimSpace(packageCode) if packageCode == "" { return false } if card != nil { currentPackageCode := appCardCurrentPackageCode(card) if currentPackageCode != "" { return currentPackageCode == packageCode } } if subscriptionBind != nil && strings.TrimSpace(subscriptionBind.PackageCode) == packageCode { return true } return latestBind != nil && strings.TrimSpace(latestBind.PackageCode) == packageCode } func (s *sAppCard) loadPublicPackageInfo(ctx context.Context, tenantId string, packageCode string) (*appPublicPackageQueryRow, error) { packageTable := dao.TSimFlowPackageInfo.Table() categoryTable := dao.TSimPackageCategory.Table() packageColumns := dao.TSimFlowPackageInfo.Columns() categoryColumns := dao.TSimPackageCategory.Columns() var pkg *appPublicPackageQueryRow err := dao.TSimFlowPackageInfo.Ctx(ctx). FieldsPrefix(packageTable, entity.TSimFlowPackageInfo{}). Fields(categoryTable+"."+categoryColumns.CategoryName+" as categoryName"). LeftJoin(categoryTable, categoryTable+"."+categoryColumns.CategoryCode+"="+packageTable+"."+packageColumns.CategoryCode+" AND "+categoryTable+"."+categoryColumns.TenantId+"="+packageTable+"."+packageColumns.TenantId). Where(packageTable+"."+packageColumns.TenantId, strings.TrimSpace(tenantId)). Where(packageTable+"."+packageColumns.PackageCode, strings.TrimSpace(packageCode)). Limit(1). Scan(&pkg) if err != nil { return nil, gerror.Wrap(err, "查询套餐详情失败") } if pkg == nil || pkg.Id == 0 { return nil, nil } return pkg, nil } func appFillPublicPackageFromBind(pkg *model.AppPackageModel, bind *entity.TSimCardBindPkg) { if pkg == nil || bind == nil { return } pkg.Id = bind.Id pkg.SubscriptionNo = bind.SubscriptionNo pkg.BusinessType = bind.BusinessType pkg.BusinessTypeName = appBusinessTypeName(bind.BusinessType) pkg.EffectiveStatus = bind.EffectiveStatus pkg.EffectiveTime = bind.EffectiveTime pkg.ExpireTime = bind.ExpectedExpireTime pkg.ValidText = appPackageValidText(bind.EffectiveTime, bind.ExpectedExpireTime) pkg.EffectText = appPackageEffectText(bind.EffectiveStatus) } func (s *sAppCard) visiblePackageModel(ctx context.Context, user *entity.SysUser) *gdb.Model { cardTable := dao.TSimCardInfo.Table() bindPkgTable := dao.TSimCardBindPkg.Table() packageTable := dao.TSimFlowPackageInfo.Table() categoryTable := dao.TSimPackageCategory.Table() terminalBindTable := dao.TSimTerminal.Table() mod := dao.TSimCardBindPkg.Ctx(ctx). FieldsPrefix(bindPkgTable, entity.TSimCardBindPkg{}). Fields(cardTable+"."+dao.TSimCardInfo.Columns().Id+" as cardId"). Fields(cardTable+"."+dao.TSimCardInfo.Columns().DeptId+" as cardDeptId"). Fields(cardTable+"."+dao.TSimCardInfo.Columns().Remark+" as cardRemark"). Fields(packageTable+"."+dao.TSimFlowPackageInfo.Columns().PackageName+" as packageName"). Fields(packageTable+"."+dao.TSimFlowPackageInfo.Columns().CategoryCode+" as categoryCode"). Fields(packageTable+"."+dao.TSimFlowPackageInfo.Columns().FlowMb+" as flowMb"). Fields(categoryTable+"."+dao.TSimPackageCategory.Columns().CategoryName+" as categoryName"). LeftJoin(cardTable, cardTable+"."+dao.TSimCardInfo.Columns().Iccid+"="+bindPkgTable+"."+dao.TSimCardBindPkg.Columns().Iccid+" AND "+cardTable+"."+dao.TSimCardInfo.Columns().TenantId+"="+bindPkgTable+"."+dao.TSimCardBindPkg.Columns().TenantId). LeftJoin(packageTable, packageTable+"."+dao.TSimFlowPackageInfo.Columns().PackageCode+"="+bindPkgTable+"."+dao.TSimCardBindPkg.Columns().PackageCode+" AND "+packageTable+"."+dao.TSimFlowPackageInfo.Columns().TenantId+"="+bindPkgTable+"."+dao.TSimCardBindPkg.Columns().TenantId). LeftJoin(categoryTable, categoryTable+"."+dao.TSimPackageCategory.Columns().CategoryCode+"="+packageTable+"."+dao.TSimFlowPackageInfo.Columns().CategoryCode+" AND "+categoryTable+"."+dao.TSimPackageCategory.Columns().TenantId+"="+packageTable+"."+dao.TSimFlowPackageInfo.Columns().TenantId) if s.isTerminalUser(ctx, user) { return mod. Fields(terminalBindTable+"."+dao.TSimTerminal.Columns().TerminalName+" as terminalName"). InnerJoin(terminalBindTable, terminalBindTable+"."+dao.TSimTerminal.Columns().Iccid+"="+cardTable+"."+dao.TSimCardInfo.Columns().Iccid+" AND "+terminalBindTable+"."+dao.TSimTerminal.Columns().TenantId+"="+cardTable+"."+dao.TSimCardInfo.Columns().TenantId). Where(terminalBindTable+"."+dao.TSimTerminal.Columns().TenantId, user.TenantId). Where(terminalBindTable+"."+dao.TSimTerminal.Columns().TerminalId, user.UserId). Where(bindPkgTable+"."+dao.TSimCardBindPkg.Columns().TenantId, user.TenantId) } mod = mod.Where(bindPkgTable+"."+dao.TSimCardBindPkg.Columns().TenantId, user.TenantId) return appApplyEnterpriseDataScope( ctx, user, mod, cardTable+"."+dao.TSimCardInfo.Columns().DeptId, cardTable+"."+dao.TSimCardInfo.Columns().CreatedBy, func(legacyMod *gdb.Model) *gdb.Model { return appLegacyEnterpriseDeptAndSubScope(ctx, user, legacyMod, cardTable+"."+dao.TSimCardInfo.Columns().DeptId) }, ) } func (s *sAppCard) applyPackageFilters(mod *gdb.Model, param *model.AppPackageListParam) *gdb.Model { if strings.TrimSpace(param.Keyword) != "" { keyword := "%" + strings.TrimSpace(param.Keyword) + "%" mod = mod.Where( "("+dao.TSimCardBindPkg.Table()+"."+dao.TSimCardBindPkg.Columns().Iccid+" LIKE ? OR "+ dao.TSimCardBindPkg.Table()+"."+dao.TSimCardBindPkg.Columns().Msisdn+" LIKE ? OR "+ dao.TSimCardInfo.Table()+"."+dao.TSimCardInfo.Columns().Imsi+" LIKE ? OR "+ dao.TSimCardInfo.Table()+"."+dao.TSimCardInfo.Columns().Imei+" LIKE ? OR "+ dao.TSimCardBindPkg.Table()+"."+dao.TSimCardBindPkg.Columns().PackageCode+" LIKE ? OR "+ dao.TSimFlowPackageInfo.Table()+"."+dao.TSimFlowPackageInfo.Columns().PackageName+" LIKE ? OR "+ dao.TSimPackageCategory.Table()+"."+dao.TSimPackageCategory.Columns().CategoryName+" LIKE ? OR "+ dao.TSimCardBindPkg.Table()+"."+dao.TSimCardBindPkg.Columns().Remark+" LIKE ?)", keyword, keyword, keyword, keyword, keyword, keyword, keyword, keyword, ) } if strings.TrimSpace(param.CardValue) != "" { value := strings.TrimSpace(param.CardValue) mod = mod.Where( "("+dao.TSimCardBindPkg.Table()+"."+dao.TSimCardBindPkg.Columns().Iccid+" = ? OR "+ dao.TSimCardBindPkg.Table()+"."+dao.TSimCardBindPkg.Columns().Msisdn+" = ? OR "+ dao.TSimCardInfo.Table()+"."+dao.TSimCardInfo.Columns().Imsi+" = ? OR "+ dao.TSimCardInfo.Table()+"."+dao.TSimCardInfo.Columns().Imei+" = ?)", value, value, value, value, ) } if strings.TrimSpace(param.SubscriptionNo) != "" { mod = mod.Where(dao.TSimCardBindPkg.Table()+"."+dao.TSimCardBindPkg.Columns().SubscriptionNo, strings.TrimSpace(param.SubscriptionNo)) } if strings.TrimSpace(param.PackageCode) != "" { mod = mod.Where(dao.TSimCardBindPkg.Table()+"."+dao.TSimCardBindPkg.Columns().PackageCode, strings.TrimSpace(param.PackageCode)) } if strings.TrimSpace(param.CategoryCode) != "" { mod = mod.Where(dao.TSimFlowPackageInfo.Table()+"."+dao.TSimFlowPackageInfo.Columns().CategoryCode, strings.TrimSpace(param.CategoryCode)) } switch strings.TrimSpace(param.Status) { case "active": mod = mod.Where(dao.TSimCardBindPkg.Table()+"."+dao.TSimCardBindPkg.Columns().EffectiveStatus, 1) case "expiring": mod = mod.Where(dao.TSimCardBindPkg.Table()+"."+dao.TSimCardBindPkg.Columns().ExpectedExpireTime+" IS NOT NULL"). Where(dao.TSimCardBindPkg.Table()+"."+dao.TSimCardBindPkg.Columns().ExpectedExpireTime+" >= ?", gtime.Now()). Where(dao.TSimCardBindPkg.Table()+"."+dao.TSimCardBindPkg.Columns().ExpectedExpireTime+" <= ?", gtime.Now().AddDate(0, 0, 30)) case "expired": mod = mod.Where(dao.TSimCardBindPkg.Table()+"."+dao.TSimCardBindPkg.Columns().EffectiveStatus, 2) case "pending": mod = mod.Where(dao.TSimCardBindPkg.Table()+"."+dao.TSimCardBindPkg.Columns().EffectiveStatus, 0) case "addon": mod = mod.WhereIn(dao.TSimCardBindPkg.Table()+"."+dao.TSimCardBindPkg.Columns().PackageType, []int{103, 104}) } return mod }