# 数据模型:商家门店分管账号 ## `info_user` 扩展 | 字段 | 类型 | 可空 | 默认值 | 说明 | |---|---|---:|---|---| | `merchant_owner_id` | `BIGINT` | 是 | `NULL` | 类型 5 分管账号所属的商家主账号 ID;其他类型为空 | | `subaccount_status` | `CHAR(1)` | 是 | `NULL` | 主账号控制状态:`0=启用`、`1=停用`;仅类型 5 使用 | | `last_login_at` | `DATETIME` | 是 | `NULL` | 商家端最近一次成功登录时间 | 新增索引: ```sql KEY idx_info_user_merchant_owner (merchant_owner_id, user_type, del_flag) ``` ### 类型与状态约束 | 账号 | `user_type` | `merchant_owner_id` | `status` | `subaccount_status` | |---|---:|---|---|---| | 普通商家主账号 | `1` | `NULL` | 平台控制 | `NULL` | | 夜市账号 | `3` | `NULL` | 平台控制 | `NULL` | | 摊位商家 | `4` | 现有规则 | 平台控制 | `NULL` | | 商家分管账号 | `5` | 必须为类型 1 主账号 | 平台控制 | 主账号控制 | 类型 5 不创建独立商家钱包,不参与商家审核,不写入商户资质、收款配置或 `store_id` 单店字段。 ## `merchant_subaccount_store` | 字段 | 类型 | 可空 | 说明 | |---|---|---:|---| | `id` | `BIGINT AUTO_INCREMENT` | 否 | 主键 | | `subaccount_user_id` | `BIGINT` | 否 | `info_user.user_id`,必须是类型 5 | | `store_id` | `BIGINT` | 否 | `pos_store.id` | | `create_time` | `DATETIME` | 否 | 创建时间 | | `update_time` | `DATETIME` | 否 | 更新时间 | 索引与唯一性: ```sql PRIMARY KEY (id) UNIQUE KEY uk_subaccount_store (subaccount_user_id, store_id) KEY idx_subaccount_store_store (store_id, subaccount_user_id) ``` 不使用软删除。取消授权时删除关联行;权限查询始终同时验证分管账号状态、所属主账号状态和店铺当前所有者。 ## 聚合视图 ### `MerchantSubaccountView` - `userId` - `name` - `phone` - `merchantOwnerId` - `ownerEnabled`:主账号是否启用该分管账号 - `platformEnabled`:平台是否允许该分管账号 - `online`:是否存在有效商家 App 或 PC 会话 - `lastLoginAt` - `stores[]`:`storeId`、`storeName` ### 可用性判定 ```text subaccount.del_flag = 0 AND subaccount.user_type = 5 AND subaccount.status = 0 AND subaccount.subaccount_status = 0 AND owner.user_type = 1 AND owner.del_flag = 0 AND owner.status = 0 ``` 通知接收还必须满足目标店铺授权有效、App 会话有效且 CID 非空。 ## 数据生命周期 1. 主账号创建分管账号:插入 `info_user` 类型 5,再批量插入授权关系,单事务提交。 2. 调整店铺:验证全部店铺归属后,以事务替换该账号授权集合。 3. 主账号停用:只更新 `subaccount_status=1` 并撤销该账号商家会话。 4. 平台停用:只更新 `status=1` 并撤销该账号商家会话。 5. 删除店铺:同步删除该店铺授权关系;即使清理失败,权限服务也因店铺所有权或有效性不符而拒绝访问。 6. 主商家停用:不批量改写子账号字段;可用性判定通过主账号状态统一阻断,恢复主商家后仍保留原分配关系。