59 lines
2.9 KiB
Go
59 lines
2.9 KiB
Go
// Package wallet 提供代理主钱包复杂写用例。
|
|
package wallet
|
|
|
|
import (
|
|
"context"
|
|
|
|
domainwallet "github.com/break/junhong_cmp_fiber/internal/domain/wallet"
|
|
"github.com/break/junhong_cmp_fiber/internal/model"
|
|
"github.com/break/junhong_cmp_fiber/internal/model/dto"
|
|
"github.com/break/junhong_cmp_fiber/pkg/constants"
|
|
"github.com/break/junhong_cmp_fiber/pkg/errors"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// ChangeCreditService 调整既有店铺主钱包实际信用额度。
|
|
type ChangeCreditService struct {
|
|
db *gorm.DB
|
|
}
|
|
|
|
// NewChangeCreditService 创建实际信用额度调整服务。
|
|
func NewChangeCreditService(db *gorm.DB) *ChangeCreditService {
|
|
return &ChangeCreditService{db: db}
|
|
}
|
|
|
|
// Execute 按主钱包类型和版本条件更新,不修改余额、冻结金额或钱包流水。
|
|
func (s *ChangeCreditService) Execute(ctx context.Context, shopID uint, enabled bool, limit int64, version int) (*dto.ShopCreditLimitResponse, error) {
|
|
var result *dto.ShopCreditLimitResponse
|
|
err := s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
|
var stored model.AgentWallet
|
|
if err := tx.Where("shop_id = ? AND wallet_type = ?", shopID, constants.AgentWalletTypeMain).First(&stored).Error; err != nil {
|
|
return errors.New(errors.CodeWalletNotFound, "店铺主钱包不存在")
|
|
}
|
|
aggregate := domainwallet.AgentWallet{ID: stored.ID, ShopID: stored.ShopID, WalletType: stored.WalletType, Balance: stored.Balance, FrozenBalance: stored.FrozenBalance, CreditEnabled: stored.CreditEnabled, CreditLimit: stored.CreditLimit, Status: stored.Status, Version: stored.Version}
|
|
if err := aggregate.ChangeCredit(enabled, limit); err != nil {
|
|
return err
|
|
}
|
|
update := tx.Model(&model.AgentWallet{}).
|
|
Where("id = ? AND wallet_type = ? AND version = ? AND balance::numeric - frozen_balance::numeric + ?::numeric >= 0", stored.ID, constants.AgentWalletTypeMain, version, aggregate.EffectiveCredit()).
|
|
Updates(map[string]any{"credit_enabled": enabled, "credit_limit": limit, "version": gorm.Expr("version + 1")})
|
|
if update.Error != nil {
|
|
return errors.Wrap(errors.CodeInternalError, update.Error, "更新店铺信用额度失败")
|
|
}
|
|
if update.RowsAffected != 1 {
|
|
var current model.AgentWallet
|
|
if err := tx.Where("id = ? AND wallet_type = ?", stored.ID, constants.AgentWalletTypeMain).First(¤t).Error; err != nil {
|
|
return errors.New(errors.CodeWalletNotFound, "店铺主钱包不存在")
|
|
}
|
|
if current.Version != version {
|
|
return errors.New(errors.CodeConflict, "钱包版本已变化,请刷新后重试")
|
|
}
|
|
return errors.New(errors.CodeInsufficientQuota, "当前资金占用无法降低或关闭信用额度")
|
|
}
|
|
available, _ := aggregate.AvailableBalance()
|
|
result = &dto.ShopCreditLimitResponse{ShopID: shopID, WalletID: stored.ID, Balance: stored.Balance, FrozenBalance: stored.FrozenBalance, CreditEnabled: enabled, CreditLimit: limit, AvailableBalance: available, Version: version + 1}
|
|
return nil
|
|
})
|
|
return result, err
|
|
}
|