Files
starRiverProperty/docs/testing/tenant-visitor-default-floor-isolation.md
反编译工作区 8b15445328 feat: add service config templates and extraction script
Former-commit-id: 1de24b7eb79676d1aba9d799a58c5a753290cf52
2026-05-01 19:38:01 +08:00

118 lines
5.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 租户访客默认楼层(广发及后续租户定制)与「不影响其他公司」的边界说明
## 1. 目标表述
| 诉求 | 含义 |
|------|------|
| **定制** | 某租户希望:访客在 **不传 `floorIds`** 时,仅开通 **接待层等默认楼层**(与员工本人多层权限区分)。 |
| **不影响未定义公司** | 未启用该能力的租户 / 机构,行为与改造前一致:**不因他人策略误伤**。 |
实现落点在本仓库:**`PersonRuleServiceImpl#addVisitor`** + 表 **`tenant_visitor_floor_policy`**(详见 `visitor-registration-business-flow.md`)。
---
## 2. 当前实现下的真实隔离粒度(必读)
### 2.1 策略生效键:**`business_id`(机构/租户 ID**
- DAO**`TenantVisitorFloorPolicyDao#selectEnabledTenantDefault(businessId)`**
- SQL(节选):`WHERE business_id = ? AND enabled = 1 AND policy_type = 'INTERSECT_ALLOWLIST' AND (building_id IS NULL OR building_id = '')`
- **含义**:一行策略绑定的是 **Cloudwalk 上下文里的 `companyId`(即 Header `businessid`**,不是单个「公司名称字符串」,也不是单个部门 `org_id`
### 2.2 「未定义」租户的行为 — **不受影响**
```mermaid
flowchart LR
subgraph T1["租户 A:库中无策略行"]
A1[addVisitor floorIds 空]
A2[detail 取 host floorList]
A3[selectEnabledTenantDefault → null]
A4[effectiveFloors = hostFloors 全集]
A1 --> A2 --> A3 --> A4
end
subgraph T2["租户 B:有启用策略"]
B1[detail 取 host floorList]
B2[与 allow_zone_ids 求交]
B1 --> B2
end
```
- **无策略行**或 **enabled≠1**:代码分支 **不执行求交**,访客楼层等同于 **被访人 `floorList`**(在「不传 floorIds」前提下)。
**其他未配置策略的 `business_id`**:逻辑 **不变**,满足「未定义则不收紧」。
### 2.3 「广发定制」与同一 `business_id` 下其他部门 — **当前同属租户级策略**
-**星河湾中心**与 **广发基金**等业务共用一个 **`business_id`**(现场组织库 `cw_is_organization.BUSINESS_ID` 相同),则 **库中一条租户默认策略会对该 ID 下全部主体生效**,**无法**仅靠配置表做到「只收紧广发公司、不收紧同租户下其他公司」。
- **产品级隔离选项(需实施选型,超出当前表结构默认能力)**:
- **拆租户**:广发使用 **独立 `business_id`**(独立机构树),策略只插入该行;或
- **演进能力**:使用/扩展 **`building_id`** 维度的策略行(表已预留列,需扩展 Mapper 查询与产品规则);或
- **调用方传 `floorIds`**:由 BFF 按公司算出楼层,电梯不再依赖默认求交。
---
## 3. 业务流程图(有 / 无策略)
```mermaid
flowchart TD
Start([POST /elevator/person/add/visitor]) --> Empty{floorIds 空?}
Empty -- 否 --> UseIn[使用传入 floorIds]
Empty -- 是 --> Det[PersonService.detail 被访人 personId]
Det --> HF{floorList 非空?}
HF -- 否 --> E31[76260531]
HF -- 是 --> Pol{存在启用租户默认策略且 allow 非空?}
Pol -- 否 --> UseIn2[effectiveFloors = floorList]
Pol -- 是 --> Xsect[floorList ∩ allow_zone_ids]
Xsect --> Xe{交集非空?}
Xe -- 否 --> E32[76260532]
Xe -- 是 --> UseIn3[effectiveFloors = 交集]
UseIn --> Zone[首层→楼栋→imageStoreId]
UseIn2 --> Zone
UseIn3 --> 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 Pol as TenantVisitorFloorPolicyDao
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
PR->>Pol: selectEnabledTenantDefault(businessId)
Pol-->>PR: allow_zone_ids JSON
Note over PR: effectiveFloors = intersect(floorList, allow)
PR->>Ir: insertList 每层默认规则 visitorId
PR->>IS: batchBind(visitorId, 访期)
IS-->>PR: ok
PR-->>API: success
```
---
## 5. 与测试矩阵的关系
- **自动化快照**按 **`business_id`** 拉策略与人员;若需验证「无策略租户」,使用 **第二 `business_id`** 套件或 **空策略库**
- **每部门 10 名员工**:验证「同一策略下不同被访人 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`