代码初始化
This commit is contained in:
153
service/wallet/wallet_service.go
Normal file
153
service/wallet/wallet_service.go
Normal file
@@ -0,0 +1,153 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
|
||||
walletDao "shop-user-trade/dao/wallet"
|
||||
walletDto "shop-user-trade/model/dto/wallet"
|
||||
walletEntity "shop-user-trade/model/entity/wallet"
|
||||
)
|
||||
|
||||
type wallet struct{}
|
||||
|
||||
// Wallet 钱包服务
|
||||
var Wallet = new(wallet)
|
||||
|
||||
// GetByUserId 根据用户ID获取钱包
|
||||
func (s *wallet) GetByUserId(ctx context.Context, req *walletDto.GetWalletByUserIdReq) (*walletDto.GetWalletByUserIdResp, error) {
|
||||
w, err := walletDao.Wallet.GetByUserID(ctx, req.UserId)
|
||||
if err != nil {
|
||||
g.Log().Errorf(ctx, "获取用户钱包失败, userId: %d, error: %v", req.UserId, err)
|
||||
return nil, err
|
||||
}
|
||||
if w == nil {
|
||||
return nil, errors.New("钱包不存在")
|
||||
}
|
||||
return &walletDto.GetWalletByUserIdResp{
|
||||
Data: walletDto.WalletInfo{
|
||||
ID: w.Id,
|
||||
UserID: w.UserID,
|
||||
Balance: w.Balance,
|
||||
Currency: w.Currency,
|
||||
Status: int(w.Status),
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Create 创建钱包
|
||||
func (s *wallet) Create(ctx context.Context, req *walletDto.CreateWalletReq) (*walletDto.CreateWalletResp, error) {
|
||||
// 检查钱包是否已存在
|
||||
existing, err := walletDao.Wallet.GetByUserID(ctx, req.UserId)
|
||||
if err != nil {
|
||||
g.Log().Errorf(ctx, "检查用户钱包失败, userId: %d, error: %v", req.UserId, err)
|
||||
return nil, err
|
||||
}
|
||||
if existing != nil {
|
||||
return nil, errors.New("钱包已存在")
|
||||
}
|
||||
id, err := walletDao.Wallet.Create(ctx, req)
|
||||
if err != nil {
|
||||
g.Log().Errorf(ctx, "创建钱包失败, userId: %d, error: %v", req.UserId, err)
|
||||
return nil, err
|
||||
}
|
||||
return &walletDto.CreateWalletResp{
|
||||
Data: walletDto.CreateWalletData{WalletID: id},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// UpdateBalance 更新余额
|
||||
func (s *wallet) UpdateBalance(ctx context.Context, req *walletDto.UpdateBalanceReq) (*walletDto.UpdateBalanceResp, error) {
|
||||
w, err := walletDao.Wallet.GetByID(ctx, req.WalletID)
|
||||
if err != nil {
|
||||
g.Log().Errorf(ctx, "获取钱包失败, walletId: %d, error: %v", req.WalletID, err)
|
||||
return nil, err
|
||||
}
|
||||
if w == nil {
|
||||
return nil, errors.New("钱包不存在")
|
||||
}
|
||||
|
||||
// 检查余额是否充足
|
||||
if req.Type == "expense" && w.Balance < req.Amount {
|
||||
return nil, errors.New("余额不足")
|
||||
}
|
||||
|
||||
// 记录操作前余额
|
||||
balanceBefore := w.Balance
|
||||
var balanceAfter int64
|
||||
switch req.Type {
|
||||
case "income":
|
||||
balanceAfter = balanceBefore + req.Amount
|
||||
case "expense":
|
||||
balanceAfter = balanceBefore - req.Amount
|
||||
default:
|
||||
balanceAfter = balanceBefore
|
||||
}
|
||||
|
||||
// 更新余额(乐观锁)
|
||||
success, err := walletDao.Wallet.UpdateBalance(ctx, req.WalletID, req.Amount, req.Type, w.Version)
|
||||
if err != nil {
|
||||
g.Log().Errorf(ctx, "更新余额失败, walletId: %d, error: %v", req.WalletID, err)
|
||||
return nil, err
|
||||
}
|
||||
if !success {
|
||||
return nil, errors.New("余额更新失败,请重试")
|
||||
}
|
||||
|
||||
// 记录流水日志
|
||||
logReq := &walletDto.CreateWalletLogReq{
|
||||
UserID: w.UserID,
|
||||
WalletID: w.Id,
|
||||
OrderNo: req.OrderNo,
|
||||
TransactionNo: req.TransactionNo,
|
||||
Type: req.Type,
|
||||
Amount: req.Amount,
|
||||
BalanceBefore: balanceBefore,
|
||||
BalanceAfter: balanceAfter,
|
||||
Currency: w.Currency,
|
||||
Description: req.Description,
|
||||
ExtraData: req.ExtraData,
|
||||
}
|
||||
if _, err = walletDao.Wallet.CreateLog(ctx, logReq); err != nil {
|
||||
g.Log().Warningf(ctx, "记录钱包日志失败, walletId: %d, error: %v", req.WalletID, err)
|
||||
}
|
||||
|
||||
return &walletDto.UpdateBalanceResp{
|
||||
Success: true,
|
||||
Message: "更新成功",
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetWalletLogs 获取钱包日志
|
||||
func (s *wallet) GetWalletLogs(ctx context.Context, req *walletDto.GetWalletLogsReq) (*walletDto.GetWalletLogsResp, error) {
|
||||
logs, total, err := walletDao.Wallet.ListLogs(ctx, req.UserId, req.Page, req.PageSize)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("获取钱包日志失败: %w", err)
|
||||
}
|
||||
var logInfos []walletDto.WalletLogInfo
|
||||
for _, log := range logs {
|
||||
logInfos = append(logInfos, s.logEntityToInfo(&log))
|
||||
}
|
||||
return &walletDto.GetWalletLogsResp{
|
||||
Data: walletDto.WalletLogData{
|
||||
Logs: logInfos,
|
||||
Total: total,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// logEntityToInfo 日志实体转换为Info
|
||||
func (s *wallet) logEntityToInfo(e *walletEntity.WalletLog) walletDto.WalletLogInfo {
|
||||
info := walletDto.WalletLogInfo{}
|
||||
_ = gconv.Struct(e, &info)
|
||||
info.ID = e.Id
|
||||
info.Type = string(e.Type)
|
||||
if e.CreatedAt != nil {
|
||||
info.CreatedAt = e.CreatedAt.String()
|
||||
}
|
||||
return info
|
||||
}
|
||||
Reference in New Issue
Block a user