优化结构
This commit is contained in:
@@ -146,7 +146,17 @@ func (r *paymentOrderRepo) CreatePaymentOrder(ctx context.Context, order *bizpay
|
||||
if !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, false, err
|
||||
}
|
||||
if err = db.Create(po).Error; err == nil {
|
||||
err = db.Transaction(func(tx *gorm.DB) error {
|
||||
if createErr := tx.Create(po).Error; createErr != nil {
|
||||
return createErr
|
||||
}
|
||||
return appendPaymentEvent(ctx, tx, po, &bizpayment.PaymentEvent{
|
||||
Type: bizpayment.PaymentEventOrderCreated, Source: "client", Status: po.PaymentStatus,
|
||||
Amount: po.Amount, Currency: po.Currency, ClientIP: order.ClientIP,
|
||||
UserAgent: order.UserAgent, DeviceID: order.DeviceID,
|
||||
})
|
||||
})
|
||||
if err == nil {
|
||||
return toBizPaymentOrder(po), true, nil
|
||||
}
|
||||
if lookupErr := db.Where("provider = ? AND trade_no = ?", po.Provider, po.TradeNo).First(¤t).Error; lookupErr == nil {
|
||||
@@ -167,25 +177,7 @@ func (r *paymentOrderRepo) FindPaymentOrder(ctx context.Context, provider, trade
|
||||
}
|
||||
|
||||
func (r *paymentOrderRepo) ListPaymentOrders(ctx context.Context, page, pageSize int, filter bizpayment.PaymentOrderFilter) ([]*bizpayment.PaymentOrder, int64, error) {
|
||||
db := r.data.DB().WithContext(ctx).Model(&paymentOrderPO{})
|
||||
if value := strings.TrimSpace(filter.Provider); value != "" {
|
||||
db = db.Where("provider = ?", value)
|
||||
}
|
||||
if value := strings.TrimSpace(filter.TradeNo); value != "" {
|
||||
db = db.Where("trade_no LIKE ?", "%"+value+"%")
|
||||
}
|
||||
if value := strings.TrimSpace(filter.BusinessType); value != "" {
|
||||
db = db.Where("business_type = ?", value)
|
||||
}
|
||||
if value := strings.TrimSpace(filter.BusinessID); value != "" {
|
||||
db = db.Where("business_id LIKE ?", "%"+value+"%")
|
||||
}
|
||||
if value := strings.TrimSpace(filter.PaymentStatus); value != "" {
|
||||
db = db.Where("payment_status = ?", value)
|
||||
}
|
||||
if value := strings.TrimSpace(filter.RefundStatus); value != "" {
|
||||
db = db.Where("refund_status = ?", value)
|
||||
}
|
||||
db := r.filteredPaymentOrders(ctx, filter)
|
||||
var total int64
|
||||
if err := db.Count(&total).Error; err != nil {
|
||||
return nil, 0, err
|
||||
@@ -201,6 +193,105 @@ func (r *paymentOrderRepo) ListPaymentOrders(ctx context.Context, page, pageSize
|
||||
return items, total, nil
|
||||
}
|
||||
|
||||
func (r *paymentOrderRepo) filteredPaymentOrders(ctx context.Context, filter bizpayment.PaymentOrderFilter) *gorm.DB {
|
||||
db := r.data.DB().WithContext(ctx).Model(&paymentOrderPO{})
|
||||
if value := strings.TrimSpace(filter.Provider); value != "" {
|
||||
db = db.Where("provider = ?", value)
|
||||
}
|
||||
if value := strings.TrimSpace(filter.TradeNo); value != "" {
|
||||
db = db.Where("trade_no LIKE ?", "%"+value+"%")
|
||||
}
|
||||
if value := strings.TrimSpace(filter.ProviderTradeNo); value != "" {
|
||||
db = db.Where("provider_trade_no LIKE ?", "%"+value+"%")
|
||||
}
|
||||
if value := strings.TrimSpace(filter.Keyword); value != "" {
|
||||
like := "%" + value + "%"
|
||||
db = db.Where("trade_no LIKE ? OR provider_trade_no LIKE ? OR business_id LIKE ? OR subject LIKE ?", like, like, like, like)
|
||||
}
|
||||
if value := strings.TrimSpace(filter.BusinessType); value != "" {
|
||||
db = db.Where("business_type = ?", value)
|
||||
}
|
||||
if value := strings.TrimSpace(filter.BusinessID); value != "" {
|
||||
db = db.Where("business_id LIKE ?", "%"+value+"%")
|
||||
}
|
||||
if value := strings.TrimSpace(filter.PaymentStatus); value != "" {
|
||||
db = db.Where("payment_status = ?", value)
|
||||
}
|
||||
if value := strings.TrimSpace(filter.RefundStatus); value != "" {
|
||||
db = db.Where("refund_status = ?", value)
|
||||
}
|
||||
if filter.CreatedFrom != nil {
|
||||
db = db.Where("created_at >= ?", filter.CreatedFrom.UTC())
|
||||
}
|
||||
if filter.CreatedTo != nil {
|
||||
db = db.Where("created_at < ?", filter.CreatedTo.UTC())
|
||||
}
|
||||
if filter.PaidFrom != nil {
|
||||
db = db.Where("paid_at >= ?", filter.PaidFrom.UTC())
|
||||
}
|
||||
if filter.PaidTo != nil {
|
||||
db = db.Where("paid_at < ?", filter.PaidTo.UTC())
|
||||
}
|
||||
if filter.IssueOnly {
|
||||
db = db.Where("payment_status = ? OR fulfillment_status = ? OR refund_status = ? OR last_error <> ''",
|
||||
bizpayment.PaymentStatusFailed, bizpayment.FulfillmentStatusFailed, bizpayment.RefundStatusFailed)
|
||||
}
|
||||
return db
|
||||
}
|
||||
|
||||
func (r *paymentOrderRepo) SummarizePaymentOrders(ctx context.Context, filter bizpayment.PaymentOrderFilter) (*bizpayment.PaymentOrderSummary, error) {
|
||||
type countRow struct {
|
||||
OrderCount int64
|
||||
PendingCount int64
|
||||
PaidCount int64
|
||||
RefundedCount int64
|
||||
IssueCount int64
|
||||
}
|
||||
var counts countRow
|
||||
if err := r.filteredPaymentOrders(ctx, filter).Select(`
|
||||
COUNT(*) AS order_count,
|
||||
COALESCE(SUM(CASE WHEN payment_status IN ? THEN 1 ELSE 0 END), 0) AS pending_count,
|
||||
COALESCE(SUM(CASE WHEN payment_status IN ? THEN 1 ELSE 0 END), 0) AS paid_count,
|
||||
COALESCE(SUM(CASE WHEN refunded_amount > 0 THEN 1 ELSE 0 END), 0) AS refunded_count,
|
||||
COALESCE(SUM(CASE WHEN payment_status = ? OR fulfillment_status = ? OR refund_status = ? OR last_error <> '' THEN 1 ELSE 0 END), 0) AS issue_count`,
|
||||
[]string{bizpayment.PaymentStatusInitialized, bizpayment.PaymentStatusPending},
|
||||
[]string{bizpayment.PaymentStatusPaid, bizpayment.PaymentStatusPartiallyRefunded, bizpayment.PaymentStatusRefunded},
|
||||
bizpayment.PaymentStatusFailed, bizpayment.FulfillmentStatusFailed, bizpayment.RefundStatusFailed,
|
||||
).Scan(&counts).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
type currencyRow struct {
|
||||
Currency string
|
||||
OrderAmount int64
|
||||
PaidAmount int64
|
||||
RefundedAmount int64
|
||||
SettlementAmount int64
|
||||
}
|
||||
var rows []currencyRow
|
||||
if err := r.filteredPaymentOrders(ctx, filter).
|
||||
Select(`currency,
|
||||
COALESCE(SUM(amount), 0) AS order_amount,
|
||||
COALESCE(SUM(paid_amount), 0) AS paid_amount,
|
||||
COALESCE(SUM(refunded_amount), 0) AS refunded_amount,
|
||||
COALESCE(SUM(CASE WHEN settlement_amount > 0 THEN settlement_amount ELSE paid_amount END), 0) AS settlement_amount`).
|
||||
Group("currency").Order("currency ASC").Scan(&rows).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
summary := &bizpayment.PaymentOrderSummary{
|
||||
OrderCount: counts.OrderCount, PendingCount: counts.PendingCount, PaidCount: counts.PaidCount,
|
||||
RefundedCount: counts.RefundedCount, IssueCount: counts.IssueCount,
|
||||
Currencies: make([]bizpayment.PaymentCurrencySummary, 0, len(rows)),
|
||||
}
|
||||
for _, row := range rows {
|
||||
summary.Currencies = append(summary.Currencies, bizpayment.PaymentCurrencySummary{
|
||||
Currency: row.Currency, OrderAmount: row.OrderAmount, PaidAmount: row.PaidAmount,
|
||||
RefundedAmount: row.RefundedAmount, SettlementAmount: row.SettlementAmount,
|
||||
NetAmount: row.SettlementAmount - row.RefundedAmount,
|
||||
})
|
||||
}
|
||||
return summary, nil
|
||||
}
|
||||
|
||||
func (r *paymentOrderRepo) RecordPaymentCreate(ctx context.Context, provider, tradeNo string, update *bizpayment.PaymentProviderUpdate) (*bizpayment.PaymentOrder, error) {
|
||||
return r.withLockedOrder(ctx, provider, tradeNo, func(tx *gorm.DB, po *paymentOrderPO) error {
|
||||
if update == nil {
|
||||
@@ -224,7 +315,11 @@ func (r *paymentOrderRepo) RecordPaymentCreate(ctx context.Context, provider, tr
|
||||
po.PaymentStatus = status
|
||||
}
|
||||
po.Version++
|
||||
return tx.Save(po).Error
|
||||
return savePaymentOrderWithEvent(ctx, tx, po, &bizpayment.PaymentEvent{
|
||||
Type: bizpayment.PaymentEventProviderCreated, Source: update.EventSource, Status: po.PaymentStatus,
|
||||
ProviderStatus: po.ProviderStatus, Message: update.EventMessage, EventID: update.EventID,
|
||||
PayloadHash: update.PayloadHash, Amount: po.Amount, Currency: po.Currency,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -279,7 +374,15 @@ func (r *paymentOrderRepo) ApplyPaymentResult(ctx context.Context, provider, tra
|
||||
}
|
||||
}
|
||||
po.Version++
|
||||
return tx.Save(po).Error
|
||||
eventType := update.EventType
|
||||
if eventType == "" {
|
||||
eventType = bizpayment.PaymentEventPaymentSynchronized
|
||||
}
|
||||
return savePaymentOrderWithEvent(ctx, tx, po, &bizpayment.PaymentEvent{
|
||||
Type: eventType, Source: update.EventSource, Status: po.PaymentStatus,
|
||||
ProviderStatus: po.ProviderStatus, Message: update.EventMessage, EventID: update.EventID,
|
||||
PayloadHash: update.PayloadHash, Amount: po.PaidAmount, Currency: po.Currency,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -308,7 +411,9 @@ func (r *paymentOrderRepo) BeginPaymentFulfillment(ctx context.Context, provider
|
||||
po.FulfillmentLeaseUntil = &until
|
||||
po.LastError = ""
|
||||
po.Version++
|
||||
return tx.Save(po).Error
|
||||
return savePaymentOrderWithEvent(ctx, tx, po, &bizpayment.PaymentEvent{
|
||||
Type: bizpayment.PaymentEventFulfillmentStarted, Status: po.FulfillmentStatus,
|
||||
})
|
||||
})
|
||||
return order, token, duplicate, err
|
||||
}
|
||||
@@ -329,7 +434,9 @@ func (r *paymentOrderRepo) CompletePaymentFulfillment(ctx context.Context, provi
|
||||
po.FulfillmentStatus = bizpayment.FulfillmentStatusFailed
|
||||
}
|
||||
po.Version++
|
||||
return tx.Save(po).Error
|
||||
return savePaymentOrderWithEvent(ctx, tx, po, &bizpayment.PaymentEvent{
|
||||
Type: bizpayment.PaymentEventFulfillmentFinished, Status: po.FulfillmentStatus, Message: message,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -378,7 +485,9 @@ func (r *paymentOrderRepo) BeginPaymentRefund(ctx context.Context, provider, tra
|
||||
po.RefundLeaseUntil = &until
|
||||
po.LastError = ""
|
||||
po.Version++
|
||||
return tx.Save(po).Error
|
||||
return savePaymentOrderWithEvent(ctx, tx, po, &bizpayment.PaymentEvent{
|
||||
Type: bizpayment.PaymentEventRefundStarted, Status: po.RefundStatus, Amount: amount, Currency: po.Currency,
|
||||
})
|
||||
})
|
||||
return order, token, err
|
||||
}
|
||||
@@ -399,7 +508,10 @@ func (r *paymentOrderRepo) CompletePaymentRefundRequest(ctx context.Context, pro
|
||||
po.RefundNo = ""
|
||||
}
|
||||
po.Version++
|
||||
return tx.Save(po).Error
|
||||
return savePaymentOrderWithEvent(ctx, tx, po, &bizpayment.PaymentEvent{
|
||||
Type: bizpayment.PaymentEventRefundSubmitted, Status: po.RefundStatus, Message: message,
|
||||
Amount: po.RefundRequestedAmount, Currency: po.Currency,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -414,7 +526,10 @@ func (r *paymentOrderRepo) ConfirmPaymentRefund(ctx context.Context, provider, t
|
||||
po.RefundStatus = bizpayment.RefundStatusFailed
|
||||
po.RefundNo = ""
|
||||
po.Version++
|
||||
return tx.Save(po).Error
|
||||
return savePaymentOrderWithEvent(ctx, tx, po, &bizpayment.PaymentEvent{
|
||||
Type: bizpayment.PaymentEventRefundConfirmed, Status: po.RefundStatus, Message: message,
|
||||
Amount: amount, Currency: po.Currency,
|
||||
})
|
||||
}
|
||||
po.RefundedAmount += amount
|
||||
if po.RefundedAmount >= po.Amount {
|
||||
@@ -428,7 +543,10 @@ func (r *paymentOrderRepo) ConfirmPaymentRefund(ctx context.Context, provider, t
|
||||
now := time.Now().UTC()
|
||||
po.RefundedAt = &now
|
||||
po.Version++
|
||||
return tx.Save(po).Error
|
||||
return savePaymentOrderWithEvent(ctx, tx, po, &bizpayment.PaymentEvent{
|
||||
Type: bizpayment.PaymentEventRefundConfirmed, Status: po.RefundStatus, Message: message,
|
||||
Amount: amount, Currency: po.Currency,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user