修复财务支付记录展示

This commit is contained in:
czl231
2026-08-16 23:55:50 +08:00
parent 27a4e62a43
commit 64248973ee
8 changed files with 267 additions and 3 deletions

View File

@@ -5,15 +5,152 @@ import (
"encoding/json"
"errors"
"io"
"strconv"
"strings"
"time"
"git.apinb.com/bsm-sdk/core/errcode"
"git.apinb.com/bsm-sdk/core/infra"
"git.apinb.com/heqiapp/platforms/backend/api/internal/impl"
"git.apinb.com/heqiapp/platforms/backend/api/internal/logic/common"
"git.apinb.com/heqiapp/platforms/backend/api/internal/models"
"github.com/gin-gonic/gin"
)
// finPaymentProductSnapshot 是商城下单时固化的商品成交快照最小结构。
type finPaymentProductSnapshot struct {
Name string `json:"name"`
}
// ListFinPayment 返回财务支付记录列表,并批量附加成交商品摘要。
func ListFinPayment(ctx *gin.Context) {
page, size := common.PageSize(ctx)
var payments []models.FinPayment
var total int64
query := common.ApplyKeywordFilter(
ctx,
common.ActiveRecords(impl.DBService.Model(&models.FinPayment{})),
&models.FinPayment{},
)
if err := query.Count(&total).Error; err != nil {
infra.Response.Error(ctx, err)
return
}
if err := query.Order("created_at desc").Offset((page - 1) * size).Limit(size).Find(&payments).Error; err != nil {
infra.Response.Error(ctx, err)
return
}
summaries, err := loadFinPaymentProductSummaries(payments)
if err != nil {
infra.Response.Error(ctx, err)
return
}
response, err := common.PublicResourceResponse(payments)
if err != nil {
infra.Response.Error(ctx, err)
return
}
rows, ok := response.([]any)
if !ok || len(rows) != len(payments) {
infra.Response.Error(ctx, errors.New("invalid finance payment list response"))
return
}
for index, payment := range payments {
row, valid := rows[index].(map[string]any)
if !valid {
infra.Response.Error(ctx, errors.New("invalid finance payment row response"))
return
}
row["product_summary"] = summaries[payment.EcOrderID]
}
infra.Response.Success(ctx, gin.H{
"total": total,
"list": common.ProtectPreciseLocation(ctx, &models.FinPayment{}, response),
})
}
// loadFinPaymentProductSummaries 一次查询当前页全部订单明细,避免列表逐行查询。
func loadFinPaymentProductSummaries(payments []models.FinPayment) (map[uint64]string, error) {
orderIDs := make([]uint64, 0, len(payments))
seen := make(map[uint64]struct{}, len(payments))
for _, payment := range payments {
if _, exists := seen[payment.EcOrderID]; exists {
continue
}
seen[payment.EcOrderID] = struct{}{}
orderIDs = append(orderIDs, payment.EcOrderID)
}
itemsByOrder := make(map[uint64][]models.EcOrderItem, len(orderIDs))
if len(orderIDs) > 0 {
var items []models.EcOrderItem
if err := common.ActiveRecords(impl.DBService).
Where("ec_order_id IN ?", orderIDs).
Order("ec_order_id asc, id asc").Find(&items).Error; err != nil {
return nil, err
}
for _, item := range items {
itemsByOrder[item.EcOrderID] = append(itemsByOrder[item.EcOrderID], item)
}
}
summaries := make(map[uint64]string, len(orderIDs))
for _, orderID := range orderIDs {
summaries[orderID] = finPaymentProductSummary(itemsByOrder[orderID])
}
return summaries, nil
}
// GetFinPayment 返回支付详情,并从订单商品快照生成财务可读的商品摘要。
func GetFinPayment(ctx *gin.Context) {
var payment models.FinPayment
if err := common.ActiveRecords(impl.DBService).
Where("identity = ?", ctx.Param("identity")).First(&payment).Error; err != nil {
common.RespondRecordError(ctx, err)
return
}
var items []models.EcOrderItem
if err := common.ActiveRecords(impl.DBService).
Where("ec_order_id = ?", payment.EcOrderID).
Order("id asc").Find(&items).Error; err != nil {
infra.Response.Error(ctx, err)
return
}
response, err := common.PublicResourceResponse(payment)
if err != nil {
infra.Response.Error(ctx, err)
return
}
data, ok := response.(map[string]any)
if !ok {
infra.Response.Error(ctx, errors.New("invalid finance payment response"))
return
}
data["product_summary"] = finPaymentProductSummary(items)
infra.Response.Success(ctx, data)
}
// finPaymentProductSummary 优先使用不可变成交快照,避免商品改名后财务详情发生漂移。
func finPaymentProductSummary(items []models.EcOrderItem) string {
summaries := make([]string, 0, len(items))
for _, item := range items {
var snapshot finPaymentProductSnapshot
if err := json.Unmarshal([]byte(item.ProductSnapshot), &snapshot); err != nil {
continue
}
name := strings.TrimSpace(snapshot.Name)
if name == "" {
continue
}
if item.Quantity > 1 {
name += " × " + strconv.Itoa(item.Quantity)
}
summaries = append(summaries, name)
}
if len(summaries) == 0 {
return "商品信息缺失"
}
return strings.Join(summaries, "、")
}
func FinSettlementHandlers() (gin.HandlerFunc, gin.HandlerFunc, gin.HandlerFunc, gin.HandlerFunc) {
fields := []string{"settlement_no", "subject_type", "subject_id", "period_start", "period_end"}
return func(ctx *gin.Context) { common.ListResource(ctx, &models.FinSettlement{}) },