Made-with: Cursor
16 KiB
租户访客默认楼层:数据库配置阶段 — 详细技术设计
文档性质:实施级技术设计(TDD 范围:本阶段仅 数据库表 + 电梯服务侧读表求交;不包含 物业管理端前端页面与开放管理 API)。
产品依据:租户访客默认楼层技术产品方案(策略类型、安全底线、AC 验收)。
流程依据:访客注册与派梯楼层业务流程走查(UC-01 / UC-02、PersonRuleServiceImpl.addVisitor)。
| 项目 | 内容 |
|---|---|
| 版本 | v0.1 草案(数据库阶段) |
| 适用工程 | maven-cw-elevator-application(电梯应用库;落库表位于电梯库或与电梯同数据源的业务库,以现网数据源划分为准) |
| 读者 | 后端开发、DBA、集成测试、运维 |
1. 背景与阶段目标
1.1 问题复述
多租户场景下,部分机构要求:在调用方不传 floorIds(走 UC-01)时,访客派梯生效楼层不得简单等同于被访人组织侧 floorList 全集,而应收敛为机构允许的若干 zoneId(如固定接待层)。未做特殊要求的租户须与现网行为完全一致。
1.2 本阶段目标(范围边界)
| 目标 | 说明 |
|---|---|
| 配置方式 | 通过 数据库表 维护「哪些租户启用访客楼层策略及允许列表」;由实施/DBA/SQL 脚本录入,不提供 物业/客服可视化管理界面(后续阶段再做)。 |
| 行为 | 仅对存在有效策略行的 businessId:在 UC-01 路径上,在取得被访人 floorList 后执行 allow_zone_ids ∩ floorList(顺序建议保持 floorList 顺序 过滤)。 |
| 兼容 | 表中无该租户配置、或 enabled=0、或 allow_zone_ids 为空:与现网 UC-01 一致(仍使用组织返回的 floorList 全集)。 |
| 显式楼层 | 请求体已带非空 floorIds(UC-02):本阶段 不改变 现网语义,不读策略表、不对传入列表做求交(与产品方案 AC-4 一致;若未来合同要求「显式也求交」须另立变更)。 |
| 访客业务系统 / 登记页 | 本阶段不要求改第三方 BFF;但若登记页仍只拉组织 floorList 展示,则展示可能与电梯最终开通楼层不一致 —— 见 §8 风险与后续工作。 |
1.3 非目标(明确排除)
- 物业管理端 CRUD 页面、审计日志界面、策略版本与登记单快照联动(产品方案 §2.7、§3.4 完整能力)。
- 组织侧收窄
floorList、Nacos 配置中心等其它路径(参见产品方案 §4.1 方案族)。 - 按楼栋
building_id的多套策略并行(表结构可预留字段,本阶段查询规则见 §4.3)。
2. 设计原则与安全约束
-
权限上界(不变量)
租户策略仅表达允许集合;在 UC-01 路径下,最终写入电梯规则的zoneId列表必须是allow_zone_ids与PersonResult.floorList的交集 的子集(实现上等价于交集本身)。禁止在交集为空时静默落到其它楼层。 -
交集为空
租户已配置非空允许列表,但与被访人floorList无交集:返回明确业务错误(禁止继续zone/page、get(0)等,避免走查文档 UC-04 类 NPE)。 -
被访人无楼层
组织detail返回的floorList为 null 或空列表:在应用层短路失败(与产品方案建议的空集校验一致),错误信息区别于「策略求交为空」。 -
数据源
策略表以businessId(机构 ID) 与调用上下文CloudwalkCallContext.company.companyId对齐;所有查询必须带business_id条件,避免串租户。
3. 总体架构(本阶段)
flowchart LR
subgraph callers [调用方不变]
T[第三方 / intelligent]
end
subgraph elev [cw-elevator-application]
API["POST /elevator/person/add/visitor"]
SVC["PersonRuleServiceImpl.addVisitor"]
ORG["Feign PersonService.detail"]
DB[("tenant_visitor_floor_policy")]
end
subgraph orgsvc [组织服务]
DETAIL["POST /component/person/detail"]
end
T --> API --> SVC
SVC -->|floorIds 为空| ORG --> DETAIL
SVC -->|读策略| DB
SVC -->|后续现有逻辑| Z["zoneService.page 等"]
职责划分:
- 策略存储与读取:电梯应用访问本表(与现网
image_rule_ref等表同一数据源即可,减少分布式事务)。 - 「访客系统只获取对应楼层」:若「访客系统」指登记页/第三方 BFF,本阶段不强制其改代码;电梯侧已保证开通结果收敛。展示一致需后续 预览接口或 BFF 同源计算(产品方案 §2.3、§2.5)。
4. 数据模型设计
4.1 逻辑模型
与产品方案 §4.3 对齐,本阶段至少使用下列语义字段:
| 字段 | 类型(建议) | 必填 | 说明 |
|---|---|---|---|
id |
VARCHAR(32) PK |
是 | 主键,UUID |
business_id |
VARCHAR(64) |
是 | 机构/租户 ID,与 businessId 一致 |
policy_type |
VARCHAR(32) |
是 | 本阶段仅使用 INTERSECT_ALLOWLIST;预留 HOST_FLOOR_LIST 等枚举便于扩展 |
allow_zone_ids |
TEXT |
条件 | JSON 数组,元素为 zoneId 字符串;策略生效时须非空(见 §4.4) |
building_id |
VARCHAR(64) NULL |
否 | 租户级默认:本阶段固定 NULL 表示全机构默认一条;非 NULL 预留给「按楼栋」扩展 |
enabled |
TINYINT(1) |
是 | 1 启用,0 停用(等价于未配置) |
policy_version |
BIGINT |
是 | 每次配置变更递增;本阶段可不接入登记快照,但建议表结构一次到位 |
remark |
VARCHAR(256) |
否 | 实施备注(如「广发基金接待层」) |
created_by / updated_by |
VARCHAR(64) |
否 | 本阶段手工 SQL 可填运维账号 |
created_at / updated_at |
BIGINT |
否 | Unix 毫秒时间戳,与项目内其它表风格一致 |
唯一约束建议:UNIQUE KEY uk_biz_building (business_id, building_id)。
MySQL 中 building_id 为 NULL 时多行 (biz, NULL) 在部分版本下可能被唯一索引允许多条 —— 实施约束:应用层查询 WHERE business_id = ? AND building_id IS NULL ... LIMIT 1,DBA 规范每个租户仅一行租户级策略。
4.2 DDL 草案(MySQL)
CREATE TABLE tenant_visitor_floor_policy (
id VARCHAR(32) NOT NULL COMMENT '主键',
business_id VARCHAR(64) NOT NULL COMMENT '机构/租户 ID',
policy_type VARCHAR(32) NOT NULL DEFAULT 'INTERSECT_ALLOWLIST' COMMENT '策略类型',
allow_zone_ids TEXT NULL COMMENT 'JSON 数组,zoneId 列表',
building_id VARCHAR(64) NULL COMMENT '预留:楼栋维度;租户默认填 NULL',
enabled TINYINT(1) NOT NULL DEFAULT 1 COMMENT '1 启用 0 停用',
policy_version BIGINT NOT NULL DEFAULT 1 COMMENT '配置版本号',
remark VARCHAR(256) NULL,
created_by VARCHAR(64) NULL,
created_at BIGINT NULL,
updated_by VARCHAR(64) NULL,
updated_at BIGINT NULL,
PRIMARY KEY (id),
UNIQUE KEY uk_biz_building (business_id, building_id),
KEY idx_business_enabled (business_id, enabled)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='租户访客默认楼层策略(与组织 floorList 求交)';
脚本落地路径:docs/sql/tenant_visitor_floor_policy.sql(本仓库已提供);亦可复制到各环境 Flyway/Liquibase 目录(以现网规范为准)。
实现分支:feature/tenant-visitor-floor-policy-db(电梯 PersonRuleServiceImpl.addVisitor + TenantVisitorFloorPolicyDao)。
4.3 查询语义(应用层)
单条加载(租户级、启用、默认楼栋):
SELECT ... FROM tenant_visitor_floor_policy
WHERE business_id = ?
AND enabled = 1
AND policy_type = 'INTERSECT_ALLOWLIST'
AND (building_id IS NULL OR building_id = '')
ORDER BY updated_at DESC, policy_version DESC
LIMIT 1;
若无行 → 不应用策略。
若 allow_zone_ids 为 NULL、空串、或 JSON 解析为空数组 → 本设计建议:视为未配置有效允许列表,行为与「无策略」一致(避免误配导致全员无法开通);可选变体(需产品签字):解析为空则判为配置错误并拒绝 UC-01 —— 实施前二选一写死。
4.4 allow_zone_ids JSON 约定
- 格式:
["zoneId1","zoneId2"],UTF-8,无 BOM。 - 元素与组织
floorList、空间服务zoneId同一套 ID。 - 实施前在空间服务或台账中核对「28 楼」等业务语言与
zoneId映射(产品方案 §4.6)。
4.5 配置示例(实施 SQL)
-- 示例:某租户仅允许访客到达 zone A、B(需替换为真实 business_id / zoneId)
INSERT INTO tenant_visitor_floor_policy
(id, business_id, policy_type, allow_zone_ids, building_id, enabled, policy_version, remark, created_at, updated_at)
VALUES
(REPLACE(UUID(),'-',''), 'REPLACE_WITH_BUSINESS_ID', 'INTERSECT_ALLOWLIST',
'["REPLACE_ZONE_A","REPLACE_ZONE_B"]', NULL, 1, 1, '实施录入:接待层', UNIX_TIMESTAMP(NOW())*1000, UNIX_TIMESTAMP(NOW())*1000);
停用某租户策略:UPDATE ... SET enabled = 0, policy_version = policy_version + 1, updated_at = ...。
5. 应用层设计(电梯服务)
5.1 改造锚点
| 组件 | 路径 | 说明 |
|---|---|---|
| HTTP | AcsPersonController#addVisitor |
入参不变 |
| 服务 | PersonRuleServiceImpl#addVisitor |
在 仅当 floorIds 为空分支内,于 personService.detail 取回 floorList 之后,插入策略加载与求交 |
| 数据访问 | 新建 TenantVisitorFloorPolicyDao + MyBatis Mapper |
仅 select;本阶段无写接口 |
5.2 控制流(伪代码)
函数 addVisitor(param, context):
callerProvidedFloors = (param.floorIds 非空)
若 NOT callerProvidedFloors:
调用组织 detail(personId, businessId)
若 detail 失败: 返回 detail 的 code/message
hostFloors = PersonResult.floorList;若 null 则 []
若 hostFloors 为空:
返回业务错误「被访人无派梯楼层」
policy = DAO.selectEnabledTenantDefault(businessId) // building_id IS NULL
若 policy 存在且 allow_zone_ids 解析为非空列表 allow:
effective = [ z for z in hostFloors if z in allowSet ] // 保持 hostFloors 顺序
若 effective 为空:
返回业务错误「租户访客楼层与被访人授权无交集」
param.floorIds = effective
否则:
param.floorIds = hostFloors
// callerProvidedFloors: 不读策略表,param.floorIds 保持调用方原值
若 param.floorIds 为空:
返回业务错误「无可用派梯楼层」
后续沿用现有: zoneService.page、image_rule_ref、batchBind ...
5.3 与 UC 对照矩阵
| 场景 | floorIds 请求 |
表中是否有启用策略 | 期望生效列表 |
|---|---|---|---|
| UC-01 现网 | 空 | 否 | floorList(与现网一致) |
| UC-01 + 策略 | 空 | 是且 allow 非空 | allow ∩ floorList |
| UC-01 + 策略无交集 | 空 | 是且 allow 非空 | 失败,明确错误码 |
| UC-01 被访人无层 | 空 | 任意 | 失败(无 floorList) |
| UC-02 | 非空 | 任意 | 以请求为准(本阶段不读表) |
5.4 错误码与文案(建议)
| 错误码 | 场景 | 用户/集成方可见文案(中文示例) |
|---|---|---|
| 沿用组织失败码 | detail 失败 |
透传组织返回 |
新增 76260531(示例) |
floorList 为空或求交后仍无可用楼层(可归并细分) |
无法为访客开通派梯:被访人无授权楼层或无可生效楼层 |
新增 76260532(示例) |
租户允许列表与被访人 floorList 无交集 |
无法为访客开通派梯:租户访客楼层策略与被访人授权楼层不一致,请联系管理员 |
注:具体码段需与现网
762605xx资源文件及网关错误码规范对齐;实施时在messages或统一错误表中登记。
5.5 异常与日志
addVisitor外层catch (Exception)若吞掉ServiceException,会导致业务错误码丢失;须对ServiceException单独rethrow或改为提前返回CloudwalkResult.fail,避免一律映射为76260530。- 日志:在求交前后打 INFO(
businessId、personId、visitorId、策略id、policy_version、脱敏后的effective楼层数量或 zoneId 列表 —— 按合规要求决定是否打全量 ID)。
5.6 事务与性能
- 策略查询为只读,可与现有
addVisitor事务边界一致;无跨服务写。 - QPS 不高场景可不加缓存;若加缓存:key=
businessId+building_id,失效条件为策略UPDATE(或 TTL + 版本号)。本阶段可省略。
6. 测试设计
6.1 单元测试
| 用例 ID | 输入 | 期望 |
|---|---|---|
| T-U01 | 无策略,floorList=[a,b],不传 floorIds |
生效 [a,b] |
| T-U02 | 策略 allow=[b,c],floorList=[a,b] |
生效 [b] |
| T-U03 | 策略 allow=[x],floorList=[a,b] |
失败,码 76260532 类 |
| T-U04 | floorList=[] |
失败 |
| T-U05 | 调用方传 floorIds=[x] |
不读表,生效 [x] |
| T-U06 | enabled=0 |
等同无策略 |
| T-U07 | allow_zone_ids 空或解析为空 |
等同无策略(若采用 §4.3 建议) |
6.2 集成 / 回归
- 未插表租户:全量回归 UC-01 / UC-02。
- 插表租户:组织造数
floorList与策略 allow 多种组合,验证 AC-1~AC-3(产品方案 §3.5)。
7. 发布与运维
- 发布顺序:先 DDL 上线(表空不影响行为)→ 再发 应用包(读表逻辑)。
- 配置变更:仅
INSERT/UPDATE;重大变更递增policy_version并记录remark。 - 回滚:应用回滚后行为恢复现网;表数据可保留。
- 监控:对新增错误码计数;对「求交为空」单独告警便于实施核对 zoneId。
8. 风险、依赖与后续阶段
| 项 | 说明 |
|---|---|
| 登记页与开通不一致 | 第三方若仍只展示 floorList 全集,而电梯已求交,易产生客诉。缓解:阶段 2 提供管理 API + 预览接口,或 BFF 读同一策略源(若表在电梯库,可通过只读副本或同步配置解决跨库)。 |
| 直连电梯绕过 BFF | 本阶段在电梯侧兜底,直连仍受策略约束(产品方案 §6.2 中「B+C」思路的部分收益)。 |
| 多楼栋 | 预留 building_id;待产品定义「按楼栋策略」后再扩展查询与 UI。 |
| 阶段 2(产品已规划) | 物业管理端页面:策略维护、空间树多选、policy_version 审计、可选 preview-floors 与登记快照对齐(产品方案 §2.5、§4.4)。 |
9. 文档维护
| 项目 | 内容 |
|---|---|
| 路径 | docs/business/租户访客默认楼层-数据库配置阶段技术设计.md |
| 变更记录 | 租户访客默认楼层-数据库阶段变更记录(发版/评审用) |
| 修订触发 | add/visitor 契约变更;策略表字段变更;决定 UC-02 是否参与求交 |
| 关联 PR | 实现类、Mapper.xml、DDL 脚本与错误码资源文件 |
本文档为数据库阶段详细设计;实施以现网分支、代码评审与安全评审结论为准。