feat: add transaction

This commit is contained in:
王性驊 2025-04-26 20:01:05 +08:00
parent 14082dc5f5
commit 1282c1e1a1
3 changed files with 81 additions and 2 deletions

View File

@ -90,6 +90,8 @@ type UserWalletService interface {
GetOrderBalance(ctx context.Context, orderID string) (entity.Transaction, error)
// GetOrderBalanceForUpdate 查詢某筆交易(訂單),詳情寫入本地暫存 (FOR UPDATE)
GetOrderBalanceForUpdate(ctx context.Context, orderID string) (entity.Transaction, error)
// AddOrderBalance order 加入本地塊曲中
AddOrderBalance(ctx context.Context, orderID string, amount decimal.Decimal) error
// ClearCache 清空本地所有暫存
ClearCache()
}

View File

@ -232,9 +232,24 @@ func (use *WalletUseCase) AppendFreeze(ctx context.Context, tx usecase.WalletTra
})
}
// UnFreeze 解凍
// 1. 新增一筆解凍交易
// 2. 減少order餘額
// 3. 錢包減少凍結餘額
// 4. 錢包變化新增一筆減少凍結餘額資料
func (use *WalletUseCase) UnFreeze(ctx context.Context, tx usecase.WalletTransferRequest) error {
//TODO implement me
panic("implement me")
// 確認錢包新增或減少的餘額是否正確
if !tx.Amount.IsPositive() {
return errs.InvalidRange("failed to get correct amount")
}
tx.TxType = wallet.UnFreeze
return use.ProcessTransaction(ctx, tx, userWalletFlow{
UID: tx.FromUID,
Asset: tx.Asset,
Actions: []walletActionOption{use.withSubOrder(nil), use.withLockFreeze(), use.withSubFreeze()},
})
}
func (use *WalletUseCase) RollbackFreeze(ctx context.Context, tx usecase.WalletTransferRequest) error {

View File

@ -1,6 +1,7 @@
package usecase
import (
"code.30cm.net/digimon/app-cloudep-wallet-service/pkg/domain/entity"
"code.30cm.net/digimon/app-cloudep-wallet-service/pkg/domain/repository"
"code.30cm.net/digimon/app-cloudep-wallet-service/pkg/domain/usecase"
"code.30cm.net/digimon/app-cloudep-wallet-service/pkg/domain/wallet"
@ -187,6 +188,67 @@ func (use *WalletUseCase) withAppendFreeze() walletActionOption {
}
}
func (use *WalletUseCase) withSubOrder(fTx func(*usecase.WalletTransferRequest, entity.Transaction)) walletActionOption {
return func(ctx context.Context, tx *usecase.WalletTransferRequest, w repository.UserWalletService) error {
order, err := w.GetOrderBalance(ctx, tx.ReferenceOrderID)
if err != nil {
return err
}
// 檢查order wallet 餘額<=0
if !order.Amount.IsPositive() {
return err
}
// 以id來做lock更可以確保只lock到該筆而不會因為index關係lock到多筆導致死鎖
// 而且先不lock把資料先拉出來判斷餘額是否足夠在不足夠時可以直接return而不用lock減少開銷
order, err = w.GetOrderBalanceForUpdate(ctx, order.OrderID)
if err != nil {
return err
}
tx.Asset = order.Asset
tx.FromUID = order.UID
//// 解凍BusinessType必須跟建立凍結訂單的BusinessType一致
//if tx.Business != domain.SystemTransferCommissionBusinessTypeBusinessName {
// // 只有系統劃轉會有轉入錢包不同的狀況
// tx.BusinessType = domain.BusinessTypeToString(order.BusinessType)
//}
if fTx != nil {
fTx(tx, order)
}
if err := w.AddOrderBalance(ctx, order.OrderID, tx.Amount.Neg()); err != nil {
return err
}
return nil
}
}
func (use *WalletUseCase) withLockFreeze() walletActionOption {
return func(ctx context.Context, tx *usecase.WalletTransferRequest, w repository.UserWalletService) error {
_, err := w.GetBalancesForUpdate(ctx, []wallet.Types{wallet.TypeFreeze})
if err != nil {
return err
}
return nil
}
}
func (use *WalletUseCase) withSubFreeze() walletActionOption {
return func(ctx context.Context, tx *usecase.WalletTransferRequest, w repository.UserWalletService) error {
if err := w.DecreaseBalance(wallet.TypeFreeze, tx.ReferenceOrderID, tx.Amount); err != nil {
return err
}
return nil
}
}
//// withSubFreeze 減少用戶凍結餘額
//func (use *WalletUseCase) withSubFreeze() walletActionOption {
// return func(_ context.Context, tx *usecase.Transaction, wallet repository.UserWallet) error {