资产模块功能实现
This commit is contained in:
@@ -38,6 +38,11 @@ func Init() {
|
||||
hlog.Error("AutoMigrate failed: " + err.Error())
|
||||
return
|
||||
}
|
||||
err = DB.AutoMigrate(model.UserAssets{}, model.Diamond{}, model.GoldBean{}, model.GoldLeaf{}, model.Bankcard{}, model.ConsumptionRecord{})
|
||||
if err != nil {
|
||||
hlog.Error("AutoMigrate failed: " + err.Error())
|
||||
return
|
||||
}
|
||||
// 连接池配置
|
||||
sqlDB, _ := DB.DB()
|
||||
sqlDB.SetMaxIdleConns(10)
|
||||
|
700
acquaintances/biz/dal/mysql/user_assets.go
Normal file
700
acquaintances/biz/dal/mysql/user_assets.go
Normal file
@@ -0,0 +1,700 @@
|
||||
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) {
|
||||
// 检查用户ID是否为空
|
||||
if req.UserID == "" {
|
||||
return nil, errors.New("用户ID不能为空")
|
||||
}
|
||||
|
||||
// 初始化接收结果的结构体
|
||||
userAssets := &user_assets.UserAssets{}
|
||||
|
||||
// 构建查询:关联用户资产主表和各类资产表
|
||||
db := DB.Model(&model.UserAssets{}).
|
||||
Joins("JOIN diamond ON user_assets.user_id = diamond.user_id").
|
||||
Joins("JOIN gold_bean ON user_assets.user_id = gold_bean.user_id").
|
||||
Joins("JOIN gold_leaf ON user_assets.user_id = gold_leaf.user_id").
|
||||
Where("user_assets.user_id = ?", req.UserID)
|
||||
|
||||
// 执行查询并扫描结果到结构体
|
||||
err := db.Select(`
|
||||
user_assets.user_id,
|
||||
user_assets.status,
|
||||
user_assets.created_at,
|
||||
user_assets.updated_at,
|
||||
diamond.diamond,
|
||||
gold_bean.gold_bean,
|
||||
gold_leaf.gold_leaf
|
||||
`).First(userAssets).Error
|
||||
|
||||
// 处理查询错误
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, errors.New("用户资产记录不存在")
|
||||
}
|
||||
return nil, fmt.Errorf("查询用户资产失败: %w", err)
|
||||
}
|
||||
|
||||
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")
|
||||
}
|
||||
|
||||
// 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: fmt.Sprintf("银行卡充值: %s", 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: fmt.Sprintf("银行卡充值: %s", 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: fmt.Sprintf("银行卡充值: %s", 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 = ?", targetUserID, model.SourceTypeBankcard)
|
||||
|
||||
// 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
|
||||
}
|
@@ -3,6 +3,7 @@
|
||||
package user_assets
|
||||
|
||||
import (
|
||||
"acquaintances/biz/dal/mysql"
|
||||
"context"
|
||||
|
||||
user_assets "acquaintances/biz/model/user_assets"
|
||||
@@ -20,9 +21,13 @@ func GetUserAssets(ctx context.Context, c *app.RequestContext) {
|
||||
c.String(consts.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
assets, err := mysql.GetUserAssets(req)
|
||||
if err != nil {
|
||||
c.String(consts.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
resp := new(user_assets.GetUserAssetsResponse)
|
||||
|
||||
resp.UserAssets = assets
|
||||
c.JSON(consts.StatusOK, resp)
|
||||
}
|
||||
|
||||
@@ -36,7 +41,11 @@ func AddDiamond(ctx context.Context, c *app.RequestContext) {
|
||||
c.String(consts.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
err = mysql.AddDiamond(req)
|
||||
if err != nil {
|
||||
c.String(consts.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
resp := new(user_assets.AddDiamondResponse)
|
||||
|
||||
c.JSON(consts.StatusOK, resp)
|
||||
@@ -52,7 +61,11 @@ func AddGoldBean(ctx context.Context, c *app.RequestContext) {
|
||||
c.String(consts.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
err = mysql.AddGoldBean(req)
|
||||
if err != nil {
|
||||
c.String(consts.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
resp := new(user_assets.AddGoldBeanResponse)
|
||||
|
||||
c.JSON(consts.StatusOK, resp)
|
||||
@@ -68,7 +81,11 @@ func AddGoldLeaf(ctx context.Context, c *app.RequestContext) {
|
||||
c.String(consts.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
err = mysql.AddGoldLeaf(req)
|
||||
if err != nil {
|
||||
c.String(consts.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
resp := new(user_assets.AddGoldLeafResponse)
|
||||
|
||||
c.JSON(consts.StatusOK, resp)
|
||||
@@ -84,7 +101,11 @@ func AddBankcard(ctx context.Context, c *app.RequestContext) {
|
||||
c.String(consts.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
err = mysql.AddBankcard(req)
|
||||
if err != nil {
|
||||
c.String(consts.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
resp := new(user_assets.AddBankcardResponse)
|
||||
|
||||
c.JSON(consts.StatusOK, resp)
|
||||
@@ -100,7 +121,11 @@ func RemoveBankcard(ctx context.Context, c *app.RequestContext) {
|
||||
c.String(consts.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
err = mysql.RemoveBankcard(req)
|
||||
if err != nil {
|
||||
c.String(consts.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
resp := new(user_assets.RemoveBankcardResponse)
|
||||
|
||||
c.JSON(consts.StatusOK, resp)
|
||||
@@ -116,8 +141,54 @@ func ListBankcardByUser(ctx context.Context, c *app.RequestContext) {
|
||||
c.String(consts.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
bankcards, total, err := mysql.ListBankcardByUser(req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
resp := new(user_assets.ListBankcardByUserResponse)
|
||||
|
||||
resp.Bankcards = bankcards
|
||||
resp.Total = total
|
||||
c.JSON(consts.StatusOK, resp)
|
||||
}
|
||||
|
||||
// ListConsumptionByBankcard .
|
||||
// @router /v1/user_assets/bankcard/consumption/ [GET]
|
||||
func ListConsumptionByBankcard(ctx context.Context, c *app.RequestContext) {
|
||||
var err error
|
||||
var req user_assets.ListConsumptionByBankcardRequest
|
||||
err = c.BindAndValidate(&req)
|
||||
if err != nil {
|
||||
c.String(consts.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
record, total, err := mysql.ListConsumptionByBankcard(req)
|
||||
if err != nil {
|
||||
c.String(consts.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
resp := new(user_assets.ListConsumptionByBankcardResponse)
|
||||
resp.Records = record
|
||||
resp.Total = total
|
||||
c.JSON(consts.StatusOK, resp)
|
||||
}
|
||||
|
||||
// ListConsumptionByUser .
|
||||
// @router /v1/user_assets/consumption/ [GET]
|
||||
func ListConsumptionByUser(ctx context.Context, c *app.RequestContext) {
|
||||
var err error
|
||||
var req user_assets.ListConsumptionByUserRequest
|
||||
err = c.BindAndValidate(&req)
|
||||
if err != nil {
|
||||
c.String(consts.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
record, total, err := mysql.ListConsumptionByUser(req)
|
||||
if err != nil {
|
||||
c.String(consts.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
resp := new(user_assets.ListConsumptionByUserResponse)
|
||||
resp.Records = record
|
||||
resp.Total = total
|
||||
c.JSON(consts.StatusOK, resp)
|
||||
}
|
||||
|
@@ -1,21 +1,24 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"google.golang.org/genproto/googleapis/type/decimal"
|
||||
"github.com/shopspring/decimal"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// Asset Type
|
||||
// source Type
|
||||
type SourceType uint8
|
||||
|
||||
const (
|
||||
diamond = iota
|
||||
goldBean
|
||||
goldLeaf
|
||||
SourceTypeBankcard SourceType = iota + 1 // 银行卡
|
||||
SourceTypeUSDT // USDT
|
||||
)
|
||||
|
||||
// source Type
|
||||
type ItemType uint8
|
||||
|
||||
const (
|
||||
bankcard = iota
|
||||
usdt
|
||||
ItemTypeDiamond ItemType = 1 // 钻石
|
||||
ItemTypeGoldBean ItemType = 2 // 金豆
|
||||
ItemTypeGoldLeaf ItemType = 3 // 金叶
|
||||
)
|
||||
|
||||
type UserAssets struct {
|
||||
@@ -61,52 +64,33 @@ func (*GoldLeaf) TableName() string {
|
||||
return "gold_leaf"
|
||||
}
|
||||
|
||||
// Bankcard 银行卡信息
|
||||
type Bankcard struct {
|
||||
gorm.Model
|
||||
UserID string `gorm:"column:user_id;type:varchar(32);not null;index:idx_user_id;comment:'用户ID'"`
|
||||
BankCardNumber string `gorm:"column:bankcard_number;type:varchar(19);not null;uniqueIndex:uniq_bank_card_number;comment:'银行卡号码'"`
|
||||
BankName string `gorm:"column:bank_name;type:varchar(100);not null;index:idx_bank_name;comment:'银行名称'"`
|
||||
AccountName string `gorm:"column:account_name;type:varchar(100);not null;comment:'账户名'"` // 新增:持卡人姓名
|
||||
AccountType string `gorm:"column:account_type;type:varchar(50);not null;default:'basic';comment:'账户类型'"`
|
||||
IsDefault bool `gorm:"column:is_default;type:tinyint(1);not null;default:0;index:idx_is_default;comment:'是否默认银行卡'"`
|
||||
ExpireDate string `gorm:"column:expire_date;type:varchar(7);comment:'有效期(信用卡)'"` // 新增:支持信用卡
|
||||
}
|
||||
|
||||
func (*Bankcard) TableName() string {
|
||||
return "bank_card"
|
||||
}
|
||||
|
||||
type AssetHistory struct {
|
||||
gorm.Model
|
||||
UserID string `gorm:"column:user_id;type:varchar(32);not null;index:idx_user_id;comment:'用户ID'"`
|
||||
TargetID string `gorm:"column:target_id;type:bigint;comment:'目标商品id'"`
|
||||
AssetType int8 `gorm:"column:asset_type;type:tinyint;not null;comment:资产类型(0-钻石,1-金叶,2-金豆)"`
|
||||
Amount decimal.Decimal `gorm:"column:amount;type:decimal(15,2);not null;default:0.00;comment:'数量'"`
|
||||
SourceType int8 `gorm:"column:source_type;type:tinyint;not null;comment:来源类型(0-银行卡,1-usdt)"`
|
||||
SourceAccount string `gorm:"column:source_account;type:varchar(50);not null;index:uniq_bank_card_number;comment:'来源账号'"`
|
||||
}
|
||||
|
||||
func (*AssetHistory) TableName() string {
|
||||
return "asset_history"
|
||||
}
|
||||
|
||||
// 物品类型枚举,定义支持的消费物品类型
|
||||
type ItemType uint8
|
||||
|
||||
const (
|
||||
ItemTypeDiamond ItemType = 1 // 钻石
|
||||
ItemTypeGoldBean ItemType = 2 // 金豆
|
||||
ItemTypeGoldLeaf ItemType = 3 // 金叶
|
||||
)
|
||||
|
||||
// ConsumptionRecord 物品消费记录表
|
||||
type ConsumptionRecord struct {
|
||||
gorm.Model
|
||||
UserID string `gorm:"column:user_id;type:varchar(32);not null;index:idx_user_id;comment:'用户ID'"`
|
||||
ItemType ItemType `gorm:"column:item_type;type:tinyint unsigned;not null;index:idx_item_type;comment:'物品类型 1:钻石 2:金豆 3:金叶'"`
|
||||
Amount decimal.Decimal `gorm:"column:amount;type:decimal(15,2);not null;comment:'消费数量'"`
|
||||
Amount decimal.Decimal `gorm:"column:amount;type:decimal(15,2);not null;comment:'变动数量,正数增加,负数减少'"`
|
||||
BeforeAmount decimal.Decimal `gorm:"column:before_amount;type:decimal(15,2);not null;comment:'操作前数量'"`
|
||||
AfterAmount decimal.Decimal `gorm:"column:after_amount;type:decimal(15,2);not null;comment:'操作后数量'"`
|
||||
BusinessType string `gorm:"column:business_type;type:varchar(32);not null;index:idx_business_type;comment:'业务类型,如:buy_vip购买会员、send_gift赠送礼物'"`
|
||||
BusinessID string `gorm:"column:business_id;type:varchar(64);index:idx_business_id;comment:'关联业务ID,如订单ID、礼物ID'"`
|
||||
BusinessType string `gorm:"column:business_type;type:varchar(32);not null;index:idx_business_type;comment:'业务类型'"`
|
||||
BusinessID string `gorm:"column:business_id;type:varchar(64);index:idx_business_id;comment:'关联业务ID'"`
|
||||
SourceType SourceType `gorm:"column:source_type;type:tinyint;comment:'来源类型 1:银行卡 2:USDT'"` // 新增:记录资金来源
|
||||
Remark string `gorm:"column:remark;type:varchar(255);comment:'备注信息'"`
|
||||
Operator string `gorm:"column:operator;type:varchar(32);comment:'操作人,系统操作填system'"`
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -75,3 +75,23 @@ func _addgoldleafMw() []app.HandlerFunc {
|
||||
// your code...
|
||||
return nil
|
||||
}
|
||||
|
||||
func _consumptionMw() []app.HandlerFunc {
|
||||
// your code...
|
||||
return nil
|
||||
}
|
||||
|
||||
func _listconsumptionbybankcardMw() []app.HandlerFunc {
|
||||
// your code...
|
||||
return nil
|
||||
}
|
||||
|
||||
func _consumption0Mw() []app.HandlerFunc {
|
||||
// your code...
|
||||
return nil
|
||||
}
|
||||
|
||||
func _listconsumptionbyuserMw() []app.HandlerFunc {
|
||||
// your code...
|
||||
return nil
|
||||
}
|
||||
|
@@ -27,6 +27,14 @@ func Register(r *server.Hertz) {
|
||||
_bankcard.DELETE("/", append(_removebankcardMw(), user_assets.RemoveBankcard)...)
|
||||
_bankcard.GET("/", append(_listbankcardbyuserMw(), user_assets.ListBankcardByUser)...)
|
||||
_bankcard.POST("/", append(_addbankcardMw(), user_assets.AddBankcard)...)
|
||||
{
|
||||
_consumption := _bankcard.Group("/consumption", _consumptionMw()...)
|
||||
_consumption.GET("/", append(_listconsumptionbybankcardMw(), user_assets.ListConsumptionByBankcard)...)
|
||||
}
|
||||
}
|
||||
{
|
||||
_consumption0 := _user_assets.Group("/consumption", _consumption0Mw()...)
|
||||
_consumption0.GET("/", append(_listconsumptionbyuserMw(), user_assets.ListConsumptionByUser)...)
|
||||
}
|
||||
{
|
||||
_diamond := _user_assets.Group("/diamond", _diamondMw()...)
|
||||
|
@@ -9,7 +9,9 @@ require (
|
||||
github.com/cloudwego/hertz v0.10.1
|
||||
github.com/hertz-contrib/cors v0.1.0
|
||||
github.com/hertz-contrib/registry/etcd v0.0.0-20250319055937-8a220332e808
|
||||
github.com/shopspring/decimal v1.4.0
|
||||
golang.org/x/crypto v0.22.0
|
||||
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c
|
||||
gopkg.in/ini.v1 v1.67.0
|
||||
gorm.io/driver/mysql v1.6.0
|
||||
gorm.io/gorm v1.30.0
|
||||
@@ -47,7 +49,6 @@ require (
|
||||
golang.org/x/net v0.24.0 // indirect
|
||||
golang.org/x/sys v0.24.0 // indirect
|
||||
golang.org/x/text v0.20.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c // indirect
|
||||
google.golang.org/grpc v1.41.0 // indirect
|
||||
google.golang.org/protobuf v1.34.1 // indirect
|
||||
)
|
||||
|
@@ -310,6 +310,8 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k=
|
||||
github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
|
@@ -25,7 +25,7 @@ struct GetUserAssetsResponse{
|
||||
struct AddDiamondRequest {
|
||||
1: string user_id
|
||||
2: string bankcard_number
|
||||
3: string diamond
|
||||
3: string diamond_number
|
||||
}
|
||||
|
||||
struct AddDiamondResponse {
|
||||
@@ -36,7 +36,7 @@ struct AddDiamondResponse {
|
||||
struct AddGoldBeanRequest {
|
||||
1: string user_id
|
||||
2: string bankcard_number
|
||||
3: string diamond
|
||||
3: string gold_bean_number
|
||||
}
|
||||
|
||||
struct AddGoldBeanResponse {
|
||||
@@ -47,7 +47,7 @@ struct AddGoldBeanResponse {
|
||||
struct AddGoldLeafRequest {
|
||||
1: string user_id
|
||||
2: string bankcard_number
|
||||
3: string diamond
|
||||
3: string gold_leaf_number
|
||||
}
|
||||
|
||||
struct AddGoldLeafResponse {
|
||||
@@ -61,6 +61,7 @@ struct Bankcard {
|
||||
3: string bank_name
|
||||
4: string account_type
|
||||
5: bool is_default
|
||||
6: string account_name
|
||||
}
|
||||
|
||||
struct AddBankcardRequest {
|
||||
@@ -69,6 +70,7 @@ struct AddBankcardRequest {
|
||||
3: string bank_name
|
||||
4: string account_type
|
||||
5: bool is_default
|
||||
6: string account_name
|
||||
}
|
||||
|
||||
struct AddBankcardResponse {
|
||||
@@ -88,6 +90,8 @@ struct RemoveBankcardResponse {
|
||||
|
||||
struct ListBankcardByUserRequest {
|
||||
1: string user_id
|
||||
2: i32 page // 页码,默认1
|
||||
3: i32 page_size // 每页数量,默认10
|
||||
}
|
||||
|
||||
struct ListBankcardByUserResponse {
|
||||
@@ -97,6 +101,48 @@ struct ListBankcardByUserResponse {
|
||||
4: i32 total
|
||||
}
|
||||
|
||||
// 消费记录结构体
|
||||
struct ConsumptionRecord {
|
||||
1: string user_id, // 用户ID
|
||||
2: i8 item_type, // 物品类型
|
||||
3: string amount, // 变动数量(使用字符串存储 decimal 类型)
|
||||
4: string before_amount, // 操作前数量
|
||||
5: string after_amount, // 操作后数量
|
||||
6: string business_type, // 业务类型
|
||||
7: string business_id, // 关联业务ID
|
||||
8: i8 source_type,// 来源类型
|
||||
9: string remark, // 备注信息
|
||||
10: string operator, // 操作人
|
||||
|
||||
}
|
||||
|
||||
struct ListConsumptionByBankcardRequest{
|
||||
1: string bankcard_number
|
||||
2: string user_id
|
||||
3: i32 page
|
||||
4: i32 page_size
|
||||
}
|
||||
|
||||
struct ListConsumptionByBankcardResponse{
|
||||
1: list<ConsumptionRecord> records
|
||||
2: i32 total
|
||||
3: Code code
|
||||
4: string msg
|
||||
}
|
||||
|
||||
struct ListConsumptionByUserRequest{
|
||||
1: string user_id
|
||||
2: i32 page
|
||||
3: i32 page_size
|
||||
}
|
||||
|
||||
struct ListConsumptionByUserResponse{
|
||||
1: list<ConsumptionRecord> records
|
||||
2: i32 total
|
||||
3: Code code
|
||||
4: string msg
|
||||
}
|
||||
|
||||
service UserAssetsService {
|
||||
GetUserAssetsResponse GetUserAssets(1:GetUserAssetsRequest req)(api.get="/v1/user_assets/") //获取指定用户银行卡列表
|
||||
AddDiamondResponse AddDiamond(1:AddDiamondRequest req)(api.post="/v1/user_assets/diamond/") //充值钻石
|
||||
@@ -105,4 +151,6 @@ service UserAssetsService {
|
||||
AddBankcardResponse AddBankcard(1:AddBankcardRequest req)(api.post="/v1/user_assets/bankcard/") //添加银行卡
|
||||
RemoveBankcardResponse RemoveBankcard(1:RemoveBankcardRequest req)(api.delete="/v1/user_assets/bankcard/") //删除银行卡
|
||||
ListBankcardByUserResponse ListBankcardByUser(1:ListBankcardByUserRequest req)(api.get="/v1/user_assets/bankcard/") //获取指定用户银行卡列表
|
||||
ListConsumptionByBankcardResponse ListConsumptionByBankcard(1:ListConsumptionByBankcardRequest req)(api.get="/v1/user_assets/bankcard/consumption/") //获取指定用户银行卡消费记录
|
||||
ListConsumptionByUserResponse ListConsumptionByUser(1:ListConsumptionByUserRequest req)(api.get="/v1/user_assets/consumption/") //获取指定用户消费记录
|
||||
}
|
Reference in New Issue
Block a user