# 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**: 数据权限过滤正确应用：平台用户无过滤，代理按店铺过滤，企业按企业过滤
