// Package gen // @Link https://github.com/xiujiecn/xiu-admin // @Copyright Copyright (c) 2026 LiXiujie // @Author Lxj // @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE // @AutoGenerate Version package common import ( "context" "fmt" "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" "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/model" "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" "strconv" "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/gctx" "github.com/gogf/gf/v2/os/gtime" "github.com/gogf/gf/v2/util/gconv" ) type sCommonTFinCommissionDetail struct{} func NewCommonTFinCommissionDetail() *sCommonTFinCommissionDetail { return &sCommonTFinCommissionDetail{} } func init() { service.RegisterCommonTFinCommissionDetail(NewCommonTFinCommissionDetail()) } // Model 分润明细表ORM模型 func (s *sCommonTFinCommissionDetail) 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.TFinCommissionDetail.Ctx(ctx), option...) } // List 获取分润明细表列表 func (s *sCommonTFinCommissionDetail) List(ctx context.Context, in *model.TFinCommissionDetailListParam) (list []*model.TFinCommissionDetailListModel, totalCount int, err error) { mod := s.Model(ctx) // 字段过滤 mod = mod.Fields(model.TFinCommissionDetailListModel{}) // 查询主键ID if in.Id > 0 { mod = mod.Where(dao.TFinCommissionDetail.Columns().Id, in.Id) } // 查询分润状态:0待结算,1可提现 if in.CommissionStatus > 0 { mod = mod.Where(dao.TFinCommissionDetail.Columns().CommissionStatus, in.CommissionStatus) } // 查询创建时间 if len(in.CreatedAt) == 2 { in.CreatedAt[1] = in.CreatedAt[1].EndOfDay() } if len(in.CreatedAt) == 2 { mod = mod.WhereBetween(dao.TFinCommissionDetail.Columns().CreatedAt, in.CreatedAt[0], in.CreatedAt[1]) } // 分页 mod = mod.Page(in.Page, in.PageSize) // 排序 mod = mod.OrderDesc(dao.TFinCommissionDetail.Columns().Id) // 操作人摘要信息 mod = mod.Hook(hook.MemberSummary) // 查询数据 if err = mod.ScanAndCount(&list, &totalCount, false); err != nil { err = gerror.Wrap(err, "获取分润明细表列表失败,请稍后重试!") return } return } // Export 导出分润明细表 func (s *sCommonTFinCommissionDetail) Export(ctx context.Context, in *model.TFinCommissionDetailListParam) (err error) { list, totalCount, err := s.List(ctx, in) if err != nil { return } // 字段的排序是依据tags的字段顺序,如果你不想使用默认的排序方式,可以直接定义 tags = []string{"字段名称", "字段名称2", ...} tags, err := convert.GetEntityDescTags(model.TFinCommissionDetailExportModel{}) if err != nil { return } var ( fileName = "导出分润明细表-" + gctx.CtxId(ctx) sheetName = fmt.Sprintf("索引条件共%v行,共%v页,当前导出是第%v页,本页共%v行", totalCount, (totalCount+in.PageSize-1)/in.PageSize, in.Page, len(list)) exports []model.TFinCommissionDetailExportModel ) if err = gconv.Scan(list, &exports); err != nil { return } err = excel.ExportByStructs(ctx, tags, exports, fileName, sheetName) return } // Edit 修改/新增分润明细表 func (s *sCommonTFinCommissionDetail) Edit(ctx context.Context, in *model.TFinCommissionDetailEditParam) (err error) { // 验证'CommissionNo'唯一 if err = xgorm.IsUnique(ctx, &dao.TFinCommissionDetail, g.Map{dao.TFinCommissionDetail.Columns().CommissionNo: in.CommissionNo}, "分润明细编号已存在", in.Id); err != nil { return } return g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) (err error) { // 修改 if in.Id > 0 { updatedBy := contexts.GetUserId(ctx) in.UpdatedBy = &updatedBy in.UpdatedAt = gtime.Now() if _, err = s.Model(ctx). Fields(model.TFinCommissionDetailUpdateFields{}). WherePri(in.Id).Data(in).Update(); err != nil { err = gerror.Wrap(err, "修改分润明细表失败,请稍后重试!") } return } // 新增 tenantId := contexts.GetTenantId(ctx) in.TenantId = &tenantId createdDept := contexts.GetDeptId(ctx) in.CreatedDept = &createdDept createdBy := contexts.GetUserId(ctx) in.CreatedBy = &createdBy in.CreatedAt = gtime.Now() if _, err = s.Model(ctx, &handler.Option{FilterAuth: false}). Fields(model.TFinCommissionDetailInsertFields{}). Data(in).Insert(); err != nil { err = gerror.Wrap(err, "新增分润明细表失败,请稍后重试!") } return }) } // Delete 删除分润明细表 func (s *sCommonTFinCommissionDetail) Delete(ctx context.Context, in *model.TFinCommissionDetailDeleteParam) (err error) { if _, err = s.Model(ctx).WherePri(in.Id).Unscoped().Delete(); err != nil { err = gerror.Wrap(err, "删除分润明细表失败,请稍后重试!") return } return } // View 获取分润明细表指定信息 func (s *sCommonTFinCommissionDetail) View(ctx context.Context, in *model.TFinCommissionDetailViewParam) (res *model.TFinCommissionDetailViewModel, err error) { if err = s.Model(ctx).WherePri(in.Id).Hook(hook.MemberSummary).Scan(&res); err != nil { err = gerror.Wrap(err, "获取分润明细表信息,请稍后重试!") return } return } // MarkSettled 批量标记分润明细为可提现状态。 func (s *sCommonTFinCommissionDetail) MarkSettled(ctx context.Context, tx gdb.TX, in *model.TFinCommissionSettleUpdateParam) error { if in == nil { return gerror.New("分润结算更新参数不能为空") } if len(in.Ids) == 0 { return gerror.New("分润明细ID不能为空") } settlementTime := in.SettlementTime if settlementTime == nil { settlementTime = gtime.Now() } userId := contexts.GetUserId(ctx) columns := dao.TFinCommissionDetail.Columns() result, err := tx.Ctx(ctx).Model(dao.TFinCommissionDetail.Table()). WhereIn(columns.Id, in.Ids). Where(columns.CommissionStatus, financeCommissionStatusPending). Data(g.Map{ columns.CommissionStatus: financeCommissionStatusSettled, columns.SettlementTime: settlementTime, columns.UpdatedBy: userId, columns.UpdatedAt: settlementTime, }). Update() if err != nil { return gerror.Wrap(err, "更新分润明细结算状态失败,请稍后重试!") } affected, err := result.RowsAffected() if err != nil { return gerror.Wrap(err, "获取分润明细结算状态更新结果失败") } if affected != int64(len(in.Ids)) { return gerror.New("部分分润明细状态已变化,请下次任务重试") } return nil } // 分层分润概览 分润表 // 一级客户收入 benefit_dept_level=1 commission_amount相加 // 二级客户收入 benefit_dept_level=2 commission_amount相加 // 三级客户收入 benefit_dept_level=3 commission_amount相加 // 总收入 一级二级三级加起来总和 func (s *sCommonTFinCommissionDetail) GetCommissionOverview(ctx context.Context, in *model.TCommissionOverviewParam) (res *model.TCommissionOverviewModel, err error) { res = &model.TCommissionOverviewModel{} deptId := contexts.GetDeptId(ctx) // 解析账期参数 var startPeriod, endPeriod string if in.Type == 1 { // 年 startPeriod = in.Year + "-01" endPeriod = in.Year + "-12" } else if in.Type == 2 { // 月 startPeriod = in.Month endPeriod = in.Month } // 查询一级客户收入 type levelRow struct { CommissionAmount float64 `orm:"commission_amount"` } var level1Result *levelRow if err = handler.Model(dao.TFinCommissionDetail.Ctx(ctx)). Where(dao.TFinCommissionDetail.Columns().BenefitDeptId, deptId). Where(dao.TFinCommissionDetail.Columns().BenefitDeptLevel, 1). WhereGTE(dao.TFinCommissionDetail.Columns().AccountPeriod, startPeriod). WhereLTE(dao.TFinCommissionDetail.Columns().AccountPeriod, endPeriod). Fields("SUM(" + dao.TFinCommissionDetail.Columns().CommissionAmount + ") as commission_amount"). Scan(&level1Result); err != nil { err = gerror.Wrap(err, "查询一级客户收入失败,请稍后重试!") return } if level1Result != nil { res.Level1Income = level1Result.CommissionAmount } // 查询二级客户收入 var level2Result *levelRow if err = handler.Model(dao.TFinCommissionDetail.Ctx(ctx)). Where(dao.TFinCommissionDetail.Columns().BenefitDeptId, deptId). Where(dao.TFinCommissionDetail.Columns().BenefitDeptLevel, 2). WhereGTE(dao.TFinCommissionDetail.Columns().AccountPeriod, startPeriod). WhereLTE(dao.TFinCommissionDetail.Columns().AccountPeriod, endPeriod). Fields("SUM(" + dao.TFinCommissionDetail.Columns().CommissionAmount + ") as commission_amount"). Scan(&level2Result); err != nil { err = gerror.Wrap(err, "查询二级客户收入失败,请稍后重试!") return } if level2Result != nil { res.Level2Income = level2Result.CommissionAmount } // 查询三级客户收入 var level3Result *levelRow if err = handler.Model(dao.TFinCommissionDetail.Ctx(ctx)). Where(dao.TFinCommissionDetail.Columns().BenefitDeptId, deptId). Where(dao.TFinCommissionDetail.Columns().BenefitDeptLevel, 3). WhereGTE(dao.TFinCommissionDetail.Columns().AccountPeriod, startPeriod). WhereLTE(dao.TFinCommissionDetail.Columns().AccountPeriod, endPeriod). Fields("SUM(" + dao.TFinCommissionDetail.Columns().CommissionAmount + ") as commission_amount"). Scan(&level3Result); err != nil { err = gerror.Wrap(err, "查询三级客户收入失败,请稍后重试!") return } if level3Result != nil { res.Level3Income = level3Result.CommissionAmount } // 计算总收入 res.TotalIncome = res.Level1Income + res.Level2Income + res.Level3Income return } // GetLevelSummary 获取层级汇总表 // 客户数 根据 benefit_dept_level 收益机构层级分组 // 收入金额 根据收益机构id去 t_profit_account_month_bill 查,dept_id=收益机构id,收入=分润结算+余额转提现 // 分润金额 根据收益机构id去 t_profit_account_month_bill 查,commission_income // 顶级利润贡献 等于分润金额 // 收入占比 // 环比 选年与去年对比,选月与上个月对比 func (s *sCommonTFinCommissionDetail) GetLevelSummary(ctx context.Context, in *model.TLevelSummaryParam) (res *model.TLevelSummaryModel, err error) { res = &model.TLevelSummaryModel{} deptId := contexts.GetDeptId(ctx) // 解析账期参数 var startPeriod, endPeriod string if in.Type == 1 { // 年 startPeriod = in.Year + "-01" endPeriod = in.Year + "-12" } else if in.Type == 2 { // 月 startPeriod = in.Month endPeriod = in.Month } // 查询各层级的客户数和分润金额(从分润表) type levelData struct { Level int `orm:"level"` CustomerCount int `orm:"customer_count"` CommissionAmount float64 `orm:"commission_amount"` } var levelResults []*levelData if err = handler.Model(dao.TFinCommissionDetail.Ctx(ctx)). Where(dao.TFinCommissionDetail.Columns().BenefitDeptId, deptId). WhereGTE(dao.TFinCommissionDetail.Columns().AccountPeriod, startPeriod). WhereLTE(dao.TFinCommissionDetail.Columns().AccountPeriod, endPeriod). Fields("SUM(" + dao.TFinCommissionDetail.Columns().CommissionAmount + ") as commission_amount, COUNT(DISTINCT " + dao.TFinCommissionDetail.Columns().PayerDeptId + ") as customer_count, " + dao.TFinCommissionDetail.Columns().BenefitDeptLevel + " as level"). Group(dao.TFinCommissionDetail.Columns().BenefitDeptLevel). Scan(&levelResults); err != nil { err = gerror.Wrap(err, "查询层级数据失败,请稍后重试!") return } // 构建层级与分润金额的映射 levelCommissionMap := make(map[int]float64) for _, lr := range levelResults { levelCommissionMap[lr.Level] = lr.CommissionAmount } // 查询各层级的收入金额(从盈利月账单表:total_income) // 先从分润表获取各层级的机构ID列表 type deptLevelRow struct { Level int `orm:"level"` DeptId int64 `orm:"dept_id"` } var deptLevelResults []*deptLevelRow if err = handler.Model(dao.TFinCommissionDetail.Ctx(ctx)). Where(dao.TFinCommissionDetail.Columns().BenefitDeptId, deptId). WhereGTE(dao.TFinCommissionDetail.Columns().AccountPeriod, startPeriod). WhereLTE(dao.TFinCommissionDetail.Columns().AccountPeriod, endPeriod). Fields("DISTINCT " + dao.TFinCommissionDetail.Columns().BenefitDeptLevel + " as level, " + dao.TFinCommissionDetail.Columns().BenefitDeptId + " as dept_id"). Scan(&deptLevelResults); err != nil { err = gerror.Wrap(err, "查询层级机构失败,请稍后重试!") return } // 根据层级汇总机构ID levelDeptMap := make(map[int][]int64) for _, dlr := range deptLevelResults { levelDeptMap[dlr.Level] = append(levelDeptMap[dlr.Level], dlr.DeptId) } // 构建收入金额映射 incomeMap := make(map[int]float64) for level, deptIds := range levelDeptMap { if len(deptIds) == 0 { continue } incomeResult, err := s.getProfitAccountIncome(ctx, &model.IncomeQueryParams{ DeptIds: deptIds, StartPeriod: startPeriod, EndPeriod: endPeriod, }) if err != nil { return nil, err } incomeMap[level] = incomeResult } // 计算总收入 var totalIncome float64 for _, item := range levelResults { totalIncome += item.CommissionAmount } // 构建结果 for level := 1; level <= 3; level++ { item := model.TLevelSummaryItem{ Level: level, } // 设置客户数、分润金额 for _, lr := range levelResults { if lr.Level == level { item.CustomerCount = lr.CustomerCount item.CommissionAmount = lr.CommissionAmount break } } // 设置收入金额 item.IncomeAmount = incomeMap[level] // 计算收入占比 if totalIncome > 0 { item.IncomeRatio = item.CommissionAmount / totalIncome * 100 } res.Items = append(res.Items, item) } return } // getProfitAccountIncome 查询盈利账户收入 func (s *sCommonTFinCommissionDetail) getProfitAccountIncome(ctx context.Context, params *model.IncomeQueryParams) (float64, error) { type incomeRow struct { TotalIncome float64 `orm:"total_income"` } var row *incomeRow if err := handler.Model(dao.TProfitAccountMonthBill.Ctx(ctx)). WhereIn(dao.TProfitAccountMonthBill.Columns().DeptId, params.DeptIds). WhereGTE(dao.TProfitAccountMonthBill.Columns().AccountPeriod, params.StartPeriod). WhereLTE(dao.TProfitAccountMonthBill.Columns().AccountPeriod, params.EndPeriod). Fields("SUM(" + dao.TProfitAccountMonthBill.Columns().TotalIncome + ") as total_income"). Scan(&row); err != nil { return 0, gerror.Wrap(err, "查询盈利账户收入失败") } if row == nil { return 0, nil } return row.TotalIncome, nil } // mustAtoi 安全转换字符串为int func mustAtoi(s string) int { i, _ := strconv.Atoi(s) return i }