# 技术调研：商家门店分管账号

## 1. 账号存储方案

### 决策

分管账号继续存放在 `info_user`，使用新的 `user_type=5` 表示“商家分管账号”，并通过 `merchant_owner_id` 关联唯一的商家主账号。

### 依据

- 商家端登录、JWT、Redis 会话、CID、语言和消息归属都以 `InfoUser.userId` 为中心，复用 `info_user` 可以保持现有认证与推送链路。
- 平台商家页固定传 `userType=1`，Mapper 使用 `user_type = #{userType}`；类型 5 天然不会进入商家列表、导出和商家数量统计。
- `user_type=4` 已用于摊位商家，不能复用。

### 否决方案

- **分管账号仍使用 `user_type=1`，另加角色字段**：所有按 `user_type=1` 统计、审核和导出的查询都必须额外排除分管账号，漏改一个入口就会污染平台商家管理。
- **单独建立完整账号表**：需要复制登录、Token、CID、语言和消息体系，认证链路复杂且容易产生两套用户主键。

## 2. 双重停用状态

### 决策

- 复用 `info_user.status` 作为平台控制状态：`0=正常`、`1=平台停用`。
- 新增 `subaccount_status` 作为主账号控制状态：`0=启用`、`1=主账号停用`，只对类型 5 生效。
- 分管账号可用条件为：自身未删除、平台状态正常、主账号控制状态正常、所属主账号未删除且平台状态正常。

### 原因

如果主账号和平台共用一个可写状态，主账号可以重新启用平台强制停用的账号。两个状态必须独立，并由不同接口控制。

## 3. 店铺授权模型

### 决策

新增 `merchant_subaccount_store` 多对多关联表。授权保存时同时校验：分管账号的 `merchant_owner_id` 等于 `pos_store.user_id`。

### 原因

一个分管账号可负责多个店铺，一个店铺也可配置多个分管账号；JSON、逗号字符串或 `info_user.store_id` 都不能可靠表达该关系。

## 4. 权限校验边界

### 决策

在 `ruoyi-system` 建立统一的 `MerchantStoreAccessService`，每次业务请求从数据库读取当前账号和目标数据的真实门店归属：

- 主账号可访问 `pos_store.user_id = 当前账号` 的全部门店。
- 分管账号只可访问关联表中的有效门店。
- 订单以 `pos_order.md_id`、商品以 `pos_food.md_id`、分类和规格以其实际关联商品或门店为准。
- 新增店铺、分管账号管理、支付配置、结算和提现必须调用 `requireOwner`。

不把店铺集合写入 Token，也不依赖前端传入的主账号 ID，因此撤销授权后下一次请求立即生效。

## 5. 平台呈现

### 决策

不新增顶级“商家”行或独立商家审核流程。在平台 `sjuser.vue` 的主商家操作区增加“分管账号”入口，以对话框/抽屉展示该主账号的下属账号。

平台可以修改 `info_user.status` 以强制停用或恢复，但不能修改 `subaccount_status`、密码或店铺授权。

## 6. 在线状态与通知资格

### 决策

- 平台“在线”状态：Redis 中存在该账号的商家 App 或 PC 有效会话。
- 外部推送资格：账号满足全部启用条件、拥有目标店铺授权、存在商家 App 有效会话且 CID 非空。
- 任一可接收分管账号存在时，消息分别归属这些账号，主账号不重复接收。
- 没有可接收分管账号时，消息归属主账号并尝试主账号推送。
- 外部推送按 CID 去重；站内消息仍按账号分别入库。

商家登录成功时更新 `last_login_at`。停用账号时删除其商家 App/PC Redis 会话；分管账号的每次业务请求仍重新检查数据库状态，不能只依赖会话存在。

## 7. 现有代码风险与兼容措施

- `InfoUserController.shanglodeing` 当前允许类型 1、3、4，且没有校验 `status`。实现时加入类型 5，并在签发 Token 前统一执行账号可用性检查。
- `PosStoreController.addmendian`、`PosFoodController.setposfood` 等有效商家端写入口存在未声明 token 或信任请求体归属字段的情况。实现时按 Controller 规范补充 `@RequestHeader String token`，并从 Token 解析操作者。
- 平台商家列表、导出、统计仍使用 `user_type=1`，新增回归测试证明类型 5 不会出现或计数。
- `user_type=4` 的摊位逻辑、类型 3 的夜市逻辑保持不变；不能把分管账号塞入现有单店 `store_id` 规则。
- 当前工作区已有订单状态和推送调整，实施时必须在其基础上接入通知路由，不能覆盖或回退这些未提交改动。

## 8. 安全要求

- 新接口使用明确 DTO 和 `@RequestBody`，App token 使用 `@RequestHeader`，不使用 `Map` 接收请求。
- 手机号、名称、密码和店铺 ID 集合在 Controller/Service 中显式校验；错误使用现有国际化机制。
- 密码沿用现有商家端 RSA 传输与存储兼容方式，禁止记录明文、密文或 Token。
- 所有 Mapper 使用参数绑定，不拼接用户输入 SQL。
- 批量授权在事务内完成；任一店铺越权时整体回滚。
- 通过实体真实归属校验订单、商品和退款，防止 IDOR（越权直接对象访问）。
