# 租户访客默认楼层(广发及后续租户定制)与「不影响其他公司」的边界说明 ## 1. 目标表述 | 诉求 | 含义 | |------|------| | **定制** | 某租户希望:访客在 **不传 `floorIds`** 时,仅开通 **接待层等默认楼层**(与员工本人多层权限区分)。 | | **不影响未定义公司** | 未启用该能力的租户 / 机构,行为与改造前一致:**不因他人策略误伤**。 | 实现落点:**组织** `ImgPersonServiceImpl#detail`(将策略 **`allow_zone_ids` 替代写入 `floorList`**)+ 电梯 **`PersonRuleServiceImpl#addVisitor`**(**透传** `detail.floorList`,**不**读策略表、**不** ∩)。策略数据表仍可在组织侧或迁移期参照 `tenant_visitor_floor_policy`(历史上在电梯库)。详见 `visitor-registration-business-flow.md`、`docs/superpowers/specs/2026-05-06-tenant-visitor-policy-organization-implementation.md`。 --- ## 2. 当前实现下的真实隔离粒度(必读) ### 2.1 策略生效键:**`business_id`(机构/租户 ID)** - **规范**:策略行仍按租户维度启用;组织侧策略服务读取时与 **`companyId`(Header `businessid`)** 及被访人 **`organizationIds`** 对齐。 - 电梯 **`addVisitor`** **不再**调用 **`TenantVisitorFloorPolicyDao`**。 ### 2.2 「未定义」租户的行为 — **不受影响** ```mermaid flowchart LR subgraph T1["租户 A:未命中租户访客策略"] A1[addVisitor floorIds 空] A2[detail:floorList = listByImageId 原始楼层] A4[effectiveFloors = detail.floorList] A1 --> A2 --> A4 end subgraph T2["租户 B:策略命中"] B1[detail:floorList = allow_zone_ids 替代结果] B1 --> B2[addVisitor 透传] end ``` - **未命中策略**:`detail` 返回 **`listByImageId` 遍历楼层**,与其它租户一致。 → **未单独配置策略的 `business_id`**:行为与改造前「无收紧」一致。 ### 2.3 「广发定制」与同一 `business_id` 下其他部门 — **当前同属租户级策略** - 若 **星河湾中心**与 **广发基金**等业务共用一个 **`business_id`**(现场组织库 `cw_is_organization.BUSINESS_ID` 相同),则 **库中一条租户默认策略会对该 ID 下全部主体生效**,**无法**仅靠配置表做到「只收紧广发公司、不收紧同租户下其他公司」。 - **产品级隔离选项(需实施选型,超出当前表结构默认能力)**: - **拆租户**:广发使用 **独立 `business_id`**(独立机构树),策略只插入该行;或 - **演进能力**:使用/扩展 **`building_id`** 维度的策略行(表已预留列,需扩展 Mapper 查询与产品规则);或 - **调用方传 `floorIds`**:由 BFF 预先收窄;电梯 **UC-02** 以请求为准。 --- ## 3. 业务流程图(规范) ```mermaid flowchart TD Start([POST /elevator/person/add/visitor]) --> Empty{floorIds 空?} Empty -- 否 --> UseIn[UC-02 effective = 请求 floorIds] Empty -- 是 --> Det[PersonService.detail:floorList 已含组织侧策略替代] Det --> HF{floorList 非空?} HF -- 否 --> E31[76260531] HF -- 是 --> UseIn2[UC-01 effective = detail.floorList] UseIn --> Zone[首层→楼栋→imageStoreId] UseIn2 --> Zone Zone --> IRR[写 image_rule_ref personId=visitorId] IRR --> Bind[图库 batchBind visitorId] Bind --> OK([成功]) ``` --- ## 4. 时序图(不传 floorIds) ```mermaid sequenceDiagram participant Caller as 调用方/BFF participant API as AcsPersonController participant PR as PersonRuleServiceImpl participant PS as PersonService 组件 participant Ir as ImageRuleRefDao participant IS as ImageStorePersonService Caller->>API: visitorId, personId(被访人), floorIds=[] API->>PR: addVisitor PR->>PS: detail(personId, businessId) PS-->>PR: PersonResult.floorList(组织已替代) Note over PR: effectiveFloors = floorList;电梯不读策略表 PR->>Ir: insertList 每层默认规则 visitorId PR->>IS: batchBind(visitorId, 访期) IS-->>PR: ok PR-->>API: success ``` --- ## 5. 与测试矩阵的关系 - **自动化快照**按 **`business_id`** 拉策略与人员;若需验证「无策略租户」,使用 **第二 `business_id`** 套件或 **空策略库**。 - **每部门 10 名员工**:验证「同一策略下不同被访人」在 **detail** 得到的 **`floorList`(替代后)** 多样性;**不**等价于「按公司隔离策略」。 --- ## 6. 文档索引 - 租户 / 组织 / 人员 / 访客 ER、表关系与用例:`docs/architecture/租户组织人员访客-数据模型与用例.md` - 楼层与 API 字段:`docs/testing/visitor-registration-business-flow.md` - 服务层逐步说明:`cw-elevator-application-service/docs/08-visitor-registration-and-elevator-auth.md` - 测试方案:`docs/testing/visitor-registration-floor-validation.md`