feat(subscription): add admin quota reset actions (#5952)
* feat(subscription): add admin quota reset actions * fix(subscription): keep quota reset in plan row actions * refactor(subscription): move user subscription actions into menu
This commit is contained in:
@@ -46,6 +46,9 @@ var auditContentTemplates = map[string]string{
|
||||
"channel.upstream_apply_all": "Applied upstream model changes to ${count} channels",
|
||||
|
||||
"redemption.create": "Created ${count} redemption codes named ${name} (${quota} each)",
|
||||
|
||||
"subscription.plan_reset": "Reset active subscriptions for plan ${plan_id}",
|
||||
"subscription.user_plan_reset": "Reset active plan ${plan_id} subscriptions for user ${target_user_id}",
|
||||
}
|
||||
|
||||
// auditContentEN 按 action 模板渲染英文兜底文本;未登记的 action 退回 action 本身。
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
@@ -394,6 +395,28 @@ type AdminCreateUserSubscriptionRequest struct {
|
||||
PlanId int `json:"plan_id"`
|
||||
}
|
||||
|
||||
type AdminResetSubscriptionRequest struct {
|
||||
PlanId int `json:"plan_id"`
|
||||
AdvanceResetTime *bool `json:"advance_reset_time"`
|
||||
}
|
||||
|
||||
func resolveAdvanceResetTime(value *bool) bool {
|
||||
if value == nil {
|
||||
return true
|
||||
}
|
||||
return *value
|
||||
}
|
||||
|
||||
func recordSubscriptionResetUserLogs(result *model.SubscriptionResetResult, adminInfo map[string]interface{}) {
|
||||
if result == nil || result.ResetCount == 0 {
|
||||
return
|
||||
}
|
||||
content := fmt.Sprintf("管理员重置订阅套餐 %s(ID: %d)额度", result.PlanTitle, result.PlanId)
|
||||
for _, userId := range result.AffectedUserIds {
|
||||
model.RecordLogWithAdminInfo(userId, model.LogTypeManage, content, adminInfo)
|
||||
}
|
||||
}
|
||||
|
||||
// AdminCreateUserSubscription creates a new user subscription from a plan (no payment).
|
||||
func AdminCreateUserSubscription(c *gin.Context) {
|
||||
if !requirePaymentCompliance(c) {
|
||||
@@ -422,6 +445,69 @@ func AdminCreateUserSubscription(c *gin.Context) {
|
||||
common.ApiSuccess(c, nil)
|
||||
}
|
||||
|
||||
func AdminResetUserSubscriptionsByPlan(c *gin.Context) {
|
||||
userId, _ := strconv.Atoi(c.Param("id"))
|
||||
if userId <= 0 {
|
||||
common.ApiErrorMsg(c, "无效的用户ID")
|
||||
return
|
||||
}
|
||||
var req AdminResetSubscriptionRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
common.ApiErrorMsg(c, "参数错误")
|
||||
return
|
||||
}
|
||||
if req.PlanId <= 0 {
|
||||
common.ApiErrorMsg(c, "参数错误")
|
||||
return
|
||||
}
|
||||
advanceResetTime := resolveAdvanceResetTime(req.AdvanceResetTime)
|
||||
result, err := model.AdminResetUserSubscriptionsByPlan(userId, req.PlanId, advanceResetTime)
|
||||
if err != nil {
|
||||
common.ApiError(c, err)
|
||||
return
|
||||
}
|
||||
recordSubscriptionResetUserLogs(result, auditOperatorInfo(c))
|
||||
recordManageAuditFor(c, userId, "subscription.user_plan_reset", map[string]interface{}{
|
||||
"target_user_id": userId,
|
||||
"plan_id": result.PlanId,
|
||||
"plan_title": result.PlanTitle,
|
||||
"reset_count": result.ResetCount,
|
||||
"user_count": result.UserCount,
|
||||
"advance_reset_time": result.AdvanceResetTime,
|
||||
})
|
||||
common.ApiSuccess(c, result)
|
||||
}
|
||||
|
||||
func AdminResetPlanSubscriptions(c *gin.Context) {
|
||||
planId, _ := strconv.Atoi(c.Param("id"))
|
||||
if planId <= 0 {
|
||||
common.ApiErrorMsg(c, "无效的ID")
|
||||
return
|
||||
}
|
||||
var req AdminResetSubscriptionRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
common.ApiErrorMsg(c, "参数错误")
|
||||
return
|
||||
}
|
||||
advanceResetTime := resolveAdvanceResetTime(req.AdvanceResetTime)
|
||||
result, err := model.AdminResetPlanSubscriptions(planId, advanceResetTime)
|
||||
if err != nil {
|
||||
common.ApiError(c, err)
|
||||
return
|
||||
}
|
||||
recordSubscriptionResetUserLogs(result, auditOperatorInfo(c))
|
||||
common.SysLog(fmt.Sprintf("admin reset subscription plan %d quota: reset_count=%d user_count=%d advance_reset_time=%t",
|
||||
result.PlanId, result.ResetCount, result.UserCount, result.AdvanceResetTime))
|
||||
recordManageAudit(c, "subscription.plan_reset", map[string]interface{}{
|
||||
"plan_id": result.PlanId,
|
||||
"plan_title": result.PlanTitle,
|
||||
"reset_count": result.ResetCount,
|
||||
"user_count": result.UserCount,
|
||||
"advance_reset_time": result.AdvanceResetTime,
|
||||
})
|
||||
common.ApiSuccess(c, result)
|
||||
}
|
||||
|
||||
// AdminInvalidateUserSubscription cancels a user subscription immediately.
|
||||
func AdminInvalidateUserSubscription(c *gin.Context) {
|
||||
subId, _ := strconv.Atoi(c.Param("id"))
|
||||
|
||||
Reference in New Issue
Block a user