暂存一下,防止丢失
This commit is contained in:
@@ -13,6 +13,7 @@ import (
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/clause"
|
||||
|
||||
walletapp "github.com/break/junhong_cmp_fiber/internal/application/wallet"
|
||||
"github.com/break/junhong_cmp_fiber/internal/model"
|
||||
"github.com/break/junhong_cmp_fiber/internal/model/dto"
|
||||
"github.com/break/junhong_cmp_fiber/internal/store"
|
||||
@@ -41,6 +42,7 @@ type Service struct {
|
||||
iotCardStore *postgres.IotCardStore
|
||||
deviceStore *postgres.DeviceStore
|
||||
assetWalletStore *postgres.AssetWalletStore
|
||||
agentWalletRefundService *walletapp.RefundService
|
||||
logger *zap.Logger
|
||||
}
|
||||
|
||||
@@ -77,6 +79,11 @@ func New(
|
||||
}
|
||||
}
|
||||
|
||||
// SetAgentWalletRefundService 注入代理主钱包统一退款回充用例。
|
||||
func (s *Service) SetAgentWalletRefundService(service *walletapp.RefundService) {
|
||||
s.agentWalletRefundService = service
|
||||
}
|
||||
|
||||
// Create 创建退款申请
|
||||
// 校验订单存在且已支付,检查是否存在活跃退款申请,生成退款单号并创建记录
|
||||
func (s *Service) Create(ctx context.Context, req *dto.CreateRefundRequest) (*dto.RefundResponse, error) {
|
||||
@@ -299,75 +306,33 @@ func (s *Service) refundWalletPayment(ctx context.Context, tx *gorm.DB, refund *
|
||||
|
||||
// refundAgentWalletPayment 将代理钱包支付的订单退款退回原扣款主钱包。
|
||||
func (s *Service) refundAgentWalletPayment(ctx context.Context, tx *gorm.DB, refund *model.RefundRequest, order *model.Order, amount int64, operatorID uint) error {
|
||||
wallet, relatedShopID, subtype, err := s.resolveAgentRefundWallet(tx, order)
|
||||
if err != nil {
|
||||
return err
|
||||
if s.agentWalletRefundService == nil {
|
||||
return errors.New(errors.CodeInternalError, "代理主钱包退款能力未配置")
|
||||
}
|
||||
|
||||
balanceBefore := wallet.Balance
|
||||
if err := s.agentWalletStore.AddBalanceWithTx(ctx, tx, wallet.ID, amount); err != nil {
|
||||
return errors.Wrap(errors.CodeDatabaseError, err, "退回代理预充值钱包失败")
|
||||
legacyPayerShopID, legacyRelatedShopID, _ := resolveAgentWalletRefundShopID(order)
|
||||
legacyDeductAmount := order.TotalAmount
|
||||
if order.ActualPaidAmount != nil && *order.ActualPaidAmount > 0 {
|
||||
legacyDeductAmount = *order.ActualPaidAmount
|
||||
}
|
||||
requestID := ""
|
||||
if value := middleware.GetRequestIDFromContext(ctx); value != nil {
|
||||
requestID = *value
|
||||
}
|
||||
correlationID := refund.RefundNo
|
||||
if correlationID == "" {
|
||||
correlationID = order.OrderNo
|
||||
}
|
||||
|
||||
refType := constants.ReferenceTypeRefund
|
||||
refID := refund.ID
|
||||
remark := fmt.Sprintf("订单%s退款退回预充值钱包", order.OrderNo)
|
||||
assetType, assetID, assetIdentifier := buildRefundWalletTransactionAssetSnapshot(order)
|
||||
transaction := &model.AgentWalletTransaction{
|
||||
AgentWalletID: wallet.ID,
|
||||
ShopID: wallet.ShopID,
|
||||
UserID: operatorID,
|
||||
TransactionType: constants.AgentTransactionTypeRefund,
|
||||
TransactionSubtype: subtype,
|
||||
Amount: amount,
|
||||
BalanceBefore: balanceBefore,
|
||||
BalanceAfter: balanceBefore + amount,
|
||||
Status: constants.TransactionStatusSuccess,
|
||||
ReferenceType: &refType,
|
||||
ReferenceID: &refID,
|
||||
RelatedShopID: relatedShopID,
|
||||
AssetType: assetType,
|
||||
AssetID: assetID,
|
||||
AssetIdentifier: assetIdentifier,
|
||||
Remark: &remark,
|
||||
Creator: operatorID,
|
||||
ShopIDTag: wallet.ShopIDTag,
|
||||
EnterpriseIDTag: wallet.EnterpriseIDTag,
|
||||
}
|
||||
if err := s.agentWalletTransactionStore.CreateWithTx(ctx, tx, transaction); err != nil {
|
||||
return errors.Wrap(errors.CodeDatabaseError, err, "创建代理钱包退款流水失败")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// resolveAgentRefundWallet 优先按原扣款流水定位回款钱包,兼容历史缺失扣款流水的订单。
|
||||
func (s *Service) resolveAgentRefundWallet(tx *gorm.DB, order *model.Order) (*model.AgentWallet, *uint, *string, error) {
|
||||
var deductTx model.AgentWalletTransaction
|
||||
err := tx.Where("reference_type = ? AND reference_id = ? AND transaction_type = ?",
|
||||
constants.ReferenceTypeOrder, order.ID, constants.AgentTransactionTypeDeduct).
|
||||
Order("id ASC").
|
||||
First(&deductTx).Error
|
||||
if err == nil {
|
||||
wallet, err := lockAgentMainWalletByID(tx, deductTx.AgentWalletID)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
return wallet, deductTx.RelatedShopID, deductTx.TransactionSubtype, nil
|
||||
}
|
||||
if err != gorm.ErrRecordNotFound {
|
||||
return nil, nil, nil, errors.Wrap(errors.CodeDatabaseError, err, "查询原代理钱包扣款流水失败")
|
||||
}
|
||||
|
||||
payerShopID, relatedShopID, err := resolveAgentWalletRefundShopID(order)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
wallet, err := lockAgentMainWalletByShopID(tx, payerShopID)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
return wallet, relatedShopID, nil, nil
|
||||
_, err := s.agentWalletRefundService.RefundInTx(ctx, tx, walletapp.RefundCommand{
|
||||
OrderID: order.ID, RefundID: refund.ID, Amount: amount,
|
||||
LegacyPayerShopID: legacyPayerShopID, LegacyDeductAmount: legacyDeductAmount,
|
||||
LegacyRelatedShopID: legacyRelatedShopID, UserID: operatorID, Creator: operatorID,
|
||||
AssetType: assetType, AssetID: assetID, AssetIdentifier: assetIdentifier,
|
||||
Remark: remark, RequestID: requestID, CorrelationID: correlationID,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// resolveAgentWalletRefundShopID 兼容旧订单:没有扣款流水时按订单角色推导原扣款店铺。
|
||||
@@ -389,34 +354,6 @@ func resolveAgentWalletRefundShopID(order *model.Order) (uint, *uint, error) {
|
||||
return order.BuyerID, nil, nil
|
||||
}
|
||||
|
||||
// lockAgentMainWalletByID 锁定代理主钱包,保证余额快照与后续入账一致。
|
||||
func lockAgentMainWalletByID(tx *gorm.DB, walletID uint) (*model.AgentWallet, error) {
|
||||
var wallet model.AgentWallet
|
||||
if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).
|
||||
Where("id = ? AND wallet_type = ?", walletID, constants.AgentWalletTypeMain).
|
||||
First(&wallet).Error; err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return nil, errors.New(errors.CodeWalletNotFound, "代理预充值钱包不存在")
|
||||
}
|
||||
return nil, errors.Wrap(errors.CodeDatabaseError, err, "锁定代理预充值钱包失败")
|
||||
}
|
||||
return &wallet, nil
|
||||
}
|
||||
|
||||
// lockAgentMainWalletByShopID 按店铺锁定代理主钱包。
|
||||
func lockAgentMainWalletByShopID(tx *gorm.DB, shopID uint) (*model.AgentWallet, error) {
|
||||
var wallet model.AgentWallet
|
||||
if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).
|
||||
Where("shop_id = ? AND wallet_type = ?", shopID, constants.AgentWalletTypeMain).
|
||||
First(&wallet).Error; err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return nil, errors.New(errors.CodeWalletNotFound, "代理预充值钱包不存在")
|
||||
}
|
||||
return nil, errors.Wrap(errors.CodeDatabaseError, err, "锁定代理预充值钱包失败")
|
||||
}
|
||||
return &wallet, nil
|
||||
}
|
||||
|
||||
// refundAssetWalletPayment 将个人资产钱包支付的订单退款退回原资产钱包。
|
||||
func (s *Service) refundAssetWalletPayment(ctx context.Context, tx *gorm.DB, refund *model.RefundRequest, order *model.Order, amount int64, operatorID uint) error {
|
||||
wallet, err := s.resolveAssetRefundWallet(tx, order)
|
||||
|
||||
Reference in New Issue
Block a user