feat(代理分销提现): 落地扫码注册、提现资料资格与企微终审提现
Some checks failed
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Has been cancelled
Some checks failed
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Has been cancelled
AUG26-008。
- 迁移 000214–000217:tb_shop 全局唯一且不可修改的随机分销码(含存量回填)、
tb_agent_distribution_registration 待审批注册记录、tb_withdrawal_qualification 资料版本、
tb_commission_withdrawal_request_attempt 审批尝试记录,以及提现申请的 latest_*/异常标记列;
不修改既有迁移,down 在存在本 Change 业务事实或新类型场景行时拒绝破坏性回滚。
- 公开接口 POST /api/c/v1/agent-distribution-registrations:无认证,复用既有短信验证码校验、
消费与限流;无效分销码、停用上级、验证码无效或已消费统一返回「分销码不可用」且不落库,
审批通过前不创建店铺、账号或钱包。
- 审批通过才在同一事务内建启用店铺、代理主账号、钱包、上级层级与业务员快照,驳回不建实体,
重复回调不重复建实体,提交后清理上级下级缓存。
- 提现资料资格按不可变版本保存,替换合同或法人身份证即新增版本并同事务失效旧有效版本;
超管作废原因必填;代理停用与店铺删除联动失效。
- 提现每次提交或重提新增不可变审批尝试记录并冻结金额;企业微信通过仅一次从冻结扣减、
保持状态 2 并写 paid_at(不使用状态 4),驳回/cancelled/deleted 仅一次释放,
通过后撤销不回滚、不重新冻结、只写正交异常标记;加锁顺序统一为申请→尝试→钱包。
- 本地人工终审对已关联审批实例的申请返回状态冲突,approval_instance_id 为空的存量申请保持既有行为,
不新增任何配置开关。
- 补齐审批业务类型注册点全集:业务类型与场景字段常量、场景 DTO 两处枚举与中文描述、
场景字段白名单/合法类型/中文名、数据库 CHECK、Worker 决策消费者与装配、审批审计资源映射,
以及三个新审计资源与 13 个审计动作;失败/拒绝审计改为必达。
- 新增后台路由与 OpenAPI:资格提交/查询/作废、提现申请/重提/详情、店铺详情返回只读分销码。
- 归档本 Change:主 Spec 新增 agent-distribution-withdrawal 能力(5 个 Requirement)。
验证(junhong_cmp_test + Redis DB 6,显式 DB_*,未重置整库):
- 迁移 up → version 217 且 dirty=false → down 3 → up 回 217,fixture 复核残留为 0。
- 受控状态机脚手架 227 项通过 / 0 项失败,覆盖 18 组场景(幂等与乱序回调、资金冻结/释放/重提、
退款回扣 × 在途提现并发、负向场景拒绝审计与 14 个动作码审计真实落库)。
- gofmt 空、go build/go vet 通过、gendocs 与工作区逐字节一致、context-health 通过、
openspec validate --strict 通过、doctor healthy;自动化测试按项目决策为 N/A。
运行期前置(未完成,非代码交付物):由超管经 PUT /api/admin/wecom/scenes/{business_type} 为
agent_distribution_approval、withdrawal_qualification_approval、commission_withdrawal_approval
配置启用场景与模板控件映射;未配置时相应提交失败关闭。
This commit is contained in:
34
internal/model/agent_distribution.go
Normal file
34
internal/model/agent_distribution.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package model
|
||||
|
||||
import "time"
|
||||
|
||||
// AgentDistributionRegistration 是代理扫码注册的待审批记录。
|
||||
// 审批通过前不创建店铺、账号、钱包或上下级归属;同一手机号驳回后再次扫码是新记录。
|
||||
type AgentDistributionRegistration struct {
|
||||
ID uint `gorm:"column:id;primaryKey;autoIncrement" json:"id"`
|
||||
DistributionCode string `gorm:"column:distribution_code;type:varchar(32);not null;comment:上级店铺分销码快照" json:"distribution_code"`
|
||||
ParentShopID uint `gorm:"column:parent_shop_id;not null;comment:上级店铺ID" json:"parent_shop_id"`
|
||||
Phone string `gorm:"column:phone;type:varchar(20);not null;comment:注册手机号" json:"phone"`
|
||||
PasswordHash string `gorm:"column:password_hash;type:varchar(255);not null;comment:bcrypt 密码哈希" json:"-"`
|
||||
ShopName string `gorm:"column:shop_name;type:varchar(100);not null;comment:申请店铺名称快照" json:"shop_name"`
|
||||
ShopCode string `gorm:"column:shop_code;type:varchar(50);not null;comment:申请店铺编号快照" json:"shop_code"`
|
||||
Username string `gorm:"column:username;type:varchar(50);not null;comment:申请代理主账号用户名快照" json:"username"`
|
||||
ContactName string `gorm:"column:contact_name;type:varchar(50);not null;default:'';comment:联系人姓名快照" json:"contact_name"`
|
||||
Province string `gorm:"column:province;type:varchar(50);not null;default:'';comment:省份快照" json:"province"`
|
||||
City string `gorm:"column:city;type:varchar(50);not null;default:'';comment:城市快照" json:"city"`
|
||||
District string `gorm:"column:district;type:varchar(50);not null;default:'';comment:区县快照" json:"district"`
|
||||
Address string `gorm:"column:address;type:varchar(255);not null;default:'';comment:详细地址快照" json:"address"`
|
||||
Status int `gorm:"column:status;type:smallint;not null;default:0;comment:状态 0-待审批 1-已通过 2-已驳回" json:"status"`
|
||||
ApprovalInstanceID *uint `gorm:"column:approval_instance_id;comment:关联的通用审批实例ID" json:"approval_instance_id,omitempty"`
|
||||
RejectReason string `gorm:"column:reject_reason;type:varchar(500);not null;default:'';comment:企业微信驳回原因" json:"reject_reason"`
|
||||
DecidedAt *time.Time `gorm:"column:decided_at;type:timestamptz;comment:审批终态到达时间" json:"decided_at,omitempty"`
|
||||
Creator uint `gorm:"column:creator;not null;default:0;comment:创建人用户ID" json:"creator"`
|
||||
Updater uint `gorm:"column:updater;not null;default:0;comment:最近更新人用户ID" json:"updater"`
|
||||
CreatedAt time.Time `gorm:"column:created_at;type:timestamptz;not null;autoCreateTime" json:"created_at"`
|
||||
UpdatedAt time.Time `gorm:"column:updated_at;type:timestamptz;not null;autoUpdateTime" json:"updated_at"`
|
||||
}
|
||||
|
||||
// TableName 指定代理扫码注册记录表名。
|
||||
func (AgentDistributionRegistration) TableName() string {
|
||||
return "tb_agent_distribution_registration"
|
||||
}
|
||||
149
internal/model/dto/agent_distribution_dto.go
Normal file
149
internal/model/dto/agent_distribution_dto.go
Normal file
@@ -0,0 +1,149 @@
|
||||
package dto
|
||||
|
||||
// CreateAgentDistributionRegistrationReq 公开扫码注册请求(无需认证)。
|
||||
type CreateAgentDistributionRegistrationReq struct {
|
||||
DistributionCode string `json:"distribution_code" validate:"required,min=1,max=32" required:"true" minLength:"1" maxLength:"32" description:"上级代理店铺的分销码"`
|
||||
Phone string `json:"phone" validate:"required,len=11" required:"true" minLength:"11" maxLength:"11" description:"注册手机号,必须已完成短信验证码校验"`
|
||||
Code string `json:"code" validate:"required,len=6" required:"true" minLength:"6" maxLength:"6" description:"短信验证码,校验成功即消费"`
|
||||
Password string `json:"password" validate:"required,min=6,max=64" required:"true" minLength:"6" maximum:"64" description:"代理主账号登录密码"`
|
||||
Username string `json:"username" validate:"required,min=3,max=50" required:"true" minLength:"3" maxLength:"50" description:"代理主账号用户名"`
|
||||
ShopName string `json:"shop_name" validate:"required,min=1,max=100" required:"true" minLength:"1" maxLength:"100" description:"申请店铺名称"`
|
||||
ShopCode string `json:"shop_code" validate:"required,min=1,max=50" required:"true" minLength:"1" maxLength:"50" description:"申请店铺编号"`
|
||||
ContactName string `json:"contact_name" validate:"omitempty,max=50" maxLength:"50" description:"联系人姓名"`
|
||||
Province string `json:"province" validate:"omitempty,max=50" maxLength:"50" description:"省份"`
|
||||
City string `json:"city" validate:"omitempty,max=50" maxLength:"50" description:"城市"`
|
||||
District string `json:"district" validate:"omitempty,max=50" maxLength:"50" description:"区县"`
|
||||
Address string `json:"address" validate:"omitempty,max=255" maxLength:"255" description:"详细地址"`
|
||||
}
|
||||
|
||||
// CreateAgentDistributionRegistrationResp 公开扫码注册响应。
|
||||
// 仅返回注册记录标识与待审批状态,不返回任何账号凭证或审批实例明细。
|
||||
type CreateAgentDistributionRegistrationResp struct {
|
||||
ID uint `json:"id" description:"待审批注册记录ID"`
|
||||
Status int `json:"status" description:"注册记录状态 (0:待审批, 1:已通过, 2:已驳回)"`
|
||||
StatusName string `json:"status_name" description:"状态名称(中文)"`
|
||||
}
|
||||
|
||||
// SubmitWithdrawalQualificationReq 提交或替换提现资料资格请求。
|
||||
type SubmitWithdrawalQualificationReq struct {
|
||||
ShopID uint `json:"-" params:"shop_id" path:"shop_id" validate:"required" description:"店铺ID"`
|
||||
SubjectType string `json:"subject_type" validate:"required,oneof=enterprise personal" required:"true" enum:"enterprise,personal" description:"签约主体类型 (enterprise:企业, personal:个人)"`
|
||||
SubjectCode string `json:"subject_code" validate:"omitempty,max=64" maxLength:"64" description:"签约主体代码:企业填统一社会信用代码;个人留空并按法人身份证号取值"`
|
||||
LegalPersonIDCard string `json:"legal_person_id_card" validate:"required,min=1,max=64" required:"true" minLength:"1" maxLength:"64" description:"法人身份证号"`
|
||||
ContractFileKey string `json:"contract_file_key" validate:"required,min=1,max=255" required:"true" minLength:"1" maxLength:"255" description:"合同附件对象存储 Key(单个对象)"`
|
||||
IDCardFrontFileKey string `json:"id_card_front_file_key" validate:"required,min=1,max=255" required:"true" minLength:"1" maxLength:"255" description:"法人身份证正面附件对象存储 Key(单个对象)"`
|
||||
IDCardBackFileKey string `json:"id_card_back_file_key" validate:"required,min=1,max=255" required:"true" minLength:"1" maxLength:"255" description:"法人身份证反面附件对象存储 Key(单个对象)"`
|
||||
BusinessLicenseFileKey string `json:"business_license_file_key" validate:"omitempty,max=255" maxLength:"255" description:"营业执照附件对象存储 Key(单个对象,可选)"`
|
||||
ShopFrontFileKey string `json:"shop_front_file_key" validate:"omitempty,max=255" maxLength:"255" description:"门头照附件对象存储 Key(单个对象,可选)"`
|
||||
InvoiceFileKey string `json:"invoice_file_key" validate:"omitempty,max=255" maxLength:"255" description:"发票附件对象存储 Key(单个对象,仅企业可选)"`
|
||||
InvoiceTitle string `json:"invoice_title" validate:"omitempty,max=200" maxLength:"200" description:"发票抬头,仅企业填写,必须与合同主体一致"`
|
||||
InvoiceSubjectCode string `json:"invoice_subject_code" validate:"omitempty,max=64" maxLength:"64" description:"发票统一社会信用代码,必须与签约主体代码一致"`
|
||||
}
|
||||
|
||||
// SubmitWithdrawalQualificationResp 提现资料资格提交响应。
|
||||
type SubmitWithdrawalQualificationResp struct {
|
||||
ID uint `json:"id" description:"资料版本ID"`
|
||||
Status int `json:"status" description:"资料版本状态 (0:待审批, 1:已通过有效, 2:已驳回, 3:已失效)"`
|
||||
StatusName string `json:"status_name" description:"状态名称(中文)"`
|
||||
}
|
||||
|
||||
// VoidWithdrawalQualificationReq 超级管理员作废提现资料资格请求。
|
||||
type VoidWithdrawalQualificationReq struct {
|
||||
Reason string `json:"reason" validate:"required,min=1,max=500" required:"true" minLength:"1" maxLength:"500" description:"作废原因,必填且可在资格详情查询"`
|
||||
}
|
||||
|
||||
// VoidWithdrawalQualificationParams 作废提现资料资格路径与请求参数。
|
||||
type VoidWithdrawalQualificationParams struct {
|
||||
IDReq
|
||||
VoidWithdrawalQualificationReq
|
||||
}
|
||||
|
||||
// WithdrawalQualificationListReq 提现资料资格列表查询请求。
|
||||
type WithdrawalQualificationListReq struct {
|
||||
ShopID uint `json:"-" params:"shop_id" path:"shop_id" validate:"required" required:"true" description:"店铺ID(路径参数,必填;查询前校验当前账号对该店铺的数据范围)"`
|
||||
Page int `query:"page" validate:"omitempty,min=1" minimum:"1" description:"页码(默认1)"`
|
||||
PageSize int `query:"page_size" validate:"omitempty,min=1,max=100" minimum:"1" maximum:"100" description:"每页数量(默认20,最大100)"`
|
||||
Status *int `query:"status" validate:"omitempty,oneof=0 1 2 3" enum:"0,1,2,3" description:"资料版本状态 (0:待审批, 1:已通过有效, 2:已驳回, 3:已失效)"`
|
||||
}
|
||||
|
||||
// WithdrawalQualificationItem 提现资料资格版本项。
|
||||
// 证件号按脱敏值返回,附件仅返回对象存储 Key 引用。
|
||||
type WithdrawalQualificationItem struct {
|
||||
ID uint `json:"id" description:"资料版本ID"`
|
||||
ShopID uint `json:"shop_id" description:"所属店铺ID"`
|
||||
ShopName string `json:"shop_name" description:"所属店铺名称"`
|
||||
SubjectType string `json:"subject_type" description:"签约主体类型 (enterprise:企业, personal:个人)"`
|
||||
SubjectTypeName string `json:"subject_type_name" description:"签约主体类型名称(中文)"`
|
||||
SubjectCodeMasked string `json:"subject_code_masked" description:"脱敏后的签约主体代码"`
|
||||
LegalPersonIDCardMask string `json:"legal_person_id_card_masked" description:"脱敏后的法人身份证号"`
|
||||
ContractFileKey string `json:"contract_file_key" description:"合同附件对象存储 Key"`
|
||||
IDCardFrontFileKey string `json:"id_card_front_file_key" description:"法人身份证正面附件对象存储 Key"`
|
||||
IDCardBackFileKey string `json:"id_card_back_file_key" description:"法人身份证反面附件对象存储 Key"`
|
||||
BusinessLicenseFileKey string `json:"business_license_file_key,omitempty" description:"营业执照附件对象存储 Key"`
|
||||
ShopFrontFileKey string `json:"shop_front_file_key,omitempty" description:"门头照附件对象存储 Key"`
|
||||
InvoiceFileKey string `json:"invoice_file_key,omitempty" description:"发票附件对象存储 Key"`
|
||||
InvoiceTitle string `json:"invoice_title,omitempty" description:"发票抬头"`
|
||||
Status int `json:"status" description:"状态 (0:待审批, 1:已通过有效, 2:已驳回, 3:已失效)"`
|
||||
StatusName string `json:"status_name" description:"状态名称(中文)"`
|
||||
InvalidReason string `json:"invalid_reason,omitempty" description:"失效或作废原因"`
|
||||
InvalidatedAt string `json:"invalidated_at,omitempty" description:"失效时间"`
|
||||
ApprovalInstanceID uint `json:"approval_instance_id" description:"关联的通用审批实例ID,0 表示尚未关联"`
|
||||
ApprovalStatus int `json:"approval_status" description:"通用审批实例状态 (0:提交中, 1:审批中, 2:已通过, 3:已拒绝, 4:已撤销, 5:通过后撤销, 6:已删除, 7:提交失败, 8:提交结果未知)"`
|
||||
ApprovalStatusName string `json:"approval_status_name" description:"通用审批状态名称(中文)"`
|
||||
CreatedAt string `json:"created_at" description:"创建时间"`
|
||||
UpdatedAt string `json:"updated_at" description:"最近更新时间"`
|
||||
}
|
||||
|
||||
// WithdrawalQualificationPageResult 提现资料资格分页响应。
|
||||
type WithdrawalQualificationPageResult struct {
|
||||
Items []WithdrawalQualificationItem `json:"items" description:"资料版本列表(按版本从新到旧)"`
|
||||
Total int64 `json:"total" description:"总记录数"`
|
||||
Page int `json:"page" description:"当前页码"`
|
||||
Size int `json:"size" description:"每页数量"`
|
||||
}
|
||||
|
||||
// ResubmitWithdrawalReq 驳回后重提提现申请请求。
|
||||
type ResubmitWithdrawalReq struct {
|
||||
ShopID uint `json:"-" params:"shop_id" path:"shop_id" validate:"required" description:"店铺ID"`
|
||||
ID uint `json:"-" params:"id" path:"id" validate:"required" description:"提现申请ID"`
|
||||
Amount int64 `json:"amount" validate:"required,min=1" required:"true" minimum:"1" description:"提现金额(分)"`
|
||||
WithdrawalMethod string `json:"withdrawal_method" validate:"required,oneof=alipay" required:"true" enum:"alipay" description:"收款类型"`
|
||||
AccountName string `json:"account_name" validate:"required,max=50" required:"true" maximum:"50" description:"收款人姓名"`
|
||||
AccountNumber string `json:"account_number" validate:"required,max=100" required:"true" maximum:"100" description:"收款账号"`
|
||||
InvoiceKeys []string `json:"invoice_keys" description:"本次申请级发票对象存储 Key 列表;仅企业主体有效资格可提交"`
|
||||
}
|
||||
|
||||
// ShopWithdrawalRequestDetailReq 提现申请详情路径参数。
|
||||
type ShopWithdrawalRequestDetailReq struct {
|
||||
ShopID uint `json:"-" params:"shop_id" path:"shop_id" validate:"required" description:"店铺ID"`
|
||||
ID uint `json:"-" params:"id" path:"id" validate:"required" description:"提现申请ID"`
|
||||
}
|
||||
|
||||
// WithdrawalRequestAttemptItem 提现审批尝试记录项。
|
||||
type WithdrawalRequestAttemptItem struct {
|
||||
ID uint `json:"id" description:"审批尝试记录ID"`
|
||||
AttemptNo int `json:"attempt_no" description:"第几次提交,从 1 递增"`
|
||||
Amount int64 `json:"amount" description:"本次提现金额(分)"`
|
||||
Fee int64 `json:"fee" description:"本次手续费(分)"`
|
||||
FeeRate int64 `json:"fee_rate" description:"本次手续费率(基点,100=1%)"`
|
||||
ActualAmount int64 `json:"actual_amount" description:"本次实际到账金额(分)"`
|
||||
WithdrawalMethod string `json:"withdrawal_method" description:"本次收款方式"`
|
||||
SubmittedByID uint `json:"submitted_by_account_id" description:"本次提交账号ID"`
|
||||
ApprovalInstanceID uint `json:"approval_instance_id" description:"本次尝试关联的通用审批实例ID,0 表示尚未关联"`
|
||||
ApprovalStatus int `json:"approval_status" description:"通用审批实例状态 (0:提交中, 1:审批中, 2:已通过, 3:已拒绝, 4:已撤销, 5:通过后撤销, 6:已删除, 7:提交失败, 8:提交结果未知)"`
|
||||
ApprovalStatusName string `json:"approval_status_name" description:"通用审批状态名称(中文)"`
|
||||
ReleasedAt string `json:"released_at,omitempty" description:"本次冻结释放时间,空表示冻结仍未结算"`
|
||||
CreatedAt string `json:"created_at" description:"创建时间"`
|
||||
}
|
||||
|
||||
// ShopWithdrawalRequestDetailResp 提现申请详情响应。
|
||||
type ShopWithdrawalRequestDetailResp struct {
|
||||
ShopWithdrawalRequestItem
|
||||
LatestAttemptID uint `json:"latest_attempt_id" description:"最新审批尝试记录ID,0 表示尚未接入企业微信审批"`
|
||||
LatestApprovalInstanceID uint `json:"latest_approval_instance_id" description:"最新通用审批实例ID,0 表示尚未接入"`
|
||||
ApprovalInstanceID uint `json:"approval_instance_id" description:"首次接入企业微信审批的审批实例ID,0 表示存量申请仍走本地人工终审"`
|
||||
AnomalyFlag int `json:"anomaly_flag" description:"正交异常标记 (0:无异常, 1:通过后撤销)"`
|
||||
AnomalyName string `json:"anomaly_name" description:"异常名称(中文)"`
|
||||
AnomalyReason string `json:"anomaly_reason,omitempty" description:"异常原因,供人工处理"`
|
||||
Attempts []WithdrawalRequestAttemptItem `json:"attempts" description:"审批尝试记录,按提交次序倒序;历史尝试与审批结果不被覆盖"`
|
||||
}
|
||||
@@ -86,9 +86,12 @@ func (r *UpdateShopRequest) UnmarshalJSON(data []byte) error {
|
||||
|
||||
// ShopResponse 店铺响应
|
||||
type ShopResponse struct {
|
||||
ID uint `json:"id" description:"店铺ID"`
|
||||
ShopName string `json:"shop_name" description:"店铺名称"`
|
||||
ShopCode string `json:"shop_code" description:"店铺编号"`
|
||||
ID uint `json:"id" description:"店铺ID"`
|
||||
ShopName string `json:"shop_name" description:"店铺名称"`
|
||||
ShopCode string `json:"shop_code" description:"店铺编号"`
|
||||
// DistributionCode 是创建时生成的全局唯一随机分销码,创建后不可修改。
|
||||
// 该字段为只读;它是该店铺作为上级被扫码注册的唯一入口标识,二维码只编码该码。
|
||||
DistributionCode string `json:"distribution_code" description:"分销码(全局唯一、创建后不可修改的只读随机码;该店铺作为上级被扫码注册的唯一入口标识)"`
|
||||
ParentID *uint `json:"parent_id,omitempty" description:"上级店铺ID"`
|
||||
ParentShopName string `json:"parent_shop_name,omitempty" description:"上级店铺名称"`
|
||||
BusinessOwnerAccountID *uint `json:"business_owner_account_id" description:"平台业务员账号ID,null 表示未归属"`
|
||||
|
||||
@@ -23,7 +23,7 @@ type InspectWeComTemplateParams struct {
|
||||
|
||||
// WeComBusinessFieldListParams 查询企业微信审批场景可映射字段路径参数。
|
||||
type WeComBusinessFieldListParams struct {
|
||||
BusinessType string `path:"business_type" required:"true" enum:"refund_approval,offline_recharge_approval,employee_collection_approval" description:"业务类型 (refund_approval:退款审批, offline_recharge_approval:员工线下代充值审批, employee_collection_approval:员工代收款核销审批)"`
|
||||
BusinessType string `path:"business_type" required:"true" enum:"refund_approval,offline_recharge_approval,employee_collection_approval,agent_distribution_approval,withdrawal_qualification_approval,commission_withdrawal_approval" description:"业务类型 (refund_approval:退款审批, offline_recharge_approval:员工线下代充值审批, employee_collection_approval:员工代收款核销审批, agent_distribution_approval:代理扫码分销注册审批, withdrawal_qualification_approval:提现资料资格审批, commission_withdrawal_approval:佣金提现终审)"`
|
||||
}
|
||||
|
||||
// WeComBusinessFieldResponse 企业微信审批场景可映射业务字段响应。
|
||||
@@ -67,7 +67,7 @@ type SaveWeComApprovalSceneRequest struct {
|
||||
|
||||
// SaveWeComApprovalSceneParams 保存企业微信审批场景路径与请求参数。
|
||||
type SaveWeComApprovalSceneParams struct {
|
||||
BusinessType string `path:"business_type" required:"true" enum:"refund_approval,offline_recharge_approval,employee_collection_approval" description:"业务类型 (refund_approval:退款审批, offline_recharge_approval:员工线下代充值审批, employee_collection_approval:员工代收款核销审批);可先调用 GET /api/admin/wecom/scenes/{business_type}/fields 查询允许映射的业务字段"`
|
||||
BusinessType string `path:"business_type" required:"true" enum:"refund_approval,offline_recharge_approval,employee_collection_approval,agent_distribution_approval,withdrawal_qualification_approval,commission_withdrawal_approval" description:"业务类型 (refund_approval:退款审批, offline_recharge_approval:员工线下代充值审批, employee_collection_approval:员工代收款核销审批, agent_distribution_approval:代理扫码分销注册审批, withdrawal_qualification_approval:提现资料资格审批, commission_withdrawal_approval:佣金提现终审);可先调用 GET /api/admin/wecom/scenes/{business_type}/fields 查询允许映射的业务字段"`
|
||||
SaveWeComApprovalSceneRequest
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,13 @@ type CommissionWithdrawalRequest struct {
|
||||
PaidAt *time.Time `gorm:"column:paid_at;comment:到账时间" json:"paid_at"`
|
||||
RejectReason string `gorm:"column:reject_reason;type:text;comment:拒绝原因" json:"reject_reason"`
|
||||
Remark string `gorm:"column:remark;type:text;comment:备注" json:"remark"`
|
||||
// LatestAttemptID 与 LatestApprovalInstanceID 仅用于列表投影,不是历史事实来源。
|
||||
LatestAttemptID uint `gorm:"column:latest_attempt_id;type:bigint;not null;default:0;comment:最新审批尝试记录ID" json:"latest_attempt_id"`
|
||||
LatestApprovalInstanceID uint `gorm:"column:latest_approval_instance_id;type:bigint;not null;default:0;comment:最新通用审批实例ID" json:"latest_approval_instance_id"`
|
||||
// ApprovalInstanceID 为空表示从未关联审批实例的存量申请,仍走既有本地人工终审。
|
||||
ApprovalInstanceID *uint `gorm:"column:approval_instance_id;type:bigint;comment:首次接入企业微信审批的审批实例ID" json:"approval_instance_id,omitempty"`
|
||||
AnomalyFlag int `gorm:"column:anomaly_flag;type:smallint;not null;default:0;comment:正交异常标记 0-无异常 1-通过后撤销" json:"anomaly_flag"`
|
||||
AnomalyReason string `gorm:"column:anomaly_reason;type:varchar(500);not null;default:'';comment:异常原因" json:"anomaly_reason"`
|
||||
}
|
||||
|
||||
// TableName 指定表名
|
||||
@@ -36,6 +43,30 @@ func (CommissionWithdrawalRequest) TableName() string {
|
||||
return "tb_commission_withdrawal_request"
|
||||
}
|
||||
|
||||
// CommissionWithdrawalRequestAttempt 是提现申请每次提交或重提对应的不可变审批材料与冻结事实。
|
||||
// 冻结与释放金额一律取本记录事实;released_at 是回溯可重放的幂等依据。
|
||||
type CommissionWithdrawalRequestAttempt struct {
|
||||
ID uint `gorm:"column:id;primaryKey;autoIncrement" json:"id"`
|
||||
RequestID uint `gorm:"column:request_id;type:bigint;not null;comment:所属提现申请ID" json:"request_id"`
|
||||
AttemptNo int `gorm:"column:attempt_no;type:int;not null;comment:第几次提交,从 1 递增" json:"attempt_no"`
|
||||
Amount int64 `gorm:"column:amount;type:bigint;not null;comment:本次冻结提现金额(分)" json:"amount"`
|
||||
Fee int64 `gorm:"column:fee;type:bigint;not null;default:0;comment:本次手续费(分)" json:"fee"`
|
||||
FeeRate int64 `gorm:"column:fee_rate;type:bigint;not null;default:0;comment:本次手续费率(基点)" json:"fee_rate"`
|
||||
ActualAmount int64 `gorm:"column:actual_amount;type:bigint;not null;default:0;comment:本次实际到账金额(分)" json:"actual_amount"`
|
||||
WithdrawalMethod string `gorm:"column:withdrawal_method;type:varchar(20);not null;comment:本次收款方式快照" json:"withdrawal_method"`
|
||||
AccountInfo datatypes.JSON `gorm:"column:account_info;type:jsonb;not null;comment:本次收款账户信息快照" json:"account_info"`
|
||||
InvoiceKeys datatypes.JSON `gorm:"column:invoice_keys;type:jsonb;not null;default:'[]';comment:本次申请级发票对象存储Key列表" json:"invoice_keys"`
|
||||
SubmittedByAccountID uint `gorm:"column:submitted_by_account_id;type:bigint;not null;comment:本次实际提交账号ID" json:"submitted_by_account_id"`
|
||||
ApprovalInstanceID *uint `gorm:"column:approval_instance_id;type:bigint;comment:本次尝试关联的通用审批实例ID" json:"approval_instance_id,omitempty"`
|
||||
ReleasedAt *time.Time `gorm:"column:released_at;comment:本次冻结释放时间,空表示未结算" json:"released_at,omitempty"`
|
||||
CreatedAt time.Time `gorm:"column:created_at;type:timestamptz;not null;autoCreateTime" json:"created_at"`
|
||||
}
|
||||
|
||||
// TableName 指定提现审批尝试记录表名。
|
||||
func (CommissionWithdrawalRequestAttempt) TableName() string {
|
||||
return "tb_commission_withdrawal_request_attempt"
|
||||
}
|
||||
|
||||
// CommissionWithdrawalSetting 佣金提现设置模型
|
||||
// 提现参数配置(最低金额、手续费率、到账时间等)
|
||||
type CommissionWithdrawalSetting struct {
|
||||
|
||||
@@ -7,9 +7,11 @@ import (
|
||||
// Shop 店铺模型
|
||||
type Shop struct {
|
||||
gorm.Model
|
||||
BaseModel `gorm:"embedded"`
|
||||
ShopName string `gorm:"column:shop_name;type:varchar(100);not null;comment:店铺名称" json:"shop_name"`
|
||||
ShopCode string `gorm:"column:shop_code;type:varchar(50);uniqueIndex:idx_shop_code,where:deleted_at IS NULL;comment:店铺编号" json:"shop_code"`
|
||||
BaseModel `gorm:"embedded"`
|
||||
ShopName string `gorm:"column:shop_name;type:varchar(100);not null;comment:店铺名称" json:"shop_name"`
|
||||
ShopCode string `gorm:"column:shop_code;type:varchar(50);uniqueIndex:idx_shop_code,where:deleted_at IS NULL;comment:店铺编号" json:"shop_code"`
|
||||
// DistributionCode 是创建时生成的全局唯一随机分销码,创建后不可修改;不提供人工指定或编辑入口。
|
||||
DistributionCode string `gorm:"column:distribution_code;type:varchar(32);not null;default:'';comment:全局唯一随机分销码,创建时生成且不可修改" json:"distribution_code"`
|
||||
ParentID *uint `gorm:"column:parent_id;index;comment:上级店铺ID(NULL表示一级代理)" json:"parent_id,omitempty"`
|
||||
BusinessOwnerAccountID *uint `gorm:"column:business_owner_account_id;index:idx_shop_business_owner_account_id;comment:平台业务员账号ID" json:"business_owner_account_id,omitempty"`
|
||||
Level int `gorm:"column:level;type:int;not null;default:1;comment:层级(1-7)" json:"level"`
|
||||
|
||||
36
internal/model/withdrawal_qualification.go
Normal file
36
internal/model/withdrawal_qualification.go
Normal file
@@ -0,0 +1,36 @@
|
||||
package model
|
||||
|
||||
import "time"
|
||||
|
||||
// WithdrawalQualification 是代理提现资料资格的不可变版本。
|
||||
// 历史版本、附件引用与审批结果不被覆盖:替换合同或法人身份证即新增版本并使旧有效版本失效。
|
||||
type WithdrawalQualification struct {
|
||||
ID uint `gorm:"column:id;primaryKey;autoIncrement" json:"id"`
|
||||
ShopID uint `gorm:"column:shop_id;not null;comment:所属代理店铺ID" json:"shop_id"`
|
||||
SubjectType string `gorm:"column:subject_type;type:varchar(20);not null;comment:签约主体类型 enterprise/personal" json:"subject_type"`
|
||||
SubjectCode string `gorm:"column:subject_code;type:varchar(64);not null;comment:签约主体代码" json:"subject_code"`
|
||||
LegalPersonIDCard string `gorm:"column:legal_person_id_card;type:varchar(64);not null;comment:法人身份证号" json:"legal_person_id_card"`
|
||||
ContractFileKey string `gorm:"column:contract_file_key;type:varchar(255);not null;comment:合同附件对象存储Key" json:"contract_file_key"`
|
||||
IDCardFrontFileKey string `gorm:"column:id_card_front_file_key;type:varchar(255);not null;comment:法人身份证正面附件对象存储Key" json:"id_card_front_file_key"`
|
||||
IDCardBackFileKey string `gorm:"column:id_card_back_file_key;type:varchar(255);not null;comment:法人身份证反面附件对象存储Key" json:"id_card_back_file_key"`
|
||||
BusinessLicenseFileKey string `gorm:"column:business_license_file_key;type:varchar(255);not null;default:'';comment:营业执照附件对象存储Key" json:"business_license_file_key"`
|
||||
ShopFrontFileKey string `gorm:"column:shop_front_file_key;type:varchar(255);not null;default:'';comment:门头照附件对象存储Key" json:"shop_front_file_key"`
|
||||
InvoiceFileKey string `gorm:"column:invoice_file_key;type:varchar(255);not null;default:'';comment:发票附件对象存储Key" json:"invoice_file_key"`
|
||||
InvoiceTitle string `gorm:"column:invoice_title;type:varchar(200);not null;default:'';comment:发票抬头" json:"invoice_title"`
|
||||
InvoiceSubjectCode string `gorm:"column:invoice_subject_code;type:varchar(64);not null;default:'';comment:发票统一社会信用代码" json:"invoice_subject_code"`
|
||||
Status int `gorm:"column:status;type:smallint;not null;default:0;comment:状态 0-待审批 1-已通过有效 2-已驳回 3-已失效或已作废" json:"status"`
|
||||
InvalidReason string `gorm:"column:invalid_reason;type:varchar(500);not null;default:'';comment:失效原因" json:"invalid_reason"`
|
||||
InvalidatedAt *time.Time `gorm:"column:invalidated_at;type:timestamptz;comment:失效时间" json:"invalidated_at,omitempty"`
|
||||
InvalidatedBy uint `gorm:"column:invalidated_by;not null;default:0;comment:使资格失效的操作账号ID,0 表示店铺停用联动" json:"invalidated_by"`
|
||||
ApprovalInstanceID *uint `gorm:"column:approval_instance_id;comment:关联的通用审批实例ID" json:"approval_instance_id,omitempty"`
|
||||
DecidedAt *time.Time `gorm:"column:decided_at;type:timestamptz;comment:审批终态到达时间" json:"decided_at,omitempty"`
|
||||
Creator uint `gorm:"column:creator;not null;default:0;comment:创建人用户ID" json:"creator"`
|
||||
Updater uint `gorm:"column:updater;not null;default:0;comment:最近更新人用户ID" json:"updater"`
|
||||
CreatedAt time.Time `gorm:"column:created_at;type:timestamptz;not null;autoCreateTime" json:"created_at"`
|
||||
UpdatedAt time.Time `gorm:"column:updated_at;type:timestamptz;not null;autoUpdateTime" json:"updated_at"`
|
||||
}
|
||||
|
||||
// TableName 指定提现资料资格版本表名。
|
||||
func (WithdrawalQualification) TableName() string {
|
||||
return "tb_withdrawal_qualification"
|
||||
}
|
||||
Reference in New Issue
Block a user