Files
starRiverProperty/docs/business/租户访客默认楼层-数据库配置阶段技术设计.md
T
2026-04-24 11:15:59 +08:00

16 KiB
Raw Blame History

租户访客默认楼层:数据库配置阶段 — 详细技术设计

文档性质:实施级技术设计(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 全集)。
显式楼层 请求体已带非空 floorIdsUC-02):本阶段 不改变 现网语义,读策略表、对传入列表做求交(与产品方案 AC-4 一致;若未来合同要求「显式也求交」须另立变更)。
访客业务系统 / 登记页 本阶段不要求改第三方 BFF;但若登记页仍只拉组织 floorList 展示,则展示可能与电梯最终开通楼层不一致 —— 见 §8 风险与后续工作

1.3 非目标(明确排除)

  • 物业管理端 CRUD 页面、审计日志界面、策略版本与登记单快照联动(产品方案 §2.7、§3.4 完整能力)。
  • 组织侧收窄 floorList、Nacos 配置中心等其它路径(参见产品方案 §4.1 方案族)。
  • 按楼栋 building_id 的多套策略并行(表结构可预留字段,本阶段查询规则见 §4.3)。

2. 设计原则与安全约束

  1. 权限上界(不变量)
    租户策略仅表达允许集合;在 UC-01 路径下,最终写入电梯规则的 zoneId 列表必须是 allow_zone_idsPersonResult.floorList 的交集 的子集(实现上等价于交集本身)。禁止在交集为空时静默落到其它楼层。

  2. 交集为空
    租户已配置非空允许列表,但与被访人 floorList 无交集:返回明确业务错误(禁止继续 zone/pageget(0) 等,避免走查文档 UC-04 类 NPE)。

  3. 被访人无楼层
    组织 detail 返回的 floorListnull 或空列表:在应用层短路失败(与产品方案建议的空集校验一致),错误信息区别于「策略求交为空」。

  4. 数据源
    策略表以 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 1DBA 规范每个租户仅一行租户级策略。

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
  • 日志:在求交前后打 INFObusinessIdpersonIdvisitorId、策略 idpolicy_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-1AC-3(产品方案 §3.5)。

7. 发布与运维

  1. 发布顺序:先 DDL 上线(表空不影响行为)→ 再发 应用包(读表逻辑)。
  2. 配置变更:仅 INSERT/UPDATE;重大变更递增 policy_version 并记录 remark
  3. 回滚:应用回滚后行为恢复现网;表数据可保留。
  4. 监控:对新增错误码计数;对「求交为空」单独告警便于实施核对 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 脚本与错误码资源文件

本文档为数据库阶段详细设计;实施以现网分支、代码评审与安全评审结论为准。