补全分销分账结算闭环并修复站点越权

- 权限落库:新增 000066 迁移,注册 11 个 distribution:* 权限并授权 super_admin/ops/finance
- 越权修复:siteAccessAllowed 校验贯穿站点/规则/订单/展示/支付通道/结算全部按 ID 操作
- 分账闭环:SplitSettlement 按比例拆分分成基数,销售加价归卖出方,尾差记入 rounding_adjustment_cent 归平台;支付快照与退款重算均按拆分写入参与方金额
- 结算批次:创建时聚合周期内待结算订单生成明细并汇总金额,结算时校验明细与总额一致后联动置位财务快照
- 手工补数接口禁止覆盖已有快照并写入审计日志
- 杂项:二维码池校验站点启用状态且不吞真实 DB 错误;绑定支付通道校验商户配置存在;表探测改为 sync.Once 缓存
This commit is contained in:
yml2213
2026-09-05 11:12:44 +08:00
parent 576cadcafa
commit ac777f5b16
11 changed files with 547 additions and 98 deletions
@@ -31,7 +31,8 @@ func (h *Handler) GetSite(c *gin.Context) {
if !ok {
return
}
item, err := h.service.FindSite(c.Request.Context(), id)
adminID, _ := currentAdminID(c)
item, err := h.service.FindSite(c.Request.Context(), adminID, id)
if err != nil {
writeError(c, err)
return
@@ -63,7 +64,8 @@ func (h *Handler) UpdateSite(c *gin.Context) {
response.BadRequest(c, "分销网站参数不正确")
return
}
item, err := h.service.UpdateSite(c.Request.Context(), id, req)
adminID, _ := currentAdminID(c)
item, err := h.service.UpdateSite(c.Request.Context(), adminID, id, req)
if err != nil {
writeError(c, err)
return
@@ -81,7 +83,8 @@ func (h *Handler) ListRules(c *gin.Context) {
}
siteID = &id
}
items, err := h.service.ListRules(c.Request.Context(), siteID, c.Query("mode"))
adminID, _ := currentAdminID(c)
items, err := h.service.ListRules(c.Request.Context(), adminID, siteID, c.Query("mode"))
if err != nil {
writeError(c, err)
return
@@ -118,7 +121,8 @@ func (h *Handler) UpdateRuleStatus(c *gin.Context) {
response.BadRequest(c, "规则状态不正确")
return
}
item, err := h.service.UpdateRuleStatus(c.Request.Context(), id, req.Status)
adminID, _ := currentAdminID(c)
item, err := h.service.UpdateRuleStatus(c.Request.Context(), adminID, id, req.Status)
if err != nil {
writeError(c, err)
return
@@ -152,7 +156,8 @@ func (h *Handler) FindOrder(c *gin.Context) {
if !ok {
return
}
item, err := h.service.FindOrder(c.Request.Context(), id)
adminID, _ := currentAdminID(c)
item, err := h.service.FindOrder(c.Request.Context(), adminID, id)
if err != nil {
writeError(c, err)
return
@@ -170,7 +175,8 @@ func (h *Handler) CreateFinancialSnapshot(c *gin.Context) {
response.BadRequest(c, "分销财务快照参数不正确")
return
}
item, err := h.service.CreateFinancialSnapshot(c.Request.Context(), id, req)
adminID, _ := currentAdminID(c)
item, err := h.service.CreateFinancialSnapshot(c.Request.Context(), adminID, id, req)
if err != nil {
writeError(c, err)
return
@@ -210,7 +216,8 @@ func (h *Handler) UpdateAccountDisplay(c *gin.Context) {
response.BadRequest(c, "账号展示状态不正确")
return
}
item, err := h.service.UpdateAccountDisplay(c.Request.Context(), id, req.DisplayStatus)
adminID, _ := currentAdminID(c)
item, err := h.service.UpdateAccountDisplay(c.Request.Context(), adminID, id, req.DisplayStatus)
if err != nil {
writeError(c, err)
return
@@ -268,7 +275,8 @@ func (h *Handler) UnbindPaymentChannel(c *gin.Context) {
if !ok {
return
}
if err := h.service.UnbindPaymentChannel(c.Request.Context(), id); err != nil {
adminID, _ := currentAdminID(c)
if err := h.service.UnbindPaymentChannel(c.Request.Context(), adminID, id); err != nil {
writeError(c, err)
return
}
@@ -319,7 +327,8 @@ func (h *Handler) MarkSettlementBatch(c *gin.Context) {
if !ok {
return
}
item, err := h.service.MarkSettlementBatch(c.Request.Context(), id)
adminID, _ := currentAdminID(c)
item, err := h.service.MarkSettlementBatch(c.Request.Context(), adminID, id)
if err != nil {
writeError(c, err)
return
@@ -363,7 +372,11 @@ func writeError(c *gin.Context, err error) {
switch {
case errors.Is(err, ErrSiteNotFound), errors.Is(err, ErrRuleNotFound), errors.Is(err, ErrOrderNotFound), errors.Is(err, ErrAccountDisplayNotFound), errors.Is(err, ErrPaymentChannelNotFound), errors.Is(err, ErrSettlementBatchNotFound):
response.NotFound(c, "分销资源不存在")
case errors.Is(err, ErrInvalidAmount), errors.Is(err, ErrInvalidRate), errors.Is(err, ErrInvalidServiceUnit), errors.Is(err, ErrUnsupportedMode), errors.Is(err, ErrInvalidOrderKind), errors.Is(err, ErrInvalidPeriod), errors.Is(err, ErrBatchAlreadySettled):
case errors.Is(err, ErrPaymentConfigNotFound):
response.BadRequest(c, "支付商户配置不存在")
case errors.Is(err, ErrOrderSnapshotExists):
response.Error(c, http.StatusConflict, "snapshot_exists", "该订单已存在财务快照,不能重复补数")
case errors.Is(err, ErrInvalidAmount), errors.Is(err, ErrInvalidRate), errors.Is(err, ErrInvalidServiceUnit), errors.Is(err, ErrUnsupportedMode), errors.Is(err, ErrInvalidOrderKind), errors.Is(err, ErrInvalidPeriod), errors.Is(err, ErrBatchAlreadySettled), errors.Is(err, ErrSettlementBatchEmpty), errors.Is(err, ErrSettlementTotalMismatch):
response.BadRequest(c, "分销规则参数不正确")
case errors.Is(err, ErrSiteAccessDenied):
response.Error(c, http.StatusForbidden, "forbidden", "无权访问该分销站点")