feat(资产钱包自动续费): 新增全局配置、每日扫描续购与可靠复机
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 10m15s
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 10m15s
- 新增单行配置表 tb_asset_auto_renewal_config 与尝试记录表 tb_asset_auto_renewal_attempt(迁移 000229/000230) - 每日按上海自然日扫描,窗口内以同一资产钱包可用余额续购当前主套餐,资金/订单/套餐/审计同一事务闭合 - 唯一键保证每资产每日至多一次尝试,占位中断由后续扫描收敛,当日不重试 - 四类失败原因向客户与店铺各投递每日至多一条站内通知,并注册通知类型与个人客户白名单 - 续费成功后按条件经 Outbox 可靠投递复机,新增恢复扫描只查询回填,不使用即发即弃调用 - 配置读写仅超级管理员与平台账号,保存记录操作者、前后值快照并登记统一审计 - tasks 7.1–7.15 全部验证通过(本机隔离 PostgreSQL/Redis,零外部渠道调用)
This commit is contained in:
82
internal/handler/admin/asset_auto_renewal.go
Normal file
82
internal/handler/admin/asset_auto_renewal.go
Normal file
@@ -0,0 +1,82 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
"github.com/go-playground/validator/v10"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
|
||||
assetAutoRenewalApp "github.com/break/junhong_cmp_fiber/internal/application/assetautorenewal"
|
||||
"github.com/break/junhong_cmp_fiber/internal/handler/validation"
|
||||
"github.com/break/junhong_cmp_fiber/internal/model/dto"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/constants"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/errors"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/response"
|
||||
)
|
||||
|
||||
// AssetAutoRenewalConfigHandler 资产钱包自动续费配置 Handler。
|
||||
//
|
||||
// 路由组已有「仅超级管理员与平台账号」门禁,应用层仍会复核账号类型(ENG-AUTHZ-001),
|
||||
// 因此代理、企业与个人客户即使绕过路由也无任何入口。
|
||||
type AssetAutoRenewalConfigHandler struct {
|
||||
service *assetAutoRenewalApp.Service
|
||||
validator *validator.Validate
|
||||
}
|
||||
|
||||
// NewAssetAutoRenewalConfigHandler 创建资产钱包自动续费配置 Handler。
|
||||
func NewAssetAutoRenewalConfigHandler(service *assetAutoRenewalApp.Service, validator *validator.Validate) *AssetAutoRenewalConfigHandler {
|
||||
return &AssetAutoRenewalConfigHandler{service: service, validator: validator}
|
||||
}
|
||||
|
||||
// GetConfig 读取资产钱包自动续费配置。
|
||||
// GET /api/admin/asset-auto-renewal-config
|
||||
func (h *AssetAutoRenewalConfigHandler) GetConfig(c *fiber.Ctx) error {
|
||||
config, err := h.service.GetConfig(c.UserContext())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return response.Success(c, toAssetAutoRenewalConfigResponse(config))
|
||||
}
|
||||
|
||||
// UpdateConfig 保存资产钱包自动续费配置。
|
||||
// PUT /api/admin/asset-auto-renewal-config
|
||||
func (h *AssetAutoRenewalConfigHandler) UpdateConfig(c *fiber.Ctx) error {
|
||||
var req dto.UpdateAssetAutoRenewalConfigRequest
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
return errors.New(errors.CodeInvalidParam, "请求参数格式不正确")
|
||||
}
|
||||
if err := h.validator.Struct(&req); err != nil {
|
||||
return errors.New(errors.CodeInvalidParam, validation.Message("保存自动续费配置参数不合法", &req, err))
|
||||
}
|
||||
config, err := h.service.SaveConfig(c.UserContext(), assetAutoRenewalApp.ConfigRequest{
|
||||
Enabled: req.Enabled,
|
||||
Scope: req.Scope,
|
||||
PackageIDs: req.PackageIDs,
|
||||
DaysBeforeExpiry: req.DaysBeforeExpiry,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return response.Success(c, toAssetAutoRenewalConfigResponse(config))
|
||||
}
|
||||
|
||||
// toAssetAutoRenewalConfigResponse 组装配置响应,枚举附加中文名称字段(ENG-DTO-001)。
|
||||
func toAssetAutoRenewalConfigResponse(config *assetAutoRenewalApp.ConfigView) dto.AssetAutoRenewalConfigResponse {
|
||||
packageIDs := config.PackageIDs
|
||||
if packageIDs == nil {
|
||||
packageIDs = []uint{}
|
||||
}
|
||||
enabledName := "关闭"
|
||||
if config.Enabled == constants.AssetAutoRenewalConfigEnabledOn {
|
||||
enabledName = "开启"
|
||||
}
|
||||
return dto.AssetAutoRenewalConfigResponse{
|
||||
Enabled: config.Enabled,
|
||||
Scope: config.Scope,
|
||||
PackageIDs: packageIDs,
|
||||
DaysBeforeExpiry: config.DaysBeforeExpiry,
|
||||
ConfigVersion: config.ConfigVersion,
|
||||
ScopeName: constants.GetAssetAutoRenewalScopeName(config.Scope),
|
||||
EnabledName: enabledName,
|
||||
Updater: config.Updater,
|
||||
UpdatedAt: config.UpdatedAt.Format("2006-01-02 15:04:05"),
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user