59eb34976a
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 已说明。
871 lines
32 KiB
Go
871 lines
32 KiB
Go
// Package gen
|
|
// @Link https://github.com/xiujiecn/xiu-admin
|
|
// @Copyright Copyright (c) 2026 LiXiujie
|
|
// @Author Lxj <li@xiujie.cn>
|
|
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
|
|
// @AutoGenerate Version
|
|
package iot
|
|
|
|
import (
|
|
"context"
|
|
"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/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"
|
|
"math"
|
|
"strings"
|
|
|
|
"github.com/gogf/gf/v2/database/gdb"
|
|
"github.com/gogf/gf/v2/errors/gerror"
|
|
"github.com/gogf/gf/v2/frame/g"
|
|
"github.com/gogf/gf/v2/os/gtime"
|
|
)
|
|
|
|
type sIotTSimFlowPackagePrice struct{}
|
|
|
|
func NewIotTSimFlowPackagePrice() *sIotTSimFlowPackagePrice {
|
|
return &sIotTSimFlowPackagePrice{}
|
|
}
|
|
|
|
func init() {
|
|
service.RegisterIotTSimFlowPackagePrice(NewIotTSimFlowPackagePrice())
|
|
}
|
|
|
|
func (s *sIotTSimFlowPackagePrice) 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.TSimFlowPackagePrice.Ctx(ctx), option...)
|
|
}
|
|
|
|
func (s *sIotTSimFlowPackagePrice) packageCustomerPriceListModel(ctx context.Context, deptId int64) *gdb.Model {
|
|
pkgTable := dao.TSimFlowPackageInfo.Table()
|
|
pkgColumns := dao.TSimFlowPackageInfo.Columns()
|
|
pcTable := dao.TPackageCustomer.Table()
|
|
pcColumns := dao.TPackageCustomer.Columns()
|
|
|
|
return handler.Model(dao.TSimFlowPackageInfo.Ctx(ctx), &handler.Option{
|
|
FilterTenant: false,
|
|
FilterAuth: false,
|
|
}).
|
|
InnerJoin(pcTable, pkgTable+"."+pkgColumns.PackageCode+" = "+pcTable+"."+pcColumns.PackageCode+" AND "+pkgTable+"."+pkgColumns.TenantId+" = "+pcTable+"."+pcColumns.TenantId).
|
|
Where(pkgTable+"."+pkgColumns.TenantId, contexts.GetTenantId(ctx)).
|
|
Where(pcTable+"."+pcColumns.DeptId, deptId).
|
|
Where(pcTable+"."+pcColumns.TenantId, contexts.GetTenantId(ctx))
|
|
}
|
|
|
|
func (s *sIotTSimFlowPackagePrice) AgentTree(ctx context.Context, in *model.TSimFlowPackagePriceAgentTreeParam) (res *model.TSimFlowPackagePriceAgentTreeRes, err error) {
|
|
items, err := service.AgentDept().SubCompany(ctx)
|
|
if err != nil {
|
|
err = gerror.Wrap(err, "获取渠道代理树失败,请稍后重试!")
|
|
return
|
|
}
|
|
if items == nil {
|
|
items = []*model.SysDeptTreeModel{}
|
|
}
|
|
|
|
res = &model.TSimFlowPackagePriceAgentTreeRes{Items: items}
|
|
return
|
|
}
|
|
|
|
// AgentPackagePriceList 查询指定下级代理套餐生效定价
|
|
func (s *sIotTSimFlowPackagePrice) AgentPackagePriceList(ctx context.Context, in *model.TSimFlowPackagePriceAgentPackagePriceListParam) (list []*model.TSimFlowPackagePriceAgentPackagePriceListItem, totalCount int, err error) {
|
|
if err = s.validateDirectChildAgent(ctx, in.TargetAgentId); err != nil {
|
|
return
|
|
}
|
|
pkgTable := dao.TSimFlowPackageInfo.Table()
|
|
pkgColumns := dao.TSimFlowPackageInfo.Columns()
|
|
pcTable := dao.TPackageCustomer.Table()
|
|
pcColumns := dao.TPackageCustomer.Columns()
|
|
|
|
pkgMod := s.packageCustomerPriceListModel(ctx, in.TargetAgentId)
|
|
|
|
if in.PackageCode != "" {
|
|
pkgMod = pkgMod.WhereLike(pcTable+"."+pcColumns.PackageCode, "%"+in.PackageCode+"%")
|
|
}
|
|
if in.PackageName != "" {
|
|
pkgMod = pkgMod.WhereLike(pkgTable+"."+pkgColumns.PackageName, "%"+in.PackageName+"%")
|
|
}
|
|
|
|
totalCount, err = pkgMod.Count()
|
|
if err != nil {
|
|
err = gerror.Wrap(err, "查询下级代理套餐定价列表失败,请稍后重试!")
|
|
return
|
|
}
|
|
|
|
var packages []*model.TSimFlowPackagePriceAgentDefaultPackagePricePackageItem
|
|
pkgMod = pkgMod.Fields(
|
|
pkgTable+"."+pkgColumns.PackageCode,
|
|
pkgTable+"."+pkgColumns.PackageName,
|
|
pkgTable+"."+pkgColumns.CostPrice,
|
|
pkgTable+"."+pkgColumns.TerminalCost,
|
|
pkgTable+"."+pkgColumns.SysDefaultRatio,
|
|
pkgTable+"."+pkgColumns.SysDefaultProfit,
|
|
pkgTable+"."+pkgColumns.SysDefaultTerminalRatio,
|
|
pkgTable+"."+pkgColumns.SysDefaultTerminalProfit,
|
|
)
|
|
pkgMod = pkgMod.Page(in.Page, in.PageSize)
|
|
pkgMod = pkgMod.OrderAsc(pkgTable + "." + pkgColumns.SortNo).OrderAsc(pkgTable + "." + pkgColumns.Id)
|
|
|
|
if err = pkgMod.Scan(&packages); err != nil {
|
|
err = gerror.Wrap(err, "查询下级代理套餐定价列表失败,请稍后重试!")
|
|
return
|
|
}
|
|
|
|
if len(packages) == 0 {
|
|
list = []*model.TSimFlowPackagePriceAgentPackagePriceListItem{}
|
|
return
|
|
}
|
|
|
|
packageCodes := make([]string, 0, len(packages))
|
|
for _, pkg := range packages {
|
|
packageCodes = append(packageCodes, pkg.PackageCode)
|
|
}
|
|
|
|
defaultPrices, err := s.agentDefaultPriceMap(ctx, packageCodes)
|
|
if err != nil {
|
|
return
|
|
}
|
|
targetPrices, err := s.agentTargetPriceMap(ctx, in.TargetAgentId, packageCodes)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
tenantID := contexts.GetTenantId(ctx)
|
|
currentDeptID := contexts.GetDeptId(ctx)
|
|
list = make([]*model.TSimFlowPackagePriceAgentPackagePriceListItem, 0, len(packages))
|
|
for _, pkg := range packages {
|
|
baseCosts, baseErr := resolvePackageEffectiveBaseCosts(ctx, nil, tenantID, currentDeptID, packagePriceSourceFromPriceListItem(pkg))
|
|
if baseErr != nil {
|
|
err = baseErr
|
|
return
|
|
}
|
|
item := &model.TSimFlowPackagePriceAgentPackagePriceListItem{
|
|
TargetAgentId: in.TargetAgentId,
|
|
PackageCode: pkg.PackageCode,
|
|
PackageName: pkg.PackageName,
|
|
PriceSource: "system",
|
|
AgentCost: baseCosts.AgentCost,
|
|
TerminalCost: baseCosts.TerminalCost,
|
|
AgentCostRatio: normalizePriceRatio(pkg.SysDefaultRatio),
|
|
AgentCostProfit: pkg.SysDefaultProfit,
|
|
TerminalCostRatio: normalizePriceRatio(pkg.SysDefaultTerminalRatio),
|
|
TerminalCostProfit: pkg.SysDefaultTerminalProfit,
|
|
}
|
|
|
|
if price, ok := defaultPrices[pkg.PackageCode]; ok {
|
|
item.AgentDefaultPriceId = price.Id
|
|
item.PriceSource = "agentDefault"
|
|
item.AgentCostRatio = normalizePriceRatio(price.AgentCostRatio)
|
|
item.AgentCostProfit = price.AgentCostProfit
|
|
item.TerminalCostRatio = normalizePriceRatio(price.UserCostRatio)
|
|
item.TerminalCostProfit = price.UserCostProfit
|
|
item.Remark = price.Remark
|
|
item.UpdatedAt = price.UpdatedAt
|
|
}
|
|
if price, ok := targetPrices[pkg.PackageCode]; ok {
|
|
item.TargetPriceId = price.Id
|
|
item.PriceSource = "target"
|
|
item.AgentCostRatio = normalizePriceRatio(price.AgentCostRatio)
|
|
item.AgentCostProfit = price.AgentCostProfit
|
|
item.TerminalCostRatio = normalizePriceRatio(price.UserCostRatio)
|
|
item.TerminalCostProfit = price.UserCostProfit
|
|
item.Remark = price.Remark
|
|
item.UpdatedAt = price.UpdatedAt
|
|
}
|
|
|
|
item.AgentShipmentPrice = roundAmount(item.AgentCost*item.AgentCostRatio + item.AgentCostProfit)
|
|
item.TerminalSalePrice = roundAmount(item.TerminalCost*item.TerminalCostRatio + item.TerminalCostProfit)
|
|
list = append(list, item)
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// AgentDefaultPackagePriceList 查询本级默认套餐生效定价
|
|
func (s *sIotTSimFlowPackagePrice) AgentDefaultPackagePriceList(ctx context.Context, in *model.TSimFlowPackagePriceAgentDefaultPackagePriceListParam) (list []*model.TSimFlowPackagePriceAgentDefaultPackagePriceListItem, totalCount int, err error) {
|
|
pkgTable := dao.TSimFlowPackageInfo.Table()
|
|
pkgColumns := dao.TSimFlowPackageInfo.Columns()
|
|
pcTable := dao.TPackageCustomer.Table()
|
|
pcColumns := dao.TPackageCustomer.Columns()
|
|
|
|
pkgMod := s.packageCustomerPriceListModel(ctx, contexts.GetDeptId(ctx))
|
|
|
|
if in.PackageCode != "" {
|
|
pkgMod = pkgMod.WhereLike(pcTable+"."+pcColumns.PackageCode, "%"+in.PackageCode+"%")
|
|
}
|
|
if in.PackageName != "" {
|
|
pkgMod = pkgMod.WhereLike(pkgTable+"."+pkgColumns.PackageName, "%"+in.PackageName+"%")
|
|
}
|
|
|
|
totalCount, err = pkgMod.Count()
|
|
if err != nil {
|
|
err = gerror.Wrap(err, "查询本级默认套餐定价列表失败,请稍后重试!")
|
|
return
|
|
}
|
|
|
|
var packages []*model.TSimFlowPackagePriceAgentDefaultPackagePricePackageItem
|
|
pkgMod = pkgMod.Fields(
|
|
pkgTable+"."+pkgColumns.PackageCode,
|
|
pkgTable+"."+pkgColumns.PackageName,
|
|
pkgTable+"."+pkgColumns.CostPrice,
|
|
pkgTable+"."+pkgColumns.TerminalCost,
|
|
pkgTable+"."+pkgColumns.SysDefaultRatio,
|
|
pkgTable+"."+pkgColumns.SysDefaultProfit,
|
|
pkgTable+"."+pkgColumns.SysDefaultTerminalRatio,
|
|
pkgTable+"."+pkgColumns.SysDefaultTerminalProfit,
|
|
)
|
|
pkgMod = pkgMod.Page(in.Page, in.PageSize)
|
|
pkgMod = pkgMod.OrderAsc(pkgTable + "." + pkgColumns.SortNo).OrderAsc(pkgTable + "." + pkgColumns.Id)
|
|
|
|
if err = pkgMod.Scan(&packages); err != nil {
|
|
err = gerror.Wrap(err, "查询本级默认套餐定价列表失败,请稍后重试!")
|
|
return
|
|
}
|
|
|
|
if len(packages) == 0 {
|
|
list = []*model.TSimFlowPackagePriceAgentDefaultPackagePriceListItem{}
|
|
return
|
|
}
|
|
|
|
packageCodes := make([]string, 0, len(packages))
|
|
for _, pkg := range packages {
|
|
packageCodes = append(packageCodes, pkg.PackageCode)
|
|
}
|
|
|
|
defaultPrices, err := s.agentDefaultPriceMap(ctx, packageCodes)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
tenantID := contexts.GetTenantId(ctx)
|
|
currentDeptID := contexts.GetDeptId(ctx)
|
|
list = make([]*model.TSimFlowPackagePriceAgentDefaultPackagePriceListItem, 0, len(packages))
|
|
for _, pkg := range packages {
|
|
baseCosts, baseErr := resolvePackageEffectiveBaseCosts(ctx, nil, tenantID, currentDeptID, packagePriceSourceFromPriceListItem(pkg))
|
|
if baseErr != nil {
|
|
err = baseErr
|
|
return
|
|
}
|
|
item := &model.TSimFlowPackagePriceAgentDefaultPackagePriceListItem{
|
|
PackageCode: pkg.PackageCode,
|
|
PackageName: pkg.PackageName,
|
|
PriceSource: "system",
|
|
AgentCost: baseCosts.AgentCost,
|
|
TerminalCost: baseCosts.TerminalCost,
|
|
AgentCostRatio: normalizePriceRatio(pkg.SysDefaultRatio),
|
|
AgentCostProfit: pkg.SysDefaultProfit,
|
|
TerminalCostRatio: normalizePriceRatio(pkg.SysDefaultTerminalRatio),
|
|
TerminalCostProfit: pkg.SysDefaultTerminalProfit,
|
|
}
|
|
|
|
if price, ok := defaultPrices[pkg.PackageCode]; ok {
|
|
item.AgentDefaultPriceId = price.Id
|
|
item.PriceSource = "agentDefault"
|
|
item.AgentCostRatio = normalizePriceRatio(price.AgentCostRatio)
|
|
item.AgentCostProfit = price.AgentCostProfit
|
|
item.TerminalCostRatio = normalizePriceRatio(price.UserCostRatio)
|
|
item.TerminalCostProfit = price.UserCostProfit
|
|
item.Remark = price.Remark
|
|
item.UpdatedAt = price.UpdatedAt
|
|
}
|
|
|
|
item.AgentShipmentPrice = roundAmount(item.AgentCost*item.AgentCostRatio + item.AgentCostProfit)
|
|
item.TerminalSalePrice = roundAmount(item.TerminalCost*item.TerminalCostRatio + item.TerminalCostProfit)
|
|
list = append(list, item)
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// SaveAgentDefaultPackagePrice 保存本级默认套餐生效定价
|
|
func (s *sIotTSimFlowPackagePrice) SaveAgentDefaultPackagePrice(ctx context.Context, in *model.TSimFlowPackagePriceAgentDefaultPackagePriceSaveParam) error {
|
|
if in == nil || len(in.Items) == 0 {
|
|
return gerror.New("请至少选择一个套餐")
|
|
}
|
|
if err := validateDefaultPriceSaveItems(in.Items); err != nil {
|
|
return err
|
|
}
|
|
|
|
return g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
|
|
for _, item := range in.Items {
|
|
if err := s.validateAgentOwnsPackage(ctx, tx, contexts.GetDeptId(ctx), item.PackageCode); err != nil {
|
|
return err
|
|
}
|
|
if err := s.validatePackageExists(ctx, tx, item.PackageCode); err != nil {
|
|
return err
|
|
}
|
|
|
|
switch item.PriceSource {
|
|
case "system":
|
|
if item.AgentDefaultPriceId > 0 {
|
|
return gerror.Newf("套餐%s来自系统定价,不能携带本级默认定价ID", item.PackageCode)
|
|
}
|
|
if err := s.ensurePriceOverrideNotExists(ctx, tx, 0, 0, item.PackageCode); err != nil {
|
|
return err
|
|
}
|
|
if err := s.insertPriceOverride(ctx, tx, item, 0, 0); err != nil {
|
|
return err
|
|
}
|
|
case "agentDefault":
|
|
if item.AgentDefaultPriceId <= 0 {
|
|
return gerror.Newf("套餐%s缺少本级默认定价ID", item.PackageCode)
|
|
}
|
|
if err := s.validateDefaultPriceRecordOwner(ctx, tx, item.AgentDefaultPriceId, item.PackageCode); err != nil {
|
|
return err
|
|
}
|
|
if err := s.updatePriceOverride(ctx, tx, item.AgentDefaultPriceId, item); err != nil {
|
|
return err
|
|
}
|
|
case "target":
|
|
return gerror.Newf("本级默认保存不支持下级专属定价:%s", item.PackageCode)
|
|
default:
|
|
return gerror.Newf("套餐%s价格来源不合法", item.PackageCode)
|
|
}
|
|
}
|
|
return nil
|
|
})
|
|
}
|
|
|
|
func (s *sIotTSimFlowPackagePrice) SaveAgentPackagePrice(ctx context.Context, in *model.TSimFlowPackagePriceAgentPackagePriceSaveParam) error {
|
|
if in == nil || len(in.Items) == 0 {
|
|
return gerror.New("请至少选择一个套餐")
|
|
}
|
|
if err := s.validateDirectChildAgent(ctx, in.TargetAgentId); err != nil {
|
|
return err
|
|
}
|
|
if err := validateTargetPriceSaveItems(in.Items); err != nil {
|
|
return err
|
|
}
|
|
|
|
return g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
|
|
for _, item := range in.Items {
|
|
if err := s.validateAgentOwnsPackage(ctx, tx, in.TargetAgentId, item.PackageCode); err != nil {
|
|
return err
|
|
}
|
|
if err := s.validatePackageExists(ctx, tx, item.PackageCode); err != nil {
|
|
return err
|
|
}
|
|
|
|
switch item.PriceSource {
|
|
case "system", "agentDefault":
|
|
if item.TargetPriceId > 0 {
|
|
return gerror.Newf("套餐%s尚未存在下级专属定价,不能携带下级专属定价ID", item.PackageCode)
|
|
}
|
|
if err := s.ensurePriceOverrideNotExists(ctx, tx, 1, in.TargetAgentId, item.PackageCode); err != nil {
|
|
return err
|
|
}
|
|
if err := s.insertPriceOverride(ctx, tx, targetSaveItemToDefault(item), 1, in.TargetAgentId); err != nil {
|
|
return err
|
|
}
|
|
case "target":
|
|
if item.TargetPriceId <= 0 {
|
|
return gerror.Newf("套餐%s缺少下级专属定价ID", item.PackageCode)
|
|
}
|
|
if err := s.validateTargetPriceRecordOwner(ctx, tx, item.TargetPriceId, in.TargetAgentId, item.PackageCode); err != nil {
|
|
return err
|
|
}
|
|
if err := s.updatePriceOverride(ctx, tx, item.TargetPriceId, targetSaveItemToDefault(item)); err != nil {
|
|
return err
|
|
}
|
|
default:
|
|
return gerror.Newf("套餐%s价格来源不合法", item.PackageCode)
|
|
}
|
|
}
|
|
return nil
|
|
})
|
|
}
|
|
|
|
func (s *sIotTSimFlowPackagePrice) InheritAgentDefaultPackagePrice(ctx context.Context, in *model.TSimFlowPackagePriceAgentDefaultPackagePriceInheritParam) error {
|
|
if in == nil || len(in.Items) == 0 {
|
|
return gerror.New("请至少选择一个套餐")
|
|
}
|
|
if err := validateDefaultPriceInheritItems(in.Items); err != nil {
|
|
return err
|
|
}
|
|
|
|
return g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
|
|
for _, item := range in.Items {
|
|
if err := s.validateAgentOwnsPackage(ctx, tx, contexts.GetDeptId(ctx), item.PackageCode); err != nil {
|
|
return err
|
|
}
|
|
if err := s.validateDefaultPriceRecordOwner(ctx, tx, item.AgentDefaultPriceId, item.PackageCode); err != nil {
|
|
return err
|
|
}
|
|
if err := s.deletePriceOverride(ctx, tx, item.AgentDefaultPriceId, 0, 0, item.PackageCode); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
})
|
|
}
|
|
|
|
func (s *sIotTSimFlowPackagePrice) InheritAgentPackagePrice(ctx context.Context, in *model.TSimFlowPackagePriceAgentPackagePriceInheritParam) error {
|
|
if in == nil || len(in.Items) == 0 {
|
|
return gerror.New("请至少选择一个套餐")
|
|
}
|
|
if err := s.validateDirectChildAgent(ctx, in.TargetAgentId); err != nil {
|
|
return err
|
|
}
|
|
if err := validateTargetPriceInheritItems(in.Items); err != nil {
|
|
return err
|
|
}
|
|
|
|
return g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
|
|
for _, item := range in.Items {
|
|
if err := s.validateAgentOwnsPackage(ctx, tx, in.TargetAgentId, item.PackageCode); err != nil {
|
|
return err
|
|
}
|
|
if err := s.validateTargetPriceRecordOwner(ctx, tx, item.TargetPriceId, in.TargetAgentId, item.PackageCode); err != nil {
|
|
return err
|
|
}
|
|
if err := s.deletePriceOverride(ctx, tx, item.TargetPriceId, 1, in.TargetAgentId, item.PackageCode); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
})
|
|
}
|
|
|
|
func (s *sIotTSimFlowPackagePrice) agentDefaultPriceMap(ctx context.Context, packageCodes []string) (map[string]*model.TSimFlowPackagePriceAgentDefaultPackagePriceRecord, error) {
|
|
priceTable := dao.TSimFlowPackagePrice.Table()
|
|
priceColumns := dao.TSimFlowPackagePrice.Columns()
|
|
|
|
var prices []*model.TSimFlowPackagePriceAgentDefaultPackagePriceRecord
|
|
if err := s.Model(ctx, &handler.Option{
|
|
FilterTenant: true,
|
|
FilterAuth: false,
|
|
}).
|
|
Where(priceTable+"."+priceColumns.DeptId, contexts.GetDeptId(ctx)).
|
|
Where(priceTable+"."+priceColumns.AgentScopeType, 0).
|
|
Where(priceTable+"."+priceColumns.TargetAgentId, 0).
|
|
WhereIn(priceTable+"."+priceColumns.PackageCode, packageCodes).
|
|
Fields(
|
|
priceTable+"."+priceColumns.Id,
|
|
priceTable+"."+priceColumns.PackageCode,
|
|
priceTable+"."+priceColumns.AgentCostRatio,
|
|
priceTable+"."+priceColumns.AgentCostProfit,
|
|
priceTable+"."+priceColumns.UserCostRatio,
|
|
priceTable+"."+priceColumns.UserCostProfit,
|
|
priceTable+"."+priceColumns.Remark,
|
|
priceTable+"."+priceColumns.UpdatedAt,
|
|
).
|
|
Scan(&prices); err != nil {
|
|
return nil, gerror.Wrap(err, "查询本级默认套餐定价覆盖失败,请稍后重试!")
|
|
}
|
|
|
|
priceMap := make(map[string]*model.TSimFlowPackagePriceAgentDefaultPackagePriceRecord, len(prices))
|
|
for _, price := range prices {
|
|
priceMap[price.PackageCode] = price
|
|
}
|
|
return priceMap, nil
|
|
}
|
|
|
|
func validateDefaultPriceSaveItems(items []*model.TSimFlowPackagePriceAgentDefaultPackagePriceSaveItem) error {
|
|
packageCodes := make(map[string]struct{}, len(items))
|
|
for i, item := range items {
|
|
if item == nil {
|
|
return gerror.Newf("第%d行套餐定价不能为空", i+1)
|
|
}
|
|
item.PackageCode = strings.TrimSpace(item.PackageCode)
|
|
item.PriceSource = strings.TrimSpace(item.PriceSource)
|
|
if item.PackageCode == "" {
|
|
return gerror.Newf("第%d行套餐编码不能为空", i+1)
|
|
}
|
|
if _, ok := packageCodes[item.PackageCode]; ok {
|
|
return gerror.Newf("套餐%s重复,请勿在同一批保存中重复提交", item.PackageCode)
|
|
}
|
|
packageCodes[item.PackageCode] = struct{}{}
|
|
if err := validateDefaultPackagePriceNumbers(item); err != nil {
|
|
return err
|
|
}
|
|
if item.PriceSource == "" {
|
|
return gerror.Newf("套餐%s价格来源不能为空", item.PackageCode)
|
|
}
|
|
switch item.PriceSource {
|
|
case "system":
|
|
if item.AgentDefaultPriceId > 0 {
|
|
return gerror.Newf("套餐%s来自系统定价,不能携带本级默认定价ID", item.PackageCode)
|
|
}
|
|
case "agentDefault":
|
|
if item.AgentDefaultPriceId <= 0 {
|
|
return gerror.Newf("套餐%s缺少本级默认定价ID", item.PackageCode)
|
|
}
|
|
default:
|
|
return gerror.Newf("套餐%s价格来源不合法", item.PackageCode)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func validateTargetPriceSaveItems(items []*model.TSimFlowPackagePriceAgentPackagePriceSaveItem) error {
|
|
packageCodes := make(map[string]struct{}, len(items))
|
|
for i, item := range items {
|
|
if item == nil {
|
|
return gerror.Newf("第%d行套餐定价不能为空", i+1)
|
|
}
|
|
item.PackageCode = strings.TrimSpace(item.PackageCode)
|
|
item.PriceSource = strings.TrimSpace(item.PriceSource)
|
|
if item.PackageCode == "" {
|
|
return gerror.Newf("第%d行套餐编码不能为空", i+1)
|
|
}
|
|
if _, ok := packageCodes[item.PackageCode]; ok {
|
|
return gerror.Newf("套餐%s重复,请勿在同一批保存中重复提交", item.PackageCode)
|
|
}
|
|
packageCodes[item.PackageCode] = struct{}{}
|
|
if err := validateTargetPackagePriceNumbers(item); err != nil {
|
|
return err
|
|
}
|
|
if item.PriceSource == "" {
|
|
return gerror.Newf("套餐%s价格来源不能为空", item.PackageCode)
|
|
}
|
|
switch item.PriceSource {
|
|
case "system", "agentDefault":
|
|
if item.TargetPriceId > 0 {
|
|
return gerror.Newf("套餐%s尚未存在下级专属定价,不能携带下级专属定价ID", item.PackageCode)
|
|
}
|
|
case "target":
|
|
if item.TargetPriceId <= 0 {
|
|
return gerror.Newf("套餐%s缺少下级专属定价ID", item.PackageCode)
|
|
}
|
|
default:
|
|
return gerror.Newf("套餐%s价格来源不合法", item.PackageCode)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func validateDefaultPackagePriceNumbers(item *model.TSimFlowPackagePriceAgentDefaultPackagePriceSaveItem) error {
|
|
if item == nil {
|
|
return nil
|
|
}
|
|
if err := validatePackagePriceNonNegativeNumber(item.PackageCode, "渠道系数", item.AgentCostRatio); err != nil {
|
|
return err
|
|
}
|
|
if err := validatePackagePriceNonNegativeNumber(item.PackageCode, "渠道利润", item.AgentCostProfit); err != nil {
|
|
return err
|
|
}
|
|
if err := validatePackagePriceNonNegativeNumber(item.PackageCode, "终端系数", item.TerminalCostRatio); err != nil {
|
|
return err
|
|
}
|
|
if err := validatePackagePriceNonNegativeNumber(item.PackageCode, "终端用户成本利润", item.TerminalCostProfit); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func validateTargetPackagePriceNumbers(item *model.TSimFlowPackagePriceAgentPackagePriceSaveItem) error {
|
|
if item == nil {
|
|
return nil
|
|
}
|
|
return validateDefaultPackagePriceNumbers(targetSaveItemToDefault(item))
|
|
}
|
|
|
|
func validatePackagePriceNonNegativeNumber(packageCode, label string, value float64) error {
|
|
if math.IsNaN(value) || math.IsInf(value, 0) {
|
|
return gerror.Newf("套餐%s%s必须为数字", packageCode, label)
|
|
}
|
|
if value < 0 {
|
|
return gerror.Newf("套餐%s%s不能为负数", packageCode, label)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func validateDefaultPriceInheritItems(items []*model.TSimFlowPackagePriceAgentDefaultPackagePriceInheritItem) error {
|
|
packageCodes := make(map[string]struct{}, len(items))
|
|
for i, item := range items {
|
|
if item == nil {
|
|
return gerror.Newf("第%d行套餐承袭不能为空", i+1)
|
|
}
|
|
item.PackageCode = strings.TrimSpace(item.PackageCode)
|
|
if item.PackageCode == "" {
|
|
return gerror.Newf("第%d行套餐编码不能为空", i+1)
|
|
}
|
|
if item.AgentDefaultPriceId <= 0 {
|
|
return gerror.Newf("套餐%s不存在本级默认定价,不能承袭", item.PackageCode)
|
|
}
|
|
if _, ok := packageCodes[item.PackageCode]; ok {
|
|
return gerror.Newf("套餐%s重复,请勿在同一批承袭中重复提交", item.PackageCode)
|
|
}
|
|
packageCodes[item.PackageCode] = struct{}{}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func validateTargetPriceInheritItems(items []*model.TSimFlowPackagePriceAgentPackagePriceInheritItem) error {
|
|
packageCodes := make(map[string]struct{}, len(items))
|
|
for i, item := range items {
|
|
if item == nil {
|
|
return gerror.Newf("第%d行套餐承袭不能为空", i+1)
|
|
}
|
|
item.PackageCode = strings.TrimSpace(item.PackageCode)
|
|
if item.PackageCode == "" {
|
|
return gerror.Newf("第%d行套餐编码不能为空", i+1)
|
|
}
|
|
if item.TargetPriceId <= 0 {
|
|
return gerror.Newf("套餐%s不存在下级专属定价,不能承袭", item.PackageCode)
|
|
}
|
|
if _, ok := packageCodes[item.PackageCode]; ok {
|
|
return gerror.Newf("套餐%s重复,请勿在同一批承袭中重复提交", item.PackageCode)
|
|
}
|
|
packageCodes[item.PackageCode] = struct{}{}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func targetSaveItemToDefault(item *model.TSimFlowPackagePriceAgentPackagePriceSaveItem) *model.TSimFlowPackagePriceAgentDefaultPackagePriceSaveItem {
|
|
if item == nil {
|
|
return nil
|
|
}
|
|
return &model.TSimFlowPackagePriceAgentDefaultPackagePriceSaveItem{
|
|
PriceSource: item.PriceSource,
|
|
AgentDefaultPriceId: item.AgentDefaultPriceId,
|
|
PackageCode: item.PackageCode,
|
|
AgentCostRatio: item.AgentCostRatio,
|
|
AgentCostProfit: item.AgentCostProfit,
|
|
TerminalCostRatio: item.TerminalCostRatio,
|
|
TerminalCostProfit: item.TerminalCostProfit,
|
|
Remark: item.Remark,
|
|
}
|
|
}
|
|
|
|
// validatePackageExists 校验套餐是否存在
|
|
func (s *sIotTSimFlowPackagePrice) validatePackageExists(ctx context.Context, tx gdb.TX, packageCode string) error {
|
|
pkgColumns := dao.TSimFlowPackageInfo.Columns()
|
|
count, err := tx.Ctx(ctx).Model(dao.TSimFlowPackageInfo.Table()).
|
|
Where(pkgColumns.TenantId, contexts.GetTenantId(ctx)).
|
|
Where(pkgColumns.PackageCode, packageCode).
|
|
Count()
|
|
if err != nil {
|
|
return gerror.Wrap(err, "校验套餐失败,请稍后重试!")
|
|
}
|
|
if count == 0 {
|
|
return gerror.Newf("套餐%s不存在", packageCode)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// validateAgentOwnsPackage 校验代理是否拥有套餐
|
|
func (s *sIotTSimFlowPackagePrice) validateAgentOwnsPackage(ctx context.Context, tx gdb.TX, deptId int64, packageCode string) error {
|
|
pcColumns := dao.TPackageCustomer.Columns()
|
|
count, err := tx.Ctx(ctx).Model(dao.TPackageCustomer.Table()).
|
|
Where(pcColumns.TenantId, contexts.GetTenantId(ctx)).
|
|
Where(pcColumns.DeptId, deptId).
|
|
Where(pcColumns.PackageCode, packageCode).
|
|
Count()
|
|
if err != nil {
|
|
return gerror.Wrap(err, "校验代理套餐归属失败,请稍后重试!")
|
|
}
|
|
if count == 0 {
|
|
return gerror.Newf("代理没有套餐%s", packageCode)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// validateDefaultPriceRecordOwner 校验本级默认套餐定价记录是否属于当前代理
|
|
func (s *sIotTSimFlowPackagePrice) validateDefaultPriceRecordOwner(ctx context.Context, tx gdb.TX, priceId int64, packageCode string) error {
|
|
price, err := s.priceRecordById(ctx, tx, priceId)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if price == nil ||
|
|
price.TenantId != contexts.GetTenantId(ctx) ||
|
|
price.DeptId != contexts.GetDeptId(ctx) ||
|
|
price.PackageCode != packageCode ||
|
|
price.AgentScopeType != 0 ||
|
|
price.TargetAgentId != 0 {
|
|
return gerror.Newf("套餐%s本级默认定价不存在或不属于当前代理", packageCode)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// validateTargetPriceRecordOwner 校验下级专属套餐定价记录是否属于当前代理
|
|
func (s *sIotTSimFlowPackagePrice) validateTargetPriceRecordOwner(ctx context.Context, tx gdb.TX, priceId int64, targetAgentId int64, packageCode string) error {
|
|
price, err := s.priceRecordById(ctx, tx, priceId)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if price == nil ||
|
|
price.TenantId != contexts.GetTenantId(ctx) ||
|
|
price.DeptId != contexts.GetDeptId(ctx) ||
|
|
price.TargetAgentId != targetAgentId ||
|
|
price.PackageCode != packageCode ||
|
|
price.AgentScopeType != 1 {
|
|
return gerror.Newf("套餐%s下级专属定价不存在或不属于当前代理", packageCode)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// priceRecordById 查询套餐定价记录
|
|
func (s *sIotTSimFlowPackagePrice) priceRecordById(ctx context.Context, tx gdb.TX, priceId int64) (*entity.TSimFlowPackagePrice, error) {
|
|
var price *entity.TSimFlowPackagePrice
|
|
if err := tx.Ctx(ctx).Model(dao.TSimFlowPackagePrice.Table()).
|
|
Where(dao.TSimFlowPackagePrice.Columns().Id, priceId).
|
|
Scan(&price); err != nil {
|
|
return nil, gerror.Wrap(err, "查询套餐定价记录失败,请稍后重试!")
|
|
}
|
|
return price, nil
|
|
}
|
|
|
|
// ensurePriceOverrideNotExists 校验套餐定价覆盖是否存在
|
|
func (s *sIotTSimFlowPackagePrice) ensurePriceOverrideNotExists(ctx context.Context, tx gdb.TX, agentScopeType int, targetAgentId int64, packageCode string) error {
|
|
priceColumns := dao.TSimFlowPackagePrice.Columns()
|
|
count, err := tx.Ctx(ctx).Model(dao.TSimFlowPackagePrice.Table()).
|
|
Where(priceColumns.TenantId, contexts.GetTenantId(ctx)).
|
|
Where(priceColumns.DeptId, contexts.GetDeptId(ctx)).
|
|
Where(priceColumns.AgentScopeType, agentScopeType).
|
|
Where(priceColumns.TargetAgentId, targetAgentId).
|
|
Where(priceColumns.PackageCode, packageCode).
|
|
Count()
|
|
if err != nil {
|
|
return gerror.Wrap(err, "校验套餐定价覆盖失败,请稍后重试!")
|
|
}
|
|
if count > 0 {
|
|
return gerror.Newf("套餐%s定价覆盖已存在,请刷新列表后重试", packageCode)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// insertPriceOverride 新增套餐定价覆盖
|
|
func (s *sIotTSimFlowPackagePrice) insertPriceOverride(ctx context.Context, tx gdb.TX, item *model.TSimFlowPackagePriceAgentDefaultPackagePriceSaveItem, agentScopeType int, targetAgentId int64) error {
|
|
now := gtime.Now()
|
|
deptId := contexts.GetDeptId(ctx)
|
|
data := do.TSimFlowPackagePrice{
|
|
PackageCode: item.PackageCode,
|
|
AgentScopeType: agentScopeType,
|
|
TargetAgentId: targetAgentId,
|
|
DeptId: deptId,
|
|
AgentCostRatio: item.AgentCostRatio,
|
|
AgentCostProfit: item.AgentCostProfit,
|
|
UserCostRatio: item.TerminalCostRatio,
|
|
UserCostProfit: item.TerminalCostProfit,
|
|
Remark: item.Remark,
|
|
TenantId: contexts.GetTenantId(ctx),
|
|
CreatedDept: deptId,
|
|
CreatedBy: contexts.GetUserId(ctx),
|
|
CreatedAt: now,
|
|
UpdatedBy: contexts.GetUserId(ctx),
|
|
UpdatedAt: now,
|
|
}
|
|
if _, err := tx.Ctx(ctx).Model(dao.TSimFlowPackagePrice.Table()).Data(data).OmitNil().Insert(); err != nil {
|
|
return gerror.Wrap(err, "新增套餐定价覆盖失败,请稍后重试!")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// updatePriceOverride 更新套餐定价覆盖
|
|
func (s *sIotTSimFlowPackagePrice) updatePriceOverride(ctx context.Context, tx gdb.TX, priceId int64, item *model.TSimFlowPackagePriceAgentDefaultPackagePriceSaveItem) error {
|
|
data := do.TSimFlowPackagePrice{
|
|
AgentCostRatio: item.AgentCostRatio,
|
|
AgentCostProfit: item.AgentCostProfit,
|
|
UserCostRatio: item.TerminalCostRatio,
|
|
UserCostProfit: item.TerminalCostProfit,
|
|
Remark: item.Remark,
|
|
UpdatedBy: contexts.GetUserId(ctx),
|
|
UpdatedAt: gtime.Now(),
|
|
}
|
|
if _, err := tx.Ctx(ctx).Model(dao.TSimFlowPackagePrice.Table()).
|
|
Where(dao.TSimFlowPackagePrice.Columns().Id, priceId).
|
|
Data(data).OmitNil().Update(); err != nil {
|
|
return gerror.Wrap(err, "更新套餐定价覆盖失败,请稍后重试!")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *sIotTSimFlowPackagePrice) deletePriceOverride(ctx context.Context, tx gdb.TX, priceId int64, agentScopeType int, targetAgentId int64, packageCode string) error {
|
|
priceColumns := dao.TSimFlowPackagePrice.Columns()
|
|
result, err := tx.Ctx(ctx).Model(dao.TSimFlowPackagePrice.Table()).
|
|
Where(priceColumns.Id, priceId).
|
|
Where(priceColumns.TenantId, contexts.GetTenantId(ctx)).
|
|
Where(priceColumns.DeptId, contexts.GetDeptId(ctx)).
|
|
Where(priceColumns.AgentScopeType, agentScopeType).
|
|
Where(priceColumns.TargetAgentId, targetAgentId).
|
|
Where(priceColumns.PackageCode, packageCode).
|
|
Delete()
|
|
if err != nil {
|
|
return gerror.Wrap(err, "承袭套餐定价失败,请稍后重试!")
|
|
}
|
|
affected, err := result.RowsAffected()
|
|
if err != nil {
|
|
return gerror.Wrap(err, "确认套餐定价承袭结果失败,请稍后重试!")
|
|
}
|
|
if affected != 1 {
|
|
return gerror.Newf("套餐%s定价已变更,请刷新后重试", packageCode)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// agentTargetPriceMap 查询下级代理专属套餐定价覆盖
|
|
func (s *sIotTSimFlowPackagePrice) agentTargetPriceMap(ctx context.Context, targetAgentId int64, packageCodes []string) (map[string]*model.TSimFlowPackagePriceAgentDefaultPackagePriceRecord, error) {
|
|
priceTable := dao.TSimFlowPackagePrice.Table()
|
|
priceColumns := dao.TSimFlowPackagePrice.Columns()
|
|
|
|
var prices []*model.TSimFlowPackagePriceAgentDefaultPackagePriceRecord
|
|
if err := s.Model(ctx, &handler.Option{
|
|
FilterTenant: true,
|
|
FilterAuth: false,
|
|
}).
|
|
Where(priceTable+"."+priceColumns.DeptId, contexts.GetDeptId(ctx)).
|
|
Where(priceTable+"."+priceColumns.AgentScopeType, 1).
|
|
Where(priceTable+"."+priceColumns.TargetAgentId, targetAgentId).
|
|
WhereIn(priceTable+"."+priceColumns.PackageCode, packageCodes).
|
|
Fields(
|
|
priceTable+"."+priceColumns.Id,
|
|
priceTable+"."+priceColumns.PackageCode,
|
|
priceTable+"."+priceColumns.AgentCostRatio,
|
|
priceTable+"."+priceColumns.AgentCostProfit,
|
|
priceTable+"."+priceColumns.UserCostRatio,
|
|
priceTable+"."+priceColumns.UserCostProfit,
|
|
priceTable+"."+priceColumns.Remark,
|
|
priceTable+"."+priceColumns.UpdatedAt,
|
|
).
|
|
Scan(&prices); err != nil {
|
|
return nil, gerror.Wrap(err, "查询下级代理专属套餐定价覆盖失败,请稍后重试!")
|
|
}
|
|
|
|
priceMap := make(map[string]*model.TSimFlowPackagePriceAgentDefaultPackagePriceRecord, len(prices))
|
|
for _, price := range prices {
|
|
priceMap[price.PackageCode] = price
|
|
}
|
|
return priceMap, nil
|
|
}
|
|
|
|
// validateDirectChildAgent 校验下级代理归属
|
|
func (s *sIotTSimFlowPackagePrice) validateDirectChildAgent(ctx context.Context, targetAgentId int64) error {
|
|
if targetAgentId <= 0 {
|
|
return gerror.New("请选择下级代理")
|
|
}
|
|
|
|
deptTable := dao.SysDept.Table()
|
|
deptColumns := dao.SysDept.Columns()
|
|
count, err := handler.Model(dao.SysDept.Ctx(ctx), &handler.Option{
|
|
FilterTenant: true,
|
|
FilterAuth: false,
|
|
}).
|
|
Where(deptTable+"."+deptColumns.DeptId, targetAgentId).
|
|
Where(deptTable+"."+deptColumns.ParentId, contexts.GetDeptId(ctx)).
|
|
Where(deptTable+"."+deptColumns.DeptType, 1).
|
|
Count()
|
|
if err != nil {
|
|
return gerror.Wrap(err, "校验下级代理归属失败,请稍后重试!")
|
|
}
|
|
if count == 0 {
|
|
return gerror.New("下级代理不存在或不属于当前代理")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// normalizePriceRatio 归一化套餐定价比例
|
|
func normalizePriceRatio(ratio float64) float64 {
|
|
if ratio > 10 {
|
|
return ratio / 100
|
|
}
|
|
return ratio
|
|
}
|