refactor(utils): 修复密码哈希比较逻辑错误 feat(user): 新增按状态筛选优惠券接口 docs: 添加虚拟发货与任务中心相关文档 fix(wechat): 修正Code2Session上下文传递问题 test: 补充订单折扣与积分转换测试用例 build: 更新配置文件与构建脚本 style: 清理多余的空行与注释
107 lines
3.0 KiB
Go
107 lines
3.0 KiB
Go
package user
|
||
|
||
import (
|
||
"context"
|
||
"errors"
|
||
"time"
|
||
|
||
"bindbox-game/internal/repository/mysql/model"
|
||
|
||
"gorm.io/gorm"
|
||
)
|
||
|
||
// AddItemCard 给用户添加道具卡
|
||
// 功能描述:
|
||
// - 根据道具卡模板ID查询模板信息
|
||
// - 验证道具卡状态是否有效(status=1)
|
||
// - 创建用户道具卡记录,继承模板的有效期设置
|
||
// - 支持批量添加,quantity参数控制数量
|
||
//
|
||
// 参数说明:
|
||
// - ctx: 上下文
|
||
// - userID: 用户ID
|
||
// - cardID: 道具卡模板ID
|
||
// - quantity: 添加数量,如果<=0则默认为1
|
||
//
|
||
// 返回说明:
|
||
// - error: 错误信息,包括数据库查询失败、模板不存在等情况
|
||
func (s *service) AddItemCard(ctx context.Context, userID int64, cardID int64, quantity int) error {
|
||
if quantity <= 0 {
|
||
quantity = 1
|
||
}
|
||
if quantity > 100 {
|
||
quantity = 100
|
||
}
|
||
tpl, err := s.readDB.SystemItemCards.WithContext(ctx).Where(s.readDB.SystemItemCards.ID.Eq(cardID)).First()
|
||
if err != nil {
|
||
return err
|
||
}
|
||
if tpl == nil || tpl.Status != 1 {
|
||
return errors.New("item card not found or disabled")
|
||
}
|
||
// 用户持有上限:同模板未使用数量最多10张
|
||
exist, eerr := s.readDB.UserItemCards.WithContext(ctx).
|
||
Where(s.readDB.UserItemCards.UserID.Eq(userID)).
|
||
Where(s.readDB.UserItemCards.CardID.Eq(cardID)).
|
||
Where(s.readDB.UserItemCards.Status.Eq(1)).
|
||
Count()
|
||
if eerr != nil {
|
||
return eerr
|
||
}
|
||
if exist >= 10 {
|
||
return gorm.ErrInvalidData
|
||
}
|
||
now := time.Now()
|
||
for i := 0; i < quantity; i++ {
|
||
item := &model.UserItemCards{UserID: userID, CardID: cardID, Status: 1}
|
||
if !tpl.ValidStart.IsZero() {
|
||
item.ValidStart = tpl.ValidStart
|
||
} else {
|
||
item.ValidStart = now
|
||
}
|
||
if !tpl.ValidEnd.IsZero() {
|
||
item.ValidEnd = tpl.ValidEnd
|
||
}
|
||
do := s.writeDB.UserItemCards.WithContext(ctx)
|
||
// 避免写入未使用相关字段的零值,触发 MySQL 时间字段校验错误
|
||
do = do.Omit(
|
||
s.writeDB.UserItemCards.UsedAt,
|
||
s.writeDB.UserItemCards.UsedDrawLogID,
|
||
s.writeDB.UserItemCards.UsedActivityID,
|
||
s.writeDB.UserItemCards.UsedIssueID,
|
||
)
|
||
if tpl.ValidEnd.IsZero() {
|
||
do = do.Omit(s.writeDB.UserItemCards.ValidEnd)
|
||
}
|
||
if err := do.Create(item); err != nil {
|
||
return err
|
||
}
|
||
}
|
||
return nil
|
||
}
|
||
|
||
func (s *service) VoidUserItemCard(ctx context.Context, adminID int64, userID int64, userItemCardID int64) error {
|
||
if userID <= 0 || userItemCardID <= 0 {
|
||
return gorm.ErrInvalidData
|
||
}
|
||
uc, err := s.readDB.UserItemCards.WithContext(ctx).
|
||
Where(s.readDB.UserItemCards.ID.Eq(userItemCardID)).
|
||
Where(s.readDB.UserItemCards.UserID.Eq(userID)).
|
||
First()
|
||
if err != nil {
|
||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||
return gorm.ErrRecordNotFound
|
||
}
|
||
return err
|
||
}
|
||
if uc.Status != 1 {
|
||
return gorm.ErrInvalidData
|
||
}
|
||
db := s.repo.GetDbW()
|
||
if err := db.Exec("UPDATE user_item_cards SET status=3, updated_at=NOW(3), remark=CONCAT(IFNULL(remark,''),'|void_by_admin') WHERE id=? AND user_id=? AND status=1", userItemCardID, userID).Error; err != nil {
|
||
return err
|
||
}
|
||
_ = adminID
|
||
return nil
|
||
}
|