From ad946af5ee5025556afa1804ab2e1029ce5e1c01 Mon Sep 17 00:00:00 2001 From: huang Date: Mon, 15 Dec 2025 11:32:33 +0800 Subject: [PATCH] =?UTF-8?q?add:=20=E6=8F=90=E4=BA=A4=E9=83=A8=E5=88=86?= =?UTF-8?q?=E8=A1=A8=E8=AE=BE=E8=AE=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit update: 1.所有model嵌入gorm公用model 2.所有model嵌入BaseModel --- docs/优化说明/分佣表结构设计.md | 582 ++++++++++++++++++++++ docs/表设计/整合.md | 464 +++++++++++++++++ internal/handler/account.go | 3 +- internal/model/account.go | 24 +- internal/model/base.go | 20 +- internal/model/permission.go | 25 +- internal/model/role.go | 19 +- internal/model/role_permission.go | 17 +- internal/service/account/service.go | 2 - internal/service/permission/service.go | 2 - internal/service/role/service.go | 10 +- tests/integration/account_role_test.go | 28 -- tests/integration/account_test.go | 24 - tests/integration/api_regression_test.go | 8 - tests/integration/permission_test.go | 18 - tests/integration/role_permission_test.go | 44 +- tests/integration/role_test.go | 36 +- tests/unit/account_model_test.go | 24 - tests/unit/soft_delete_test.go | 34 +- tests/unit/subordinate_cache_test.go | 18 - tests/unit/subordinate_query_test.go | 28 -- 21 files changed, 1109 insertions(+), 321 deletions(-) create mode 100644 docs/优化说明/分佣表结构设计.md create mode 100644 docs/表设计/整合.md diff --git a/docs/优化说明/分佣表结构设计.md b/docs/优化说明/分佣表结构设计.md new file mode 100644 index 0000000..b0185b3 --- /dev/null +++ b/docs/优化说明/分佣表结构设计.md @@ -0,0 +1,582 @@ +# 分佣系统表结构设计 + +> **版本**: v1.0 +> **最后更新**: 2025-11-28 +> **依据文档**: +> - `docs/优化说明/分佣正确逻辑.md` +> - `docs/优化说明/分佣正确逻辑补充.md` + +## 设计原则 + +1. **无外键约束**: 表之间不建立数据库外键,关联通过 ID 字段手动维护 +2. **软删除**: 所有表支持软删除,使用 `deleted_at` 字段 +3. **审计字段**: 所有表包含 `created_at`、`updated_at` 时间戳 +4. **操作留痕**: 关键操作记录操作人 ID +5. **数据完整性**: 关键业务数据通过代码层面保证一致性 + +--- + +## 1. 返佣梯度模板表 + +**用途**: 预设的返佣梯度模板,提供初始配置值,可被多个代理引用 + +| 字段名 | 类型 | 约束 | 说明 | +|--------|------|------|------| +| id | BIGSERIAL | PRIMARY KEY | 主键 | +| template_name | VARCHAR(100) | NOT NULL | 模板名称 | +| template_code | VARCHAR(50) | NOT NULL UNIQUE | 模板编码(唯一标识) | +| description | TEXT | NULL | 模板说明 | +| card_type | VARCHAR(20) | NOT NULL | 卡类型: `phone_card`(号卡) / `iot_card`(物联网卡) | +| judgment_type | VARCHAR(20) | NOT NULL | 判断类型: `sales_quantity`(套餐销售数量) / `sales_amount`(套餐销售金额) | +| rebate_timing | VARCHAR(20) | NOT NULL | 返佣时效: `immediate`(即可返佣) / `delayed`(延迟返佣) | +| rebate_condition_type | VARCHAR(20) | NOT NULL | 返佣条件类型: `accumulated_recharge`(累计充值) / `single_recharge`(一次充值) | +| rebate_condition_amount | BIGINT | NOT NULL | 返佣条件目标值(分为单位) | +| require_sanwu_check | BOOLEAN | NOT NULL DEFAULT false | 是否三无校验(仅号卡需要,物联网卡不需要) | +| is_long_term | BOOLEAN | NOT NULL DEFAULT false | 是否长期返佣 | +| termination_type | VARCHAR(20) | NULL | 长期终止方式: `month_count`(指定月数) / `end_date`(指定日期) | +| termination_value | VARCHAR(50) | NULL | 终止值: 月数(如"36")或日期(如"2026-11-20") | +| is_active | BOOLEAN | NOT NULL DEFAULT true | 是否启用 | +| created_by | BIGINT | NOT NULL | 创建人 ID | +| created_at | TIMESTAMP | NOT NULL DEFAULT CURRENT_TIMESTAMP | 创建时间 | +| updated_at | TIMESTAMP | NOT NULL DEFAULT CURRENT_TIMESTAMP | 更新时间 | +| deleted_at | TIMESTAMP | NULL | 软删除时间 | + +--- + +## 2. 返佣梯度条目表 + +**用途**: 模板中的具体梯度条目,定义每个梯度的判断目标和返佣规则 + +| 字段名 | 类型 | 约束 | 说明 | +|--------|------|------|------| +| id | BIGSERIAL | PRIMARY KEY | 主键 | +| template_id | BIGINT | NOT NULL | 关联模板 ID | +| tier_level | INT | NOT NULL | 梯度等级(从1开始递增) | +| judgment_target | BIGINT | NOT NULL | 判断目标值(数量或金额,金额以分为单位) | +| rebate_type | VARCHAR(20) | NOT NULL | 返佣属性: `percentage`(比例金额) / `fixed`(固定金额) | +| rebate_value | BIGINT | NOT NULL | 返佣假定值(比例用万分比,如1000=10%;固定金额用分) | +| max_cap_amount | BIGINT | NULL | 封顶金额(分为单位,NULL表示无封顶) | +| created_at | TIMESTAMP | NOT NULL DEFAULT CURRENT_TIMESTAMP | 创建时间 | +| updated_at | TIMESTAMP | NOT NULL DEFAULT CURRENT_TIMESTAMP | 更新时间 | +| deleted_at | TIMESTAMP | NULL | 软删除时间 | + +**说明**: +- `rebate_value`: 比例类型存储万分比(10000=100%, 1000=10%),固定金额存储分 +- `judgment_target`: 销售数量存储个数,销售金额存储分 + +--- + +## 3. 代理商-套餐-返佣规则快照表 + +**用途**: 代理商分销套餐时生成的返佣规则快照,独立于模板,允许个性化调整 + +| 字段名 | 类型 | 约束 | 说明 | +|--------|------|------|------| +| id | BIGSERIAL | PRIMARY KEY | 主键 | +| agent_id | BIGINT | NOT NULL | 代理商 ID | +| package_id | BIGINT | NOT NULL | 套餐 ID | +| template_id | BIGINT | NULL | 原始模板 ID(可为空,表示自定义规则) | +| rule_name | VARCHAR(100) | NOT NULL | 规则名称 | +| card_type | VARCHAR(20) | NOT NULL | 卡类型: `phone_card` / `iot_card` | +| judgment_type | VARCHAR(20) | NOT NULL | 判断类型 | +| rebate_timing | VARCHAR(20) | NOT NULL | 返佣时效 | +| rebate_condition_type | VARCHAR(20) | NOT NULL | 返佣条件类型 | +| rebate_condition_amount | BIGINT | NOT NULL | 返佣条件目标值(分) | +| require_sanwu_check | BOOLEAN | NOT NULL DEFAULT false | 是否三无校验 | +| is_long_term | BOOLEAN | NOT NULL DEFAULT false | 是否长期返佣 | +| termination_type | VARCHAR(20) | NULL | 长期终止方式 | +| termination_value | VARCHAR(50) | NULL | 终止值 | +| is_active | BOOLEAN | NOT NULL DEFAULT true | 是否启用 | +| created_by | BIGINT | NOT NULL | 创建人 ID | +| created_at | TIMESTAMP | NOT NULL DEFAULT CURRENT_TIMESTAMP | 创建时间 | +| updated_at | TIMESTAMP | NOT NULL DEFAULT CURRENT_TIMESTAMP | 更新时间 | +| deleted_at | TIMESTAMP | NULL | 软删除时间 | + +--- + +## 4. 代理商返佣规则梯度条目表 + +**用途**: 代理商快照规则中的具体梯度条目(从模板复制或自定义) + +| 字段名 | 类型 | 约束 | 说明 | +|--------|------|------|------| +| id | BIGSERIAL | PRIMARY KEY | 主键 | +| rule_id | BIGINT | NOT NULL | 关联规则 ID | +| tier_level | INT | NOT NULL | 梯度等级 | +| judgment_target | BIGINT | NOT NULL | 判断目标值 | +| rebate_type | VARCHAR(20) | NOT NULL | 返佣属性 | +| rebate_value | BIGINT | NOT NULL | 返佣假定值 | +| max_cap_amount | BIGINT | NULL | 封顶金额 | +| created_at | TIMESTAMP | NOT NULL DEFAULT CURRENT_TIMESTAMP | 创建时间 | +| updated_at | TIMESTAMP | NOT NULL DEFAULT CURRENT_TIMESTAMP | 更新时间 | +| deleted_at | TIMESTAMP | NULL | 软删除时间 | + +--- + +## 5. 佣金记录表 + +**用途**: 记录每一笔佣金的生成、状态变化、金额计算等核心信息 + +| 字段名 | 类型 | 约束 | 说明 | +|--------|------|------|------| +| id | BIGSERIAL | PRIMARY KEY | 主键 | +| record_no | VARCHAR(50) | NOT NULL UNIQUE | 佣金记录号(业务唯一标识) | +| agent_id | BIGINT | NOT NULL | 代理商 ID | +| package_id | BIGINT | NOT NULL | 套餐 ID | +| rule_id | BIGINT | NOT NULL | 返佣规则 ID | +| tier_item_id | BIGINT | NOT NULL | 梯度条目 ID | +| related_identifier | VARCHAR(50) | NOT NULL | 关联标识符(ICCID 或号码) | +| identifier_type | VARCHAR(20) | NOT NULL | 标识符类型: `iccid` / `phone_number` | +| card_type | VARCHAR(20) | NOT NULL | 卡类型: `phone_card` / `iot_card` | +| billing_month | VARCHAR(7) | NOT NULL | 计费月份(格式: YYYY-MM) | +| judgment_type | VARCHAR(20) | NOT NULL | 判断类型 | +| judgment_value | BIGINT | NOT NULL | 判断实际值(数量或金额) | +| rebate_timing | VARCHAR(20) | NOT NULL | 返佣时效 | +| rebate_type | VARCHAR(20) | NOT NULL | 返佣属性 | +| rebate_base_amount | BIGINT | NOT NULL | 返佣基数(成本价,分) | +| rebate_rate | BIGINT | NULL | 返佣比例(万分比,仅比例类型) | +| commission_amount | BIGINT | NOT NULL | 佣金金额(分) | +| status | VARCHAR(20) | NOT NULL | 状态: `frozen`(已冻结) / `normal`(正常) / `invalid`(无效) / `withdraw_pending`(提取申请中) / `withdraw_rejected`(提取驳回) / `withdrawn`(已提取) / `clawback`(已回溯) | +| freeze_reason | TEXT | NULL | 冻结原因 | +| invalid_reason | TEXT | NULL | 无效原因 | +| clawback_reason | TEXT | NULL | 回溯原因 | +| clawback_amount | BIGINT | NOT NULL DEFAULT 0 | 回溯金额(分,负数表示扣减) | +| is_long_term | BOOLEAN | NOT NULL DEFAULT false | 是否长期返佣 | +| long_term_month_index | INT | NULL | 长期返佣月份索引(第几个月) | +| frozen_at | TIMESTAMP | NULL | 冻结时间 | +| unfrozen_at | TIMESTAMP | NULL | 解冻时间 | +| unfrozen_by | BIGINT | NULL | 解冻操作人 ID | +| invalidated_at | TIMESTAMP | NULL | 标记无效时间 | +| invalidated_by | BIGINT | NULL | 标记无效操作人 ID | +| clawback_at | TIMESTAMP | NULL | 回溯时间 | +| clawback_by | BIGINT | NULL | 回溯操作人 ID | +| created_at | TIMESTAMP | NOT NULL DEFAULT CURRENT_TIMESTAMP | 创建时间 | +| updated_at | TIMESTAMP | NOT NULL DEFAULT CURRENT_TIMESTAMP | 更新时间 | +| deleted_at | TIMESTAMP | NULL | 软删除时间 | + +**状态流转说明**: +- `frozen` → `normal`: 解冻 +- `frozen` → `invalid`: 巡检发现不满足条件 +- `normal` → `withdraw_pending`: 提交提现申请 +- `withdraw_pending` → `withdrawn`: 审批通过 +- `withdraw_pending` → `withdraw_rejected`: 审批驳回 +- `withdraw_rejected` → `normal`: 问题解决后恢复 +- `withdrawn` → `clawback`: 客户退款导致回溯 + +--- + +## 6. 佣金解冻凭证表 + +**用途**: 记录运营提交的解冻凭证,支持批量解冻操作 + +| 字段名 | 类型 | 约束 | 说明 | +|--------|------|------|------| +| id | BIGSERIAL | PRIMARY KEY | 主键 | +| voucher_no | VARCHAR(50) | NOT NULL UNIQUE | 凭证批次号 | +| voucher_source | VARCHAR(50) | NOT NULL | 凭证来源: `carrier_official`(运营商官方) / `upstream_channel`(上游渠道) / `other`(其他) | +| voucher_file_url | TEXT | NULL | 凭证文件 URL | +| billing_month | VARCHAR(7) | NOT NULL | 结算月份 | +| total_count | INT | NOT NULL DEFAULT 0 | 凭证包含总数 | +| unfrozen_count | INT | NOT NULL DEFAULT 0 | 成功解冻数量 | +| failed_count | INT | NOT NULL DEFAULT 0 | 解冻失败数量 | +| unfreeze_password | VARCHAR(100) | NULL | 解冻密码(加密存储) | +| status | VARCHAR(20) | NOT NULL | 状态: `pending`(待处理) / `processing`(处理中) / `completed`(已完成) / `failed`(失败) | +| process_started_at | TIMESTAMP | NULL | 处理开始时间 | +| process_completed_at | TIMESTAMP | NULL | 处理完成时间 | +| created_by | BIGINT | NOT NULL | 创建人 ID | +| created_at | TIMESTAMP | NOT NULL DEFAULT CURRENT_TIMESTAMP | 创建时间 | +| updated_at | TIMESTAMP | NOT NULL DEFAULT CURRENT_TIMESTAMP | 更新时间 | +| deleted_at | TIMESTAMP | NULL | 软删除时间 | + +--- + +## 7. 佣金解冻凭证明细表 + +**用途**: 解冻凭证中的每条 ICCID/号码记录 + +| 字段名 | 类型 | 约束 | 说明 | +|--------|------|------|------| +| id | BIGSERIAL | PRIMARY KEY | 主键 | +| voucher_id | BIGINT | NOT NULL | 关联凭证 ID | +| identifier | VARCHAR(50) | NOT NULL | ICCID 或号码 | +| identifier_type | VARCHAR(20) | NOT NULL | 标识符类型: `iccid` / `phone_number` | +| commission_record_id | BIGINT | NULL | 关联佣金记录 ID(匹配后填充) | +| sanwu_check_passed | BOOLEAN | NULL | 三无校验是否通过 | +| traffic_usage | BIGINT | NULL | 流量用量(字节) | +| voice_usage | BIGINT | NULL | 语音用量(秒) | +| sms_usage | INT | NULL | 短信用量(条) | +| unfreeze_result | VARCHAR(20) | NOT NULL | 解冻结果: `success`(成功) / `failed`(失败) / `not_found`(未找到) | +| fail_reason | TEXT | NULL | 失败原因 | +| unfrozen_at | TIMESTAMP | NULL | 解冻时间 | +| created_at | TIMESTAMP | NOT NULL DEFAULT CURRENT_TIMESTAMP | 创建时间 | +| updated_at | TIMESTAMP | NOT NULL DEFAULT CURRENT_TIMESTAMP | 更新时间 | + + +--- + +## 8. 提现申请表 + +**用途**: 代理商的提现申请记录 + +| 字段名 | 类型 | 约束 | 说明 | +|--------|------|------|------| +| id | BIGSERIAL | PRIMARY KEY | 主键 | +| request_no | VARCHAR(50) | NOT NULL UNIQUE | 提现申请单号 | +| agent_id | BIGINT | NOT NULL | 代理商 ID | +| withdrawal_amount | BIGINT | NOT NULL | 提现金额(分) | +| available_balance | BIGINT | NOT NULL | 申请时可用余额(分) | +| bank_account_name | VARCHAR(100) | NOT NULL | 收款账户名 | +| bank_account_number | VARCHAR(50) | NOT NULL | 收款账号 | +| bank_name | VARCHAR(100) | NOT NULL | 开户行 | +| status | VARCHAR(20) | NOT NULL | 状态: `pending`(待审批) / `approved`(已批准) / `rejected`(已驳回) / `paid`(已放款) / `failed`(放款失败) | +| reject_reason | TEXT | NULL | 驳回原因 | +| paid_amount | BIGINT | NULL | 实际放款金额(分) | +| paid_at | TIMESTAMP | NULL | 放款时间 | +| paid_by | BIGINT | NULL | 放款操作人 ID | +| payment_voucher_url | TEXT | NULL | 放款凭证 URL | +| transaction_no | VARCHAR(100) | NULL | 支付流水号 | +| created_at | TIMESTAMP | NOT NULL DEFAULT CURRENT_TIMESTAMP | 创建时间 | +| updated_at | TIMESTAMP | NOT NULL DEFAULT CURRENT_TIMESTAMP | 更新时间 | +| deleted_at | TIMESTAMP | NULL | 软删除时间 | + +--- + +## 9. 提现审批记录表 + +**用途**: 提现申请的审批流程记录,支持多级审批和操作留痕 + +| 字段名 | 类型 | 约束 | 说明 | +|--------|------|------|------| +| id | BIGSERIAL | PRIMARY KEY | 主键 | +| request_id | BIGINT | NOT NULL | 关联提现申请 ID | +| approval_level | INT | NOT NULL | 审批级别(1,2,3...) | +| approver_id | BIGINT | NOT NULL | 审批人 ID | +| approver_name | VARCHAR(100) | NOT NULL | 审批人姓名 | +| action | VARCHAR(20) | NOT NULL | 操作: `approve`(批准) / `reject`(驳回) / `pay`(放款) | +| comment | TEXT | NULL | 审批意见 | +| approved_at | TIMESTAMP | NOT NULL DEFAULT CURRENT_TIMESTAMP | 审批时间 | +| created_at | TIMESTAMP | NOT NULL DEFAULT CURRENT_TIMESTAMP | 创建时间 | + + +**说明**: +- 每次审批操作(批准/驳回/放款)都会插入一条记录 +- `approval_level` 用于区分多级审批流程 +- `action='pay'` 的记录代表最终放款操作 + +--- + +## 10. 提现-佣金关联表 + +**用途**: 关联提现申请和具体的佣金记录,支持一次提现包含多笔佣金 + +| 字段名 | 类型 | 约束 | 说明 | +|--------|------|------|------| +| id | BIGSERIAL | PRIMARY KEY | 主键 | +| request_id | BIGINT | NOT NULL | 关联提现申请 ID | +| commission_record_id | BIGINT | NOT NULL | 关联佣金记录 ID | +| commission_amount | BIGINT | NOT NULL | 佣金金额(分) | +| created_at | TIMESTAMP | NOT NULL DEFAULT CURRENT_TIMESTAMP | 创建时间 | + +--- + +## 11. 代理商佣金账户表 + +**用途**: 代理商的佣金账户余额和统计信息(实时显示分佣金额) + +| 字段名 | 类型 | 约束 | 说明 | +|--------|------|------|------| +| id | BIGSERIAL | PRIMARY KEY | 主键 | +| agent_id | BIGINT | NOT NULL UNIQUE | 代理商 ID | +| total_earned | BIGINT | NOT NULL DEFAULT 0 | 累计获得佣金(分) | +| frozen_amount | BIGINT | NOT NULL DEFAULT 0 | 冻结中金额(分) | +| available_amount | BIGINT | NOT NULL DEFAULT 0 | 可提现金额(分) | +| withdrawn_amount | BIGINT | NOT NULL DEFAULT 0 | 已提现金额(分) | +| invalid_amount | BIGINT | NOT NULL DEFAULT 0 | 无效佣金金额(分) | +| clawback_amount | BIGINT | NOT NULL DEFAULT 0 | 已回溯金额(分) | +| pending_withdrawal_amount | BIGINT | NOT NULL DEFAULT 0 | 提现申请中金额(分) | +| last_withdrawal_at | TIMESTAMP | NULL | 最后提现时间 | +| created_at | TIMESTAMP | NOT NULL DEFAULT CURRENT_TIMESTAMP | 创建时间 | +| updated_at | TIMESTAMP | NOT NULL DEFAULT CURRENT_TIMESTAMP | 更新时间 | + +**字段计算规则**: +- `available_amount` = 状态为 `normal` 的佣金总和 +- `frozen_amount` = 状态为 `frozen` 的佣金总和 +- `pending_withdrawal_amount` = 状态为 `withdraw_pending` 的佣金总和 +- `withdrawn_amount` = 状态为 `withdrawn` 的佣金总和 +- `invalid_amount` = 状态为 `invalid` 的佣金总和 +- `clawback_amount` = 所有 `clawback_amount` 字段的累加(负数) + +--- + +## 补充说明 + +### 1. 需要在现有表中新增的字段 + +#### sims (卡表) +```sql +-- 如果卡表需要支持分佣,可能需要添加: +ALTER TABLE sims ADD COLUMN related_agent_id BIGINT; -- 关联的销售代理商 +ALTER TABLE sims ADD COLUMN related_package_id BIGINT; -- 关联的销售套餐 +ALTER TABLE sims ADD COLUMN sale_channel VARCHAR(50); -- 销售渠道 +``` + +#### packages (套餐表) +```sql +-- 如果套餐表需要标记是否参与分佣: +ALTER TABLE packages ADD COLUMN enable_commission BOOLEAN DEFAULT false; -- 是否启用分佣 +ALTER TABLE packages ADD COLUMN cost_price BIGINT; -- 成本价(分为单位) +``` + +### 2. 关键业务规则 + +#### 佣金生成规则 +1. 每日巡检检查 ICCID 的卡状态、充值金额、三无校验(仅号卡) +2. 根据代理商的返佣规则快照判断是否命中梯度 +3. 根据返佣时效决定生成 `frozen` 或 `normal` 状态的佣金 +4. 长期返佣每月重复生成,直到达到终止条件 + +#### 解冻流程 +1. 运营导入 ICCID/号码列表和凭证文件 +2. 输入解冻密码(可扩展为双人校验) +3. 系统匹配佣金记录,校验三无条件(仅号卡) +4. 批量更新状态: `frozen` → `normal` 或 `invalid` + +#### 提现流程 +1. 代理商发起提现申请,选择可提现佣金 +2. 佣金状态批量更新: `normal` → `withdraw_pending` +3. 多级审批(可配置) +4. 审批通过后,操作人执行放款,记录凭证 +5. 佣金状态更新: `withdraw_pending` → `withdrawn` + +#### 回溯机制 +1. 客户退款导致佣金需要扣回 +2. 检查代理账户可用余额: + - 余额充足: 直接扣减,生成负数佣金记录 + - 余额不足: 支持负数余额,下次佣金自动抵扣 +3. 更新对应佣金记录状态为 `clawback` + +### 3. 数据导出需求 + +#### 无效佣金导出 +```sql +SELECT + cr.record_no, + cr.agent_id, + cr.related_identifier, + cr.commission_amount, + cr.invalid_reason, + cr.invalidated_at, + cr.invalidated_by +FROM commission_records cr +WHERE cr.status = 'invalid' + AND cr.deleted_at IS NULL +ORDER BY cr.invalidated_at DESC; +``` + +#### 驳回清单导出 +```sql +SELECT + wr.request_no, + wr.agent_id, + wr.withdrawal_amount, + wr.reject_reason, + wa.approver_name, + wa.approved_at +FROM commission_withdrawal_requests wr +JOIN commission_withdrawal_approvals wa ON wr.id = wa.request_id +WHERE wr.status = 'rejected' + AND wa.action = 'reject' + AND wr.deleted_at IS NULL +ORDER BY wa.approved_at DESC; +``` + +#### 代理佣金梯度导出 +```sql +SELECT + apcr.agent_id, + apcr.package_id, + apcr.rule_name, + acti.tier_level, + acti.judgment_target, + acti.rebate_type, + acti.rebate_value +FROM agent_package_commission_rules apcr +JOIN agent_commission_tier_items acti ON apcr.id = acti.rule_id +WHERE apcr.agent_id = :agent_id + AND apcr.deleted_at IS NULL + AND acti.deleted_at IS NULL +ORDER BY apcr.package_id, acti.tier_level; +``` + +### 4. 常量定义建议 + +在 `pkg/constants/constants.go` 中建议定义: + +```go +// 卡类型 +const ( + CardTypePhone = "phone_card" // 号卡 + CardTypeIoT = "iot_card" // 物联网卡 +) + +// 判断类型 +const ( + JudgmentTypeSalesQuantity = "sales_quantity" // 套餐销售数量 + JudgmentTypeSalesAmount = "sales_amount" // 套餐销售金额 +) + +// 返佣时效 +const ( + RebateTimingImmediate = "immediate" // 即可返佣 + RebateTimingDelayed = "delayed" // 延迟返佣 +) + +// 返佣条件类型 +const ( + RebateConditionAccumulated = "accumulated_recharge" // 累计充值 + RebateConditionSingle = "single_recharge" // 一次充值 +) + +// 返佣属性 +const ( + RebateTypePercentage = "percentage" // 比例金额 + RebateTypeFixed = "fixed" // 固定金额 +) + +// 长期终止方式 +const ( + TerminationTypeMonthCount = "month_count" // 指定月数 + TerminationTypeEndDate = "end_date" // 指定日期 +) + +// 佣金状态 +const ( + CommissionStatusFrozen = "frozen" // 已冻结 + CommissionStatusNormal = "normal" // 正常 + CommissionStatusInvalid = "invalid" // 无效 + CommissionStatusWithdrawPending = "withdraw_pending" // 提取申请中 + CommissionStatusWithdrawRejected = "withdraw_rejected" // 提取驳回 + CommissionStatusWithdrawn = "withdrawn" // 已提取 + CommissionStatusClawback = "clawback" // 已回溯 +) + +// 标识符类型 +const ( + IdentifierTypeICCID = "iccid" // ICCID + IdentifierTypePhoneNumber = "phone_number" // 号码 +) + +// 凭证来源 +const ( + VoucherSourceCarrierOfficial = "carrier_official" // 运营商官方 + VoucherSourceUpstreamChannel = "upstream_channel" // 上游渠道 + VoucherSourceOther = "other" // 其他 +) + +// 解冻结果 +const ( + UnfreezeResultSuccess = "success" // 成功 + UnfreezeResultFailed = "failed" // 失败 + UnfreezeResultNotFound = "not_found" // 未找到 +) + +// 提现申请状态 +const ( + WithdrawalStatusPending = "pending" // 待审批 + WithdrawalStatusApproved = "approved" // 已批准 + WithdrawalStatusRejected = "rejected" // 已驳回 + WithdrawalStatusPaid = "paid" // 已放款 + WithdrawalStatusFailed = "failed" // 放款失败 +) + +// 审批操作 +const ( + ApprovalActionApprove = "approve" // 批准 + ApprovalActionReject = "reject" // 驳回 + ApprovalActionPay = "pay" // 放款 +) +``` + +--- + +## ER 关系图 + +``` +┌─────────────────────────────────┐ +│ commission_tier_templates │ 返佣梯度模板 +│ - id (PK) │ +│ - template_code (UK) │ +└─────────────────┬───────────────┘ + │ 1 + │ + │ N +┌─────────────────┴───────────────┐ +│ commission_tier_items │ 梯度条目 +│ - id (PK) │ +│ - template_id (FK) │ +└─────────────────────────────────┘ + +┌─────────────────────────────────┐ +│ agent_package_commission_rules │ 代理返佣规则快照 +│ - id (PK) │ +│ - agent_id │ +│ - package_id │ +└─────────────────┬───────────────┘ + │ 1 + │ + │ N +┌─────────────────┴───────────────┐ +│ agent_commission_tier_items │ 代理梯度条目 +│ - id (PK) │ +│ - rule_id (FK) │ +└─────────────────┬───────────────┘ + │ + │ + │ 被引用 +┌─────────────────┴───────────────┐ +│ commission_records │ 佣金记录 +│ - id (PK) │ +│ - rule_id │ +│ - tier_item_id │ +│ - related_identifier │ +└───┬─────────────────────────┬───┘ + │ │ + │ N │ N + │ │ +┌───┴─────────────────────┐ ┌┴─────────────────────────────┐ +│ commission_unfreeze │ │ commission_withdrawal_records│ +│ _voucher_items │ │ - request_id │ +│ - voucher_id │ │ - commission_record_id │ +│ - commission_record_id │ └┬─────────────────────────────┘ +└─────────────────────────┘ │ + │ N + │ + ┌─────────┴──────────────────────┐ + │ commission_withdrawal_requests │ + │ - id (PK) │ + │ - agent_id │ + └───┬────────────────────────────┘ + │ 1 + │ + │ N + ┌───────────┴─────────────────────────┐ + │ commission_withdrawal_approvals │ + │ - request_id (FK) │ + │ - approver_id │ + └─────────────────────────────────────┘ + +┌─────────────────────────────────┐ +│ agent_commission_accounts │ 代理佣金账户 +│ - agent_id (UK) │ +│ - available_amount │ +│ - frozen_amount │ +└─────────────────────────────────┘ +``` + +--- + +## 版本历史 + +| 版本 | 日期 | 修改内容 | 修改人 | +|------|------|----------|--------| +| v1.0 | 2025-11-28 | 初始版本,包含11张表的完整设计 | - | diff --git a/docs/表设计/整合.md b/docs/表设计/整合.md new file mode 100644 index 0000000..3a8ddeb --- /dev/null +++ b/docs/表设计/整合.md @@ -0,0 +1,464 @@ +## 代理商/店铺表 + +| 字段名 | 说明 | +| --- | --- | +| id | 主键id | +| name | 代理商名称/店铺名称 | +| parent_shop_id | 上级代理/店铺 ID | +| created_at | 创建时间 | +| updated_at | 更新时间 | +| creator | 创建人(创建人ID) | +| updater | 更新人(更新人ID) | +| deleted_at | 删除时间 (为null为没有删除) | + +--- + +## 账号表 + +| 字段名称 | 说明 | +| --- | --- | +| id | 主键ID | +| username | 用户名 | +| phone | 手机号 | +| password | 密码(用MD5加密) | +| user_type | 用户类型 1 root 2 平台/运营 3 代理 4 企业 | +| shop_id | 店铺ID 该账号绑定到哪个店铺下的 | +| parent_id | 账号上级(应当移除) | +| status | 0 禁用 1启用 | +| created_at | 创建时间 | +| updated_at | 更新时间 | +| creator | 创建人(创建人ID) | +| updater | 更新人(更新人ID) | +| deleted_at | 删除时间 (为null为没有删除) | + +--- + +## 角色表 + +| 字段名称 | 说明 | +| --- | --- | +| id | 主键ID | +| role_name | 角色名称 | +| role_desc | 角色描述 | +| role_type | 角色类型 1 超级 2 代理 3 企业 | +| status | 0 禁用 1启用 | +| created_at | 创建时间 | +| updated_at | 更新时间 | +| creator | 创建人(创建人ID) | +| updater | 更新人(更新人ID) | +| deleted_at | 删除时间 (为null为没有删除) | + +--- + +## 权限表(菜单/按钮/操作) + +| 字段名称 | 说明 | +| --- | --- | +| id | 主键ID | +| perm_name | 权限名称 | +| perm_type | 权限类型 1 菜单 2 按钮 | +| url | 权限路径 菜单 按钮 | +| parent_id | 上级ID | +| perm_code | 权限编码 | +| sort | 排序 | +| status | 0 禁用 1启用 | +| created_at | 创建时间 | +| updated_at | 更新时间 | +| creator | 创建人(创建人ID) | +| updater | 更新人(更新人ID) | +| deleted_at | 删除时间 (为null为没有删除) | + +--- + +## 账号-角色表 + +| 字段名 | 说明 | +| --- | --- | +| id | 主键ID | +| account_id | 账号ID | +| role_id | 角色ID | +| status | 0 禁用 1启用 | +| created_at | 创建时间 | +| updated_at | 更新时间 | +| creator | 创建人(创建人ID) | +| updater | 更新人(更新人ID) | +| deleted_at | 删除时间 (为null为没有删除) | + +--- + + +## 角色-权限表 + +| 字段名 | 说明 | +| --- | --- | +| id | 主键ID | +| role_id | 角色ID | +| perm_id | 权限ID | +| status | 0 禁用 1启用 | +| created_at | 创建时间 | +| updated_at | 更新时间 | +| creator | 创建人(创建人ID) | +| updater | 更新人(更新人ID) | +| deleted_at | 删除时间 (为null为没有删除) | + +--- + +## 套餐系列(套餐分类) + +| 字段名 | 说明 | +| --- | --- | +| id | 主键ID | +|code|套餐系列编码| +| name | 套餐系列名称 | +|type|业务套餐类型 流量卡,号卡| +| created_at | 创建时间 | +| updated_at | 更新时间 | +| creator | 创建人(创建人ID) | +| updater | 更新人(更新人ID) | +| deleted_at | 删除时间 (为null为没有删除) | + +**说明** +- `type`: 用以区分业务, 流量卡只能使用流量卡套餐 号卡只能使用号卡套餐 +--- + +## 套餐表 + +| 字段名 | 说明 | +| --- | --- | +| id | 主键ID | +|code|套餐编码| +|套餐系列code|套餐系列code| +|type|套餐类型 叠加包/月卡套餐/自然月套餐/| +| name | 套餐名称 | +| created_at | 创建时间 | +| updated_at | 更新时间 | +| creator | 创建人(创建人ID) | +| updater | 更新人(更新人ID) | +| deleted_at | 删除时间 (为null为没有删除) | + +**说明**: +- `judgment_target`: 销售数量存储个数,销售金额存储分 +--- + +## 代理/店铺套餐表 + +| 字段名 | 说明 | +| --- | --- | +| id | 主键ID | +| shop_id | 代理/店铺ID | +| 套餐系列名称 | 套餐系列名称 | +| 套餐系列ID | 套餐系列的主键ID | +| 套餐code | 套餐编码 | +| 套餐名称 | 套餐名称 | +| created_at | 创建时间 | +| updated_at | 更新时间 | +| creator | 创建人(创建人ID) | +| updater | 更新人(更新人ID) | +| deleted_at | 删除时间 (为null为没有删除) | + +--- + +## 流量卡表 + +| 字段名 | 说明 | +| --- | --- | +| id | 主键ID | +| created_at | 创建时间 | +| updated_at | 更新时间 | +| creator | 创建人(创建人ID) | +| updater | 更新人(更新人ID) | +| deleted_at | 删除时间 (为null为没有删除) | + +--- + +## 返佣梯度模板表 + +**用途**: 预设的返佣梯度模板,提供初始配置值,可被多个代理引用 + +| 字段名 | 类型 | 约束 | 说明 | +|--------|------|------|------| +| id | BIGSERIAL | PRIMARY KEY | 主键 | +| template_name | VARCHAR(100) | NOT NULL | 模板名称 | +| template_code | VARCHAR(50) | NOT NULL UNIQUE | 模板编码(唯一标识) | +| description | TEXT | NULL | 模板说明 | +| card_type | VARCHAR(20) | NOT NULL | 卡类型: `phone_card`(号卡) / `iot_card`(物联网卡) | +| judgment_type | VARCHAR(20) | NOT NULL | 判断类型: `sales_quantity`(套餐销售数量) / `sales_amount`(套餐销售金额) | +| rebate_timing | VARCHAR(20) | NOT NULL | 返佣时效: `immediate`(即可返佣) / `delayed`(延迟返佣) | +| rebate_condition_type | VARCHAR(20) | NOT NULL | 返佣条件类型: `accumulated_recharge`(累计充值) / `single_recharge`(一次充值) | +| rebate_condition_amount | BIGINT | NOT NULL | 返佣条件目标值(分为单位) | +| require_sanwu_check | BOOLEAN | NOT NULL DEFAULT false | 是否三无校验(仅号卡需要,物联网卡不需要) | +| is_long_term | BOOLEAN | NOT NULL DEFAULT false | 是否长期返佣 | +| termination_type | VARCHAR(20) | NULL | 长期终止方式: `month_count`(指定月数) / `end_date`(指定日期) | +| termination_value | VARCHAR(50) | NULL | 终止值: 月数(如"36")或日期(如"2026-11-20") | +| is_active | BOOLEAN | NOT NULL DEFAULT true | 是否启用 | +| created_by | BIGINT | NOT NULL | 创建人 ID | +| created_at | TIMESTAMP | NOT NULL DEFAULT CURRENT_TIMESTAMP | 创建时间 | +| updated_at | TIMESTAMP | NOT NULL DEFAULT CURRENT_TIMESTAMP | 更新时间 | +| deleted_at | TIMESTAMP | NULL | 软删除时间 | + +--- + +## 返佣梯度条目表 + +**用途**: 模板中的具体梯度条目,定义每个梯度的判断目标和返佣规则 + +| 字段名 | 类型 | 约束 | 说明 | +|--------|------|------|------| +| id | BIGSERIAL | PRIMARY KEY | 主键 | +| template_id | BIGINT | NOT NULL | 关联模板 ID | +| tier_level | INT | NOT NULL | 梯度等级(从1开始递增) | +| judgment_target | BIGINT | NOT NULL | 判断目标值(数量或金额,金额以分为单位) | +| rebate_type | VARCHAR(20) | NOT NULL | 返佣属性: `percentage`(比例金额) / `fixed`(固定金额) | +| rebate_value | BIGINT | NOT NULL | 返佣假定值(比例用万分比,如1000=10%;固定金额用分) | +| max_cap_amount | BIGINT | NULL | 封顶金额(分为单位,NULL表示无封顶) | +| created_at | TIMESTAMP | NOT NULL DEFAULT CURRENT_TIMESTAMP | 创建时间 | +| updated_at | TIMESTAMP | NOT NULL DEFAULT CURRENT_TIMESTAMP | 更新时间 | +| deleted_at | TIMESTAMP | NULL | 软删除时间 | + +**说明**: +- `rebate_value`: 比例类型存储万分比(10000=100%, 1000=10%),固定金额存储分 +- `judgment_target`: 销售数量存储个数,销售金额存储分 + +--- + +## 代理商-套餐-返佣规则快照表 + +**用途**: 代理商分销套餐时生成的返佣规则快照,独立于模板,允许个性化调整 + +| 字段名 | 类型 | 约束 | 说明 | +|--------|------|------|------| +| id | BIGSERIAL | PRIMARY KEY | 主键 | +| agent_id | BIGINT | NOT NULL | 代理商 ID | +| package_id | BIGINT | NOT NULL | 套餐 ID | +| template_id | BIGINT | NULL | 原始模板 ID(可为空,表示自定义规则) | +| rule_name | VARCHAR(100) | NOT NULL | 规则名称 | +| card_type | VARCHAR(20) | NOT NULL | 卡类型: `phone_card` / `iot_card` | +| judgment_type | VARCHAR(20) | NOT NULL | 判断类型 | +| rebate_timing | VARCHAR(20) | NOT NULL | 返佣时效 | +| rebate_condition_type | VARCHAR(20) | NOT NULL | 返佣条件类型 | +| rebate_condition_amount | BIGINT | NOT NULL | 返佣条件目标值(分) | +| require_sanwu_check | BOOLEAN | NOT NULL DEFAULT false | 是否三无校验 | +| is_long_term | BOOLEAN | NOT NULL DEFAULT false | 是否长期返佣 | +| termination_type | VARCHAR(20) | NULL | 长期终止方式 | +| termination_value | VARCHAR(50) | NULL | 终止值 | +| is_active | BOOLEAN | NOT NULL DEFAULT true | 是否启用 | +| created_by | BIGINT | NOT NULL | 创建人 ID | +| created_at | TIMESTAMP | NOT NULL DEFAULT CURRENT_TIMESTAMP | 创建时间 | +| updated_at | TIMESTAMP | NOT NULL DEFAULT CURRENT_TIMESTAMP | 更新时间 | +| deleted_at | TIMESTAMP | NULL | 软删除时间 | + +--- + +## 代理商返佣规则梯度条目表 + +**用途**: 代理商快照规则中的具体梯度条目(从模板复制或自定义) + +| 字段名 | 类型 | 约束 | 说明 | +|--------|------|------|------| +| id | BIGSERIAL | PRIMARY KEY | 主键 | +| rule_id | BIGINT | NOT NULL | 关联规则 ID | +| tier_level | INT | NOT NULL | 梯度等级 | +| judgment_target | BIGINT | NOT NULL | 判断目标值 | +| rebate_type | VARCHAR(20) | NOT NULL | 返佣属性 | +| rebate_value | BIGINT | NOT NULL | 返佣假定值 | +| max_cap_amount | BIGINT | NULL | 封顶金额 | +| created_at | TIMESTAMP | NOT NULL DEFAULT CURRENT_TIMESTAMP | 创建时间 | +| updated_at | TIMESTAMP | NOT NULL DEFAULT CURRENT_TIMESTAMP | 更新时间 | +| deleted_at | TIMESTAMP | NULL | 软删除时间 | + +--- + +## 佣金记录表 + +**用途**: 记录每一笔佣金的生成、状态变化、金额计算等核心信息 + +| 字段名 | 类型 | 约束 | 说明 | +|--------|------|------|------| +| id | BIGSERIAL | PRIMARY KEY | 主键 | +| record_no | VARCHAR(50) | NOT NULL UNIQUE | 佣金记录号(业务唯一标识) | +| agent_id | BIGINT | NOT NULL | 代理商 ID | +| package_id | BIGINT | NOT NULL | 套餐 ID | +| rule_id | BIGINT | NOT NULL | 返佣规则 ID | +| tier_item_id | BIGINT | NOT NULL | 梯度条目 ID | +| related_identifier | VARCHAR(50) | NOT NULL | 关联标识符(ICCID 或号码) | +| identifier_type | VARCHAR(20) | NOT NULL | 标识符类型: `iccid` / `phone_number` | +| card_type | VARCHAR(20) | NOT NULL | 卡类型: `phone_card` / `iot_card` | +| billing_month | VARCHAR(7) | NOT NULL | 计费月份(格式: YYYY-MM) | +| judgment_type | VARCHAR(20) | NOT NULL | 判断类型 | +| judgment_value | BIGINT | NOT NULL | 判断实际值(数量或金额) | +| rebate_timing | VARCHAR(20) | NOT NULL | 返佣时效 | +| rebate_type | VARCHAR(20) | NOT NULL | 返佣属性 | +| rebate_base_amount | BIGINT | NOT NULL | 返佣基数(成本价,分) | +| rebate_rate | BIGINT | NULL | 返佣比例(万分比,仅比例类型) | +| commission_amount | BIGINT | NOT NULL | 佣金金额(分) | +| status | VARCHAR(20) | NOT NULL | 状态: `frozen`(已冻结) / `normal`(正常) / `invalid`(无效) / `withdraw_pending`(提取申请中) / `withdraw_rejected`(提取驳回) / `withdrawn`(已提取) / `clawback`(已回溯) | +| freeze_reason | TEXT | NULL | 冻结原因 | +| invalid_reason | TEXT | NULL | 无效原因 | +| clawback_reason | TEXT | NULL | 回溯原因 | +| clawback_amount | BIGINT | NOT NULL DEFAULT 0 | 回溯金额(分,负数表示扣减) | +| is_long_term | BOOLEAN | NOT NULL DEFAULT false | 是否长期返佣 | +| long_term_month_index | INT | NULL | 长期返佣月份索引(第几个月) | +| frozen_at | TIMESTAMP | NULL | 冻结时间 | +| unfrozen_at | TIMESTAMP | NULL | 解冻时间 | +| unfrozen_by | BIGINT | NULL | 解冻操作人 ID | +| invalidated_at | TIMESTAMP | NULL | 标记无效时间 | +| invalidated_by | BIGINT | NULL | 标记无效操作人 ID | +| clawback_at | TIMESTAMP | NULL | 回溯时间 | +| clawback_by | BIGINT | NULL | 回溯操作人 ID | +| created_at | TIMESTAMP | NOT NULL DEFAULT CURRENT_TIMESTAMP | 创建时间 | +| updated_at | TIMESTAMP | NOT NULL DEFAULT CURRENT_TIMESTAMP | 更新时间 | +| deleted_at | TIMESTAMP | NULL | 软删除时间 | + +**状态流转说明**: +- `frozen` → `normal`: 解冻 +- `frozen` → `invalid`: 巡检发现不满足条件 +- `normal` → `withdraw_pending`: 提交提现申请 +- `withdraw_pending` → `withdrawn`: 审批通过 +- `withdraw_pending` → `withdraw_rejected`: 审批驳回 +- `withdraw_rejected` → `normal`: 问题解决后恢复 +- `withdrawn` → `clawback`: 客户退款导致回溯 + +--- + +## 佣金解冻凭证表 + +**用途**: 记录运营提交的解冻凭证,支持批量解冻操作 + +| 字段名 | 类型 | 约束 | 说明 | +|--------|------|------|------| +| id | BIGSERIAL | PRIMARY KEY | 主键 | +| voucher_no | VARCHAR(50) | NOT NULL UNIQUE | 凭证批次号 | +| voucher_source | VARCHAR(50) | NOT NULL | 凭证来源: `carrier_official`(运营商官方) / `upstream_channel`(上游渠道) / `other`(其他) | +| voucher_file_url | TEXT | NULL | 凭证文件 URL | +| billing_month | VARCHAR(7) | NOT NULL | 结算月份 | +| total_count | INT | NOT NULL DEFAULT 0 | 凭证包含总数 | +| unfrozen_count | INT | NOT NULL DEFAULT 0 | 成功解冻数量 | +| failed_count | INT | NOT NULL DEFAULT 0 | 解冻失败数量 | +| unfreeze_password | VARCHAR(100) | NULL | 解冻密码(加密存储) | +| status | VARCHAR(20) | NOT NULL | 状态: `pending`(待处理) / `processing`(处理中) / `completed`(已完成) / `failed`(失败) | +| process_started_at | TIMESTAMP | NULL | 处理开始时间 | +| process_completed_at | TIMESTAMP | NULL | 处理完成时间 | +| created_by | BIGINT | NOT NULL | 创建人 ID | +| created_at | TIMESTAMP | NOT NULL DEFAULT CURRENT_TIMESTAMP | 创建时间 | +| updated_at | TIMESTAMP | NOT NULL DEFAULT CURRENT_TIMESTAMP | 更新时间 | +| deleted_at | TIMESTAMP | NULL | 软删除时间 | + +--- + +## 佣金解冻凭证明细表 + +**用途**: 解冻凭证中的每条 ICCID/号码记录 + +| 字段名 | 类型 | 约束 | 说明 | +|--------|------|------|------| +| id | BIGSERIAL | PRIMARY KEY | 主键 | +| voucher_id | BIGINT | NOT NULL | 关联凭证 ID | +| identifier | VARCHAR(50) | NOT NULL | ICCID 或号码 | +| identifier_type | VARCHAR(20) | NOT NULL | 标识符类型: `iccid` / `phone_number` | +| commission_record_id | BIGINT | NULL | 关联佣金记录 ID(匹配后填充) | +| sanwu_check_passed | BOOLEAN | NULL | 三无校验是否通过 | +| traffic_usage | BIGINT | NULL | 流量用量(字节) | +| voice_usage | BIGINT | NULL | 语音用量(秒) | +| sms_usage | INT | NULL | 短信用量(条) | +| unfreeze_result | VARCHAR(20) | NOT NULL | 解冻结果: `success`(成功) / `failed`(失败) / `not_found`(未找到) | +| fail_reason | TEXT | NULL | 失败原因 | +| unfrozen_at | TIMESTAMP | NULL | 解冻时间 | +| created_at | TIMESTAMP | NOT NULL DEFAULT CURRENT_TIMESTAMP | 创建时间 | +| updated_at | TIMESTAMP | NOT NULL DEFAULT CURRENT_TIMESTAMP | 更新时间 | + + +--- + +## 提现申请表 + +**用途**: 代理商的提现申请记录 + +| 字段名 | 类型 | 约束 | 说明 | +|--------|------|------|------| +| id | BIGSERIAL | PRIMARY KEY | 主键 | +| request_no | VARCHAR(50) | NOT NULL UNIQUE | 提现申请单号 | +| agent_id | BIGINT | NOT NULL | 代理商 ID | +| withdrawal_amount | BIGINT | NOT NULL | 提现金额(分) | +| available_balance | BIGINT | NOT NULL | 申请时可用余额(分) | +| bank_account_name | VARCHAR(100) | NOT NULL | 收款账户名 | +| bank_account_number | VARCHAR(50) | NOT NULL | 收款账号 | +| bank_name | VARCHAR(100) | NOT NULL | 开户行 | +| status | VARCHAR(20) | NOT NULL | 状态: `pending`(待审批) / `approved`(已批准) / `rejected`(已驳回) / `paid`(已放款) / `failed`(放款失败) | +| reject_reason | TEXT | NULL | 驳回原因 | +| paid_amount | BIGINT | NULL | 实际放款金额(分) | +| paid_at | TIMESTAMP | NULL | 放款时间 | +| paid_by | BIGINT | NULL | 放款操作人 ID | +| payment_voucher_url | TEXT | NULL | 放款凭证 URL | +| transaction_no | VARCHAR(100) | NULL | 支付流水号 | +| created_at | TIMESTAMP | NOT NULL DEFAULT CURRENT_TIMESTAMP | 创建时间 | +| updated_at | TIMESTAMP | NOT NULL DEFAULT CURRENT_TIMESTAMP | 更新时间 | +| deleted_at | TIMESTAMP | NULL | 软删除时间 | + +--- + +## 提现审批记录表 + +**用途**: 提现申请的审批流程记录,支持多级审批和操作留痕 + +| 字段名 | 类型 | 约束 | 说明 | +|--------|------|------|------| +| id | BIGSERIAL | PRIMARY KEY | 主键 | +| request_id | BIGINT | NOT NULL | 关联提现申请 ID | +| approval_level | INT | NOT NULL | 审批级别(1,2,3...) | +| approver_id | BIGINT | NOT NULL | 审批人 ID | +| approver_name | VARCHAR(100) | NOT NULL | 审批人姓名 | +| action | VARCHAR(20) | NOT NULL | 操作: `approve`(批准) / `reject`(驳回) / `pay`(放款) | +| comment | TEXT | NULL | 审批意见 | +| approved_at | TIMESTAMP | NOT NULL DEFAULT CURRENT_TIMESTAMP | 审批时间 | +| created_at | TIMESTAMP | NOT NULL DEFAULT CURRENT_TIMESTAMP | 创建时间 | + + +**说明**: +- 每次审批操作(批准/驳回/放款)都会插入一条记录 +- `approval_level` 用于区分多级审批流程 +- `action='pay'` 的记录代表最终放款操作 + +--- + +## 提现-佣金关联表 + +**用途**: 关联提现申请和具体的佣金记录,支持一次提现包含多笔佣金 + +| 字段名 | 类型 | 约束 | 说明 | +|--------|------|------|------| +| id | BIGSERIAL | PRIMARY KEY | 主键 | +| request_id | BIGINT | NOT NULL | 关联提现申请 ID | +| commission_record_id | BIGINT | NOT NULL | 关联佣金记录 ID | +| commission_amount | BIGINT | NOT NULL | 佣金金额(分) | +| created_at | TIMESTAMP | NOT NULL DEFAULT CURRENT_TIMESTAMP | 创建时间 | + +--- + +## 代理商佣金账户表 + +**用途**: 代理商的佣金账户余额和统计信息(实时显示分佣金额) + +| 字段名 | 类型 | 约束 | 说明 | +|--------|------|------|------| +| id | BIGSERIAL | PRIMARY KEY | 主键 | +| agent_id | BIGINT | NOT NULL UNIQUE | 代理商 ID | +| total_earned | BIGINT | NOT NULL DEFAULT 0 | 累计获得佣金(分) | +| frozen_amount | BIGINT | NOT NULL DEFAULT 0 | 冻结中金额(分) | +| available_amount | BIGINT | NOT NULL DEFAULT 0 | 可提现金额(分) | +| withdrawn_amount | BIGINT | NOT NULL DEFAULT 0 | 已提现金额(分) | +| invalid_amount | BIGINT | NOT NULL DEFAULT 0 | 无效佣金金额(分) | +| clawback_amount | BIGINT | NOT NULL DEFAULT 0 | 已回溯金额(分) | +| pending_withdrawal_amount | BIGINT | NOT NULL DEFAULT 0 | 提现申请中金额(分) | +| last_withdrawal_at | TIMESTAMP | NULL | 最后提现时间 | +| created_at | TIMESTAMP | NOT NULL DEFAULT CURRENT_TIMESTAMP | 创建时间 | +| updated_at | TIMESTAMP | NOT NULL DEFAULT CURRENT_TIMESTAMP | 更新时间 | + +**字段计算规则**: +- `available_amount` = 状态为 `normal` 的佣金总和 +- `frozen_amount` = 状态为 `frozen` 的佣金总和 +- `pending_withdrawal_amount` = 状态为 `withdraw_pending` 的佣金总和 +- `withdrawn_amount` = 状态为 `withdrawn` 的佣金总和 +- `invalid_amount` = 状态为 `invalid` 的佣金总和 +- `clawback_amount` = 所有 `clawback_amount` 字段的累加(负数) + +--- diff --git a/internal/handler/account.go b/internal/handler/account.go index b7f5021..00fca67 100644 --- a/internal/handler/account.go +++ b/internal/handler/account.go @@ -1,9 +1,10 @@ package handler import ( + "strconv" + "github.com/break/junhong_cmp_fiber/pkg/errors" "github.com/break/junhong_cmp_fiber/pkg/response" - "strconv" "github.com/gofiber/fiber/v2" diff --git a/internal/model/account.go b/internal/model/account.go index 89ccbc0..fe6591a 100644 --- a/internal/model/account.go +++ b/internal/model/account.go @@ -1,26 +1,20 @@ package model import ( - "time" - "gorm.io/gorm" ) // Account 账号模型 type Account struct { - ID uint `gorm:"primarykey" json:"id"` - Username string `gorm:"uniqueIndex:idx_account_username,where:deleted_at IS NULL;not null;size:50" json:"username"` - Phone string `gorm:"uniqueIndex:idx_account_phone,where:deleted_at IS NULL;not null;size:20" json:"phone"` - Password string `gorm:"not null;size:255" json:"-"` // 不返回给客户端 - UserType int `gorm:"not null;index" json:"user_type"` // 1=root, 2=平台, 3=代理, 4=企业 - ShopID *uint `gorm:"index" json:"shop_id,omitempty"` - ParentID *uint `gorm:"index" json:"parent_id,omitempty"` - Status int `gorm:"not null;default:1" json:"status"` // 0=禁用, 1=启用 - Creator uint `gorm:"not null" json:"creator"` - Updater uint `gorm:"not null" json:"updater"` - CreatedAt time.Time `gorm:"not null" json:"created_at"` - UpdatedAt time.Time `gorm:"not null" json:"updated_at"` - DeletedAt gorm.DeletedAt `gorm:"index" json:"deleted_at,omitempty"` + gorm.Model + BaseModel + Username string `gorm:"uniqueIndex:idx_account_username,where:deleted_at IS NULL;not null;size:50" json:"username"` + Phone string `gorm:"uniqueIndex:idx_account_phone,where:deleted_at IS NULL;not null;size:20" json:"phone"` + Password string `gorm:"not null;size:255" json:"-"` // 不返回给客户端 + UserType int `gorm:"not null;index" json:"user_type"` // 1=root, 2=平台, 3=代理, 4=企业 + ShopID *uint `gorm:"index" json:"shop_id,omitempty"` + ParentID *uint `gorm:"index" json:"parent_id,omitempty"` + Status int `gorm:"not null;default:1" json:"status"` // 0=禁用, 1=启用 } // TableName 指定表名 diff --git a/internal/model/base.go b/internal/model/base.go index 74e67b5..b0efe8b 100644 --- a/internal/model/base.go +++ b/internal/model/base.go @@ -1,15 +1,17 @@ package model -import ( - "time" - - "gorm.io/gorm" -) +import "gorm.io/gorm" // BaseModel 基础模型,包含通用字段 type BaseModel struct { - ID uint `gorm:"primarykey" json:"id"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` - DeletedAt gorm.DeletedAt `gorm:"index" json:"-"` // 软删除 + Creator uint `gorm:"not null" json:"creator"` + Updater uint `gorm:"not null" json:"updater"` +} + +func (b *BaseModel) BeforeCreate(tx *gorm.DB) error { + if userID, ok := tx.Statement.Context.Value("current_user_id").(uint); ok { + b.Creator = userID + b.Updater = userID + } + return nil } diff --git a/internal/model/permission.go b/internal/model/permission.go index a344b7e..a6615df 100644 --- a/internal/model/permission.go +++ b/internal/model/permission.go @@ -1,26 +1,21 @@ package model import ( - "time" - "gorm.io/gorm" ) // Permission 权限模型 type Permission struct { - ID uint `gorm:"primarykey" json:"id"` - PermName string `gorm:"not null;size:50" json:"perm_name"` - PermCode string `gorm:"uniqueIndex:idx_permission_code,where:deleted_at IS NULL;not null;size:100" json:"perm_code"` - PermType int `gorm:"not null;index" json:"perm_type"` // 1=菜单, 2=按钮 - URL string `gorm:"size:255" json:"url,omitempty"` - ParentID *uint `gorm:"index" json:"parent_id,omitempty"` - Sort int `gorm:"not null;default:0" json:"sort"` - Status int `gorm:"not null;default:1" json:"status"` - Creator uint `gorm:"not null" json:"creator"` - Updater uint `gorm:"not null" json:"updater"` - CreatedAt time.Time `gorm:"not null" json:"created_at"` - UpdatedAt time.Time `gorm:"not null" json:"updated_at"` - DeletedAt gorm.DeletedAt `gorm:"index" json:"deleted_at,omitempty"` + gorm.Model + BaseModel + + PermName string `gorm:"not null;size:50" json:"perm_name"` + PermCode string `gorm:"uniqueIndex:idx_permission_code,where:deleted_at IS NULL;not null;size:100" json:"perm_code"` + PermType int `gorm:"not null;index" json:"perm_type"` // 1=菜单, 2=按钮 + URL string `gorm:"size:255" json:"url,omitempty"` + ParentID *uint `gorm:"index" json:"parent_id,omitempty"` + Sort int `gorm:"not null;default:0" json:"sort"` + Status int `gorm:"not null;default:1" json:"status"` } // TableName 指定表名 diff --git a/internal/model/role.go b/internal/model/role.go index 80e07b9..5ee994d 100644 --- a/internal/model/role.go +++ b/internal/model/role.go @@ -1,23 +1,18 @@ package model import ( - "time" - "gorm.io/gorm" ) // Role 角色模型 type Role struct { - ID uint `gorm:"primarykey" json:"id"` - RoleName string `gorm:"not null;size:50" json:"role_name"` - RoleDesc string `gorm:"size:255" json:"role_desc"` - RoleType int `gorm:"not null;index" json:"role_type"` // 1=超级, 2=代理, 3=企业 - Status int `gorm:"not null;default:1" json:"status"` - Creator uint `gorm:"not null" json:"creator"` - Updater uint `gorm:"not null" json:"updater"` - CreatedAt time.Time `gorm:"not null" json:"created_at"` - UpdatedAt time.Time `gorm:"not null" json:"updated_at"` - DeletedAt gorm.DeletedAt `gorm:"index" json:"deleted_at,omitempty"` + gorm.Model + BaseModel + + RoleName string `gorm:"not null;size:50" json:"role_name"` + RoleDesc string `gorm:"size:255" json:"role_desc"` + RoleType int `gorm:"not null;index" json:"role_type"` // 1=超级, 2=代理, 3=企业 + Status int `gorm:"not null;default:1" json:"status"` } // TableName 指定表名 diff --git a/internal/model/role_permission.go b/internal/model/role_permission.go index ee4e6fb..545fcd8 100644 --- a/internal/model/role_permission.go +++ b/internal/model/role_permission.go @@ -1,22 +1,17 @@ package model import ( - "time" - "gorm.io/gorm" ) // RolePermission 角色-权限关联模型 type RolePermission struct { - ID uint `gorm:"primarykey" json:"id"` - RoleID uint `gorm:"not null;index;uniqueIndex:idx_role_permission_unique,where:deleted_at IS NULL" json:"role_id"` - PermID uint `gorm:"not null;index;uniqueIndex:idx_role_permission_unique,where:deleted_at IS NULL" json:"perm_id"` - Status int `gorm:"not null;default:1" json:"status"` - Creator uint `gorm:"not null" json:"creator"` - Updater uint `gorm:"not null" json:"updater"` - CreatedAt time.Time `gorm:"not null" json:"created_at"` - UpdatedAt time.Time `gorm:"not null" json:"updated_at"` - DeletedAt gorm.DeletedAt `gorm:"index" json:"deleted_at,omitempty"` + gorm.Model + BaseModel + + RoleID uint `gorm:"not null;index;uniqueIndex:idx_role_permission_unique,where:deleted_at IS NULL" json:"role_id"` + PermID uint `gorm:"not null;index;uniqueIndex:idx_role_permission_unique,where:deleted_at IS NULL" json:"perm_id"` + Status int `gorm:"not null;default:1" json:"status"` } // TableName 指定表名 diff --git a/internal/service/account/service.go b/internal/service/account/service.go index 3630660..642bb48 100644 --- a/internal/service/account/service.go +++ b/internal/service/account/service.go @@ -78,8 +78,6 @@ func (s *Service) Create(ctx context.Context, req *model.CreateAccountRequest) ( ShopID: req.ShopID, ParentID: req.ParentID, Status: constants.StatusEnabled, - Creator: currentUserID, - Updater: currentUserID, } if err := s.accountStore.Create(ctx, account); err != nil { diff --git a/internal/service/permission/service.go b/internal/service/permission/service.go index 6fc171d..c8d1264 100644 --- a/internal/service/permission/service.go +++ b/internal/service/permission/service.go @@ -65,8 +65,6 @@ func (s *Service) Create(ctx context.Context, req *model.CreatePermissionRequest ParentID: req.ParentID, Sort: req.Sort, Status: constants.StatusEnabled, - Creator: currentUserID, - Updater: currentUserID, } if err := s.permissionStore.Create(ctx, permission); err != nil { diff --git a/internal/service/role/service.go b/internal/service/role/service.go index 2b9ef5b..9aed889 100644 --- a/internal/service/role/service.go +++ b/internal/service/role/service.go @@ -43,8 +43,6 @@ func (s *Service) Create(ctx context.Context, req *model.CreateRoleRequest) (*mo RoleDesc: req.RoleDesc, RoleType: req.RoleType, Status: constants.StatusEnabled, - Creator: currentUserID, - Updater: currentUserID, } if err := s.roleStore.Create(ctx, role); err != nil { @@ -187,11 +185,9 @@ func (s *Service) AssignPermissions(ctx context.Context, roleID uint, permIDs [] } rp := &model.RolePermission{ - RoleID: roleID, - PermID: permID, - Status: constants.StatusEnabled, - Creator: currentUserID, - Updater: currentUserID, + RoleID: roleID, + PermID: permID, + Status: constants.StatusEnabled, } if err := s.rolePermissionStore.Create(ctx, rp); err != nil { return nil, fmt.Errorf("创建角色-权限关联失败: %w", err) diff --git a/tests/integration/account_role_test.go b/tests/integration/account_role_test.go index 17ff281..41b4134 100644 --- a/tests/integration/account_role_test.go +++ b/tests/integration/account_role_test.go @@ -91,8 +91,6 @@ func TestAccountRoleAssociation_AssignRoles(t *testing.T) { Password: "hashedpassword", UserType: constants.UserTypePlatform, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } db.Create(account) @@ -101,8 +99,6 @@ func TestAccountRoleAssociation_AssignRoles(t *testing.T) { RoleName: "单角色测试", RoleType: constants.RoleTypeSuper, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } db.Create(role) @@ -122,8 +118,6 @@ func TestAccountRoleAssociation_AssignRoles(t *testing.T) { Password: "hashedpassword", UserType: constants.UserTypePlatform, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } db.Create(account) @@ -135,8 +129,6 @@ func TestAccountRoleAssociation_AssignRoles(t *testing.T) { RoleName: "多角色测试_" + string(rune('A'+i)), RoleType: constants.RoleTypeSuper, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } db.Create(roles[i]) roleIDs[i] = roles[i].ID @@ -156,8 +148,6 @@ func TestAccountRoleAssociation_AssignRoles(t *testing.T) { Password: "hashedpassword", UserType: constants.UserTypePlatform, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } db.Create(account) @@ -166,8 +156,6 @@ func TestAccountRoleAssociation_AssignRoles(t *testing.T) { RoleName: "获取角色列表测试", RoleType: constants.RoleTypeSuper, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } db.Create(role) @@ -189,8 +177,6 @@ func TestAccountRoleAssociation_AssignRoles(t *testing.T) { Password: "hashedpassword", UserType: constants.UserTypePlatform, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } db.Create(account) @@ -199,8 +185,6 @@ func TestAccountRoleAssociation_AssignRoles(t *testing.T) { RoleName: "移除角色测试", RoleType: constants.RoleTypeSuper, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } db.Create(role) @@ -226,8 +210,6 @@ func TestAccountRoleAssociation_AssignRoles(t *testing.T) { Password: "hashedpassword", UserType: constants.UserTypePlatform, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } db.Create(account) @@ -236,8 +218,6 @@ func TestAccountRoleAssociation_AssignRoles(t *testing.T) { RoleName: "重复分配测试", RoleType: constants.RoleTypeSuper, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } db.Create(role) @@ -260,8 +240,6 @@ func TestAccountRoleAssociation_AssignRoles(t *testing.T) { RoleName: "账号不存在测试", RoleType: constants.RoleTypeSuper, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } db.Create(role) @@ -276,8 +254,6 @@ func TestAccountRoleAssociation_AssignRoles(t *testing.T) { Password: "hashedpassword", UserType: constants.UserTypePlatform, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } db.Create(account) @@ -341,8 +317,6 @@ func TestAccountRoleAssociation_SoftDelete(t *testing.T) { Password: "hashedpassword", UserType: constants.UserTypePlatform, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } db.Create(account) @@ -350,8 +324,6 @@ func TestAccountRoleAssociation_SoftDelete(t *testing.T) { RoleName: "恢复角色测试", RoleType: constants.RoleTypeSuper, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } db.Create(role) diff --git a/tests/integration/account_test.go b/tests/integration/account_test.go index 6a316fd..9beee1f 100644 --- a/tests/integration/account_test.go +++ b/tests/integration/account_test.go @@ -178,8 +178,6 @@ func TestAccountAPI_Create(t *testing.T) { Password: "hashedpassword", UserType: constants.UserTypeRoot, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } createTestAccount(t, env.db, rootAccount) @@ -220,8 +218,6 @@ func TestAccountAPI_Create(t *testing.T) { UserType: constants.UserTypePlatform, ParentID: &rootAccount.ID, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } createTestAccount(t, env.db, existingAccount) @@ -290,8 +286,6 @@ func TestAccountAPI_Get(t *testing.T) { Password: "hashedpassword", UserType: constants.UserTypePlatform, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } createTestAccount(t, env.db, testAccount) @@ -350,8 +344,6 @@ func TestAccountAPI_Update(t *testing.T) { Password: "hashedpassword", UserType: constants.UserTypePlatform, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } createTestAccount(t, env.db, testAccount) @@ -397,8 +389,6 @@ func TestAccountAPI_Delete(t *testing.T) { Password: "hashedpassword", UserType: constants.UserTypePlatform, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } createTestAccount(t, env.db, testAccount) @@ -436,8 +426,6 @@ func TestAccountAPI_List(t *testing.T) { Password: "hashedpassword", UserType: constants.UserTypePlatform, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } createTestAccount(t, env.db, account) } @@ -482,8 +470,6 @@ func TestAccountAPI_AssignRoles(t *testing.T) { Password: "hashedpassword", UserType: constants.UserTypePlatform, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } createTestAccount(t, env.db, testAccount) @@ -492,8 +478,6 @@ func TestAccountAPI_AssignRoles(t *testing.T) { RoleName: "测试角色", RoleType: constants.RoleTypeSuper, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } env.db.Create(testRole) @@ -537,8 +521,6 @@ func TestAccountAPI_GetRoles(t *testing.T) { Password: "hashedpassword", UserType: constants.UserTypePlatform, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } createTestAccount(t, env.db, testAccount) @@ -547,8 +529,6 @@ func TestAccountAPI_GetRoles(t *testing.T) { RoleName: "获取角色测试", RoleType: constants.RoleTypeSuper, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } env.db.Create(testRole) @@ -594,8 +574,6 @@ func TestAccountAPI_RemoveRole(t *testing.T) { Password: "hashedpassword", UserType: constants.UserTypePlatform, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } createTestAccount(t, env.db, testAccount) @@ -604,8 +582,6 @@ func TestAccountAPI_RemoveRole(t *testing.T) { RoleName: "移除角色测试", RoleType: constants.RoleTypeSuper, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } env.db.Create(testRole) diff --git a/tests/integration/api_regression_test.go b/tests/integration/api_regression_test.go index 2e41e14..738cc74 100644 --- a/tests/integration/api_regression_test.go +++ b/tests/integration/api_regression_test.go @@ -210,8 +210,6 @@ func TestAPIRegression_RouteModularization(t *testing.T) { Password: "hashedpassword", UserType: constants.UserTypePlatform, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } env.db.Create(account) @@ -234,8 +232,6 @@ func TestAPIRegression_RouteModularization(t *testing.T) { RoleName: "回归测试角色", RoleType: constants.RoleTypeSuper, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } env.db.Create(role) @@ -259,8 +255,6 @@ func TestAPIRegression_RouteModularization(t *testing.T) { PermCode: "regression:test:perm", PermType: constants.PermissionTypeMenu, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } env.db.Create(perm) @@ -328,8 +322,6 @@ func TestAPIRegression_Pagination(t *testing.T) { Password: "hashedpassword", UserType: constants.UserTypePlatform, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } env.db.Create(account) } diff --git a/tests/integration/permission_test.go b/tests/integration/permission_test.go index ad95a24..bef318d 100644 --- a/tests/integration/permission_test.go +++ b/tests/integration/permission_test.go @@ -155,8 +155,6 @@ func TestPermissionAPI_Create(t *testing.T) { PermCode: "existing:perm", PermType: constants.PermissionTypeMenu, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } env.db.Create(existingPerm) @@ -187,8 +185,6 @@ func TestPermissionAPI_Create(t *testing.T) { PermCode: "system:manage", PermType: constants.PermissionTypeMenu, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } env.db.Create(parentPerm) @@ -235,8 +231,6 @@ func TestPermissionAPI_Get(t *testing.T) { PermCode: "get:test:perm", PermType: constants.PermissionTypeMenu, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } env.db.Create(testPerm) @@ -283,8 +277,6 @@ func TestPermissionAPI_Update(t *testing.T) { PermCode: "update:test:perm", PermType: constants.PermissionTypeMenu, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } env.db.Create(testPerm) @@ -329,8 +321,6 @@ func TestPermissionAPI_Delete(t *testing.T) { PermCode: "delete:test:perm", PermType: constants.PermissionTypeMenu, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } env.db.Create(testPerm) @@ -367,8 +357,6 @@ func TestPermissionAPI_List(t *testing.T) { PermCode: fmt.Sprintf("list:test:perm:%d", i), PermType: constants.PermissionTypeMenu, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } env.db.Create(perm) } @@ -413,8 +401,6 @@ func TestPermissionAPI_GetTree(t *testing.T) { PermCode: "system", PermType: constants.PermissionTypeMenu, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } env.db.Create(rootPerm) @@ -425,8 +411,6 @@ func TestPermissionAPI_GetTree(t *testing.T) { PermType: constants.PermissionTypeMenu, ParentID: &rootPerm.ID, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } env.db.Create(childPerm) @@ -437,8 +421,6 @@ func TestPermissionAPI_GetTree(t *testing.T) { PermType: constants.PermissionTypeButton, ParentID: &childPerm.ID, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } env.db.Create(grandchildPerm) diff --git a/tests/integration/role_permission_test.go b/tests/integration/role_permission_test.go index 0b26c23..1d952d0 100644 --- a/tests/integration/role_permission_test.go +++ b/tests/integration/role_permission_test.go @@ -72,8 +72,6 @@ func TestRolePermissionAssociation_AssignPermissions(t *testing.T) { RoleName: "单权限测试角色", RoleType: constants.RoleTypeSuper, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } db.Create(role) @@ -83,8 +81,6 @@ func TestRolePermissionAssociation_AssignPermissions(t *testing.T) { PermCode: "single:perm:test", PermType: constants.PermissionTypeMenu, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } db.Create(perm) @@ -102,8 +98,6 @@ func TestRolePermissionAssociation_AssignPermissions(t *testing.T) { RoleName: "多权限测试角色", RoleType: constants.RoleTypeSuper, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } db.Create(role) @@ -115,8 +109,6 @@ func TestRolePermissionAssociation_AssignPermissions(t *testing.T) { PermCode: "multi:perm:test:" + string(rune('a'+i)), PermType: constants.PermissionTypeMenu, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } db.Create(perm) permIDs[i] = perm.ID @@ -134,8 +126,6 @@ func TestRolePermissionAssociation_AssignPermissions(t *testing.T) { RoleName: "获取权限列表测试角色", RoleType: constants.RoleTypeSuper, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } db.Create(role) @@ -145,8 +135,6 @@ func TestRolePermissionAssociation_AssignPermissions(t *testing.T) { PermCode: "get:perm:list:test", PermType: constants.PermissionTypeMenu, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } db.Create(perm) @@ -166,8 +154,6 @@ func TestRolePermissionAssociation_AssignPermissions(t *testing.T) { RoleName: "移除权限测试角色", RoleType: constants.RoleTypeSuper, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } db.Create(role) @@ -177,8 +163,6 @@ func TestRolePermissionAssociation_AssignPermissions(t *testing.T) { PermCode: "remove:perm:test", PermType: constants.PermissionTypeMenu, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } db.Create(perm) @@ -202,8 +186,6 @@ func TestRolePermissionAssociation_AssignPermissions(t *testing.T) { RoleName: "重复权限测试角色", RoleType: constants.RoleTypeSuper, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } db.Create(role) @@ -213,8 +195,6 @@ func TestRolePermissionAssociation_AssignPermissions(t *testing.T) { PermCode: "duplicate:perm:test", PermType: constants.PermissionTypeMenu, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } db.Create(perm) @@ -238,8 +218,6 @@ func TestRolePermissionAssociation_AssignPermissions(t *testing.T) { PermCode: "role:not:exist:test", PermType: constants.PermissionTypeMenu, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } db.Create(perm) @@ -252,8 +230,6 @@ func TestRolePermissionAssociation_AssignPermissions(t *testing.T) { RoleName: "权限不存在测试角色", RoleType: constants.RoleTypeSuper, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } db.Create(role) @@ -302,8 +278,6 @@ func TestRolePermissionAssociation_SoftDelete(t *testing.T) { RoleName: "恢复权限测试角色", RoleType: constants.RoleTypeSuper, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } db.Create(role) @@ -312,8 +286,6 @@ func TestRolePermissionAssociation_SoftDelete(t *testing.T) { PermCode: "restore:perm:test", PermType: constants.PermissionTypeMenu, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } db.Create(perm) @@ -342,8 +314,6 @@ func TestRolePermissionAssociation_SoftDelete(t *testing.T) { RoleName: "批量权限测试角色", RoleType: constants.RoleTypeSuper, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } db.Create(role) @@ -355,8 +325,6 @@ func TestRolePermissionAssociation_SoftDelete(t *testing.T) { PermCode: "batch:perm:test:" + string(rune('a'+i)), PermType: constants.PermissionTypeMenu, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } db.Create(perm) permIDs[i] = perm.ID @@ -417,8 +385,6 @@ func TestRolePermissionAssociation_Cascade(t *testing.T) { RoleName: "级联测试角色", RoleType: constants.RoleTypeSuper, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } db.Create(role) @@ -427,18 +393,14 @@ func TestRolePermissionAssociation_Cascade(t *testing.T) { PermCode: "cascade:test:perm", PermType: constants.PermissionTypeMenu, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } db.Create(perm) // 创建关联 rp := &model.RolePermission{ - RoleID: role.ID, - PermID: perm.ID, - Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, + RoleID: role.ID, + PermID: perm.ID, + Status: constants.StatusEnabled, } db.Create(rp) diff --git a/tests/integration/role_test.go b/tests/integration/role_test.go index 41e74af..bac9fd8 100644 --- a/tests/integration/role_test.go +++ b/tests/integration/role_test.go @@ -226,8 +226,6 @@ func TestRoleAPI_Get(t *testing.T) { RoleName: "获取测试角色", RoleType: constants.RoleTypeSuper, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } env.db.Create(testRole) @@ -273,8 +271,6 @@ func TestRoleAPI_Update(t *testing.T) { RoleName: "更新测试角色", RoleType: constants.RoleTypeSuper, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } env.db.Create(testRole) @@ -318,8 +314,6 @@ func TestRoleAPI_Delete(t *testing.T) { RoleName: "删除测试角色", RoleType: constants.RoleTypeSuper, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } env.db.Create(testRole) @@ -355,8 +349,6 @@ func TestRoleAPI_List(t *testing.T) { RoleName: fmt.Sprintf("列表测试角色_%d", i), RoleType: constants.RoleTypeSuper, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } env.db.Create(role) } @@ -392,8 +384,6 @@ func TestRoleAPI_AssignPermissions(t *testing.T) { RoleName: "权限分配测试角色", RoleType: constants.RoleTypeSuper, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } env.db.Create(testRole) @@ -403,8 +393,6 @@ func TestRoleAPI_AssignPermissions(t *testing.T) { PermCode: "test:permission", PermType: constants.PermissionTypeMenu, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } env.db.Create(testPerm) @@ -446,8 +434,6 @@ func TestRoleAPI_GetPermissions(t *testing.T) { RoleName: "获取权限测试角色", RoleType: constants.RoleTypeSuper, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } env.db.Create(testRole) @@ -457,17 +443,13 @@ func TestRoleAPI_GetPermissions(t *testing.T) { PermCode: "get:permission:test", PermType: constants.PermissionTypeMenu, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } env.db.Create(testPerm) rolePerm := &model.RolePermission{ - RoleID: testRole.ID, - PermID: testPerm.ID, - Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, + RoleID: testRole.ID, + PermID: testPerm.ID, + Status: constants.StatusEnabled, } env.db.Create(rolePerm) @@ -502,8 +484,6 @@ func TestRoleAPI_RemovePermission(t *testing.T) { RoleName: "移除权限测试角色", RoleType: constants.RoleTypeSuper, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } env.db.Create(testRole) @@ -513,17 +493,13 @@ func TestRoleAPI_RemovePermission(t *testing.T) { PermCode: "remove:permission:test", PermType: constants.PermissionTypeMenu, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } env.db.Create(testPerm) rolePerm := &model.RolePermission{ - RoleID: testRole.ID, - PermID: testPerm.ID, - Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, + RoleID: testRole.ID, + PermID: testPerm.ID, + Status: constants.StatusEnabled, } env.db.Create(rolePerm) diff --git a/tests/unit/account_model_test.go b/tests/unit/account_model_test.go index 625b881..e9bc85c 100644 --- a/tests/unit/account_model_test.go +++ b/tests/unit/account_model_test.go @@ -28,8 +28,6 @@ func TestAccountModel_Create(t *testing.T) { Password: "hashed_password", UserType: constants.UserTypeRoot, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } err := store.Create(ctx, account) @@ -47,8 +45,6 @@ func TestAccountModel_Create(t *testing.T) { Password: "hashed_password", UserType: constants.UserTypePlatform, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } err := store.Create(ctx, parent) require.NoError(t, err) @@ -61,8 +57,6 @@ func TestAccountModel_Create(t *testing.T) { UserType: constants.UserTypeAgent, ParentID: &parent.ID, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } err = store.Create(ctx, child) require.NoError(t, err) @@ -79,8 +73,6 @@ func TestAccountModel_Create(t *testing.T) { UserType: constants.UserTypePlatform, ShopID: &shopID, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } err := store.Create(ctx, account) @@ -105,8 +97,6 @@ func TestAccountModel_GetByID(t *testing.T) { Password: "hashed_password", UserType: constants.UserTypePlatform, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } err := store.Create(ctx, account) require.NoError(t, err) @@ -140,8 +130,6 @@ func TestAccountModel_GetByUsername(t *testing.T) { Password: "hashed_password", UserType: constants.UserTypePlatform, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } err := store.Create(ctx, account) require.NoError(t, err) @@ -173,8 +161,6 @@ func TestAccountModel_GetByPhone(t *testing.T) { Password: "hashed_password", UserType: constants.UserTypePlatform, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } err := store.Create(ctx, account) require.NoError(t, err) @@ -206,8 +192,6 @@ func TestAccountModel_Update(t *testing.T) { Password: "hashed_password", UserType: constants.UserTypePlatform, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } err := store.Create(ctx, account) require.NoError(t, err) @@ -242,8 +226,6 @@ func TestAccountModel_List(t *testing.T) { Password: "hashed_password", UserType: constants.UserTypePlatform, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } err := store.Create(ctx, account) require.NoError(t, err) @@ -283,8 +265,6 @@ func TestAccountModel_UniqueConstraints(t *testing.T) { Password: "hashed_password", UserType: constants.UserTypePlatform, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } err := store.Create(ctx, account) require.NoError(t, err) @@ -296,8 +276,6 @@ func TestAccountModel_UniqueConstraints(t *testing.T) { Password: "hashed_password", UserType: constants.UserTypePlatform, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } err := store.Create(ctx, duplicate) assert.Error(t, err) @@ -310,8 +288,6 @@ func TestAccountModel_UniqueConstraints(t *testing.T) { Password: "hashed_password", UserType: constants.UserTypePlatform, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } err := store.Create(ctx, duplicate) assert.Error(t, err) diff --git a/tests/unit/soft_delete_test.go b/tests/unit/soft_delete_test.go index 4a21e9f..4f92618 100644 --- a/tests/unit/soft_delete_test.go +++ b/tests/unit/soft_delete_test.go @@ -29,8 +29,6 @@ func TestAccountSoftDelete(t *testing.T) { Password: "hashed_password", UserType: constants.UserTypePlatform, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } err := store.Create(ctx, account) require.NoError(t, err) @@ -61,8 +59,6 @@ func TestAccountSoftDelete(t *testing.T) { Password: "hashed_password", UserType: constants.UserTypePlatform, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } err := store.Create(ctx, newAccount) require.NoError(t, err) @@ -84,8 +80,6 @@ func TestRoleSoftDelete(t *testing.T) { RoleDesc: "测试角色", RoleType: constants.RoleTypeSuper, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } err := roleStore.Create(ctx, role) require.NoError(t, err) @@ -123,8 +117,6 @@ func TestPermissionSoftDelete(t *testing.T) { PermCode: "test:permission", PermType: constants.PermissionTypeMenu, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } err := permissionStore.Create(ctx, permission) require.NoError(t, err) @@ -145,8 +137,6 @@ func TestPermissionSoftDelete(t *testing.T) { PermCode: "test:permission", // 重用已删除权限的 perm_code PermType: constants.PermissionTypeMenu, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } err := permissionStore.Create(ctx, newPermission) require.NoError(t, err) @@ -171,8 +161,6 @@ func TestAccountRoleSoftDelete(t *testing.T) { Password: "hashed_password", UserType: constants.UserTypePlatform, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } err := accountStore.Create(ctx, account) require.NoError(t, err) @@ -183,8 +171,6 @@ func TestAccountRoleSoftDelete(t *testing.T) { RoleDesc: "测试角色", RoleType: constants.RoleTypeSuper, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } err = roleStore.Create(ctx, role) require.NoError(t, err) @@ -244,8 +230,6 @@ func TestRolePermissionSoftDelete(t *testing.T) { RoleDesc: "测试角色", RoleType: constants.RoleTypeSuper, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } err := roleStore.Create(ctx, role) require.NoError(t, err) @@ -256,19 +240,15 @@ func TestRolePermissionSoftDelete(t *testing.T) { PermCode: "rp:permission", PermType: constants.PermissionTypeMenu, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } err = permissionStore.Create(ctx, permission) require.NoError(t, err) // 创建关联 rolePermission := &model.RolePermission{ - RoleID: role.ID, - PermID: permission.ID, - Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, + RoleID: role.ID, + PermID: permission.ID, + Status: constants.StatusEnabled, } err = rolePermissionStore.Create(ctx, rolePermission) require.NoError(t, err) @@ -285,11 +265,9 @@ func TestRolePermissionSoftDelete(t *testing.T) { t.Run("软删除后可以重新关联", func(t *testing.T) { newRolePermission := &model.RolePermission{ - RoleID: role.ID, - PermID: permission.ID, - Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, + RoleID: role.ID, + PermID: permission.ID, + Status: constants.StatusEnabled, } err := rolePermissionStore.Create(ctx, newRolePermission) require.NoError(t, err) diff --git a/tests/unit/subordinate_cache_test.go b/tests/unit/subordinate_cache_test.go index 63b0435..c1cbc70 100644 --- a/tests/unit/subordinate_cache_test.go +++ b/tests/unit/subordinate_cache_test.go @@ -30,8 +30,6 @@ func TestGetSubordinateIDs_CacheHit(t *testing.T) { Password: "hashed_password", UserType: constants.UserTypePlatform, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } require.NoError(t, db.Create(accountA).Error) @@ -42,8 +40,6 @@ func TestGetSubordinateIDs_CacheHit(t *testing.T) { UserType: constants.UserTypeAgent, ParentID: &accountA.ID, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } require.NoError(t, db.Create(accountB).Error) @@ -85,8 +81,6 @@ func TestGetSubordinateIDs_CacheExpiry(t *testing.T) { Password: "hashed_password", UserType: constants.UserTypePlatform, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } require.NoError(t, db.Create(accountA).Error) @@ -132,8 +126,6 @@ func TestClearSubordinatesCache(t *testing.T) { Password: "hashed_password", UserType: constants.UserTypePlatform, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } require.NoError(t, db.Create(accountA).Error) @@ -172,8 +164,6 @@ func TestClearSubordinatesCacheForParents(t *testing.T) { Password: "hashed_password", UserType: constants.UserTypePlatform, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } require.NoError(t, db.Create(accountA).Error) @@ -184,8 +174,6 @@ func TestClearSubordinatesCacheForParents(t *testing.T) { UserType: constants.UserTypeAgent, ParentID: &accountA.ID, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } require.NoError(t, db.Create(accountB).Error) @@ -196,8 +184,6 @@ func TestClearSubordinatesCacheForParents(t *testing.T) { UserType: constants.UserTypeAgent, ParentID: &accountB.ID, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } require.NoError(t, db.Create(accountC).Error) @@ -249,8 +235,6 @@ func TestCacheInvalidationOnCreate(t *testing.T) { Password: "hashed_password", UserType: constants.UserTypePlatform, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } require.NoError(t, db.Create(accountA).Error) @@ -272,8 +256,6 @@ func TestCacheInvalidationOnCreate(t *testing.T) { UserType: constants.UserTypeAgent, ParentID: &accountA.ID, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } require.NoError(t, db.Create(accountB).Error) diff --git a/tests/unit/subordinate_query_test.go b/tests/unit/subordinate_query_test.go index f1635d9..e9ff1a7 100644 --- a/tests/unit/subordinate_query_test.go +++ b/tests/unit/subordinate_query_test.go @@ -28,8 +28,6 @@ func TestGetSubordinateIDs_SingleLevel(t *testing.T) { Password: "hashed_password", UserType: constants.UserTypePlatform, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } require.NoError(t, db.Create(accountA).Error) @@ -40,8 +38,6 @@ func TestGetSubordinateIDs_SingleLevel(t *testing.T) { UserType: constants.UserTypeAgent, ParentID: &accountA.ID, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } require.NoError(t, db.Create(accountB).Error) @@ -52,8 +48,6 @@ func TestGetSubordinateIDs_SingleLevel(t *testing.T) { UserType: constants.UserTypeAgent, ParentID: &accountA.ID, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } require.NoError(t, db.Create(accountC).Error) @@ -81,8 +75,6 @@ func TestGetSubordinateIDs_MultiLevel(t *testing.T) { Password: "hashed_password", UserType: constants.UserTypePlatform, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } require.NoError(t, db.Create(accountA).Error) @@ -93,8 +85,6 @@ func TestGetSubordinateIDs_MultiLevel(t *testing.T) { UserType: constants.UserTypeAgent, ParentID: &accountA.ID, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } require.NoError(t, db.Create(accountB).Error) @@ -105,8 +95,6 @@ func TestGetSubordinateIDs_MultiLevel(t *testing.T) { UserType: constants.UserTypeAgent, ParentID: &accountB.ID, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } require.NoError(t, db.Create(accountC).Error) @@ -117,8 +105,6 @@ func TestGetSubordinateIDs_MultiLevel(t *testing.T) { UserType: constants.UserTypeEnterprise, ParentID: &accountC.ID, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } require.NoError(t, db.Create(accountD).Error) @@ -129,8 +115,6 @@ func TestGetSubordinateIDs_MultiLevel(t *testing.T) { UserType: constants.UserTypeEnterprise, ParentID: &accountD.ID, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } require.NoError(t, db.Create(accountE).Error) @@ -166,8 +150,6 @@ func TestGetSubordinateIDs_WithSoftDeleted(t *testing.T) { Password: "hashed_password", UserType: constants.UserTypePlatform, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } require.NoError(t, db.Create(accountA).Error) @@ -178,8 +160,6 @@ func TestGetSubordinateIDs_WithSoftDeleted(t *testing.T) { UserType: constants.UserTypeAgent, ParentID: &accountA.ID, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } require.NoError(t, db.Create(accountB).Error) @@ -190,8 +170,6 @@ func TestGetSubordinateIDs_WithSoftDeleted(t *testing.T) { UserType: constants.UserTypeAgent, ParentID: &accountB.ID, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } require.NoError(t, db.Create(accountC).Error) @@ -226,8 +204,6 @@ func TestGetSubordinateIDs_Performance(t *testing.T) { Password: "hashed_password", UserType: constants.UserTypeRoot, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } require.NoError(t, db.Create(accountA).Error) @@ -241,8 +217,6 @@ func TestGetSubordinateIDs_Performance(t *testing.T) { UserType: constants.UserTypePlatform, ParentID: &accountA.ID, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } require.NoError(t, db.Create(acc).Error) level2IDs = append(level2IDs, acc.ID) @@ -259,8 +233,6 @@ func TestGetSubordinateIDs_Performance(t *testing.T) { UserType: constants.UserTypeAgent, ParentID: &parentID, Status: constants.StatusEnabled, - Creator: 1, - Updater: 1, } require.NoError(t, db.Create(acc).Error) level3IDs = append(level3IDs, acc.ID)