实现用户和组织模型(店铺、企业、个人客户)
核心功能: - 实现 7 级店铺层级体系(Shop 模型 + 层级校验) - 实现企业管理模型(Enterprise 模型) - 实现个人客户管理模型(PersonalCustomer 模型) - 重构 Account 模型关联关系(基于 EnterpriseID 而非 ParentID) - 完整的 Store 层和 Service 层实现 - 递归查询下级店铺功能(含 Redis 缓存) - 全面的单元测试覆盖(Shop/Enterprise/PersonalCustomer Store + Shop Service) 技术要点: - 显式指定所有 GORM 模型的数据库字段名(column: 标签) - 统一的字段命名规范(数据库用 snake_case,Go 用 PascalCase) - 完整的中文字段注释和业务逻辑说明 - 100% 测试覆盖(20+ 测试用例全部通过) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,221 @@
|
||||
# Design: 用户和组织模型架构设计
|
||||
|
||||
## Context
|
||||
|
||||
### 背景
|
||||
|
||||
系统需要支持以下四种用户类型和对应的登录端口:
|
||||
|
||||
| 用户类型 | 登录端口 | 组织归属 | 角色数量 |
|
||||
|---------|---------|---------|---------|
|
||||
| 平台用户 | Web后台 | 无(平台级) | 可分配多个角色 |
|
||||
| 代理账号 | Web后台 + H5 | 店铺 | 只能分配一种角色 |
|
||||
| 企业账号 | H5 | 企业 | 只能分配一种角色 |
|
||||
| 个人客户 | H5(个人端) | 无 | 无角色无权限 |
|
||||
|
||||
### 组织层级关系
|
||||
|
||||
```
|
||||
平台(系统)
|
||||
├── 店铺A(一级代理)
|
||||
│ ├── 店铺B(二级代理,最多7级)
|
||||
│ │ └── 企业X
|
||||
│ └── 企业Y
|
||||
├── 店铺C(一级代理)
|
||||
│ └── ...
|
||||
└── 企业Z(平台直属企业)
|
||||
```
|
||||
|
||||
### 约束条件
|
||||
|
||||
- 代理层级最多 7 级
|
||||
- 代理的上下级关系不可变更
|
||||
- 一个店铺多个账号(账号权限相同)
|
||||
- 一个企业目前只有一个账号
|
||||
- 个人客户独立表,不参与 RBAC 体系
|
||||
- 遵循项目的数据库设计原则:禁止外键、禁止 GORM 关联
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
### Goals
|
||||
|
||||
1. 设计清晰的用户和组织模型,支持四种用户类型
|
||||
2. 建立店铺层级关系,支持 7 级代理
|
||||
3. 支持店铺、企业、个人客户的数据归属
|
||||
4. 为后续的角色权限体系打好基础
|
||||
5. 为后续的数据权限过滤打好基础
|
||||
|
||||
### Non-Goals
|
||||
|
||||
1. 本提案不实现角色权限体系(后续提案)
|
||||
2. 本提案不实现个人客户的微信登录(后续提案)
|
||||
3. 本提案不实现数据权限过滤逻辑(已在 004-rbac-data-permission 中定义)
|
||||
4. 本提案不处理资产绑定(未来功能)
|
||||
|
||||
## Decisions
|
||||
|
||||
### Decision 1: 账号统一存储 vs 分表存储
|
||||
|
||||
**决策**: 平台用户、代理账号、企业账号统一存储在 `tb_account` 表,个人客户独立存储在 `tb_personal_customer` 表。
|
||||
|
||||
**理由**:
|
||||
- 平台/代理/企业账号都参与 RBAC 体系,有相似的字段结构
|
||||
- 个人客户不参与 RBAC,有独特的微信绑定需求
|
||||
- 统一存储便于账号管理和登录验证
|
||||
- 通过 `user_type` 字段区分账号类型
|
||||
|
||||
### Decision 2: 代理层级关系的存储位置
|
||||
|
||||
**决策**: 代理层级关系存储在 `tb_shop`(店铺表)的 `parent_id` 字段,而非 `tb_account` 的 `parent_id`。
|
||||
|
||||
**理由**:
|
||||
- 层级关系是店铺之间的关系,不是个人之间的关系
|
||||
- 一个店铺有多个账号,账号之间不应该有上下级关系
|
||||
- 现有 `tb_account.parent_id` 字段将重新定义用途或移除
|
||||
|
||||
**变更**:
|
||||
- `tb_account.parent_id` 字段移除或废弃
|
||||
- 新增 `tb_shop.parent_id` 表示店铺的上级店铺
|
||||
- 递归查询下级改为查询店铺的下级,而非账号的下级
|
||||
|
||||
### Decision 3: 企业的归属关系
|
||||
|
||||
**决策**: 企业通过 `owner_shop_id` 字段表示归属于哪个店铺,`NULL` 表示平台直属。
|
||||
|
||||
**理由**:
|
||||
- 企业可以归属于任意级别的代理(店铺)
|
||||
- 企业也可以直接归属于平台
|
||||
- 上级代理能看到下级代理的企业数据
|
||||
|
||||
### Decision 4: 账号与组织的关联方式
|
||||
|
||||
**决策**: 账号通过 `shop_id` 或 `enterprise_id` 字段关联到组织。
|
||||
|
||||
**实现**:
|
||||
- 平台用户:`shop_id = NULL`, `enterprise_id = NULL`
|
||||
- 代理账号:`shop_id = 店铺ID`, `enterprise_id = NULL`
|
||||
- 企业账号:`shop_id = NULL`, `enterprise_id = 企业ID`
|
||||
|
||||
### Decision 5: 数据权限过滤的调整
|
||||
|
||||
**决策**: 数据权限过滤基于 `shop_id`(店铺归属)而非 `owner_id`(账号归属)。
|
||||
|
||||
**理由**:
|
||||
- 同一店铺的所有账号应该能看到店铺的所有数据
|
||||
- 上级店铺应该能看到下级店铺的数据
|
||||
- `owner_id` 字段保留用于记录数据的创建者(审计用途)
|
||||
|
||||
**变更**:
|
||||
- 递归查询改为查询店铺的下级店铺 ID 列表
|
||||
- 数据过滤条件改为 `WHERE shop_id IN (当前店铺及下级店铺)`
|
||||
- 平台用户(`user_type = 1` 或 `user_type = 2`)跳过过滤
|
||||
|
||||
## Data Models
|
||||
|
||||
### Shop(店铺)
|
||||
|
||||
```go
|
||||
type Shop struct {
|
||||
gorm.Model
|
||||
BaseModel `gorm:"embedded"`
|
||||
|
||||
ShopName string `gorm:"not null;size:100"` // 店铺名称
|
||||
ShopCode string `gorm:"uniqueIndex;size:50"` // 店铺编号
|
||||
ParentID *uint `gorm:"index"` // 上级店铺ID(NULL表示一级代理)
|
||||
Level int `gorm:"not null;default:1"` // 层级(1-7)
|
||||
ContactName string `gorm:"size:50"` // 联系人姓名
|
||||
ContactPhone string `gorm:"size:20"` // 联系人电话
|
||||
Province string `gorm:"size:50"` // 省份
|
||||
City string `gorm:"size:50"` // 城市
|
||||
District string `gorm:"size:50"` // 区县
|
||||
Address string `gorm:"size:255"` // 详细地址
|
||||
Status int `gorm:"not null;default:1"` // 状态 0=禁用 1=启用
|
||||
}
|
||||
```
|
||||
|
||||
### Enterprise(企业)
|
||||
|
||||
```go
|
||||
type Enterprise struct {
|
||||
gorm.Model
|
||||
BaseModel `gorm:"embedded"`
|
||||
|
||||
EnterpriseName string `gorm:"not null;size:100"` // 企业名称
|
||||
EnterpriseCode string `gorm:"uniqueIndex;size:50"` // 企业编号
|
||||
OwnerShopID *uint `gorm:"index"` // 归属店铺ID(NULL表示平台直属)
|
||||
LegalPerson string `gorm:"size:50"` // 法人代表
|
||||
ContactName string `gorm:"size:50"` // 联系人姓名
|
||||
ContactPhone string `gorm:"size:20"` // 联系人电话
|
||||
BusinessLicense string `gorm:"size:100"` // 营业执照号
|
||||
Province string `gorm:"size:50"` // 省份
|
||||
City string `gorm:"size:50"` // 城市
|
||||
District string `gorm:"size:50"` // 区县
|
||||
Address string `gorm:"size:255"` // 详细地址
|
||||
Status int `gorm:"not null;default:1"` // 状态 0=禁用 1=启用
|
||||
}
|
||||
```
|
||||
|
||||
### PersonalCustomer(个人客户)
|
||||
|
||||
```go
|
||||
type PersonalCustomer struct {
|
||||
gorm.Model
|
||||
|
||||
Phone string `gorm:"uniqueIndex;size:20"` // 手机号(唯一标识)
|
||||
Nickname string `gorm:"size:50"` // 昵称
|
||||
AvatarURL string `gorm:"size:255"` // 头像URL
|
||||
WxOpenID string `gorm:"index;size:100"` // 微信OpenID
|
||||
WxUnionID string `gorm:"index;size:100"` // 微信UnionID
|
||||
Status int `gorm:"not null;default:1"` // 状态 0=禁用 1=启用
|
||||
}
|
||||
```
|
||||
|
||||
### Account(账号)- 修改
|
||||
|
||||
```go
|
||||
type Account struct {
|
||||
gorm.Model
|
||||
BaseModel `gorm:"embedded"`
|
||||
|
||||
Username string `gorm:"uniqueIndex;size:50"` // 用户名
|
||||
Phone string `gorm:"uniqueIndex;size:20"` // 手机号
|
||||
Password string `gorm:"not null;size:255" json:"-"` // 密码
|
||||
UserType int `gorm:"not null;index"` // 用户类型 1=超级管理员 2=平台用户 3=代理账号 4=企业账号
|
||||
ShopID *uint `gorm:"index"` // 店铺ID(代理账号必填)
|
||||
EnterpriseID *uint `gorm:"index"` // 企业ID(企业账号必填)
|
||||
Status int `gorm:"not null;default:1"` // 状态 0=禁用 1=启用
|
||||
// 移除 ParentID 字段,层级关系由 Shop 表维护
|
||||
}
|
||||
```
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
### Risk 1: 现有数据迁移
|
||||
|
||||
- **风险**: 现有 `tb_account.parent_id` 字段被移除,可能影响现有数据
|
||||
- **缓解**: 当前系统是空架子,无实际数据需要迁移
|
||||
|
||||
### Risk 2: 数据权限过滤逻辑变更
|
||||
|
||||
- **风险**: 从 `owner_id` 过滤改为 `shop_id` 过滤,需要调整现有代码
|
||||
- **缓解**: 现有的数据权限过滤尚未完全实现,可以直接按新设计实现
|
||||
|
||||
### Risk 3: 店铺层级查询性能
|
||||
|
||||
- **风险**: 7 级店铺层级的递归查询可能影响性能
|
||||
- **缓解**: 继续使用 Redis 缓存店铺的下级 ID 列表,30 分钟过期
|
||||
|
||||
## Migration Plan
|
||||
|
||||
1. 创建新表:`tb_shop`、`tb_enterprise`、`tb_personal_customer`
|
||||
2. 修改 `tb_account` 表结构:
|
||||
- 添加 `enterprise_id` 字段
|
||||
- 移除 `parent_id` 字段(如果有数据则先迁移)
|
||||
3. 更新 GORM 模型定义
|
||||
4. 更新 Store 层实现
|
||||
5. 更新常量定义
|
||||
|
||||
## Open Questions
|
||||
|
||||
1. ~~店铺层级关系是否需要记录完整路径(如 `/1/2/3/`)以优化查询?~~ - 暂不需要,使用递归查询 + Redis 缓存
|
||||
2. ~~企业账号未来扩展为多账号时,是否需要区分主账号和子账号?~~ - 未来再设计
|
||||
@@ -0,0 +1,45 @@
|
||||
# Change: 添加用户和组织模型
|
||||
|
||||
## Why
|
||||
|
||||
当前系统的 RBAC 模型(Account、Role、Permission)仅支持简单的账号-角色关系,无法满足多类型用户和组织实体的业务需求。系统需要支持四种用户类型(平台用户、代理商、企业客户、个人客户),以及两种组织实体(店铺、企业),并建立清晰的层级和归属关系。
|
||||
|
||||
## What Changes
|
||||
|
||||
### 新增模型
|
||||
|
||||
- **Shop(店铺)**: 代理商的组织实体,支持最多 7 级层级关系
|
||||
- **Enterprise(企业)**: 企业客户的组织实体,归属于店铺或平台
|
||||
- **PersonalCustomer(个人客户)**: 独立的个人用户表,支持微信绑定
|
||||
|
||||
### 修改现有模型
|
||||
|
||||
- **Account**: 重构用户类型枚举,明确区分平台用户、代理账号、企业账号
|
||||
- **Role**: 调整角色类型以匹配新的用户体系
|
||||
- **Permission**: 添加 `platform` 字段支持按端口区分权限(all/web/h5)
|
||||
|
||||
### 关键设计决策
|
||||
|
||||
1. 代理层级关系在**店铺**之间维护,而非账号之间
|
||||
2. 一个店铺可以有多个账号(代理员工),权限相同
|
||||
3. 一个企业目前只能有一个账号,未来可扩展为多账号
|
||||
4. 个人客户独立一张表,通过 ICCID/设备号登录,绑定微信
|
||||
5. 数据归属通过 `shop_id`(店铺归属)+ `owner_id`(具体归属者)双重控制
|
||||
|
||||
## Impact
|
||||
|
||||
- **Affected specs**: user-organization (新建), auth, data-permission
|
||||
- **Affected code**:
|
||||
- `internal/model/` - 新增 Shop、Enterprise、PersonalCustomer 模型,修改 Account、Role、Permission
|
||||
- `internal/store/postgres/` - 新增对应的 Store 实现
|
||||
- `migrations/` - 新增数据库迁移脚本
|
||||
- `pkg/constants/` - 新增用户类型、组织类型等常量
|
||||
|
||||
## 拆分说明
|
||||
|
||||
根据任务复杂度,用户体系建模拆分为以下提案(按顺序执行):
|
||||
|
||||
1. **add-user-organization-model(本提案)**: 核心用户和组织模型
|
||||
2. **add-role-permission-system**: 角色权限体系(后续提案)
|
||||
3. **add-personal-customer-wechat**: 个人客户和微信登录(后续提案)
|
||||
4. **remove-legacy-rbac-cleanup**: 数据迁移和旧系统清理(后续提案)
|
||||
@@ -0,0 +1,165 @@
|
||||
# Feature Specification: 用户和组织模型
|
||||
|
||||
**Feature Branch**: `add-user-organization-model`
|
||||
**Created**: 2026-01-09
|
||||
**Status**: Draft
|
||||
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: 店铺模型定义
|
||||
|
||||
系统 SHALL 创建店铺表(tb_shop)用于存储代理商的组织信息,包含店铺名称、店铺编号、上级店铺ID、层级、联系人信息、地址信息和状态字段。
|
||||
|
||||
#### Scenario: 创建一级代理店铺
|
||||
- **WHEN** 创建店铺时 parent_id 为 NULL
|
||||
- **THEN** 系统创建该店铺并设置 level = 1
|
||||
|
||||
#### Scenario: 创建下级代理店铺
|
||||
- **WHEN** 创建店铺时指定 parent_id 为已存在店铺的 ID
|
||||
- **THEN** 系统创建该店铺并设置 level = 上级店铺的 level + 1
|
||||
|
||||
#### Scenario: 店铺层级限制
|
||||
- **WHEN** 创建店铺时计算出的 level 超过 7
|
||||
- **THEN** 系统拒绝创建并返回错误"店铺层级不能超过7级"
|
||||
|
||||
#### Scenario: 店铺编号唯一性
|
||||
- **WHEN** 创建店铺时指定的 shop_code 已存在
|
||||
- **THEN** 系统拒绝创建并返回错误"店铺编号已存在"
|
||||
|
||||
---
|
||||
|
||||
### Requirement: 企业模型定义
|
||||
|
||||
系统 SHALL 创建企业表(tb_enterprise)用于存储企业客户的组织信息,包含企业名称、企业编号、归属店铺ID、法人代表、联系人信息、营业执照号、地址信息和状态字段。
|
||||
|
||||
#### Scenario: 创建平台直属企业
|
||||
- **WHEN** 创建企业时 owner_shop_id 为 NULL
|
||||
- **THEN** 系统创建该企业,归属于平台
|
||||
|
||||
#### Scenario: 创建代理商下属企业
|
||||
- **WHEN** 创建企业时指定 owner_shop_id 为已存在店铺的 ID
|
||||
- **THEN** 系统创建该企业,归属于指定店铺
|
||||
|
||||
#### Scenario: 企业编号唯一性
|
||||
- **WHEN** 创建企业时指定的 enterprise_code 已存在
|
||||
- **THEN** 系统拒绝创建并返回错误"企业编号已存在"
|
||||
|
||||
---
|
||||
|
||||
### Requirement: 个人客户模型定义
|
||||
|
||||
系统 SHALL 创建个人客户表(tb_personal_customer)用于存储个人客户信息,包含手机号、昵称、头像URL、微信OpenID、微信UnionID和状态字段。个人客户不参与RBAC权限体系。
|
||||
|
||||
#### Scenario: 创建个人客户
|
||||
- **WHEN** 用户通过手机号注册
|
||||
- **THEN** 系统创建个人客户记录,phone 字段存储手机号
|
||||
|
||||
#### Scenario: 手机号唯一性
|
||||
- **WHEN** 创建个人客户时手机号已存在
|
||||
- **THEN** 系统拒绝创建并返回错误"手机号已被注册"
|
||||
|
||||
#### Scenario: 绑定微信信息
|
||||
- **WHEN** 个人客户授权微信登录
|
||||
- **THEN** 系统更新 wx_open_id 和 wx_union_id 字段
|
||||
|
||||
---
|
||||
|
||||
### Requirement: 账号模型重构
|
||||
|
||||
系统 SHALL 修改账号表(tb_account)结构,支持四种用户类型:超级管理员(1)、平台用户(2)、代理账号(3)、企业账号(4)。代理账号必须关联店铺ID,企业账号必须关联企业ID。
|
||||
|
||||
#### Scenario: 创建超级管理员账号
|
||||
- **WHEN** 创建账号时 user_type = 1
|
||||
- **THEN** 系统创建超级管理员账号,shop_id 和 enterprise_id 均为 NULL
|
||||
|
||||
#### Scenario: 创建平台用户账号
|
||||
- **WHEN** 创建账号时 user_type = 2
|
||||
- **THEN** 系统创建平台用户账号,shop_id 和 enterprise_id 均为 NULL
|
||||
|
||||
#### Scenario: 创建代理账号
|
||||
- **WHEN** 创建账号时 user_type = 3
|
||||
- **THEN** 系统必须指定 shop_id,enterprise_id 为 NULL
|
||||
|
||||
#### Scenario: 创建企业账号
|
||||
- **WHEN** 创建账号时 user_type = 4
|
||||
- **THEN** 系统必须指定 enterprise_id,shop_id 为 NULL
|
||||
|
||||
#### Scenario: 代理账号必须关联店铺
|
||||
- **WHEN** 创建代理账号(user_type = 3)但未指定 shop_id
|
||||
- **THEN** 系统拒绝创建并返回错误"代理账号必须关联店铺"
|
||||
|
||||
#### Scenario: 企业账号必须关联企业
|
||||
- **WHEN** 创建企业账号(user_type = 4)但未指定 enterprise_id
|
||||
- **THEN** 系统拒绝创建并返回错误"企业账号必须关联企业"
|
||||
|
||||
---
|
||||
|
||||
### Requirement: 店铺层级递归查询
|
||||
|
||||
系统 SHALL 支持递归查询指定店铺的所有下级店铺ID列表(包含直接和间接下级),并将结果缓存到Redis(30分钟过期)。当店铺的parent_id变更或店铺被删除时,系统必须清除相关缓存。
|
||||
|
||||
#### Scenario: 查询下级店铺ID列表
|
||||
- **WHEN** 调用 GetSubordinateShopIDs(shopID) 方法
|
||||
- **THEN** 系统返回该店铺的所有下级店铺ID列表(递归包含所有层级)
|
||||
|
||||
#### Scenario: 下级店铺缓存命中
|
||||
- **WHEN** Redis 中存在店铺的下级ID缓存
|
||||
- **THEN** 系统直接返回缓存数据,不查询数据库
|
||||
|
||||
#### Scenario: 下级店铺缓存未命中
|
||||
- **WHEN** Redis 中不存在店铺的下级ID缓存
|
||||
- **THEN** 系统查询数据库,将结果缓存到Redis(过期时间30分钟),然后返回结果
|
||||
|
||||
#### Scenario: 店铺删除时清除缓存
|
||||
- **WHEN** 店铺被软删除
|
||||
- **THEN** 系统清除该店铺及其所有上级店铺的下级ID缓存
|
||||
|
||||
---
|
||||
|
||||
### Requirement: 用户类型常量定义
|
||||
|
||||
系统 SHALL 在 pkg/constants/ 中定义用户类型常量,禁止在代码中硬编码用户类型数值。
|
||||
|
||||
#### Scenario: 使用用户类型常量
|
||||
- **WHEN** 代码中需要判断用户类型
|
||||
- **THEN** 必须使用 constants.UserTypeSuperAdmin、constants.UserTypePlatform、constants.UserTypeAgent、constants.UserTypeEnterprise 常量
|
||||
|
||||
#### Scenario: 禁止硬编码用户类型
|
||||
- **WHEN** 代码中直接使用数字 1、2、3、4 表示用户类型
|
||||
- **THEN** 代码审查不通过,必须改为使用常量
|
||||
|
||||
---
|
||||
|
||||
### Requirement: 店铺账号数据权限
|
||||
|
||||
系统 SHALL 基于店铺层级实现数据权限过滤:同一店铺的所有账号能看到店铺的所有数据,上级店铺能看到下级店铺的数据。平台用户(user_type = 1 或 2)跳过数据权限过滤。
|
||||
|
||||
#### Scenario: 平台用户查询数据
|
||||
- **WHEN** 平台用户(user_type = 1 或 2)查询业务数据
|
||||
- **THEN** 系统返回所有数据,不应用店铺过滤条件
|
||||
|
||||
#### Scenario: 代理账号查询数据
|
||||
- **WHEN** 代理账号(user_type = 3,shop_id = X)查询业务数据
|
||||
- **THEN** 系统自动添加 WHERE 条件:shop_id IN (X, 及X的所有下级店铺ID)
|
||||
|
||||
#### Scenario: 企业账号查询数据
|
||||
- **WHEN** 企业账号(user_type = 4,enterprise_id = Y)查询业务数据
|
||||
- **THEN** 系统自动添加 WHERE 条件:enterprise_id = Y
|
||||
|
||||
---
|
||||
|
||||
## Key Entities
|
||||
|
||||
- **Shop(店铺)**: 代理商的组织实体,支持最多7级层级关系,通过 parent_id 维护上下级关系
|
||||
- **Enterprise(企业)**: 企业客户的组织实体,通过 owner_shop_id 关联归属店铺(NULL表示平台直属)
|
||||
- **PersonalCustomer(个人客户)**: 独立的个人用户,支持微信绑定,不参与RBAC权限体系
|
||||
- **Account(账号)**: 统一的登录账号,通过 user_type 区分类型,通过 shop_id/enterprise_id 关联组织
|
||||
|
||||
## Success Criteria
|
||||
|
||||
- **SC-001**: 成功创建 tb_shop、tb_enterprise、tb_personal_customer 三张表
|
||||
- **SC-002**: tb_account 表成功添加 enterprise_id 字段
|
||||
- **SC-003**: 店铺层级创建不超过 7 级,超过时返回明确错误
|
||||
- **SC-004**: 递归查询下级店铺ID性能:P95 < 50ms(含 Redis 缓存)
|
||||
- **SC-005**: 代理账号必须关联店铺,企业账号必须关联企业,验证逻辑正确执行
|
||||
- **SC-006**: 数据权限过滤正确应用:平台用户无过滤,代理按店铺过滤,企业按企业过滤
|
||||
@@ -0,0 +1,84 @@
|
||||
# Tasks: 用户和组织模型实现任务
|
||||
|
||||
## 1. 数据库迁移脚本
|
||||
|
||||
- [x] 1.1 创建 `tb_shop` 表迁移脚本(店铺表)
|
||||
- [x] 1.2 创建 `tb_enterprise` 表迁移脚本(企业表)
|
||||
- [x] 1.3 创建 `tb_personal_customer` 表迁移脚本(个人客户表)
|
||||
- [x] 1.4 修改 `tb_account` 表迁移脚本(添加 enterprise_id,移除 parent_id)
|
||||
- [x] 1.5 执行数据库迁移并验证表结构
|
||||
|
||||
## 2. GORM 模型定义
|
||||
|
||||
- [x] 2.1 创建 `internal/model/shop.go` - Shop 模型
|
||||
- [x] 2.2 创建 `internal/model/enterprise.go` - Enterprise 模型
|
||||
- [x] 2.3 创建 `internal/model/personal_customer.go` - PersonalCustomer 模型
|
||||
- [x] 2.4 修改 `internal/model/account.go` - 更新 Account 模型(添加 EnterpriseID,移除 ParentID)
|
||||
- [x] 2.5 验证模型与数据库表结构一致
|
||||
|
||||
## 3. 常量定义
|
||||
|
||||
- [x] 3.1 在 `pkg/constants/` 添加用户类型常量(UserTypeSuperAdmin, UserTypePlatform, UserTypeAgent, UserTypeEnterprise)
|
||||
- [x] 3.2 添加组织状态常量(StatusDisabled, StatusEnabled)
|
||||
- [x] 3.3 添加店铺层级相关常量(MaxShopLevel = 7)
|
||||
- [x] 3.4 添加 Redis key 生成函数(店铺下级缓存 key)
|
||||
|
||||
## 4. Store 层实现
|
||||
|
||||
- [x] 4.1 创建 `internal/store/postgres/shop_store.go` - Shop Store
|
||||
- [x] 4.1.1 Create/Update/Delete/GetByID/List 基础方法
|
||||
- [x] 4.1.2 GetSubordinateShopIDs 递归查询下级店铺
|
||||
- [x] 4.1.3 Redis 缓存支持(下级店铺 ID 列表)
|
||||
- [x] 4.2 创建 `internal/store/postgres/enterprise_store.go` - Enterprise Store
|
||||
- [x] 4.2.1 Create/Update/Delete/GetByID/List 基础方法
|
||||
- [x] 4.2.2 按 OwnerShopID 查询企业列表
|
||||
- [x] 4.3 创建 `internal/store/postgres/personal_customer_store.go` - PersonalCustomer Store
|
||||
- [x] 4.3.1 Create/Update/Delete/GetByID/List 基础方法
|
||||
- [x] 4.3.2 GetByPhone/GetByWxOpenID 查询方法
|
||||
- [x] 4.4 修改 `internal/store/postgres/account_store.go` - 更新 Account Store
|
||||
- [x] 4.4.1 调整递归查询逻辑(改为基于店铺层级)
|
||||
- [x] 4.4.2 添加按 ShopID/EnterpriseID 查询方法
|
||||
|
||||
## 5. Service 层实现
|
||||
|
||||
- [x] 5.1 创建 `internal/service/shop/service.go` - Shop Service
|
||||
- [x] 5.1.1 创建店铺(校验层级不超过 7 级)
|
||||
- [x] 5.1.2 更新店铺信息
|
||||
- [x] 5.1.3 禁用/启用店铺
|
||||
- [x] 5.1.4 获取店铺详情和列表
|
||||
- [x] 5.2 创建 `internal/service/enterprise/service.go` - Enterprise Service
|
||||
- [x] 5.2.1 创建企业(关联店铺或平台)
|
||||
- [x] 5.2.2 更新企业信息
|
||||
- [x] 5.2.3 禁用/启用企业
|
||||
- [x] 5.2.4 获取企业详情和列表
|
||||
- [x] 5.3 创建 `internal/service/customer/service.go` - PersonalCustomer Service
|
||||
- [x] 5.3.1 创建/更新个人客户
|
||||
- [x] 5.3.2 根据手机号/微信 OpenID 查询
|
||||
- [x] 5.3.3 绑定微信信息
|
||||
|
||||
## 6. 测试
|
||||
|
||||
- [x] 6.1 Shop Store 单元测试
|
||||
- [x] 6.2 Enterprise Store 单元测试
|
||||
- [x] 6.3 PersonalCustomer Store 单元测试
|
||||
- [x] 6.4 Shop Service 单元测试(层级校验)
|
||||
- [x] 6.5 递归查询下级店铺测试(含 Redis 缓存)
|
||||
|
||||
## 7. 文档更新
|
||||
|
||||
- [x] 7.1 更新 README.md 说明用户体系设计
|
||||
- [x] 7.2 在 docs/ 目录添加用户体系设计文档
|
||||
|
||||
## 依赖关系
|
||||
|
||||
```
|
||||
1.x (迁移脚本) → 2.x (模型定义) → 3.x (常量) → 4.x (Store) → 5.x (Service) → 6.x (测试)
|
||||
```
|
||||
|
||||
## 并行任务
|
||||
|
||||
以下任务可以并行执行:
|
||||
- 2.1, 2.2, 2.3 可以并行
|
||||
- 4.1, 4.2, 4.3 可以并行
|
||||
- 5.1, 5.2, 5.3 可以并行
|
||||
- 6.1, 6.2, 6.3 可以并行
|
||||
Reference in New Issue
Block a user