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__lte"] = endTime
params["merchant_name__icontains"] = merchantName
params["merchant_order_id"] = orderNo
params["bank_order_id"] = bankOrderId
params["merchant_order_id__icontains"] = orderNo
params["bank_order_id__icontains"] = bankOrderId
params["status"] = status
params["pay_product_code"] = supplierUid
params["pay_type_code"] = payWayCode
@@ -922,18 +922,21 @@ func (c *GetController) GetOrderSummary() {
freeStatus := strings.TrimSpace(c.GetString("freeStatus"))
cardData := strings.TrimSpace(c.GetString("cardData"))
roadUid := strings.TrimSpace(c.GetString("roadUid"))
message := strings.TrimSpace(c.GetString("message"))
params := make(map[string]string)
params["create_time__gte"] = startTime
params["create_time__lte"] = endTime
params["merchant_name__icontains"] = merchantName
params["merchant_order_id"] = orderNo
params["bank_order_id"] = bankOrderId
params["merchant_order_id__icontains"] = orderNo
params["bank_order_id__icontains"] = bankOrderId
params["status"] = status
params["pay_product_code"] = supplierUid
params["pay_type_code"] = payWayCode
params["ex_value__icontains"] = cardData
params["road_uid"] = roadUid
params["card_return_data__icontains"] = message
switch freeStatus {
case "free":
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 (
"context"
"errors"
"fmt"
"strconv"
"strings"
"time"
"github.com/beego/beego/v2/client/orm"
@@ -132,6 +134,114 @@ func GetOrderCountByMap(ctx context.Context, params map[string]string) (count in
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 {
o := orm.NewOrm()
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 {
supplierAll := 0.0
platformAll := 0.0
agentAll := 0.0
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 //代理利润
}
summaryInfos, err := order.GetOrderRawSummary(ctx, params)
if err != nil {
logs.Error("获取订单汇总信息失败:", err)
}
succeedRate := 0.0
if totalNum != 0 {
succeedRate = math.Round(float64(succeedNum)/float64(totalNum)*100*100) / 100
profit, err := order.GetOrderProfitRawSummary(ctx, params)
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 {
succeedRate = 0
output.SucceedRate = math.Round(float64(output.PaidNum)/float64(output.TotalNum)*100*100) / 100
}
return order.Summary{
TotalNum: totalNum,
TotalAmount: math.Round(allAmount*100) / 100,
PaidNum: succeedNum,
PaidAmount: math.Round(succeedPaidAmount*100) / 100,
PlatformIncome: math.Round(platformAll*100) / 100,
SucceedRate: succeedRate,
}
output.PlatformIncome = profit
return output
}
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 {
now := time.Now()
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")
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
}
todaySuccessNum := 0
todayAllAmount := 0.0
todaySupplierAll := 0.0
todayPlatformAll := 0.0
todayAgentAll := 0.0
todayPaidAmount := 0.0
summaryInfos, err := order.GetOrderRawSummary(ctx, paramsProfit)
if err != nil {
logs.Error("获取订单汇总信息失败:", err)
}
profit, err := order.GetOrderProfitRawSummary(ctx, params)
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 {
orderInfoList := order.GetOrderByMap(ctx, paramsProfit, 1000, i)
bankIdList := slice.Map(orderInfoList, func(index int, item order.OrderInfo) string {
return item.BankOrderId
})
dataInfo := order.GetOrderProfitListByBankOrderIdList(ctx, bankIdList)
for _, info := range dataInfo {
todayAllAmount += info.FactAmount
if info.Status != common.OrderStatusSuccess {
continue
}
todaySupplierAll += info.SupplierProfit
todayPlatformAll += info.PlatformProfit
todayAgentAll += info.AgentProfit
todayPaidAmount += info.FactAmount
todaySuccessNum += 1
}
}
succeedRate := 0.0
if totalNum != 0 {
succeedRate = math.Round(float64(todaySuccessNum)/float64(totalNum)*100*100) / 100
}
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,
}
//
//todaySuccessNum := 0
//todayAllAmount := 0.0
//todaySupplierAll := 0.0
//todayPlatformAll := 0.0
//todayAgentAll := 0.0
//todayPaidAmount := 0.0
//
//totalNum := order.GetOrderCountByMap(ctx, paramsProfit)
//for i := int64(0); i < totalNum; i += 1000 {
// orderInfoList := order.GetOrderByMap(ctx, paramsProfit, 1000, i)
// bankIdList := slice.Map(orderInfoList, func(index int, item order.OrderInfo) string {
// return item.BankOrderId
// })
// dataInfo := order.GetOrderProfitListByBankOrderIdList(ctx, bankIdList)
// for _, info := range dataInfo {
// todayAllAmount += info.FactAmount
// if info.Status != common.OrderStatusSuccess {
// continue
// }
// todaySupplierAll += info.SupplierProfit
// todayPlatformAll += info.PlatformProfit
// todayAgentAll += info.AgentProfit
// todayPaidAmount += info.FactAmount
// todaySuccessNum += 1
// }
//}
//
//succeedRate := 0.0
//if totalNum != 0 {
// succeedRate = math.Round(float64(todaySuccessNum)/float64(totalNum)*100*100) / 100
//}
//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 {

View File

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