feat(backend): 对齐业务服务额度与内容治理口径

仪表盘待办与穿搭概况改为公开/私密/已封禁口径,移除恒为零的待审核统计;补齐额度凭证来源 source=4 与流水 change_type=7 枚举及订单商品类型、额度有效期快照字段;管理员发放与回收额度凭证在同一事务内写入人工调整流水,回收流水使用独立 order_no 避免撞唯一索引,并增加凭证归属校验;对齐 Quota 配置免费额度值,同步更新 README 与配置说明。
This commit is contained in:
2026-09-16 02:58:56 +08:00
parent 5d6109bb52
commit 0863234bc5
13 changed files with 460 additions and 110 deletions
+36 -3
View File
@@ -233,7 +233,18 @@ func (s *UserService) QuotaAdjust(ctx context.Context, adminID int64, userUUID s
grant.CreatedBy = adminID
grant.UpdatedBy = adminID
if err := s.quotaGrantDao.QuotaGrantCreate(ctx, grant); err != nil {
// 凭证与「人工调整」流水同事务写入:小程序额度明细中能看到对应的增加记录,
// 避免业务侧到期失效任务补记了扣减、却查不到发放来源的账实不符。
if err := s.quotaGrantDao.QuotaGrantCreateWithFlow(ctx, grant, mysqldao.QuotaFlowParams{
UserID: user.ID,
VipExpire: user.VIPExpire,
QuotaType: request.QuotaType,
Delta: request.Amount,
FreeTotal: defaultQuotaValue(request.QuotaType),
StatDate: todayStatDate(),
OrderNo: grant.RefID, // 与业务侧到期失效流水按 ref_id 关联的口径保持一致
Reason: "管理员发放额度凭证",
}); err != nil {
return errcode.DatabaseError
}
return nil
@@ -252,14 +263,36 @@ func (s *UserService) GrantRevoke(ctx context.Context, adminID int64, userUUID s
return errcode.DatabaseError
}
if _, err := s.quotaGrantDao.QuotaGrantGetByID(ctx, grantID); err != nil {
grant, err := s.quotaGrantDao.QuotaGrantGetByID(ctx, grantID)
if err != nil {
if isNotFound(err) {
return errcode.UserGrantNotFound
}
return errcode.DatabaseError
}
// 归属校验:凭证必须属于该用户,防止越权回收他人凭证。
if grant.UserID != user.ID {
return errcode.UserGrantNotFound
}
if err := s.quotaGrantDao.QuotaGrantSoftDelete(ctx, grantID, user.ID); err != nil {
// 回收使「未用完的部分」失效:Cos 为 Amount-Used,每日额度 Used 恒为 0(口径与业务侧到期失效一致)。
revoke := grant.Amount - grant.Used
if revoke < 0 {
revoke = 0
}
// 回收流水使用独立 order_no:同一凭证的发放流水同为 change_type=5,
// 复用 ref_id 会撞 uk_quota_flow_idem(order_no, quota_type, change_type) 唯一索引。
if err := s.quotaGrantDao.QuotaGrantRevokeWithFlow(ctx, mysqldao.QuotaFlowParams{
UserID: user.ID,
VipExpire: user.VIPExpire,
QuotaType: grant.QuotaType,
Delta: -revoke,
FreeTotal: defaultQuotaValue(grant.QuotaType),
StatDate: todayStatDate(),
OrderNo: "revoke_" + genUUID(),
RelatedID: grant.ID,
Reason: "管理员回收额度凭证",
}); err != nil {
return errcode.DatabaseError
}
return nil