feat(order): 添加订单汇总功能- 新增 OrderSummaryOutput 结构体用于订单汇总信息

- 实现 GetOrderRawSummary 和 GetOrderProfitRawSummary 函数获取订单汇总数据
- 重构 QueryTotalSummary 和 QueryTodaySummary 函数,使用新的汇总查询逻辑
- 优化订单查询参数处理,支持模糊匹配和自定义字段筛选
This commit is contained in:
danial
2025-06-24 21:55:47 +08:00
parent 3629b6252b
commit 6ce7e2faba
5 changed files with 218 additions and 84 deletions

View File

@@ -782,8 +782,8 @@ func (c *GetController) GetOrder() {
params["create_time__gte"] = startTime params["create_time__gte"] = startTime
params["create_time__lte"] = endTime params["create_time__lte"] = endTime
params["merchant_name__icontains"] = merchantName params["merchant_name__icontains"] = merchantName
params["merchant_order_id"] = orderNo params["merchant_order_id__icontains"] = orderNo
params["bank_order_id"] = bankOrderId params["bank_order_id__icontains"] = bankOrderId
params["status"] = status params["status"] = status
params["pay_product_code"] = supplierUid params["pay_product_code"] = supplierUid
params["pay_type_code"] = payWayCode params["pay_type_code"] = payWayCode
@@ -922,18 +922,21 @@ func (c *GetController) GetOrderSummary() {
freeStatus := strings.TrimSpace(c.GetString("freeStatus")) freeStatus := strings.TrimSpace(c.GetString("freeStatus"))
cardData := strings.TrimSpace(c.GetString("cardData")) cardData := strings.TrimSpace(c.GetString("cardData"))
roadUid := strings.TrimSpace(c.GetString("roadUid")) roadUid := strings.TrimSpace(c.GetString("roadUid"))
message := strings.TrimSpace(c.GetString("message"))
params := make(map[string]string) params := make(map[string]string)
params["create_time__gte"] = startTime params["create_time__gte"] = startTime
params["create_time__lte"] = endTime params["create_time__lte"] = endTime
params["merchant_name__icontains"] = merchantName params["merchant_name__icontains"] = merchantName
params["merchant_order_id"] = orderNo params["merchant_order_id__icontains"] = orderNo
params["bank_order_id"] = bankOrderId params["bank_order_id__icontains"] = bankOrderId
params["status"] = status params["status"] = status
params["pay_product_code"] = supplierUid params["pay_product_code"] = supplierUid
params["pay_type_code"] = payWayCode params["pay_type_code"] = payWayCode
params["ex_value__icontains"] = cardData params["ex_value__icontains"] = cardData
params["road_uid"] = roadUid params["road_uid"] = roadUid
params["card_return_data__icontains"] = message
switch freeStatus { switch freeStatus {
case "free": case "free":
params["free"] = "yes" params["free"] = "yes"

View File

@@ -0,0 +1,17 @@
package order
//road_uid,
//SUM(order_amount) AS total_order_amount,
//COUNT(id) AS total_order_count,
//SUM(CASE WHEN STATUS = 'success' THEN order_amount ELSE 0 END) AS success_fact_amount,
//SUM(CASE WHEN STATUS = 'success' THEN 1 ELSE 0 END) AS success_fact_count,
//SUM(CASE WHEN STATUS = 'success' THEN 1 ELSE 0 END) / COUNT(id) AS success_fact_avg
type OrderSummaryOutput struct {
RoadUid string `json:"road_uid" orm:"road_uid"`
TotalOrderAmount float64 `json:"total_order_amount" orm:"total_order_amount"`
TotalOrderCount int64 `json:"total_order_count" orm:"total_order_count"`
SuccessFactAmount float64 `json:"success_fact_amount" orm:"success_fact_amount"`
SuccessFactCount int64 `json:"success_fact_count" orm:"success_fact_count"`
SuccessFactAvg float64 `json:"success_fact_avg" orm:"success_fact_avg"`
}

View File

@@ -2,8 +2,10 @@ package order
import ( import (
"context" "context"
"errors"
"fmt" "fmt"
"strconv" "strconv"
"strings"
"time" "time"
"github.com/beego/beego/v2/client/orm" "github.com/beego/beego/v2/client/orm"
@@ -132,6 +134,114 @@ func GetOrderCountByMap(ctx context.Context, params map[string]string) (count in
return return
} }
func GetOrderRawSummary(ctx context.Context, params map[string]string) (data []OrderSummaryOutput, err error) {
o := orm.NewOrm()
sql := `SELECT
road_uid,
SUM(order_amount) AS total_order_amount,
COUNT(id) AS total_order_count,
SUM(CASE WHEN STATUS = 'success' THEN order_amount ELSE 0 END) AS success_fact_amount,
SUM(CASE WHEN STATUS = 'success' THEN 1 ELSE 0 END) AS success_fact_count,
SUM(CASE WHEN STATUS = 'success' THEN 1 ELSE 0 END) / COUNT(id) AS success_fact_avg
FROM
order_info
`
if len(params) > 0 {
subSQL := ""
for k, v := range params {
if v == "" {
continue
}
switch k {
case "create_time__gte":
subSQL += fmt.Sprintf("create_time >= '%s' AND ", v)
case "create_time__lte":
subSQL += fmt.Sprintf("create_time <= '%s' AND ", v)
case "merchant_name__icontains":
subSQL += fmt.Sprintf("merchant_name LIKE '%%%s%%' AND ", v)
case "merchant_order_id__icontains":
subSQL += fmt.Sprintf("merchant_order_id LIKE '%%%s%%' AND ", v)
case "bank_order_id__icontains":
subSQL += fmt.Sprintf("bank_order_id LIKE '%%%s%%' AND ", v)
case "card_return_data__icontains":
subSQL += fmt.Sprintf("card_return_data LIKE '%%%s%%' AND ", v)
case "ex_value__icontains":
subSQL += fmt.Sprintf("ex_value LIKE '%%%s%%' AND ", v)
default:
if !strings.Contains(k, "__") {
subSQL += fmt.Sprintf("%s = '%s' AND ", k, v)
}
}
}
if len(subSQL) > 0 {
sql += "WHERE " + subSQL
}
}
sql = strings.TrimRight(sql, " AND ")
sql += `
GROUP BY
road_uid`
logs.Error(sql)
_, err = o.RawWithCtx(ctx, sql).QueryRows(&data)
if errors.Is(err, orm.ErrNoRows) {
err = nil
}
return
}
func GetOrderProfitRawSummary(ctx context.Context, params map[string]string) (platformProfit float64, err error) {
o := orm.NewOrm()
sql := `
SELECT
SUM(platform_profit) AS platform_profit
FROM
order_profit_info
LEFT JOIN order_info ON order_profit_info.bank_order_id = order_info.bank_order_id
WHERE
order_info.status='success' AND `
if len(params) > 0 {
subSQL := ""
for k, v := range params {
if v == "" {
continue
}
switch k {
case "create_time__gte":
subSQL += fmt.Sprintf("order_profit_info.create_time >= '%s' AND ", v)
case "create_time__lte":
subSQL += fmt.Sprintf("order_profit_info.create_time <= '%s' AND ", v)
case "merchant_name__icontains":
subSQL += fmt.Sprintf("order_profit_info.merchant_name LIKE '%%%s%%' AND ", v)
case "merchant_order_id__icontains":
subSQL += fmt.Sprintf("order_info.merchant_order_id = '%%%s%%' AND ", v)
case "bank_order_id__icontains":
subSQL += fmt.Sprintf("order_info.bank_order_id LIKE '%%%s%%' AND ", v)
case "ex_value__icontains":
subSQL += fmt.Sprintf("order_info.ex_value LIKE '%%%s%%' AND ", v)
default:
if !strings.Contains(k, "__") {
subSQL += fmt.Sprintf("%s = '%s' AND ", k, v)
}
}
}
if len(subSQL) > 0 {
sql += subSQL
}
}
sql = strings.TrimRight(sql, " AND ")
sql += `
GROUP BY
road_uid`
logs.Error(sql)
platformProfit = 0.0
err = o.RawWithCtx(ctx, sql).QueryRow(&platformProfit)
if errors.Is(err, orm.ErrNoRows) {
return 0.0, nil
}
return
}
func GetOrderAllByMap(ctx context.Context, params map[string]string) []OrderInfo { func GetOrderAllByMap(ctx context.Context, params map[string]string) []OrderInfo {
o := orm.NewOrm() o := orm.NewOrm()
var orderInfoList []OrderInfo var orderInfoList []OrderInfo

View File

@@ -100,48 +100,28 @@ func querySupplierPayForResult(ctx context.Context, bankOrderId string) bool {
} }
func QueryTotalSummary(ctx context.Context, params map[string]string) order.Summary { func QueryTotalSummary(ctx context.Context, params map[string]string) order.Summary {
supplierAll := 0.0 summaryInfos, err := order.GetOrderRawSummary(ctx, params)
platformAll := 0.0 if err != nil {
agentAll := 0.0 logs.Error("获取订单汇总信息失败:", err)
allAmount := 0.0
succeedNum := int64(0)
succeedPaidAmount := 0.0
totalNum := order.GetOrderCountByMap(ctx, params)
for i := int64(0); i < totalNum; i += 1000 {
orderInfoList := order.GetOrderByMap(ctx, params, 1000, i)
bankIdList := slice.Map(orderInfoList, func(index int, item order.OrderInfo) string {
return item.BankOrderId
})
orderProfitList := order.GetOrderProfitListByBankOrderIdList(ctx, bankIdList)
for _, v := range orderProfitList {
allAmount += v.ShowAmount //订单总金额
if v.Status != common.OrderStatusSuccess {
continue
}
succeedNum += 1
succeedPaidAmount += v.FactAmount
supplierAll += v.SupplierProfit //上游利润
platformAll += v.PlatformProfit //平台利润
agentAll += v.AgentProfit //代理利润
}
} }
succeedRate := 0.0 profit, err := order.GetOrderProfitRawSummary(ctx, params)
if totalNum != 0 { if err != nil {
succeedRate = math.Round(float64(succeedNum)/float64(totalNum)*100*100) / 100 logs.Error("获取订单利润信息失败:", err)
}
output := order.Summary{}
slice.ForEach(summaryInfos, func(index int, item order.OrderSummaryOutput) {
output.TotalAmount += item.TotalOrderAmount
output.TotalNum += item.TotalOrderCount
output.PaidNum += item.SuccessFactCount
output.PaidAmount += item.SuccessFactAmount
})
if output.TotalNum == 0 {
output.SucceedRate = 0
} else { } else {
succeedRate = 0 output.SucceedRate = math.Round(float64(output.PaidNum)/float64(output.TotalNum)*100*100) / 100
} }
return order.Summary{ output.PlatformIncome = profit
TotalNum: totalNum, return output
TotalAmount: math.Round(allAmount*100) / 100,
PaidNum: succeedNum,
PaidAmount: math.Round(succeedPaidAmount*100) / 100,
PlatformIncome: math.Round(platformAll*100) / 100,
SucceedRate: succeedRate,
}
} }
func QuerySummaryByOrderInfo(ctx context.Context, infoInfoList []order.OrderInfo) order.Summary { func QuerySummaryByOrderInfo(ctx context.Context, infoInfoList []order.OrderInfo) order.Summary {
@@ -193,7 +173,7 @@ func QuerySummaryByOrderInfo(ctx context.Context, infoInfoList []order.OrderInfo
func QueryTodaySummary(ctx context.Context, params map[string]string) order.Summary { func QueryTodaySummary(ctx context.Context, params map[string]string) order.Summary {
now := time.Now() now := time.Now()
todayAtMidnight := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location()) todayAtMidnight := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
tomorrowAtMidNight := time.Date(now.Year(), now.Month(), now.Day(), 59, 59, 59, 0, now.Location()) tomorrowAtMidNight := todayAtMidnight.Add(time.Hour * 24)
st := todayAtMidnight.Format("2006-01-02 15:04:05") st := todayAtMidnight.Format("2006-01-02 15:04:05")
end := tomorrowAtMidNight.Format("2006-01-02 15:04:05") end := tomorrowAtMidNight.Format("2006-01-02 15:04:05")
@@ -225,46 +205,70 @@ func QueryTodaySummary(ctx context.Context, params map[string]string) order.Summ
paramsProfit["create_time__lte"] = end paramsProfit["create_time__lte"] = end
} }
todaySuccessNum := 0 summaryInfos, err := order.GetOrderRawSummary(ctx, paramsProfit)
todayAllAmount := 0.0 if err != nil {
todaySupplierAll := 0.0 logs.Error("获取订单汇总信息失败:", err)
todayPlatformAll := 0.0 }
todayAgentAll := 0.0 profit, err := order.GetOrderProfitRawSummary(ctx, params)
todayPaidAmount := 0.0 if err != nil {
logs.Error("获取订单利润信息失败:", err)
}
output := order.Summary{}
slice.ForEach(summaryInfos, func(index int, item order.OrderSummaryOutput) {
output.TotalAmount += item.TotalOrderAmount
output.TotalNum += item.TotalOrderCount
output.PaidNum += item.SuccessFactCount
output.PaidAmount += item.SuccessFactAmount
})
if output.TotalNum == 0 {
output.SucceedRate = 0
} else {
output.SucceedRate = math.Round(float64(output.PaidNum)/float64(output.TotalNum)*100*100) / 100
}
output.PlatformIncome = profit
return output
totalNum := order.GetOrderCountByMap(ctx, paramsProfit) //
for i := int64(0); i < totalNum; i += 1000 { //todaySuccessNum := 0
orderInfoList := order.GetOrderByMap(ctx, paramsProfit, 1000, i) //todayAllAmount := 0.0
bankIdList := slice.Map(orderInfoList, func(index int, item order.OrderInfo) string { //todaySupplierAll := 0.0
return item.BankOrderId //todayPlatformAll := 0.0
}) //todayAgentAll := 0.0
dataInfo := order.GetOrderProfitListByBankOrderIdList(ctx, bankIdList) //todayPaidAmount := 0.0
for _, info := range dataInfo { //
todayAllAmount += info.FactAmount //totalNum := order.GetOrderCountByMap(ctx, paramsProfit)
if info.Status != common.OrderStatusSuccess { //for i := int64(0); i < totalNum; i += 1000 {
continue // orderInfoList := order.GetOrderByMap(ctx, paramsProfit, 1000, i)
} // bankIdList := slice.Map(orderInfoList, func(index int, item order.OrderInfo) string {
todaySupplierAll += info.SupplierProfit // return item.BankOrderId
todayPlatformAll += info.PlatformProfit // })
todayAgentAll += info.AgentProfit // dataInfo := order.GetOrderProfitListByBankOrderIdList(ctx, bankIdList)
todayPaidAmount += info.FactAmount // for _, info := range dataInfo {
todaySuccessNum += 1 // todayAllAmount += info.FactAmount
} // if info.Status != common.OrderStatusSuccess {
} // continue
// }
succeedRate := 0.0 // todaySupplierAll += info.SupplierProfit
if totalNum != 0 { // todayPlatformAll += info.PlatformProfit
succeedRate = math.Round(float64(todaySuccessNum)/float64(totalNum)*100*100) / 100 // todayAgentAll += info.AgentProfit
} // todayPaidAmount += info.FactAmount
return order.Summary{ // todaySuccessNum += 1
TotalNum: int64(totalNum), // }
TotalAmount: math.Round(todayAllAmount*100) / 100, //}
PaidNum: int64(todaySuccessNum), //
PaidAmount: todayPaidAmount, //succeedRate := 0.0
PlatformIncome: math.Round(todayPlatformAll*100) / 100, //if totalNum != 0 {
AgencyIncome: todayAgentAll, // succeedRate = math.Round(float64(todaySuccessNum)/float64(totalNum)*100*100) / 100
SucceedRate: succeedRate, //}
} //return order.Summary{
// TotalNum: int64(totalNum),
// TotalAmount: math.Round(todayAllAmount*100) / 100,
// PaidNum: int64(todaySuccessNum),
// PaidAmount: todayPaidAmount,
// PlatformIncome: math.Round(todayPlatformAll*100) / 100,
// AgencyIncome: todayAgentAll,
// SucceedRate: succeedRate,
//}
} }
func ValidTotp(ctx context.Context, accountUid, totpCode string) bool { func ValidTotp(ctx context.Context, accountUid, totpCode string) bool {

View File

@@ -198,7 +198,7 @@
</label> </label>
</div> </div>
<div> <div>
<span>产品名称: </span> <span>产品名称</span>
<label> <label>
<select id="product-name"> <select id="product-name">
</select> </select>