Files
junhong_cmp_fiber/internal/exporter/agent_wallet_transaction_scene.go
break 73f5125d3d
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 8m26s
七月迭代短暂完结,还有很多后端的关键东西没有弄,这是一版赶时间做的东西
2026-07-25 17:06:58 +08:00

169 lines
6.6 KiB
Go

package exporter
import (
"context"
"strconv"
"time"
"gorm.io/gorm"
"github.com/break/junhong_cmp_fiber/pkg/constants"
)
// AgentWalletTransactionDataSource 代理主钱包流水导出数据源。
type AgentWalletTransactionDataSource struct {
db *gorm.DB
}
// NewAgentWalletTransactionDataSource 创建代理主钱包流水导出数据源。
func NewAgentWalletTransactionDataSource(db *gorm.DB) *AgentWalletTransactionDataSource {
return &AgentWalletTransactionDataSource{db: db}
}
// Scene 返回导出场景编码。
func (s *AgentWalletTransactionDataSource) Scene() string {
return constants.ExportTaskSceneAgentWalletTransaction
}
// Count 统计代理主钱包流水导出行数。
func (s *AgentWalletTransactionDataSource) Count(ctx context.Context, params ExportParams) (int, error) {
var total int64
query := s.applyFilters(s.baseQuery(ctx), params)
if err := query.Count(&total).Error; err != nil {
return 0, err
}
return int(total), nil
}
// Headers 返回代理主钱包流水导出表头。
func (s *AgentWalletTransactionDataSource) Headers(context.Context, ExportParams) ([]string, error) {
return []string{
"店铺名称", "交易类型", "交易金额(元)", "状态", "资产类型", "资产标识", "交易时间",
"交易前金额(元)", "交易后金额(元)", "购买套餐名称", "操作人", "交易ID", "关联业务订单号", "交易渠道/支付方式",
}, nil
}
// Fetch 按 offset/limit 查询代理主钱包流水导出数据。
func (s *AgentWalletTransactionDataSource) Fetch(ctx context.Context, params ExportParams, offset, limit int) ([][]string, error) {
if limit <= 0 {
return [][]string{}, nil
}
var items []agentWalletTransactionExportRow
query := s.applyFilters(s.baseQuery(ctx), params).
Select(`
t.id,
t.transaction_type,
t.amount,
t.status,
t.asset_type,
t.asset_identifier,
t.created_at,
t.balance_before,
t.balance_after,
COALESCE(sh.shop_name, '') AS shop_name,
COALESCE(items.package_names, t.metadata ->> 'package_name', '') AS package_name,
COALESCE(ac.username, '') AS operator_name,
COALESCE(
CASE t.reference_type
WHEN ? THEN o.order_no
WHEN ? THEN ar.recharge_no
WHEN ? THEN rr.refund_no
WHEN ? THEN wr.withdrawal_no
WHEN ? THEN ex.exchange_no
END,
''
) AS business_order_no,
COALESCE(t.metadata ->> 'payment_method', '') AS payment_method
`, constants.ReferenceTypeOrder, constants.ReferenceTypeTopup, constants.ReferenceTypeRefund, constants.ReferenceTypeWithdrawal, constants.ReferenceTypeExchange).
Joins("LEFT JOIN tb_shop AS sh ON sh.id = t.shop_id").
Joins("LEFT JOIN tb_account AS ac ON ac.id = COALESCE(NULLIF(t.creator, 0), t.user_id)").
Joins("LEFT JOIN tb_order AS o ON t.reference_type = ? AND o.id = t.reference_id AND o.deleted_at IS NULL", constants.ReferenceTypeOrder).
Joins("LEFT JOIN tb_agent_recharge_record AS ar ON t.reference_type = ? AND ar.id = t.reference_id AND ar.deleted_at IS NULL", constants.ReferenceTypeTopup).
Joins("LEFT JOIN tb_refund_request AS rr ON t.reference_type = ? AND rr.id = t.reference_id AND rr.deleted_at IS NULL", constants.ReferenceTypeRefund).
Joins("LEFT JOIN tb_commission_withdrawal_request AS wr ON t.reference_type = ? AND wr.id = t.reference_id AND wr.deleted_at IS NULL", constants.ReferenceTypeWithdrawal).
Joins("LEFT JOIN tb_exchange_order AS ex ON t.reference_type = ? AND ex.id = t.reference_id AND ex.deleted_at IS NULL", constants.ReferenceTypeExchange).
Joins(`LEFT JOIN LATERAL (
SELECT string_agg(oi.package_name, ',' ORDER BY oi.id) AS package_names
FROM tb_order_item AS oi
WHERE t.reference_type = ?
AND oi.order_id = t.reference_id
AND oi.deleted_at IS NULL
) AS items ON TRUE`, constants.ReferenceTypeOrder).
Order("t.id ASC").
Limit(limit).
Offset(offset)
if err := query.Scan(&items).Error; err != nil {
return nil, err
}
rows := make([][]string, 0, len(items))
for _, item := range items {
paymentMethod := item.PaymentMethod
if paymentMethod == "" && item.TransactionType == constants.AgentTransactionTypeDeduct {
paymentMethod = constants.PaymentMethodWallet
}
rows = append(rows, []string{
item.ShopName,
constants.GetAgentTransactionTypeName(item.TransactionType),
formatMoneyYuan(item.Amount),
constants.GetTransactionStatusName(item.Status),
constants.GetWalletAssetTypeName(item.AssetType),
item.AssetIdentifier,
item.CreatedAt.Format(exportTimeLayout),
formatMoneyYuan(item.BalanceBefore),
formatMoneyYuan(item.BalanceAfter),
item.PackageName,
item.OperatorName,
strconv.FormatUint(uint64(item.ID), 10),
item.BusinessOrderNo,
constants.GetBusinessPaymentMethodName(paymentMethod),
})
}
return rows, nil
}
func (s *AgentWalletTransactionDataSource) baseQuery(ctx context.Context) *gorm.DB {
return s.db.WithContext(ctx).
Table("tb_agent_wallet_transaction AS t").
Joins("INNER JOIN tb_agent_wallet AS w ON w.id = t.agent_wallet_id AND w.wallet_type = ? AND w.deleted_at IS NULL", constants.AgentWalletTypeMain).
Where("t.deleted_at IS NULL")
}
func (s *AgentWalletTransactionDataSource) applyFilters(query *gorm.DB, params ExportParams) *gorm.DB {
query = applyExportShopScope(query, params, "t.shop_id")
if shopID, ok := filterUint(params.Filters, "shop_id"); ok {
query = query.Where("t.shop_id = ?", shopID)
}
if transactionType, ok := filterString(params.Filters, "transaction_type"); ok {
query = query.Where("t.transaction_type = ?", transactionType)
}
if start, ok := filterTime(params.Filters, "start_date"); ok {
query = query.Where("t.created_at >= ?", start)
}
if end, ok := filterEndDate(params.Filters, "end_date"); ok {
query = query.Where("t.created_at <= ?", end)
}
if assetIdentifier, ok := filterString(params.Filters, "asset_identifier"); ok {
query = query.Where("t.asset_identifier = ?", assetIdentifier)
}
return query
}
type agentWalletTransactionExportRow struct {
ID uint `gorm:"column:id"`
ShopName string `gorm:"column:shop_name"`
TransactionType string `gorm:"column:transaction_type"`
Amount int64 `gorm:"column:amount"`
Status int `gorm:"column:status"`
AssetType string `gorm:"column:asset_type"`
AssetIdentifier string `gorm:"column:asset_identifier"`
CreatedAt time.Time `gorm:"column:created_at"`
BalanceBefore int64 `gorm:"column:balance_before"`
BalanceAfter int64 `gorm:"column:balance_after"`
PackageName string `gorm:"column:package_name"`
OperatorName string `gorm:"column:operator_name"`
BusinessOrderNo string `gorm:"column:business_order_no"`
PaymentMethod string `gorm:"column:payment_method"`
}