Files
IUQT/acquaintances/biz/dal/mysql/user_assets.go
2025-08-20 19:52:13 +08:00

723 lines
22 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 mysql
import (
"acquaintances/biz/model"
"acquaintances/biz/model/user_assets"
"errors"
"fmt"
"github.com/shopspring/decimal"
"gorm.io/gorm"
"regexp"
"time"
)
func GetUserAssets(req user_assets.GetUserAssetsRequest) (*user_assets.UserAssets, error) { // 1. 参数验证 if req.UserID == "" { return nil, errors.New("用户ID不能为空") }
// 2. 初始化响应结构体
userAssets := &user_assets.UserAssets{
UserID: req.UserID, // 确保用户 ID 始终返回
}
// 3. 查询用户资产主表信息(状态、时间戳)
var mainAsset model.UserAssets
err := DB.Model(&model.UserAssets{}).
Where("user_id = ?", req.UserID).
First(&mainAsset).Error
// 4. 处理主表记录不存在的情况(不直接报错,允许资产明细单独存在)
if err != nil {
if !errors.Is(err, gorm.ErrRecordNotFound) {
// 非 "记录不存在" 的数据库错误才返回错误
return nil, fmt.Errorf("查询用户资产主表失败: % w", err)
}
}
// 5. 分别查询各类资产明细(避免 JOIN 导致的记录缺失问题)
var (
diamond model.Diamond
goldBean model.GoldBean
goldLeaf model.GoldLeaf
)
// 查询钻石
if err := DB.Where("user_id = ?", req.UserID).First(&diamond).Error; err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
return nil, fmt.Errorf("查询钻石资产失败: %w", err)
}
userAssets.Diamond = diamond.Diamond.String()
// 查询金豆
if err := DB.Where("user_id = ?", req.UserID).First(&goldBean).Error; err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
return nil, fmt.Errorf("查询金豆资产失败: %w", err)
}
userAssets.GoldBean = goldBean.GoldBean.String()
// 查询金叶
if err := DB.Where("user_id = ?", req.UserID).First(&goldLeaf).Error; err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
return nil, fmt.Errorf("查询金叶资产失败: %w", err)
}
userAssets.GoldLeaf = goldLeaf.GoldLeaf.String()
// 6. 检查是否所有资产都不存在(可选:根据业务需求决定是否返回错误)
if mainAsset.ID == 0 && diamond.ID == 0 && goldBean.ID == 0 && goldLeaf.ID == 0 {
return nil, errors.New("用户资产记录不存在")
}
return userAssets, nil
}
// AddDiamond 为用户添加钻石(包含事务处理)
func AddDiamond(req user_assets.AddDiamondRequest) error {
// 1. 参数验证
if err := validateAddDiamondRequest(req); err != nil {
return fmt.Errorf("参数验证失败: %w", err)
}
// 2. 转换钻石数量为decimal类型
diamondNum, err := decimal.NewFromString(req.DiamondNumber)
if err != nil {
return fmt.Errorf("钻石数量格式错误: %w", err)
}
if diamondNum.LessThanOrEqual(decimal.Zero) {
return errors.New("钻石数量必须大于0")
}
// 查询银行卡信息,验证存在性和归属关系
var bankcard model.Bankcard
if err := DB.Where("bankcard_number = ?", req.BankcardNumber).First(&bankcard).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return errors.New("银行卡不存在")
}
return fmt.Errorf("查询银行卡信息失败: %w", err)
}
// 4. 验证用户ID如果指定
if bankcard.UserID != req.UserID {
return errors.New("银行卡不属于指定用户")
}
// 3. 使用事务确保数据一致性
return DB.Transaction(func(tx *gorm.DB) error {
// 4. 查询用户当前钻石数量
var diamond model.Diamond
result := tx.Where("user_id = ?", req.UserID).First(&diamond)
// 5. 处理用户钻石记录不存在的情况(自动初始化)
if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
diamond = model.Diamond{
UserID: req.UserID,
Diamond: decimal.Zero,
}
} else {
return fmt.Errorf("查询用户钻石记录失败: %w", result.Error)
}
}
// 6. 计算更新后的值
beforeAmount := diamond.Diamond
afterAmount := beforeAmount.Add(diamondNum)
// 7. 更新钻石数量
if diamond.ID == 0 {
// 新增记录
diamond.Diamond = afterAmount
if err := tx.Create(&diamond).Error; err != nil {
return fmt.Errorf("创建钻石记录失败: %w", err)
}
} else {
// 更新现有记录
if err := tx.Model(&diamond).Update("diamond", afterAmount).Error; err != nil {
return fmt.Errorf("更新钻石数量失败: %w", err)
}
}
// 8. 记录消费记录(作为增加记录)
record := model.ConsumptionRecord{
UserID: req.UserID,
ItemType: model.ItemTypeDiamond,
Amount: diamondNum, // 正数表示增加
BeforeAmount: beforeAmount,
AfterAmount: afterAmount,
BusinessType: "recharge_diamond", // 业务类型:钻石充值
BusinessID: generateBusinessID(), // 生成业务唯一ID
Remark: req.BankcardNumber,
Operator: "system",
SourceType: model.SourceTypeBankcard,
}
if err := tx.Create(&record).Error; err != nil {
return fmt.Errorf("记录消费日志失败: %w", err)
}
return nil
})
}
// 验证请求参数
func validateAddDiamondRequest(req user_assets.AddDiamondRequest) error {
if req.UserID == "" {
return errors.New("用户ID不能为空")
}
if req.BankcardNumber == "" {
return errors.New("银行卡号不能为空")
}
if req.DiamondNumber == "" {
return errors.New("钻石数量不能为空")
}
// 可添加银行卡号格式验证
return nil
}
// 生成业务唯一ID
func generateBusinessID() string {
return fmt.Sprintf("diamond_%d", time.Now().UnixNano())
}
// AddGoldBean 为用户添加金豆(包含事务处理)
func AddGoldBean(req user_assets.AddGoldBeanRequest) error {
// 1. 参数验证
if err := validateAddGoldBeanRequest(req); err != nil {
return fmt.Errorf("参数验证失败: %w", err)
}
// 2. 转换金豆数量为decimal类型
goldBeanNum, err := decimal.NewFromString(req.GoldBeanNumber)
if err != nil {
return fmt.Errorf("金豆数量格式错误: %w", err)
}
if goldBeanNum.LessThanOrEqual(decimal.Zero) {
return errors.New("金豆数量必须大于0")
}
// 3. 使用事务确保数据一致性
return DB.Transaction(func(tx *gorm.DB) error {
// 4. 查询用户当前金豆数量
var goldBean model.GoldBean
result := tx.Where("user_id = ?", req.UserID).First(&goldBean)
// 5. 处理用户金豆记录不存在的情况(自动初始化)
if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
goldBean = model.GoldBean{
UserID: req.UserID,
GoldBean: decimal.Zero,
}
} else {
return fmt.Errorf("查询用户金豆记录失败: %w", result.Error)
}
}
// 6. 计算更新后的值
beforeAmount := goldBean.GoldBean
afterAmount := beforeAmount.Add(goldBeanNum)
// 7. 更新金豆数量
if goldBean.ID == 0 {
// 新增记录
goldBean.GoldBean = afterAmount
if err := tx.Create(&goldBean).Error; err != nil {
return fmt.Errorf("创建金豆记录失败: %w", err)
}
} else {
// 更新现有记录
if err := tx.Model(&goldBean).Update("gold_bean", afterAmount).Error; err != nil {
return fmt.Errorf("更新金豆数量失败: %w", err)
}
}
// 8. 记录消费记录(作为增加记录)
record := model.ConsumptionRecord{
UserID: req.UserID,
ItemType: model.ItemTypeGoldBean, // 物品类型为金豆
Amount: goldBeanNum, // 正数表示增加
BeforeAmount: beforeAmount,
AfterAmount: afterAmount,
BusinessType: "recharge_gold_bean", // 业务类型:金豆充值
BusinessID: generateGoldBeanBusinessID(),
Remark: req.BankcardNumber,
Operator: "system",
SourceType: model.SourceTypeBankcard,
}
if err := tx.Create(&record).Error; err != nil {
return fmt.Errorf("记录金豆消费日志失败: %w", err)
}
return nil
})
}
// 验证请求参数
func validateAddGoldBeanRequest(req user_assets.AddGoldBeanRequest) error {
if req.UserID == "" {
return errors.New("用户ID不能为空")
}
if req.BankcardNumber == "" {
return errors.New("银行卡号不能为空")
}
if req.GoldBeanNumber == "" {
return errors.New("金豆数量不能为空")
}
// 可添加银行卡号格式验证(如长度、校验位等)
return nil
}
// 生成金豆业务唯一ID
func generateGoldBeanBusinessID() string {
return fmt.Sprintf("gold_bean_%d", time.Now().UnixNano())
}
// AddGoldLeaf 为用户添加金叶(包含事务处理)
func AddGoldLeaf(req user_assets.AddGoldLeafRequest) error {
// 1. 参数验证
if err := validateAddGoldLeafRequest(req); err != nil {
return fmt.Errorf("参数验证失败: %w", err)
}
// 2. 转换金叶数量为decimal类型
goldLeafNum, err := decimal.NewFromString(req.GoldLeafNumber)
if err != nil {
return fmt.Errorf("金叶数量格式错误: %w", err)
}
if goldLeafNum.LessThanOrEqual(decimal.Zero) {
return errors.New("金叶数量必须大于0")
}
// 3. 使用事务确保数据一致性
return DB.Transaction(func(tx *gorm.DB) error {
// 4. 查询用户当前金叶数量
var goldLeaf model.GoldLeaf
result := tx.Where("user_id = ?", req.UserID).First(&goldLeaf)
// 5. 处理用户金叶记录不存在的情况(自动初始化)
if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
goldLeaf = model.GoldLeaf{
UserID: req.UserID,
GoldLeaf: decimal.Zero,
}
} else {
return fmt.Errorf("查询用户金叶记录失败: %w", result.Error)
}
}
// 6. 计算更新后的值
beforeAmount := goldLeaf.GoldLeaf
afterAmount := beforeAmount.Add(goldLeafNum)
// 7. 更新金叶数量
if goldLeaf.ID == 0 {
// 新增记录
goldLeaf.GoldLeaf = afterAmount
if err := tx.Create(&goldLeaf).Error; err != nil {
return fmt.Errorf("创建金叶记录失败: %w", err)
}
} else {
// 更新现有记录
if err := tx.Model(&goldLeaf).Update("gold_leaf", afterAmount).Error; err != nil {
return fmt.Errorf("更新金叶数量失败: %w", err)
}
}
// 8. 记录消费记录(作为增加记录)
record := model.ConsumptionRecord{
UserID: req.UserID,
ItemType: model.ItemTypeGoldLeaf, // 物品类型为金叶
Amount: goldLeafNum, // 正数表示增加
BeforeAmount: beforeAmount,
AfterAmount: afterAmount,
BusinessType: "recharge_gold_leaf", // 业务类型:金叶充值
BusinessID: generateGoldLeafBusinessID(),
Remark: req.BankcardNumber,
Operator: "system",
SourceType: model.SourceTypeBankcard,
}
if err := tx.Create(&record).Error; err != nil {
return fmt.Errorf("记录金叶消费日志失败: %w", err)
}
return nil
})
}
// 验证请求参数
func validateAddGoldLeafRequest(req user_assets.AddGoldLeafRequest) error {
if req.UserID == "" {
return errors.New("用户ID不能为空")
}
if req.BankcardNumber == "" {
return errors.New("银行卡号不能为空")
}
if req.GoldLeafNumber == "" {
return errors.New("金叶数量不能为空")
}
// 可添加银行卡号格式验证如16-19位数字校验
return nil
}
// 生成金叶业务唯一ID
func generateGoldLeafBusinessID() string {
return fmt.Sprintf("gold_leaf_%d", time.Now().UnixNano())
}
// 银行卡号格式验证正则支持16-19位数字
var bankcardRegex = regexp.MustCompile(`^\d{16,19}$`)
// AddBankcard 为用户添加银行卡
func AddBankcard(req user_assets.AddBankcardRequest) error {
// 1. 参数验证
if err := validateAddBankcardRequest(req); err != nil {
return fmt.Errorf("参数验证失败: %w", err)
}
// 2. 使用事务处理,确保默认卡状态一致性
return DB.Transaction(func(tx *gorm.DB) error {
// 3. 检查银行卡号是否已被当前用户添加
var existingCount int64
if err := tx.Model(&model.Bankcard{}).
Where("user_id = ? AND bankcard_number = ?", req.UserID, req.BankcardNumber).
Count(&existingCount).Error; err != nil {
return fmt.Errorf("查询银行卡记录失败: %w", err)
}
if existingCount > 0 {
return errors.New("该银行卡已添加,不可重复添加")
}
// 4. 如果设置为默认卡,需要将用户其他默认卡设为非默认
if req.IsDefault {
if err := tx.Model(&model.Bankcard{}).
Where("user_id = ? AND is_default = 1", req.UserID).
Update("is_default", false).Error; err != nil {
return fmt.Errorf("更新默认银行卡状态失败: %w", err)
}
} else {
// 5. 如果用户没有默认卡,强制设置当前卡为默认卡
var defaultCount int64
if err := tx.Model(&model.Bankcard{}).
Where("user_id = ? AND is_default = 1", req.UserID).
Count(&defaultCount).Error; err != nil {
return fmt.Errorf("查询默认银行卡失败: %w", err)
}
if defaultCount == 0 {
req.IsDefault = true // 自动设为默认卡
}
}
// 6. 创建银行卡记录
bankcard := model.Bankcard{
UserID: req.UserID,
BankCardNumber: req.BankcardNumber,
BankName: req.BankName,
AccountType: req.AccountType,
IsDefault: req.IsDefault,
AccountName: req.AccountName,
}
if err := tx.Create(&bankcard).Error; err != nil {
return fmt.Errorf("创建银行卡记录失败: %w", err)
}
return nil
})
}
// 验证银行卡添加请求参数
func validateAddBankcardRequest(req user_assets.AddBankcardRequest) error {
if req.UserID == "" {
return errors.New("用户ID不能为空")
}
if req.BankcardNumber == "" {
return errors.New("银行卡号不能为空")
}
// 验证银行卡号格式16-19位数字
if !bankcardRegex.MatchString(req.BankcardNumber) {
return errors.New("银行卡号格式错误应为16-19位数字")
}
if req.BankName == "" {
return errors.New("银行名称不能为空")
}
if req.AccountName == "" {
return errors.New("账户名(持卡人姓名)不能为空")
}
// 账户类型为空时设置默认值
if req.AccountType == "" {
req.AccountType = "basic"
}
return nil
}
// RemoveBankcard 为用户删除银行卡
func RemoveBankcard(req user_assets.RemoveBankcardRequest) error {
// 1. 参数验证
if err := validateRemoveBankcardRequest(req); err != nil {
return fmt.Errorf("参数验证失败: %w", err)
}
// 2. 使用事务处理,确保删除后默认卡状态合理
return DB.Transaction(func(tx *gorm.DB) error {
// 2. 查询银行卡是否存在且属于当前用户
var bankcard model.Bankcard
if err := tx.Where("user_id = ? AND bankcard_number = ?",
req.UserID, req.BankcardNumber).First(&bankcard).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return errors.New("银行卡不存在或不属于当前用户")
}
return fmt.Errorf("查询银行卡信息失败: %w", err)
}
// 3. 检查是否为默认卡,若为默认卡需要特殊处理
if bankcard.IsDefault {
// 3.1 查询用户是否还有其他银行卡
var otherCount int64
if err := tx.Model(&model.Bankcard{}).
Where("user_id = ? AND bankcard_number != ?",
req.UserID, req.BankcardNumber).
Count(&otherCount).Error; err != nil {
return fmt.Errorf("查询用户其他银行卡失败: %w", err)
}
// 3.2 若还有其他卡,需要指定一张作为新默认卡
if otherCount > 0 {
var firstBankcard model.Bankcard
if err := tx.Model(&model.Bankcard{}).
Where("user_id = ? AND bankcard_number != ?",
req.UserID, req.BankcardNumber).
First(&firstBankcard).Error; err != nil {
return fmt.Errorf("查询替代默认卡失败: %w", err)
}
// 设置新默认卡
if err := tx.Model(&model.Bankcard{}).
Where("id = ?", firstBankcard.ID).
Update("is_default", true).Error; err != nil {
return fmt.Errorf("更新默认卡失败: %w", err)
}
}
// 若没有其他卡,删除后用户将没有默认卡(允许这种状态)
}
// 4. 执行删除操作
if err := tx.Where("id = ?", bankcard.ID).Delete(&model.Bankcard{}).Error; err != nil {
return fmt.Errorf("删除银行卡失败: %w", err)
}
return nil
})
}
// 验证银行卡删除请求参数
func validateRemoveBankcardRequest(req user_assets.RemoveBankcardRequest) error {
if req.UserID == "" {
return errors.New("用户ID不能为空")
}
if req.BankcardNumber == "" {
return errors.New("银行卡号不能为空")
}
// 验证银行卡号格式
if !bankcardRegex.MatchString(req.BankcardNumber) {
return errors.New("银行卡号格式错误应为16-19位数字")
}
return nil
}
// ListBankcardByUser 分页查询用户的银行卡列表
func ListBankcardByUser(req user_assets.ListBankcardByUserRequest) ([]*user_assets.Bankcard, int32, error) {
// 1. 参数验证与处理
if req.UserID == "" {
return nil, 0, errors.New("用户ID不能为空")
}
// 处理默认分页参数
page := req.Page
if page <= 0 {
page = 1 // 默认第一页
}
pageSize := req.PageSize
if pageSize <= 0 || pageSize > 100 {
pageSize = 10 // 默认每页10条最大100条
}
offset := (page - 1) * pageSize
// 2. 查询总记录数
var total int64
if err := DB.Model(&model.Bankcard{}).
Where("user_id = ?", req.UserID).
Count(&total).Error; err != nil {
return nil, 0, fmt.Errorf("查询银行卡总数失败: %w", err)
}
// 3. 查询当前页数据
var bankcards []*model.Bankcard
if err := DB.Where("user_id = ?", req.UserID).
Order("is_default DESC, created_at DESC"). // 默认卡优先,按创建时间倒序
Limit(int(pageSize)).
Offset(int(offset)).
Find(&bankcards).Error; err != nil {
return nil, 0, fmt.Errorf("查询银行卡列表失败: %w", err)
}
// 4. 转换为响应结构体
var resp []*user_assets.Bankcard
for _, card := range bankcards {
resp = append(resp, &user_assets.Bankcard{
UserID: card.UserID,
BankcardNumber: maskBankcard(card.BankCardNumber), // 脱敏处理
BankName: card.BankName,
AccountType: card.AccountType,
IsDefault: card.IsDefault,
AccountName: card.AccountName,
})
}
return resp, int32(total), nil
}
// 银行卡号脱敏处理保留前4位和后4位
func maskBankcard(bankcard string) string {
if len(bankcard) <= 8 {
return "****"
}
return bankcard[:4] + "****" + bankcard[len(bankcard)-4:]
}
// ListConsumptionByBankcard 根据银行卡号查询消费记录列表
func ListConsumptionByBankcard(req user_assets.ListConsumptionByBankcardRequest) ([]*user_assets.ConsumptionRecord, int32, error) {
// 1. 参数验证
if err := validateListConsumptionParams(req); err != nil {
return nil, 0, fmt.Errorf("参数验证失败: %w", err)
}
// 2. 处理分页参数
page := req.Page
if page <= 0 {
page = 1
}
pageSize := req.PageSize
if pageSize <= 0 || pageSize > 100 {
pageSize = 10 // 限制最大每页数量
}
offset := (page - 1) * pageSize
// 3. 查询银行卡信息,验证存在性和归属关系
var bankcard model.Bankcard
if err := DB.Where("bankcard_number = ?", req.BankcardNumber).First(&bankcard).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, 0, errors.New("银行卡不存在")
}
return nil, 0, fmt.Errorf("查询银行卡信息失败: %w", err)
}
// 4. 验证用户ID如果指定
if req.UserID != "" && bankcard.UserID != req.UserID {
return nil, 0, errors.New("银行卡不属于指定用户")
}
targetUserID := bankcard.UserID
// 5. 构建查询条件用户ID + 银行卡来源类型
query := DB.Model(&model.ConsumptionRecord{}).
Where("user_id = ? AND source_type = ? AND remark= ?", targetUserID, model.SourceTypeBankcard, req.BankcardNumber)
// 6. 查询总记录数
var total int64
if err := query.Count(&total).Error; err != nil {
return nil, 0, fmt.Errorf("统计消费记录总数失败: %w", err)
}
// 7. 分页查询消费记录
var dbRecords []*model.ConsumptionRecord
if err := query.
Order("created_at DESC"). // 按创建时间倒序,最新记录在前
Limit(int(pageSize)).
Offset(int(offset)).
Find(&dbRecords).Error; err != nil {
return nil, 0, fmt.Errorf("查询消费记录失败: %w", err)
}
// 8. 转换为Thrift响应结构体
respRecords := make([]*user_assets.ConsumptionRecord, 0, len(dbRecords))
for _, dbRec := range dbRecords {
respRec := &user_assets.ConsumptionRecord{
UserID: dbRec.UserID,
ItemType: int8(dbRec.ItemType),
Amount: dbRec.Amount.String(),
BeforeAmount: dbRec.BeforeAmount.String(),
AfterAmount: dbRec.AfterAmount.String(),
BusinessType: dbRec.BusinessType,
BusinessID: dbRec.BusinessID,
SourceType: int8(dbRec.SourceType),
Remark: dbRec.Remark,
Operator: dbRec.Operator,
}
respRecords = append(respRecords, respRec)
}
return respRecords, int32(total), nil
}
// 参数验证函数
func validateListConsumptionParams(req user_assets.ListConsumptionByBankcardRequest) error {
if req.BankcardNumber == "" {
return errors.New("银行卡号不能为空")
}
if !bankcardRegex.MatchString(req.BankcardNumber) {
return errors.New("银行卡号格式错误应为16-19位数字")
}
return nil
}
// ListConsumptionByUser 根据用户ID查询消费记录列表
func ListConsumptionByUser(req user_assets.ListConsumptionByUserRequest) ([]*user_assets.ConsumptionRecord, int32, error) {
// 1. 参数验证
if err := validateListConsumptionByUserParams(req); err != nil {
return nil, 0, fmt.Errorf("参数验证失败: %w", err)
}
// 2. 处理分页参数
page := req.Page
if page <= 0 {
page = 1 // 默认第一页
}
pageSize := req.PageSize
if pageSize <= 0 || pageSize > 100 {
pageSize = 10 // 限制最大每页数量
}
offset := (page - 1) * pageSize
// 3. 构建查询条件用户ID
query := DB.Model(&model.ConsumptionRecord{}).
Where("user_id = ?", req.UserID)
// 4. 查询总记录数
var total int64
if err := query.Count(&total).Error; err != nil {
return nil, 0, fmt.Errorf("统计消费记录总数失败: %w", err)
}
// 5. 分页查询消费记录
var dbRecords []*model.ConsumptionRecord
if err := query.
Order("created_at DESC"). // 按创建时间倒序,最新记录在前
Limit(int(pageSize)).
Offset(int(offset)).
Find(&dbRecords).Error; err != nil {
return nil, 0, fmt.Errorf("查询消费记录失败: %w", err)
}
// 6. 转换为Thrift响应结构体
respRecords := make([]*user_assets.ConsumptionRecord, 0, len(dbRecords))
for _, dbRec := range dbRecords {
respRec := &user_assets.ConsumptionRecord{
UserID: dbRec.UserID,
ItemType: int8(dbRec.ItemType),
Amount: dbRec.Amount.String(),
BeforeAmount: dbRec.BeforeAmount.String(),
AfterAmount: dbRec.AfterAmount.String(),
BusinessType: dbRec.BusinessType,
BusinessID: dbRec.BusinessID,
SourceType: int8(dbRec.SourceType),
Remark: dbRec.Remark,
Operator: dbRec.Operator,
}
respRecords = append(respRecords, respRec)
}
return respRecords, int32(total), nil
}
// 参数验证函数
func validateListConsumptionByUserParams(req user_assets.ListConsumptionByUserRequest) error {
if req.UserID == "" {
return errors.New("用户ID不能为空")
}
return nil
}