package usecase import ( "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" "context" "errors" "fmt" ) type uidAssetKey struct { uid string asset string } // walletActionOption 表示一個「錢包操作函式」,可在錢包流程中插入自定義動作(例如:扣款、加值、凍結) type walletActionOption func( ctx context.Context, tx *usecase.WalletTransferRequest, wallet repository.UserWalletService, ) error // withLockAvailable 鎖定用戶可用餘額 func (use *WalletUseCase) withLockAvailable() walletActionOption { return func(ctx context.Context, tx *usecase.WalletTransferRequest, w repository.UserWalletService) error { uidAsset := uidAssetKey{ uid: tx.FromUID, asset: tx.Asset, } if !use.checkWalletExistence(uidAsset) { // 找不到錢包存不存在 wStatus, err := w.CheckReady(ctx) if err != nil { return fmt.Errorf("failed to check wallet: %w", err) } // 錢包不存在要做新增 if !wStatus { //// 是合約模擬交易或帳變且錢包不存在才建立錢包 //if !(tx.Business == wa.ContractSimulationBusinessTypeBusinessName || tx.BusinessType == domain.DistributionBusinessTypeBusinessName) { // // 新增錢包有命中 UK 不需要額外上鎖 // return use.translateError(err) //} if _, err := w.Init(ctx, tx.FromUID, tx.Asset, tx.Brand); err != nil { return err } return nil } use.markWalletAsExisting(uidAsset) } _, err := w.GetWithLock(ctx, []wallet.Types{wallet.TypeAvailable}) if err != nil { return err } return nil } } // subAvailable 減少用戶可用餘額 func (use *WalletUseCase) withSubAvailable() walletActionOption { return func(_ context.Context, tx *usecase.WalletTransferRequest, w repository.UserWalletService) error { if err := w.Sub(wallet.TypeAvailable, tx.ReferenceOrderID, tx.Amount); err != nil { if errors.Is(err, repository.ErrBalanceInsufficient) { // todo 錯誤要看怎麼給(餘額不足) return fmt.Errorf("balance insufficient") } return err } return nil } }