chore: 初始开源发布
iotlcm-admin-svr:管理后台服务。 - Go module:iotlcm → git.5iot.com/iotlcm-public/iotlcm-admin-svr(729 文件) - 凭据与地址脱敏:JWT signingKey(含代码里的 MustGet 默认值)、 MySQL DSN、Redis 口令、告警邮件发件人邮箱全部改为占位; 私网 IP → 文档地址段;库名 xiujie_admin → iotlcm - 真实手机号/邮箱 → 合法 11 位编造号 / example.com - 移除内部资产:CI 触发器、过时 DDL(sql/db_iotlcm.sql)、 私有依赖 go get 行、明文 registry 登录口令 - 启动 banner 统一 IOTLCM 方块字 + 社区惯例署名 - Dockerfile 改用公共基础镜像 - 拼错的 RADEME.md → README.md,README 重写 - 需要真实数据库的用例改为可用 IOTLCM_TEST_WITH_DB=1 显式启用 - 补 Apache-2.0 LICENSE,LF 行尾 + .gitattributes 数据库 schema 不随本仓发布(生产 DDL 已过时),README 已说明。
This commit is contained in:
@@ -0,0 +1,707 @@
|
||||
package iot
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math"
|
||||
"strings"
|
||||
|
||||
"git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/dao"
|
||||
"git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/library/contexts"
|
||||
"git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/library/xgorm/handler"
|
||||
"git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/library/xgorm/hook"
|
||||
"git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/logic/iot/packageduration"
|
||||
"git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/logic/packagecustomer"
|
||||
"git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/model"
|
||||
"git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/model/do"
|
||||
"git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/model/entity"
|
||||
"git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/service"
|
||||
"git.5iot.com/iotlcm-public/iotlcm-admin-svr/utility/convert"
|
||||
"git.5iot.com/iotlcm-public/iotlcm-admin-svr/utility/excel"
|
||||
|
||||
"github.com/gogf/gf/v2/database/gdb"
|
||||
"github.com/gogf/gf/v2/encoding/gjson"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gctx"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
)
|
||||
|
||||
type sIotTSimFlowPackageInfo struct{}
|
||||
|
||||
func NewIotTSimFlowPackageInfo() *sIotTSimFlowPackageInfo {
|
||||
return &sIotTSimFlowPackageInfo{}
|
||||
}
|
||||
|
||||
func init() {
|
||||
service.RegisterIotTSimFlowPackageInfo(NewIotTSimFlowPackageInfo())
|
||||
}
|
||||
|
||||
func (s *sIotTSimFlowPackageInfo) Model(ctx context.Context, option ...*handler.Option) *gdb.Model {
|
||||
if len(option) == 0 {
|
||||
option = append(option, &handler.Option{
|
||||
FilterTenant: true,
|
||||
FilterAuth: true,
|
||||
})
|
||||
}
|
||||
return handler.Model(dao.TSimFlowPackageInfo.Ctx(ctx), option...)
|
||||
}
|
||||
|
||||
func (s *sIotTSimFlowPackageInfo) packageListModel(ctx context.Context) (*gdb.Model, error) {
|
||||
mainTable := dao.TSimFlowPackageInfo.Table()
|
||||
pcTable := dao.TPackageCustomer.Table()
|
||||
pcColumns := dao.TPackageCustomer.Columns()
|
||||
mod := s.Model(ctx, &handler.Option{FilterTenant: true, FilterAuth: false})
|
||||
|
||||
isTop, _, err := service.AgentDept().IsTopDept(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if isTop {
|
||||
return mod, nil
|
||||
}
|
||||
|
||||
return mod.
|
||||
InnerJoin(pcTable, pcTable+"."+pcColumns.PackageCode+" = "+mainTable+"."+dao.TSimFlowPackageInfo.Columns().PackageCode).
|
||||
Where(pcTable+"."+pcColumns.DeptId, contexts.GetDeptId(ctx)).
|
||||
Where(pcTable+"."+pcColumns.TenantId, contexts.GetTenantId(ctx)), nil
|
||||
}
|
||||
|
||||
func (s *sIotTSimFlowPackageInfo) applyListFilter(mod *gdb.Model, mainTable string, in *model.TSimFlowPackageInfoListParam) *gdb.Model {
|
||||
if in.PackageCode != "" {
|
||||
mod = mod.WhereLike(mainTable+"."+dao.TSimFlowPackageInfo.Columns().PackageCode, "%"+in.PackageCode+"%")
|
||||
}
|
||||
if in.CategoryCode != "" {
|
||||
mod = mod.Where(mainTable+"."+dao.TSimFlowPackageInfo.Columns().CategoryCode, in.CategoryCode)
|
||||
}
|
||||
if in.PackageType != "" {
|
||||
mod = mod.Where(mainTable+"."+dao.TSimFlowPackageInfo.Columns().PackageType, in.PackageType)
|
||||
}
|
||||
if in.PackageName != "" {
|
||||
mod = mod.WhereLike(mainTable+"."+dao.TSimFlowPackageInfo.Columns().PackageName, "%"+in.PackageName+"%")
|
||||
}
|
||||
if in.Enabled != nil {
|
||||
mod = mod.Where(mainTable+"."+dao.TSimFlowPackageInfo.Columns().Enabled, *in.Enabled)
|
||||
}
|
||||
if len(in.CreatedAt) == 2 {
|
||||
mod = mod.WhereBetween(mainTable+"."+dao.TSimFlowPackageInfo.Columns().CreatedAt, in.CreatedAt[0], in.CreatedAt[1].EndOfDay())
|
||||
}
|
||||
return mod
|
||||
}
|
||||
|
||||
func (s *sIotTSimFlowPackageInfo) buildPackageCustomer(ctx context.Context, dept *entity.SysDept, packageCode, packageName string, now *gtime.Time) do.TPackageCustomer {
|
||||
userId := contexts.GetUserId(ctx)
|
||||
return do.TPackageCustomer{
|
||||
PackageCode: packageCode,
|
||||
PackageName: packageName,
|
||||
DeptId: dept.DeptId,
|
||||
DeptName: dept.DeptName,
|
||||
TenantId: contexts.GetTenantId(ctx),
|
||||
CreatedDept: contexts.GetDeptId(ctx),
|
||||
CreatedBy: userId,
|
||||
CreatedAt: now,
|
||||
UpdatedBy: userId,
|
||||
UpdatedAt: now,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *sIotTSimFlowPackageInfo) List(ctx context.Context, in *model.TSimFlowPackageInfoListParam) (list []*model.TSimFlowPackageInfoListModel, totalCount int, err error) {
|
||||
mainTable := dao.TSimFlowPackageInfo.Table()
|
||||
catTable := dao.TSimPackageCategory.Table()
|
||||
|
||||
countBaseMod, err := s.packageListModel(ctx)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
countMod := s.applyListFilter(countBaseMod, mainTable, in)
|
||||
totalCount, err = countMod.Count()
|
||||
if err != nil {
|
||||
err = gerror.Wrap(err, "获取SIM流量套餐管理列表失败,请稍后重试")
|
||||
return
|
||||
}
|
||||
|
||||
mod, err := s.packageListModel(ctx)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
mod = mod.LeftJoin(catTable, mainTable+"."+dao.TSimFlowPackageInfo.Columns().CategoryCode+" = "+catTable+"."+dao.TSimPackageCategory.Columns().CategoryCode)
|
||||
mod = s.applyListFilter(mod, mainTable, in)
|
||||
mod = mod.FieldsPrefix(mainTable, model.TSimFlowPackageInfoListModel{})
|
||||
mod = mod.Fields(catTable + "." + dao.TSimPackageCategory.Columns().CategoryName + " as categoryName")
|
||||
mod = mod.Page(in.Page, in.PageSize)
|
||||
mod = mod.OrderAsc(mainTable + "." + dao.TSimFlowPackageInfo.Columns().SortNo)
|
||||
mod = mod.Hook(hook.MemberSummary)
|
||||
|
||||
if err = mod.Scan(&list); err != nil {
|
||||
err = gerror.Wrap(err, "获取SIM流量套餐管理列表失败,请稍后重试")
|
||||
return
|
||||
}
|
||||
if err = s.fillPackageListPrices(ctx, list); err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
normalizePackageListRows(list)
|
||||
return
|
||||
}
|
||||
|
||||
// 可配置池列表(PackageType=102)
|
||||
func (s *sIotTSimFlowPackageInfo) FlowPackageList(ctx context.Context, in *model.TSimFlowPackageInfoFlowPackageListParam) (list []*model.TSimFlowPackageInfoListModel, err error) {
|
||||
mainTable := dao.TSimFlowPackageInfo.Table()
|
||||
mod := dao.TSimFlowPackageInfo.Ctx(ctx)
|
||||
|
||||
// 该接口只供流量池套餐配置弹窗使用,返回套餐编码和名称即可。
|
||||
// pool_package_code 是字符串编码,旧列表模型仍为整数类型,这里不查询该字段,
|
||||
// 避免编辑已有池配置时发生字符串转整数的扫描错误。
|
||||
mod = mod.Fields(
|
||||
mainTable+"."+dao.TSimFlowPackageInfo.Columns().PackageCode,
|
||||
mainTable+"."+dao.TSimFlowPackageInfo.Columns().PackageName,
|
||||
mainTable+"."+dao.TSimFlowPackageInfo.Columns().SortNo,
|
||||
)
|
||||
currentPoolPackageCode := ""
|
||||
if in != nil {
|
||||
currentPoolPackageCode = strings.TrimSpace(in.PoolPackageCode)
|
||||
}
|
||||
mod = applyPoolFlowPackageBaseFilter(mod, mainTable, currentPoolPackageCode)
|
||||
|
||||
// 根据流量套餐过滤(格式:100.000,102400.000,前边是GB后边是MB)
|
||||
if in != nil && in.Flow != "" {
|
||||
flow := strings.Trim(in.Flow, "\"")
|
||||
parts := strings.Split(flow, ",")
|
||||
if len(parts) == 2 {
|
||||
flowGb := strings.TrimSpace(parts[0])
|
||||
flowMb := strings.TrimSpace(parts[1])
|
||||
if flowGb == "" {
|
||||
mod = mod.Where(mainTable + "." + dao.TSimFlowPackageInfo.Columns().FlowGb + " IS NULL")
|
||||
} else {
|
||||
mod = mod.Where(mainTable+"."+dao.TSimFlowPackageInfo.Columns().FlowGb+" = ?", flowGb)
|
||||
}
|
||||
mod = mod.Where(mainTable+"."+dao.TSimFlowPackageInfo.Columns().FlowMb+" = ?", flowMb)
|
||||
}
|
||||
}
|
||||
|
||||
mod = mod.OrderAsc(mainTable + "." + dao.TSimFlowPackageInfo.Columns().SortNo)
|
||||
mod = mod.Hook(hook.MemberSummary)
|
||||
|
||||
if err = mod.Scan(&list); err != nil {
|
||||
err = gerror.Wrap(err, "获取SIM流量套餐管理列表失败,请稍后重试")
|
||||
return
|
||||
}
|
||||
normalizePackageListRows(list)
|
||||
return
|
||||
}
|
||||
|
||||
// 可配置池加油包列表(PackageType=104)
|
||||
func (s *sIotTSimFlowPackageInfo) FlowPackageAddList(ctx context.Context) (list []*model.TSimFlowPackageInfoListModel, err error) {
|
||||
mainTable := dao.TSimFlowPackageInfo.Table()
|
||||
|
||||
mod := dao.TSimFlowPackageInfo.Ctx(ctx)
|
||||
// 弹窗只使用套餐编码和名称,不查询字符串类型的池编码字段。
|
||||
mod = mod.Fields(
|
||||
mainTable+"."+dao.TSimFlowPackageInfo.Columns().PackageCode,
|
||||
mainTable+"."+dao.TSimFlowPackageInfo.Columns().PackageName,
|
||||
mainTable+"."+dao.TSimFlowPackageInfo.Columns().SortNo,
|
||||
)
|
||||
mod = mod.Where(mainTable+"."+dao.TSimFlowPackageInfo.Columns().PackageType, "104")
|
||||
mod = mod.OrderAsc(mainTable + "." + dao.TSimFlowPackageInfo.Columns().SortNo)
|
||||
mod = mod.Hook(hook.MemberSummary)
|
||||
|
||||
if err = mod.Scan(&list); err != nil {
|
||||
err = gerror.Wrap(err, "获取SIM流量套餐管理列表失败,请稍后重试")
|
||||
return
|
||||
}
|
||||
normalizePackageListRows(list)
|
||||
return
|
||||
}
|
||||
|
||||
// GetFlowPackageOptions 获取流量套餐GB+MB组合选项
|
||||
func (s *sIotTSimFlowPackageInfo) RenewablePackageOptions(ctx context.Context, in *model.TSimFlowPackageInfoRenewablePackageOptionsParam) (list []*model.TSimFlowPackageInfoListModel, err error) {
|
||||
if in == nil {
|
||||
in = &model.TSimFlowPackageInfoRenewablePackageOptionsParam{}
|
||||
}
|
||||
mainTable := dao.TSimFlowPackageInfo.Table()
|
||||
columns := dao.TSimFlowPackageInfo.Columns()
|
||||
mod := s.Model(ctx, &handler.Option{FilterTenant: true, FilterAuth: false}).
|
||||
Fields(model.TSimFlowPackageInfoListModel{}).
|
||||
Where(mainTable+"."+columns.Enabled, 1)
|
||||
if packageType := strings.TrimSpace(in.PackageType); packageType != "" {
|
||||
mod = mod.Where(mainTable+"."+columns.PackageType, packageType)
|
||||
}
|
||||
if packageCode := strings.TrimSpace(in.ExcludePackageCode); packageCode != "" {
|
||||
mod = mod.WhereNot(mainTable+"."+columns.PackageCode, packageCode)
|
||||
}
|
||||
mod = mod.OrderAsc(mainTable + "." + columns.SortNo)
|
||||
if err = mod.Scan(&list); err != nil {
|
||||
return nil, gerror.Wrap(err, "获取可续费套餐候选列表失败,请稍后重试")
|
||||
}
|
||||
normalizePackageListRows(list)
|
||||
return list, nil
|
||||
}
|
||||
|
||||
func (s *sIotTSimFlowPackageInfo) GetFlowPackageOptions(ctx context.Context, in *model.TSimFlowPackageInfoFlowPackageOptionsParam) ([]string, error) {
|
||||
var results []string
|
||||
mainTable := dao.TSimFlowPackageInfo.Table()
|
||||
currentPoolPackageCode := ""
|
||||
if in != nil {
|
||||
currentPoolPackageCode = strings.TrimSpace(in.PoolPackageCode)
|
||||
}
|
||||
|
||||
var rows []*struct {
|
||||
FlowGb string
|
||||
FlowMb string
|
||||
}
|
||||
g.Log().Info(ctx, "获取流量套餐选项")
|
||||
mod := s.Model(ctx, &handler.Option{FilterTenant: true, FilterAuth: false}).
|
||||
Fields(mainTable+"."+dao.TSimFlowPackageInfo.Columns().FlowGb, mainTable+"."+dao.TSimFlowPackageInfo.Columns().FlowMb).
|
||||
Where(mainTable+"."+dao.TSimFlowPackageInfo.Columns().PackageType, "102").
|
||||
Distinct().
|
||||
Where("(" + mainTable + "." + dao.TSimFlowPackageInfo.Columns().FlowGb + " <> '' OR " + mainTable + "." + dao.TSimFlowPackageInfo.Columns().FlowMb + " <> '')").
|
||||
OrderAsc(mainTable + "." + dao.TSimFlowPackageInfo.Columns().FlowGb).
|
||||
OrderAsc(mainTable + "." + dao.TSimFlowPackageInfo.Columns().FlowMb)
|
||||
if currentPoolPackageCode == "" {
|
||||
mod = mod.Where("(" + mainTable + "." + dao.TSimFlowPackageInfo.Columns().PoolPackageCode + " IS NULL OR " + mainTable + "." + dao.TSimFlowPackageInfo.Columns().PoolPackageCode + " = '')")
|
||||
} else {
|
||||
mod = mod.Where("("+mainTable+"."+dao.TSimFlowPackageInfo.Columns().PoolPackageCode+" IS NULL OR "+mainTable+"."+dao.TSimFlowPackageInfo.Columns().PoolPackageCode+" = '' OR "+mainTable+"."+dao.TSimFlowPackageInfo.Columns().PoolPackageCode+" = ?)", currentPoolPackageCode)
|
||||
}
|
||||
|
||||
if err := mod.Scan(&rows); err != nil {
|
||||
return nil, gerror.Wrap(err, "获取流量套餐选项失败")
|
||||
}
|
||||
|
||||
for _, row := range rows {
|
||||
results = append(results, row.FlowGb+","+row.FlowMb)
|
||||
}
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func normalizePackageListRows(list []*model.TSimFlowPackageInfoListModel) {
|
||||
for _, item := range list {
|
||||
if item == nil {
|
||||
continue
|
||||
}
|
||||
if item.RenewableDurationConfig == nil {
|
||||
continue
|
||||
}
|
||||
if normalized, normalizeErr := packageduration.NormalizeRenewableDurationConfig(item.RenewableDurationConfig); normalizeErr == nil {
|
||||
item.RenewableDurationConfig = normalized
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *sIotTSimFlowPackageInfo) fillPackageListPrices(ctx context.Context, list []*model.TSimFlowPackageInfoListModel) error {
|
||||
if len(list) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
tenantID := contexts.GetTenantId(ctx)
|
||||
currentDeptID := contexts.GetDeptId(ctx)
|
||||
ownerDeptID, err := loadPackagePriceParentDeptID(ctx, nil, tenantID, currentDeptID)
|
||||
if err != nil {
|
||||
return gerror.Wrap(err, "get package price owner department failed")
|
||||
}
|
||||
|
||||
for _, item := range list {
|
||||
if item == nil {
|
||||
continue
|
||||
}
|
||||
salePrice, err := resolvePackageEffectiveSalePrice(
|
||||
ctx,
|
||||
nil,
|
||||
tenantID,
|
||||
ownerDeptID,
|
||||
currentDeptID,
|
||||
packagePriceSourceFromListModel(item),
|
||||
)
|
||||
if err != nil {
|
||||
return gerror.Wrapf(err, "calculate effective price for package %s failed", item.PackageCode)
|
||||
}
|
||||
item.AgentShipmentPrice = salePrice.AgentShipmentPrice
|
||||
item.TerminalSalePrice = salePrice.TerminalSalePrice
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func packagePriceSourceFromListModel(pkg *model.TSimFlowPackageInfoListModel) packagePriceSource {
|
||||
if pkg == nil {
|
||||
return packagePriceSource{}
|
||||
}
|
||||
return packagePriceSource{
|
||||
PackageCode: strings.TrimSpace(pkg.PackageCode),
|
||||
CostPrice: pkg.CostPrice,
|
||||
TerminalCost: pkg.TerminalCost,
|
||||
SysDefaultRatio: pkg.SysDefaultRatio,
|
||||
SysDefaultProfit: pkg.SysDefaultProfit,
|
||||
SysDefaultTerminalRatio: pkg.SysDefaultTerminalRatio,
|
||||
SysDefaultTerminalProfit: pkg.SysDefaultTerminalProfit,
|
||||
}
|
||||
}
|
||||
|
||||
func applyPoolFlowPackageBaseFilter(mod *gdb.Model, mainTable, currentPoolPackageCode string) *gdb.Model {
|
||||
columns := dao.TSimFlowPackageInfo.Columns()
|
||||
poolPackageColumn := mainTable + "." + columns.PoolPackageCode
|
||||
if currentPoolPackageCode == "" {
|
||||
return mod.
|
||||
Where("("+poolPackageColumn+" IS NULL OR "+poolPackageColumn+" = '')").
|
||||
Where(mainTable+"."+columns.PackageType, "102")
|
||||
}
|
||||
return mod.
|
||||
Where("("+poolPackageColumn+" IS NULL OR "+poolPackageColumn+" = '' OR "+poolPackageColumn+" = ?)", currentPoolPackageCode).
|
||||
Where(mainTable+"."+columns.PackageType, "102")
|
||||
}
|
||||
|
||||
func (s *sIotTSimFlowPackageInfo) Export(ctx context.Context, in *model.TSimFlowPackageInfoListParam) (err error) {
|
||||
list, totalCount, err := s.List(ctx, in)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
tags, err := convert.GetEntityDescTags(model.TSimFlowPackageInfoExportModel{})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var (
|
||||
fileName = "导出SIM流量套餐管理-" + gctx.CtxId(ctx)
|
||||
sheetName = fmt.Sprintf("索引条件共%v行 共%v页 当前导出是第%v页 本页共%v行", totalCount, (totalCount+in.PageSize-1)/in.PageSize, in.Page, len(list))
|
||||
exports []model.TSimFlowPackageInfoExportModel
|
||||
)
|
||||
|
||||
if err = gconv.Scan(list, &exports); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = excel.ExportByStructs(ctx, tags, exports, fileName, sheetName)
|
||||
return
|
||||
}
|
||||
|
||||
func (s *sIotTSimFlowPackageInfo) Edit(ctx context.Context, in *model.TSimFlowPackageInfoEditParam) (err error) {
|
||||
if in == nil {
|
||||
return gerror.New("package information cannot be empty")
|
||||
}
|
||||
if err = validateFlowMb(in); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if in.BillingMethod == nil || strings.TrimSpace(*in.BillingMethod) == "" {
|
||||
billingMethod := packageduration.MonthBillingMethodValue()
|
||||
in.BillingMethod = &billingMethod
|
||||
}
|
||||
if in.RenewableDurationConfig != nil {
|
||||
in.RenewableDurationConfig, err = packageduration.NormalizeRenewableDurationConfig(in.RenewableDurationConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
packageCode := gconv.String(in.PackageCode)
|
||||
normalizeFlowPackageRenewableCodes(in, packageCode)
|
||||
if packageCode != "" {
|
||||
uniqueMod := s.Model(ctx, &handler.Option{FilterTenant: true, FilterAuth: false}).
|
||||
Where(dao.TSimFlowPackageInfo.Columns().PackageCode, packageCode)
|
||||
if in.Id > 0 {
|
||||
uniqueMod = uniqueMod.WhereNot(dao.TSimFlowPackageInfo.Columns().Id, in.Id)
|
||||
}
|
||||
count, countErr := uniqueMod.Count()
|
||||
if countErr != nil {
|
||||
return countErr
|
||||
}
|
||||
if count > 0 {
|
||||
return gerror.New("套餐编码已存在")
|
||||
}
|
||||
}
|
||||
|
||||
return g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) (err error) {
|
||||
now := gtime.Now()
|
||||
userId := contexts.GetUserId(ctx)
|
||||
|
||||
if in.Id > 0 {
|
||||
var oldPackage entity.TSimFlowPackageInfo
|
||||
if err = s.Model(ctx, &handler.Option{FilterTenant: true, FilterAuth: false}).WherePri(in.Id).Scan(&oldPackage); err != nil {
|
||||
return gerror.Wrap(err, "获取套餐信息失败,请稍后重试")
|
||||
}
|
||||
if oldPackage.Id == 0 {
|
||||
return gerror.New("套餐不存在")
|
||||
}
|
||||
|
||||
in.UpdatedBy = &userId
|
||||
in.UpdatedAt = now
|
||||
if _, err = tx.Ctx(ctx).Model(dao.TSimFlowPackageInfo.Table()).
|
||||
Fields(model.TSimFlowPackageInfoUpdateFields{}).
|
||||
WherePri(in.Id).
|
||||
Where(dao.TSimFlowPackageInfo.Columns().TenantId, contexts.GetTenantId(ctx)).
|
||||
Data(in).Update(); err != nil {
|
||||
return gerror.Wrap(err, "修改SIM流量套餐管理失败,请稍后重试")
|
||||
}
|
||||
|
||||
newPackageCode := oldPackage.PackageCode
|
||||
if in.PackageCode != nil {
|
||||
newPackageCode = *in.PackageCode
|
||||
}
|
||||
newPackageName := oldPackage.PackageName
|
||||
if in.PackageName != nil {
|
||||
newPackageName = *in.PackageName
|
||||
}
|
||||
if newPackageCode != oldPackage.PackageCode || newPackageName != oldPackage.PackageName {
|
||||
updateCustomer := do.TPackageCustomer{
|
||||
PackageCode: newPackageCode,
|
||||
PackageName: newPackageName,
|
||||
UpdatedBy: userId,
|
||||
UpdatedAt: now,
|
||||
}
|
||||
if _, err = tx.Ctx(ctx).Model(dao.TPackageCustomer.Table()).
|
||||
Where(dao.TPackageCustomer.Columns().TenantId, contexts.GetTenantId(ctx)).
|
||||
Where(dao.TPackageCustomer.Columns().PackageCode, oldPackage.PackageCode).
|
||||
Data(updateCustomer).Update(); err != nil {
|
||||
return gerror.Wrap(err, "同步套餐客户关联失败,请稍后重试")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
// 新增套餐
|
||||
tenantId := contexts.GetTenantId(ctx)
|
||||
in.TenantId = &tenantId
|
||||
createdDept := contexts.GetDeptId(ctx)
|
||||
in.CreatedDept = &createdDept
|
||||
in.CreatedBy = &userId
|
||||
in.CreatedAt = now
|
||||
if _, err = tx.Ctx(ctx).Model(dao.TSimFlowPackageInfo.Table()).
|
||||
Fields(model.TSimFlowPackageInfoInsertFields{}).
|
||||
Data(in).Insert(); err != nil {
|
||||
return gerror.Wrap(err, "新增SIM流量套餐管理失败,请稍后重试")
|
||||
}
|
||||
|
||||
_, dept, err := service.AgentDept().IsTopDept(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
packageName := gconv.String(in.PackageName)
|
||||
customer := s.buildPackageCustomer(ctx, dept, packageCode, packageName, now)
|
||||
if _, err = tx.Ctx(ctx).Model(dao.TPackageCustomer.Table()).Data(customer).Insert(); err != nil {
|
||||
return gerror.Wrap(err, "新增套餐客户关联失败,请稍后重试")
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func validateFlowMb(in *model.TSimFlowPackageInfoEditParam) error {
|
||||
if in == nil {
|
||||
return gerror.New("package information cannot be empty")
|
||||
}
|
||||
if in.Id <= 0 && in.FlowMb == nil {
|
||||
return gerror.New("套餐流量(MB)不能为空")
|
||||
}
|
||||
if in.FlowMb != nil && (*in.FlowMb <= 0 || math.IsNaN(*in.FlowMb) || math.IsInf(*in.FlowMb, 0)) {
|
||||
return gerror.New("套餐流量(MB)必须大于0")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func normalizeFlowPackageRenewableCodes(in *model.TSimFlowPackageInfoEditParam, packageCode string) {
|
||||
if in == nil || in.RenewablePackageCodes == nil {
|
||||
return
|
||||
}
|
||||
codes := make([]string, 0)
|
||||
_ = in.RenewablePackageCodes.Scan(&codes)
|
||||
in.RenewablePackageCodes = gjson.New(uniquePackageCodes(codes))
|
||||
}
|
||||
|
||||
func uniquePackageCodes(codes []string) []string {
|
||||
result := make([]string, 0, len(codes))
|
||||
seen := make(map[string]struct{}, len(codes))
|
||||
for _, code := range codes {
|
||||
code = strings.TrimSpace(code)
|
||||
if code == "" {
|
||||
continue
|
||||
}
|
||||
if _, ok := seen[code]; ok {
|
||||
continue
|
||||
}
|
||||
seen[code] = struct{}{}
|
||||
result = append(result, code)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (s *sIotTSimFlowPackageInfo) Delete(ctx context.Context, in *model.TSimFlowPackageInfoDeleteParam) (err error) {
|
||||
var packageInfo entity.TSimFlowPackageInfo
|
||||
if err = s.Model(ctx, &handler.Option{FilterTenant: true, FilterAuth: false}).WherePri(in.Id).Scan(&packageInfo); err != nil {
|
||||
return gerror.Wrap(err, "获取套餐信息失败,请稍后重试")
|
||||
}
|
||||
if packageInfo.Id == 0 {
|
||||
return gerror.New("套餐不存在")
|
||||
}
|
||||
|
||||
return g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) (err error) {
|
||||
if _, err = tx.Ctx(ctx).Model(dao.TSimFlowPackageInfo.Table()).
|
||||
WherePri(in.Id).
|
||||
Where(dao.TSimFlowPackageInfo.Columns().TenantId, contexts.GetTenantId(ctx)).
|
||||
Unscoped().Delete(); err != nil {
|
||||
return gerror.Wrap(err, "删除SIM流量套餐管理失败,请稍后重试")
|
||||
}
|
||||
if _, err = tx.Ctx(ctx).Model(dao.TPackageCustomer.Table()).
|
||||
Where(dao.TPackageCustomer.Columns().TenantId, contexts.GetTenantId(ctx)).
|
||||
Where(dao.TPackageCustomer.Columns().PackageCode, packageInfo.PackageCode).
|
||||
Delete(); err != nil {
|
||||
return gerror.Wrap(err, "清理套餐客户关联失败,请稍后重试")
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (s *sIotTSimFlowPackageInfo) View(ctx context.Context, in *model.TSimFlowPackageInfoViewParam) (res *model.TSimFlowPackageInfoViewModel, err error) {
|
||||
mainTable := dao.TSimFlowPackageInfo.Table()
|
||||
catTable := dao.TSimPackageCategory.Table()
|
||||
|
||||
mod, err := s.packageListModel(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mod = mod.LeftJoin(catTable, mainTable+"."+dao.TSimFlowPackageInfo.Columns().CategoryCode+" = "+catTable+"."+dao.TSimPackageCategory.Columns().CategoryCode)
|
||||
mod = mod.Fields(
|
||||
mainTable+".*",
|
||||
catTable+"."+dao.TSimPackageCategory.Columns().CategoryName+" as categoryName",
|
||||
)
|
||||
|
||||
if err = mod.Where(mainTable+"."+dao.TSimFlowPackageInfo.Columns().Id, in.Id).Hook(hook.MemberSummary).Scan(&res); err != nil {
|
||||
return nil, gerror.Wrap(err, "获取SIM流量套餐管理信息失败,请稍后重试")
|
||||
}
|
||||
if res == nil || res.Id == 0 {
|
||||
return nil, gerror.New("套餐不存在或无权限")
|
||||
}
|
||||
if res.RenewableDurationConfig != nil {
|
||||
if normalized, normalizeErr := packageduration.NormalizeRenewableDurationConfig(res.RenewableDurationConfig); normalizeErr == nil {
|
||||
res.RenewableDurationConfig = normalized
|
||||
}
|
||||
}
|
||||
if err = s.fillPackageRelationNames(ctx, res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *sIotTSimFlowPackageInfo) fillPackageRelationNames(ctx context.Context, res *model.TSimFlowPackageInfoViewModel) error {
|
||||
if res == nil {
|
||||
return nil
|
||||
}
|
||||
renewableCodes := packageCodesFromJSON(res.RenewablePackageCodes)
|
||||
changeableCodes := packageCodesFromJSON(res.ChangeablePackageCodes)
|
||||
topupCodes := packageCodesFromJSON(res.TopupPackageCodes)
|
||||
allCodes := uniquePackageCodes(append(append(renewableCodes, changeableCodes...), topupCodes...))
|
||||
if len(allCodes) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
nameMap, err := s.packageNamesByCode(ctx, res.TenantId, allCodes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
res.RenewablePackageNames = gjson.New(packageNamesForCodes(renewableCodes, nameMap))
|
||||
res.ChangeablePackageNames = gjson.New(packageNamesForCodes(changeableCodes, nameMap))
|
||||
res.TopupPackageNames = gjson.New(packageNamesForCodes(topupCodes, nameMap))
|
||||
return nil
|
||||
}
|
||||
|
||||
func packageCodesFromJSON(value *gjson.Json) []string {
|
||||
if value == nil {
|
||||
return nil
|
||||
}
|
||||
var codes []string
|
||||
_ = value.Scan(&codes)
|
||||
return uniquePackageCodes(codes)
|
||||
}
|
||||
|
||||
func (s *sIotTSimFlowPackageInfo) packageNamesByCode(ctx context.Context, tenantId string, codes []string) (map[string]string, error) {
|
||||
result := make(map[string]string, len(codes))
|
||||
if len(codes) == 0 {
|
||||
return result, nil
|
||||
}
|
||||
columns := dao.TSimFlowPackageInfo.Columns()
|
||||
var packages []struct {
|
||||
PackageCode string `orm:"package_code"`
|
||||
PackageName string `orm:"package_name"`
|
||||
}
|
||||
mod := s.Model(ctx, &handler.Option{FilterTenant: true, FilterAuth: false}).
|
||||
Fields(columns.PackageCode, columns.PackageName).
|
||||
WhereIn(columns.PackageCode, codes)
|
||||
if tenantId != "" {
|
||||
mod = mod.Where(columns.TenantId, tenantId)
|
||||
}
|
||||
if err := mod.Scan(&packages); err != nil {
|
||||
return nil, gerror.Wrap(err, "查询套餐名称失败")
|
||||
}
|
||||
for _, pkg := range packages {
|
||||
code := strings.TrimSpace(pkg.PackageCode)
|
||||
name := strings.TrimSpace(pkg.PackageName)
|
||||
if code == "" || name == "" {
|
||||
continue
|
||||
}
|
||||
result[code] = name
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func packageNamesForCodes(codes []string, nameMap map[string]string) []string {
|
||||
names := make([]string, 0, len(codes))
|
||||
for _, code := range codes {
|
||||
if name := strings.TrimSpace(nameMap[code]); name != "" {
|
||||
names = append(names, name)
|
||||
}
|
||||
}
|
||||
return names
|
||||
}
|
||||
|
||||
// GetPoolPackagesByCardPackages 根据卡套餐编码列表获取对应的池套餐编码列表
|
||||
func (s *sIotTSimFlowPackageInfo) GetPoolPackagesByCardPackages(ctx context.Context, cardPackageCodes []string) (poolPackageMap102 map[string]int64, poolPackageMap104 map[string]int64, err error) {
|
||||
poolPackageMap102 = make(map[string]int64)
|
||||
poolPackageMap104 = make(map[string]int64)
|
||||
if len(cardPackageCodes) == 0 {
|
||||
return
|
||||
}
|
||||
g.Log().Info(ctx, "GetPoolPackagesByCardPackages cardPackageCodes:", cardPackageCodes) //这些不存在 104
|
||||
mod := s.Model(ctx)
|
||||
mod = mod.Where(dao.TSimFlowPackageInfo.Columns().PackageCode+" IN (?)", cardPackageCodes)
|
||||
|
||||
// 查询 102 池套餐
|
||||
mod102 := mod.Where(dao.TSimFlowPackageInfo.Columns().PackageType, 102)
|
||||
var packages102 []*model.TSimFlowPackageInfoListModel
|
||||
var poolPackageCodes []int64
|
||||
if err = mod102.Scan(&packages102); err != nil {
|
||||
return nil, nil, gerror.Wrap(err, "获取102池套餐列表失败,请稍后重试!")
|
||||
}
|
||||
g.Log().Info(ctx, "获取102池套餐列表:%v", packages102)
|
||||
for _, pkg := range packages102 {
|
||||
poolPackageMap102[pkg.PackageCode] = pkg.PoolPackageCode
|
||||
poolPackageCodes = append(poolPackageCodes, pkg.PoolPackageCode)
|
||||
}
|
||||
|
||||
// 查询 104 池套餐
|
||||
mod104 := s.Model(ctx).Where(dao.TSimFlowPackageInfo.Columns().PackageType, 104).Where(dao.TSimFlowPackageInfo.Columns().PoolPackageCode+" IN (?)", poolPackageCodes)
|
||||
var packages104 []*model.TSimFlowPackageInfoListModel
|
||||
if err = mod104.Scan(&packages104); err != nil {
|
||||
return nil, nil, gerror.Wrap(err, "获取104池套餐列表失败,请稍后重试!")
|
||||
}
|
||||
g.Log().Info(ctx, "GetPoolPackagesByCardPackages packages104:", packages104)
|
||||
for _, pkg := range packages104 {
|
||||
poolPackageMap104[pkg.PackageCode] = pkg.PoolPackageCode
|
||||
}
|
||||
g.Log().Info(ctx, "GetPoolPackagesByCardPackages poolPackageMap102:", poolPackageMap102)
|
||||
g.Log().Info(ctx, "GetPoolPackagesByCardPackages poolPackageMap104:", poolPackageMap104)
|
||||
|
||||
return poolPackageMap102, poolPackageMap104, nil
|
||||
}
|
||||
|
||||
func (s *sIotTSimFlowPackageInfo) SyncDeptPackages(ctx context.Context) (err error) {
|
||||
_, dept, err := service.AgentDept().IsTopDept(ctx)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return packagecustomer.PublishSync(ctx, model.PackageCustomerSyncMessage{
|
||||
TenantId: contexts.GetTenantId(ctx),
|
||||
DeptId: dept.DeptId,
|
||||
UserId: contexts.GetUserId(ctx),
|
||||
Trigger: "manual_sync",
|
||||
})
|
||||
}
|
||||
|
||||
func (s *sIotTSimFlowPackageInfo) SyncDeptPackagesByDept(ctx context.Context, tenantId string, deptId int64, userId int64) error {
|
||||
return packagecustomer.SyncDeptPackagesByDept(ctx, tenantId, deptId, userId)
|
||||
}
|
||||
Reference in New Issue
Block a user