696 lines
24 KiB
Go
696 lines
24 KiB
Go
// Package gen
|
|
// @Link https://github.com/xiujiecn/xiu-admin
|
|
// @Copyright Copyright (c) 2026 LiXiujie
|
|
// @Author Lxj <xxx@example.com>
|
|
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
|
|
// @AutoGenerate Version
|
|
package common
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"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/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"
|
|
"time"
|
|
|
|
"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 sCommonProfitAccountMonthBill struct{}
|
|
|
|
func NewCommonProfitAccountMonthBill() *sCommonProfitAccountMonthBill {
|
|
return &sCommonProfitAccountMonthBill{}
|
|
}
|
|
|
|
func init() {
|
|
service.RegisterCommonProfitAccountMonthBill(NewCommonProfitAccountMonthBill())
|
|
}
|
|
|
|
// Model 盈利账户月账单表ORM模型
|
|
func (s *sCommonProfitAccountMonthBill) 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.TProfitAccountMonthBill.Ctx(ctx), option...)
|
|
}
|
|
|
|
// List 获取盈利账户月账单表列表
|
|
func (s *sCommonProfitAccountMonthBill) List(ctx context.Context, in *model.TProfitAccountMonthBillListParam) (list []*model.TProfitAccountMonthBillListModel, totalCount int, err error) {
|
|
mod := s.Model(ctx)
|
|
|
|
// 字段过滤
|
|
mod = mod.Fields(model.TProfitAccountMonthBillListModel{})
|
|
|
|
// 查询账单ID
|
|
if in.Id > 0 {
|
|
mod = mod.Where(dao.TProfitAccountMonthBill.Columns().Id, in.Id)
|
|
}
|
|
|
|
// 查询账单状态:1正常,2已调整,3已作废
|
|
if in.BillStatus > 0 {
|
|
mod = mod.Where(dao.TProfitAccountMonthBill.Columns().BillStatus, in.BillStatus)
|
|
}
|
|
|
|
// 查询创建时间
|
|
if len(in.CreatedAt) == 2 {
|
|
in.CreatedAt[1] = in.CreatedAt[1].EndOfDay()
|
|
}
|
|
if len(in.CreatedAt) == 2 {
|
|
mod = mod.WhereBetween(dao.TProfitAccountMonthBill.Columns().CreatedAt, in.CreatedAt[0], in.CreatedAt[1])
|
|
}
|
|
|
|
// 分页
|
|
mod = mod.Page(in.Page, in.PageSize)
|
|
|
|
// 排序
|
|
mod = mod.OrderDesc(dao.TProfitAccountMonthBill.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 *sCommonProfitAccountMonthBill) Export(ctx context.Context, in *model.TProfitAccountMonthBillListParam) (err error) {
|
|
list, totalCount, err := s.List(ctx, in)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
// 字段的排序是依据tags的字段顺序,如果你不想使用默认的排序方式,可以直接定义 tags = []string{"字段名称", "字段名称2", ...}
|
|
tags, err := convert.GetEntityDescTags(model.TProfitAccountMonthBillExportModel{})
|
|
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.TProfitAccountMonthBillExportModel
|
|
)
|
|
|
|
if err = gconv.Scan(list, &exports); err != nil {
|
|
return
|
|
}
|
|
|
|
err = excel.ExportByStructs(ctx, tags, exports, fileName, sheetName)
|
|
return
|
|
}
|
|
|
|
// Edit 修改/新增盈利账户月账单表
|
|
func (s *sCommonProfitAccountMonthBill) Edit(ctx context.Context, in *model.TProfitAccountMonthBillEditParam) (err error) {
|
|
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.TProfitAccountMonthBillUpdateFields{}).
|
|
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.TProfitAccountMonthBillInsertFields{}).
|
|
Data(in).Insert(); err != nil {
|
|
err = gerror.Wrap(err, "新增盈利账户月账单表失败,请稍后重试!")
|
|
}
|
|
return
|
|
})
|
|
}
|
|
|
|
// Delete 删除盈利账户月账单表
|
|
func (s *sCommonProfitAccountMonthBill) Delete(ctx context.Context, in *model.TProfitAccountMonthBillDeleteParam) (err error) {
|
|
|
|
if _, err = s.Model(ctx).WherePri(in.Id).Unscoped().Delete(); err != nil {
|
|
err = gerror.Wrap(err, "删除盈利账户月账单表失败,请稍后重试!")
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
// View 获取盈利账户月账单表指定信息
|
|
func (s *sCommonProfitAccountMonthBill) View(ctx context.Context, in *model.TProfitAccountMonthBillViewParam) (res *model.TProfitAccountMonthBillViewModel, err error) {
|
|
if err = s.Model(ctx).WherePri(in.Id).Hook(hook.MemberSummary).Scan(&res); err != nil {
|
|
err = gerror.Wrap(err, "获取盈利账户月账单表信息,请稍后重试!")
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
// SettleProfitAccountMonthBill 按可提现变动明细统计并写入盈利账户月账单。
|
|
func (s *sCommonProfitAccountMonthBill) SettleProfitAccountMonthBill(ctx context.Context, in *model.TProfitAccountMonthBillSettleParam) (res *model.TProfitAccountMonthBillSettleResult, err error) {
|
|
if in == nil {
|
|
in = &model.TProfitAccountMonthBillSettleParam{}
|
|
}
|
|
if err = in.Filter(ctx); err != nil {
|
|
return nil, gerror.Wrap(err, "账期格式错误,请使用YYYY-MM")
|
|
}
|
|
|
|
_, err = time.Parse("2006-01", in.AccountPeriod)
|
|
if err != nil {
|
|
return nil, gerror.Wrap(err, "账期格式错误,请使用YYYY-MM")
|
|
}
|
|
now := gtime.Now()
|
|
userId := contexts.GetUserId(ctx)
|
|
tenantId := contexts.GetTenantId(ctx)
|
|
changeColumns := dao.TFinWithdrawableChange.Columns()
|
|
billColumns := dao.TProfitAccountMonthBill.Columns()
|
|
|
|
type changeRow struct {
|
|
Id int64 `orm:"id"`
|
|
DeptId int64 `orm:"dept_id"`
|
|
TenantId string `orm:"tenant_id"`
|
|
CreatedDept int64 `orm:"created_dept"`
|
|
ChangeType int `orm:"change_type"`
|
|
IncomeExpenseType int `orm:"income_expense_type"`
|
|
ChangeAmount float64 `orm:"change_amount"`
|
|
BeforeBalance float64 `orm:"before_balance"`
|
|
CreatedAt *gtime.Time `orm:"created_at"`
|
|
}
|
|
|
|
var rows []*changeRow
|
|
mod := handler.Model(dao.TFinWithdrawableChange.Ctx(ctx), &handler.Option{
|
|
FilterTenant: false,
|
|
FilterAuth: false,
|
|
}).
|
|
Fields(
|
|
changeColumns.Id,
|
|
changeColumns.DeptId,
|
|
changeColumns.TenantId,
|
|
changeColumns.CreatedDept,
|
|
changeColumns.ChangeType,
|
|
changeColumns.IncomeExpenseType,
|
|
changeColumns.ChangeAmount,
|
|
changeColumns.BeforeBalance,
|
|
changeColumns.CreatedAt,
|
|
).
|
|
Where(changeColumns.AccountPeriod, in.AccountPeriod)
|
|
if tenantId != "" {
|
|
mod = mod.Where(changeColumns.TenantId, tenantId)
|
|
}
|
|
if err = mod.OrderAsc(changeColumns.TenantId).OrderAsc(changeColumns.DeptId).OrderAsc(changeColumns.CreatedAt).OrderAsc(changeColumns.Id).Scan(&rows); err != nil {
|
|
return nil, gerror.Wrap(err, "查询可提现变动明细失败,请稍后重试!")
|
|
}
|
|
|
|
type billGroup struct {
|
|
DeptId int64
|
|
TenantId string
|
|
CreatedDept int64
|
|
AccountPeriod string
|
|
OpeningBalance float64
|
|
CommissionIncome float64
|
|
BalanceTransferInIncome float64
|
|
WithdrawalExpense float64
|
|
WithdrawableTransferOutExpense float64
|
|
ProfitCreditRepayExpense float64
|
|
TotalIncome float64
|
|
TotalExpense float64
|
|
IncomeCount int
|
|
ExpenseCount int
|
|
DetailCount int
|
|
}
|
|
|
|
groups := make(map[string]*billGroup)
|
|
keys := make([]string, 0, 16)
|
|
for _, row := range rows {
|
|
if row == nil || row.DeptId <= 0 {
|
|
continue
|
|
}
|
|
switch row.ChangeType {
|
|
case 0, 1, 2, 3, 4:
|
|
default:
|
|
continue
|
|
}
|
|
key := fmt.Sprintf("%s:%d", row.TenantId, row.DeptId)
|
|
group := groups[key]
|
|
if group == nil {
|
|
group = &billGroup{
|
|
DeptId: row.DeptId,
|
|
TenantId: row.TenantId,
|
|
CreatedDept: row.CreatedDept,
|
|
AccountPeriod: in.AccountPeriod,
|
|
OpeningBalance: row.BeforeBalance,
|
|
}
|
|
groups[key] = group
|
|
keys = append(keys, key)
|
|
}
|
|
group.DetailCount++
|
|
switch row.ChangeType {
|
|
case 0:
|
|
group.CommissionIncome += row.ChangeAmount
|
|
case 1:
|
|
group.WithdrawalExpense += row.ChangeAmount
|
|
case 2:
|
|
group.WithdrawableTransferOutExpense += row.ChangeAmount
|
|
case 3:
|
|
group.BalanceTransferInIncome += row.ChangeAmount
|
|
case 4:
|
|
group.ProfitCreditRepayExpense += row.ChangeAmount
|
|
}
|
|
if row.IncomeExpenseType == 0 {
|
|
group.TotalIncome += row.ChangeAmount
|
|
group.IncomeCount++
|
|
} else if row.IncomeExpenseType == 1 {
|
|
group.TotalExpense += row.ChangeAmount
|
|
group.ExpenseCount++
|
|
}
|
|
}
|
|
|
|
res = &model.TProfitAccountMonthBillSettleResult{
|
|
AccountPeriod: in.AccountPeriod,
|
|
}
|
|
if len(groups) == 0 {
|
|
return res, nil
|
|
}
|
|
|
|
err = g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
|
|
for _, key := range keys {
|
|
group := groups[key]
|
|
if group == nil {
|
|
continue
|
|
}
|
|
totalIncome := group.TotalIncome
|
|
totalExpense := group.TotalExpense
|
|
closingBalance := group.OpeningBalance + totalIncome - totalExpense
|
|
group.TotalIncome = totalIncome
|
|
group.TotalExpense = totalExpense
|
|
|
|
lookup := tx.Ctx(ctx).Model(dao.TProfitAccountMonthBill.Table()).
|
|
Fields(billColumns.Id).
|
|
Where(billColumns.DeptId, group.DeptId).
|
|
Where(billColumns.AccountPeriod, group.AccountPeriod)
|
|
if group.TenantId != "" {
|
|
lookup = lookup.Where(billColumns.TenantId, group.TenantId)
|
|
}
|
|
var existing struct {
|
|
Id int64 `orm:"id"`
|
|
}
|
|
if err := lookup.LockUpdate().Scan(&existing); err != nil && err != sql.ErrNoRows {
|
|
return gerror.Wrap(err, "查询盈利账户月账单失败,请稍后重试!")
|
|
}
|
|
|
|
tenantValue := group.TenantId
|
|
if tenantValue == "" {
|
|
tenantValue = tenantId
|
|
}
|
|
if tenantValue == "" {
|
|
return gerror.New("租户ID不能为空")
|
|
}
|
|
createdDeptValue := group.CreatedDept
|
|
if createdDeptValue == 0 {
|
|
createdDeptValue = contexts.GetDeptId(ctx)
|
|
}
|
|
if createdDeptValue == 0 {
|
|
return gerror.New("创建部门不能为空")
|
|
}
|
|
|
|
data := g.Map{
|
|
billColumns.DeptId: group.DeptId,
|
|
billColumns.AccountPeriod: group.AccountPeriod,
|
|
billColumns.OpeningBalance: group.OpeningBalance,
|
|
billColumns.CommissionIncome: group.CommissionIncome,
|
|
billColumns.BalanceTransferInIncome: group.BalanceTransferInIncome,
|
|
billColumns.WithdrawalExpense: group.WithdrawalExpense,
|
|
billColumns.WithdrawableTransferOutExpense: group.WithdrawableTransferOutExpense,
|
|
billColumns.ProfitCreditRepayExpense: group.ProfitCreditRepayExpense,
|
|
billColumns.TotalIncome: totalIncome,
|
|
billColumns.TotalExpense: totalExpense,
|
|
billColumns.ClosingBalance: closingBalance,
|
|
billColumns.IncomeCount: group.IncomeCount,
|
|
billColumns.ExpenseCount: group.ExpenseCount,
|
|
billColumns.BillStatus: 1,
|
|
billColumns.SettleTime: now,
|
|
billColumns.SettleBy: userId,
|
|
billColumns.Remark: "根据可提现变动明细统计生成",
|
|
billColumns.TenantId: tenantValue,
|
|
billColumns.UpdatedBy: userId,
|
|
billColumns.UpdatedAt: now,
|
|
}
|
|
if existing.Id > 0 {
|
|
if _, err := tx.Ctx(ctx).Model(dao.TProfitAccountMonthBill.Table()).
|
|
WherePri(existing.Id).
|
|
Data(data).
|
|
Update(); err != nil {
|
|
return gerror.Wrap(err, "更新盈利账户月账单失败,请稍后重试!")
|
|
}
|
|
res.UpdateCount++
|
|
} else {
|
|
data[billColumns.CreatedDept] = createdDeptValue
|
|
data[billColumns.CreatedBy] = userId
|
|
data[billColumns.CreatedAt] = now
|
|
if _, err := tx.Ctx(ctx).Model(dao.TProfitAccountMonthBill.Table()).
|
|
Data(data).
|
|
Insert(); err != nil {
|
|
return gerror.Wrap(err, "新增盈利账户月账单失败,请稍后重试!")
|
|
}
|
|
res.InsertCount++
|
|
}
|
|
res.DeptCount++
|
|
res.DetailCount += group.DetailCount
|
|
res.TotalIncome += totalIncome
|
|
res.TotalExpense += totalExpense
|
|
}
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return res, nil
|
|
}
|
|
|
|
// 获取月账单盈利账户汇总信息
|
|
func (s *sCommonProfitAccountMonthBill) GetProfitBillSummary(ctx context.Context, month string) (res *model.TProfitBillModel, err error) {
|
|
// 计算上月账期(基于当前时间)
|
|
// now := time.Now()
|
|
// lastMonthTime := now.AddDate(0, -1, 0)
|
|
// lastMonthPeriod := lastMonthTime.Format("2006-01")
|
|
|
|
var bill *model.TProfitAccountMonthBillViewModel
|
|
if err = dao.TProfitAccountMonthBill.Ctx(ctx).
|
|
Where(dao.TProfitAccountMonthBill.Columns().AccountPeriod, month).
|
|
Where(dao.TProfitAccountMonthBill.Columns().DeptId, contexts.GetDeptId(ctx)).
|
|
Scan(&bill); err != nil {
|
|
err = gerror.Wrap(err, "查询上月账单失败,请稍后重试!")
|
|
return
|
|
}
|
|
if bill == nil {
|
|
return
|
|
}
|
|
|
|
res = &model.TProfitBillModel{}
|
|
res.TotalIncome = bill.TotalIncome
|
|
res.TotalExpense = bill.TotalExpense
|
|
return
|
|
}
|
|
|
|
// GetCoreFinancialData 获取核心财务指标
|
|
func (s *sCommonProfitAccountMonthBill) GetCoreFinancialData(ctx context.Context, in *model.TCommissionOverviewParam) (res *model.TCoreFinancialDataModel, err error) {
|
|
res = &model.TCoreFinancialDataModel{}
|
|
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
|
|
}
|
|
|
|
// 1. 获取总收入:统计 t_profit_account_month_bill 的 total_income
|
|
type totalIncomeRow struct {
|
|
TotalIncome float64 `orm:"total_income"`
|
|
}
|
|
var totalIncomeResult *totalIncomeRow
|
|
if err = s.Model(ctx, &handler.Option{FilterAuth: false}).
|
|
Where(dao.TProfitAccountMonthBill.Columns().DeptId, deptId).
|
|
WhereGTE(dao.TProfitAccountMonthBill.Columns().AccountPeriod, startPeriod).
|
|
WhereLTE(dao.TProfitAccountMonthBill.Columns().AccountPeriod, endPeriod).
|
|
Fields("SUM(" + dao.TProfitAccountMonthBill.Columns().TotalIncome + ") as total_income").
|
|
Scan(&totalIncomeResult); err != nil {
|
|
err = gerror.Wrap(err, "查询总收入失败,请稍后重试!")
|
|
return
|
|
}
|
|
if totalIncomeResult != nil {
|
|
res.TotalIncome = totalIncomeResult.TotalIncome
|
|
}
|
|
|
|
// 2. 获取顶级利润:查询 t_fin_commission_detail 中顶级部门的 commission_income
|
|
// 顶级部门ID通常为1或当前部门的顶级父部门
|
|
|
|
type topProfitRow struct {
|
|
CommissionIncome float64 `orm:"commission_income"`
|
|
}
|
|
var topProfitResult *topProfitRow
|
|
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_income").
|
|
Scan(&topProfitResult); err != nil {
|
|
err = gerror.Wrap(err, "查询顶级利润失败,请稍后重试!")
|
|
return
|
|
}
|
|
if topProfitResult != nil {
|
|
res.TopLevelProfit = topProfitResult.CommissionIncome
|
|
}
|
|
|
|
// 3. 获取待审核提现:从 t_profit_account_month_bill 查询 withdrawable_transfer_out_expense
|
|
type pendingWithdrawRow struct {
|
|
WithdrawableTransferOutExpense float64 `orm:"withdrawable_transfer_out_expense"`
|
|
}
|
|
var pendingWithdrawResult *pendingWithdrawRow
|
|
if err = s.Model(ctx, &handler.Option{FilterAuth: false}).
|
|
Where(dao.TProfitAccountMonthBill.Columns().DeptId, deptId).
|
|
WhereGTE(dao.TProfitAccountMonthBill.Columns().AccountPeriod, startPeriod).
|
|
WhereLTE(dao.TProfitAccountMonthBill.Columns().AccountPeriod, endPeriod).
|
|
Fields("SUM(" + dao.TProfitAccountMonthBill.Columns().WithdrawableTransferOutExpense + ") as withdrawable_transfer_out_expense").
|
|
Scan(&pendingWithdrawResult); err != nil {
|
|
err = gerror.Wrap(err, "查询待审核提现失败,请稍后重试!")
|
|
return
|
|
}
|
|
if pendingWithdrawResult != nil {
|
|
res.PendingWithdrawAmount = pendingWithdrawResult.WithdrawableTransferOutExpense
|
|
}
|
|
|
|
// 4. 获取已提现金额:统计 t_profit_account_month_bill 的 balance_transfer_in_income
|
|
type withdrawedRow struct {
|
|
WithdrawalExpense float64 `orm:"withdrawal_expense"`
|
|
}
|
|
var withdrawedResult *withdrawedRow
|
|
if err = s.Model(ctx, &handler.Option{FilterAuth: false}).
|
|
Where(dao.TProfitAccountMonthBill.Columns().DeptId, deptId).
|
|
WhereGTE(dao.TProfitAccountMonthBill.Columns().AccountPeriod, startPeriod).
|
|
WhereLTE(dao.TProfitAccountMonthBill.Columns().AccountPeriod, endPeriod).
|
|
Fields("SUM(" + dao.TProfitAccountMonthBill.Columns().WithdrawalExpense + ") as withdrawal_expense").
|
|
Scan(&withdrawedResult); err != nil {
|
|
err = gerror.Wrap(err, "查询已提现金额失败,请稍后重试!")
|
|
return
|
|
}
|
|
if withdrawedResult != nil {
|
|
res.WithdrawedAmount = withdrawedResult.WithdrawalExpense
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// GetFinancialTrend 获取财务趋势折线图
|
|
// 指标类型:1总收入,2顶级利润,3待审核提现,4已提现金额
|
|
// 月份视图:按天查询 t_fin_withdrawable_change
|
|
// 年份视图:按月查询 t_profit_account_month_bill
|
|
func (s *sCommonProfitAccountMonthBill) GetFinancialTrend(ctx context.Context, in *model.TFinancialTrendParam) (res *model.TFinancialTrendModel, err error) {
|
|
res = &model.TFinancialTrendModel{}
|
|
|
|
// 默认查询所有指标
|
|
indicators := in.Indicators
|
|
if len(indicators) == 0 {
|
|
indicators = []int{1, 2, 3, 4}
|
|
}
|
|
|
|
// 指标名称映射
|
|
indicatorNames := map[int]string{
|
|
1: "总收入",
|
|
2: "顶级利润",
|
|
3: "待审核提现",
|
|
4: "已提现金额",
|
|
}
|
|
|
|
if in.Type == 1 {
|
|
// 年视图:按月查询 t_profit_account_month_bill
|
|
year := in.Year
|
|
months := []string{"01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12"}
|
|
res.Labels = make([]string, 0, 12)
|
|
for _, m := range months {
|
|
res.Labels = append(res.Labels, year+"-"+m)
|
|
}
|
|
|
|
type monthBillRow struct {
|
|
AccountPeriod string `orm:"account_period"`
|
|
TotalIncome float64 `orm:"total_income"`
|
|
CommissionIncome float64 `orm:"commission_income"`
|
|
BalanceTransferInIncome float64 `orm:"balance_transfer_in_income"`
|
|
WithdrawalExpense float64 `orm:"withdrawal_expense"`
|
|
}
|
|
var bills []*monthBillRow
|
|
if err = s.Model(ctx, &handler.Option{FilterAuth: false}).
|
|
Where(dao.TProfitAccountMonthBill.Columns().DeptId, contexts.GetDeptId(ctx)).
|
|
WhereGTE(dao.TProfitAccountMonthBill.Columns().AccountPeriod, year+"-01").
|
|
WhereLTE(dao.TProfitAccountMonthBill.Columns().AccountPeriod, year+"-12").
|
|
Fields(
|
|
dao.TProfitAccountMonthBill.Columns().AccountPeriod,
|
|
dao.TProfitAccountMonthBill.Columns().TotalIncome,
|
|
dao.TProfitAccountMonthBill.Columns().CommissionIncome,
|
|
dao.TProfitAccountMonthBill.Columns().BalanceTransferInIncome,
|
|
dao.TProfitAccountMonthBill.Columns().WithdrawalExpense,
|
|
).
|
|
Scan(&bills); err != nil {
|
|
return nil, gerror.Wrap(err, "查询财务趋势数据失败,请稍后重试!")
|
|
}
|
|
|
|
// 构建月份映射
|
|
billMap := make(map[string]*monthBillRow)
|
|
for _, bill := range bills {
|
|
billMap[bill.AccountPeriod] = bill
|
|
}
|
|
|
|
// 构建每个指标的数据数组
|
|
res.Series = make([]model.TFinancialTrendSeries, 0, len(indicators))
|
|
for _, ind := range indicators {
|
|
series := model.TFinancialTrendSeries{
|
|
Name: indicatorNames[ind],
|
|
Type: ind,
|
|
Values: make([]float64, 0, 12),
|
|
}
|
|
for _, period := range res.Labels {
|
|
var val float64
|
|
if bill, ok := billMap[period]; ok {
|
|
switch ind {
|
|
case 1:
|
|
val = bill.TotalIncome
|
|
case 2:
|
|
val = bill.CommissionIncome
|
|
case 3:
|
|
val = bill.BalanceTransferInIncome
|
|
case 4:
|
|
val = bill.WithdrawalExpense
|
|
}
|
|
}
|
|
series.Values = append(series.Values, val)
|
|
}
|
|
res.Series = append(res.Series, series)
|
|
}
|
|
|
|
} else if in.Type == 2 {
|
|
// 月视图:按天查询 t_fin_withdrawable_change
|
|
month := in.Month
|
|
t := gtime.NewFromStr(month + "-01")
|
|
daysInMonth := t.EndOfMonth().Day()
|
|
|
|
res.Labels = make([]string, 0, daysInMonth)
|
|
for day := 1; day <= daysInMonth; day++ {
|
|
res.Labels = append(res.Labels, month+"-"+strconv.Itoa(day))
|
|
}
|
|
|
|
// 解析月份获取开始和结束日期
|
|
startDate := month + "-01"
|
|
endDate := month + "-" + strconv.Itoa(daysInMonth)
|
|
|
|
type dailyRow struct {
|
|
Date string `orm:"date"`
|
|
IncomeAmt float64 `orm:"income_amt"`
|
|
Expense1Amt float64 `orm:"expense1_amt"`
|
|
Expense3Amt float64 `orm:"expense3_amt"`
|
|
}
|
|
var dailyResults []*dailyRow
|
|
if err = handler.Model(dao.TFinWithdrawableChange.Ctx(ctx)).
|
|
Where(dao.TFinWithdrawableChange.Columns().DeptId, contexts.GetDeptId(ctx)).
|
|
WhereGTE(dao.TFinWithdrawableChange.Columns().CreatedAt, startDate).
|
|
WhereLTE(dao.TFinWithdrawableChange.Columns().CreatedAt, endDate).
|
|
Fields(`
|
|
DATE_FORMAT(` + dao.TFinWithdrawableChange.Columns().CreatedAt + `, '%Y-%m-%d') as date,
|
|
SUM(CASE WHEN ` + dao.TFinWithdrawableChange.Columns().IncomeExpenseType + `=0 THEN ` + dao.TFinWithdrawableChange.Columns().ChangeAmount + ` ELSE 0 END) as income_amt,
|
|
SUM(CASE WHEN ` + dao.TFinWithdrawableChange.Columns().IncomeExpenseType + `=1 THEN ` + dao.TFinWithdrawableChange.Columns().ChangeAmount + ` ELSE 0 END) as expense1_amt,
|
|
SUM(CASE WHEN ` + dao.TFinWithdrawableChange.Columns().IncomeExpenseType + `=3 THEN ` + dao.TFinWithdrawableChange.Columns().ChangeAmount + ` ELSE 0 END) as expense3_amt
|
|
`).
|
|
Group("DATE_FORMAT(" + dao.TFinWithdrawableChange.Columns().CreatedAt + ", '%Y-%m-%d')").
|
|
Order("date ASC").
|
|
Scan(&dailyResults); err != nil {
|
|
return nil, gerror.Wrap(err, "查询日趋势数据失败,请稍后重试!")
|
|
}
|
|
|
|
// 构建日期映射
|
|
dailyMap := make(map[string]*dailyRow)
|
|
for _, row := range dailyResults {
|
|
dailyMap[row.Date] = row
|
|
}
|
|
|
|
// 查询顶级利润(从分润表)
|
|
type commissionRow struct {
|
|
CommissionAmount float64 `orm:"commission_amount"`
|
|
}
|
|
var commissionResult *commissionRow
|
|
if err = handler.Model(dao.TFinCommissionDetail.Ctx(ctx)).
|
|
Where(dao.TFinCommissionDetail.Columns().BenefitDeptId, contexts.GetDeptId(ctx)).
|
|
WhereGTE(dao.TFinCommissionDetail.Columns().AccountPeriod, month).
|
|
WhereLTE(dao.TFinCommissionDetail.Columns().AccountPeriod, month).
|
|
Fields("SUM(" + dao.TFinCommissionDetail.Columns().CommissionAmount + ") as commission_amount").
|
|
Scan(&commissionResult); err != nil {
|
|
return nil, gerror.Wrap(err, "查询顶级利润失败,请稍后重试!")
|
|
}
|
|
|
|
topProfit := 0.0
|
|
if commissionResult != nil {
|
|
topProfit = commissionResult.CommissionAmount
|
|
}
|
|
|
|
// 构建每个指标的数据数组
|
|
res.Series = make([]model.TFinancialTrendSeries, 0, len(indicators))
|
|
for _, ind := range indicators {
|
|
series := model.TFinancialTrendSeries{
|
|
Name: indicatorNames[ind],
|
|
Type: ind,
|
|
Values: make([]float64, 0, daysInMonth),
|
|
}
|
|
for _, date := range res.Labels {
|
|
var val float64
|
|
switch ind {
|
|
case 1: // 总收入
|
|
if row, ok := dailyMap[date]; ok {
|
|
val = row.IncomeAmt
|
|
}
|
|
case 2: // 顶级利润
|
|
val = topProfit
|
|
case 3: // 待审核提现
|
|
if row, ok := dailyMap[date]; ok {
|
|
val = row.Expense3Amt
|
|
}
|
|
case 4: // 已提现金额
|
|
if row, ok := dailyMap[date]; ok {
|
|
val = row.Expense1Amt
|
|
}
|
|
}
|
|
series.Values = append(series.Values, val)
|
|
}
|
|
res.Series = append(res.Series, series)
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|