Files
junhong_cmp_fiber/internal/service/asset_wallet/service.go
Break 5f57429fb0
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 8m28s
直接换货流程
2026-06-03 16:55:32 +08:00

161 lines
4.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package asset_wallet
import (
"context"
"github.com/break/junhong_cmp_fiber/internal/model/dto"
"github.com/break/junhong_cmp_fiber/internal/store/postgres"
"github.com/break/junhong_cmp_fiber/pkg/constants"
"github.com/break/junhong_cmp_fiber/pkg/errors"
"gorm.io/gorm"
)
// Service 资产钱包业务服务
// 负责管理端资产(卡/设备)钱包概况查询和流水列表查询
type Service struct {
assetWalletStore *postgres.AssetWalletStore
assetWalletTransactionStore *postgres.AssetWalletTransactionStore
}
// New 创建资产钱包服务实例
func New(assetWalletStore *postgres.AssetWalletStore, assetWalletTransactionStore *postgres.AssetWalletTransactionStore) *Service {
return &Service{
assetWalletStore: assetWalletStore,
assetWalletTransactionStore: assetWalletTransactionStore,
}
}
// GetWallet 查询资产钱包概况
// assetType 为 card 或 device映射到 resourceType = iot_card 或 device
func (s *Service) GetWallet(ctx context.Context, assetType string, assetID uint) (*dto.AssetWalletResponse, error) {
resourceType, err := mapAssetTypeToResourceType(assetType)
if err != nil {
return nil, err
}
wallet, err := s.assetWalletStore.GetByResourceTypeAndID(ctx, resourceType, assetID)
if err != nil {
if err == gorm.ErrRecordNotFound {
// 暂无钱包记录属于正常业务状态(企业卡/未充值资产),返回 nil 而非错误
return nil, nil
}
return nil, errors.Wrap(errors.CodeDatabaseError, err, "查询钱包失败")
}
statusText := walletStatusText(wallet.Status)
return &dto.AssetWalletResponse{
WalletID: wallet.ID,
ResourceType: wallet.ResourceType,
ResourceID: wallet.ResourceID,
Balance: wallet.Balance,
FrozenBalance: wallet.FrozenBalance,
AvailableBalance: wallet.Balance - wallet.FrozenBalance,
Currency: wallet.Currency,
Status: wallet.Status,
StatusText: statusText,
CreatedAt: wallet.CreatedAt,
UpdatedAt: wallet.UpdatedAt,
}, nil
}
// ListTransactions 查询资产钱包流水列表(分页)
func (s *Service) ListTransactions(ctx context.Context, assetType string, assetID uint, req *dto.AssetWalletTransactionListRequest) (*dto.AssetWalletTransactionListResponse, error) {
resourceType, err := mapAssetTypeToResourceType(assetType)
if err != nil {
return nil, err
}
page := req.Page
if page < 1 {
page = 1
}
pageSize := req.PageSize
if pageSize < 1 {
pageSize = 20
}
if pageSize > 100 {
pageSize = 100
}
offset := (page - 1) * pageSize
transactions, err := s.assetWalletTransactionStore.ListByResourceIDWithFilter(
ctx, resourceType, assetID, req.TransactionType, req.StartTime, req.EndTime, offset, pageSize,
)
if err != nil {
return nil, errors.Wrap(errors.CodeDatabaseError, err, "查询流水列表失败")
}
total, err := s.assetWalletTransactionStore.CountByResourceIDWithFilter(
ctx, resourceType, assetID, req.TransactionType, req.StartTime, req.EndTime,
)
if err != nil {
return nil, errors.Wrap(errors.CodeDatabaseError, err, "统计流水数量失败")
}
list := make([]*dto.AssetWalletTransactionItem, 0, len(transactions))
for _, tx := range transactions {
list = append(list, &dto.AssetWalletTransactionItem{
ID: tx.ID,
TransactionType: tx.TransactionType,
TransactionTypeText: transactionTypeText(tx.TransactionType),
Amount: tx.Amount,
BalanceBefore: tx.BalanceBefore,
BalanceAfter: tx.BalanceAfter,
ReferenceType: tx.ReferenceType,
ReferenceNo: tx.ReferenceNo,
Remark: tx.Remark,
CreatedAt: tx.CreatedAt,
})
}
return &dto.AssetWalletTransactionListResponse{
List: list,
Total: total,
Page: page,
PageSize: pageSize,
}, nil
}
// mapAssetTypeToResourceType 将路由参数 assetTypecard/device映射到数据库资源类型
func mapAssetTypeToResourceType(assetType string) (string, error) {
switch assetType {
case "card":
return "iot_card", nil
case "device":
return "device", nil
default:
return "", errors.New(errors.CodeInvalidParam, "无效的资产类型,仅支持 card 或 device")
}
}
// walletStatusText 翻译钱包状态文本
func walletStatusText(status int) string {
switch status {
case 1:
return "正常"
case 2:
return "冻结"
case 3:
return "关闭"
default:
return "未知"
}
}
// transactionTypeText 翻译交易类型文本
func transactionTypeText(transactionType string) string {
switch transactionType {
case constants.AssetTransactionTypeRecharge:
return "充值"
case constants.AssetTransactionTypeDeduct:
return "扣款"
case constants.AssetTransactionTypeRefund:
return "退款"
case constants.AssetTransactionTypeExchange:
return "换货迁移"
default:
return transactionType
}
}