feat(#4): 删除抽奖活动接口 DELETE /admin/lottery/activities/:id
- 软删活动 + 硬删其奖品(同事务)+ 审计日志 - 运行中的活动禁止删除(需先暂停) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -43,6 +43,10 @@ service ppanel {
|
||||
@handler UpdateLotteryRules
|
||||
put /activities/rules (UpdateAdminLotteryRulesRequest)
|
||||
|
||||
@doc "Delete activity (soft-delete; running must be paused first)"
|
||||
@handler DeleteLotteryActivity
|
||||
delete /activities/:id (AdminActivityIdRequest)
|
||||
|
||||
@doc "Create prize"
|
||||
@handler CreateLotteryPrize
|
||||
post /prizes (CreateAdminLotteryPrizeRequest) returns (AdminLotteryPrize)
|
||||
|
||||
@@ -175,3 +175,20 @@ func GrantLotteryChanceHandler(svcCtx *svc.ServiceContext) func(c *gin.Context)
|
||||
result.HttpResult(c, nil, l.GrantLotteryChance(&req))
|
||||
}
|
||||
}
|
||||
|
||||
// DeleteLotteryActivityHandler DELETE /v1/admin/lottery/activities/:id
|
||||
func DeleteLotteryActivityHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
var req types.AdminActivityIdRequest
|
||||
_ = c.ShouldBind(&req)
|
||||
if id, err := strconv.ParseInt(c.Param("id"), 10, 64); err == nil {
|
||||
req.Id = id
|
||||
}
|
||||
if err := svcCtx.Validate(&req); err != nil {
|
||||
result.ParamErrorResult(c, err)
|
||||
return
|
||||
}
|
||||
l := adminlottery.NewDeleteLotteryActivityLogic(c.Request.Context(), svcCtx)
|
||||
result.HttpResult(c, nil, l.DeleteLotteryActivity(&req))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ func registerLotteryRoutes(router *gin.Engine, serverCtx *svc.ServiceContext) {
|
||||
adminGroup.POST("/activities/publish", adminLottery.PublishLotteryActivityHandler(serverCtx))
|
||||
adminGroup.POST("/activities/pause", adminLottery.PauseLotteryActivityHandler(serverCtx))
|
||||
adminGroup.PUT("/activities/rules", adminLottery.UpdateLotteryRulesHandler(serverCtx))
|
||||
adminGroup.DELETE("/activities/:id", adminLottery.DeleteLotteryActivityHandler(serverCtx))
|
||||
|
||||
adminGroup.POST("/prizes", adminLottery.CreateLotteryPrizeHandler(serverCtx))
|
||||
adminGroup.PUT("/prizes/:id", adminLottery.UpdateLotteryPrizeHandler(serverCtx))
|
||||
|
||||
@@ -318,6 +318,55 @@ func (l *PauseLotteryActivityLogic) PauseLotteryActivity(req *types.AdminActivit
|
||||
return t.run(req.Id)
|
||||
}
|
||||
|
||||
// ---- DeleteLotteryActivity -------------------------------------------------
|
||||
|
||||
type DeleteLotteryActivityLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewDeleteLotteryActivityLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DeleteLotteryActivityLogic {
|
||||
return &DeleteLotteryActivityLogic{Logger: logger.WithContext(ctx), ctx: ctx, svcCtx: svcCtx}
|
||||
}
|
||||
|
||||
// DeleteLotteryActivity 软删活动 + 硬删其奖品(同事务)。运行中的活动禁止删除,
|
||||
// 需先暂停,避免误删正在进行的抽奖。历史抽奖记录/快照保留(独立于奖品行)。
|
||||
func (l *DeleteLotteryActivityLogic) DeleteLotteryActivity(req *types.AdminActivityIdRequest) error {
|
||||
actor := currentAdminId(l.ctx)
|
||||
if actor == 0 {
|
||||
return xerr.NewErrCode(xerr.ErrorTokenInvalid)
|
||||
}
|
||||
return l.svcCtx.DB.WithContext(l.ctx).Transaction(func(tx *gorm.DB) error {
|
||||
var a modelLottery.Activity
|
||||
if err := tx.Where("id = ?", req.Id).First(&a).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return xerr.NewErrCode(xerr.LotteryActivityEnded)
|
||||
}
|
||||
return errors.Wrap(xerr.NewErrCode(xerr.DatabaseQueryError), err.Error())
|
||||
}
|
||||
if a.Status == modelLottery.ActivityStatusRunning {
|
||||
return xerr.NewErrCodeMsg(xerr.InvalidParams, "运行中的活动请先暂停再删除")
|
||||
}
|
||||
// 软删活动(Activity 有 gorm.DeletedAt)。
|
||||
if err := tx.Delete(&modelLottery.Activity{}, req.Id).Error; err != nil {
|
||||
return errors.Wrap(xerr.NewErrCode(xerr.DatabaseDeletedError), err.Error())
|
||||
}
|
||||
// 硬删奖品(Prize 无软删字段),避免残留孤儿奖品。
|
||||
if err := tx.Where("activity_id = ?", req.Id).Delete(&modelLottery.Prize{}).Error; err != nil {
|
||||
return errors.Wrap(xerr.NewErrCode(xerr.DatabaseDeletedError), err.Error())
|
||||
}
|
||||
ip, ua := requestMeta(l.ctx)
|
||||
return audit.WriteAdminAction(l.ctx, tx, audit.Entry{
|
||||
ActorUserId: actor,
|
||||
Action: audit.ActionLotteryActivityDelete,
|
||||
TargetIds: int64ToStr(req.Id),
|
||||
IP: ip,
|
||||
UserAgent: ua,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// ---- UpdateLotteryRules (with caps) ----------------------------------------
|
||||
|
||||
type UpdateLotteryRulesLogic struct {
|
||||
|
||||
Reference in New Issue
Block a user