Files
starRiverProperty/docs/business/租户访客楼层策略-代码重构实施指南.md
hpd840321 7b2bd307f1 Initial commit: reorganized source tree
- backend/: 13 Maven modules (cw-elevator-application, cloudwalk-cloud, intelligent-cwoscomponent, ninca-crk, etc.)
- frontend/: 4 Vue projects (elevator-front, cwos-portal, alarm-front, front_acs) + decompiled + scripts
- scripts/: build, test-env, tools (Docker Compose, service templates, API parity)
- docs/: AGENTS.md, superpowers specs, architecture docs
- .gitignore: standard Java/Maven exclusions

Moved from legacy maven-*/ root layout to backend/ organized structure.
2026-05-09 09:56:45 +08:00

7.8 KiB
Raw Permalink Blame History

租户访客楼层策略 — 代码重构实施指南

目标:在不破坏对外 HTTP / Feign 契约的前提下,实现规范中的 「组织 detail 内以 allow_zone_ids 替代 PersonResult.floorList,使邀约页、UC-01 派梯租户策略一致。
依据访客邀约与派梯楼层一致性梳理迁入组织规格(以下简称 《组织规格》)。
当前状态:电梯 PersonRuleServiceImpl#addVisitor读策略表、做 ∩。组织侧已落地 TenantVisitorFloorPolicyService + ImgPersonServiceImpl#detail / page(isVisitor)allow_zone_ids 替代;部署组织库需执行 docs/sql/organization_tenant_visitor_floor_policy.sql。电梯工程内已无 TenantVisitorFloorPolicyDao(死代码已删)。


1. 重构原则(必须遵守)

原则 说明
策略语义 「替代」:命中策略时 floorList = 配置中的 allow_zone_ids 解析结果不要listByImageId 结果做 作为规范主路径。
唯一对外楼层权威 消费「被访人可派梯/可邀约楼层」必须PersonService.detailfloorList(经 Intelligent → 组织)。
电梯侧 新增「再算一遍策略」;恢复 TenantVisitorFloorPolicyDao 参与 addVisitor 有效楼层计算。
接口兼容 《组织规格》约定:cwos-component-organization-interface 为策略新增公开 DTO/方法时,策略仅作为服务层内部实现;对外仍只通过现有 detail 返回里的 floorList / floorNames 体现。
UC-02 显式 floorIds 仍由调用方负责与业务单一致;若需 ⊆ 策略 的硬约束,在 BFF 实现,或单独立项改电梯经评审。

2. 分阶段实施任务

阶段 A — 数据与组织工程骨架

  1. 策略表落库位置(二选一,推荐 组织库 为唯一主库)

    • 推荐:在 组织服务使用的 MySQL 库 中创建与《组织规格》一致的表结构(字段含 business_idpolicy_typeallow_zone_ids JSON、enabledbuilding_id 可空等)。
    • 迁移期:若生产数据仍在电梯库 tenant_visitor_floor_policy,做 一次性迁移脚本 + 运维切换窗口;迁移完成后电梯侧 Dao 仅删除调用,不必双写。
  2. 组织模块新增(均在 maven-ninca-common-component-organization

    • Entity / Mapper / XMLtenant_visitor_floor_policy CRUD 或至少 business_id + enabled 查询租户默认行(building_id IS NULL)。
    • TenantVisitorFloorPolicyService(命名可依项目惯例):
      • boolean isPolicyActive(String businessId)Optional<PolicyRow> findTenantDefault(String businessId)
      • List<String> parseAllowZoneIds(String json)(健壮解析,非法 JSON → 视为未启用或记录告警)。
    • 不做:在 interface 模块暴露新 REST(除非产品明确要求管理 API)。

阶段 B — 在 ImgPersonServiceImpl#detail 接入替代逻辑(核心)

文件cwos-component-organization-service/.../ImgPersonServiceImpl.java,方法 detail

插入点:在 elevatorFeignClient.listByImageId 成功、已根据 images 遍历得到 floorList / floorNames(原始) 之后;在 result.setFloorList / setFloorNames 之前增加分支:

伪代码:

原始列表 = 当前遍历 listByImageId 得到的 floorList, floorNames

若 TenantVisitorFloorPolicyService 对 businessId(及必要时 organizationIds)判定「启用且 allow 非空」:
    floorList := allow_zone_ids 解析后的 zoneId 列表(顺序:与 JSON 数组顺序一致)
    floorNames := 需与 floorList 对齐展示
        选项 1:配置侧同时存 id→name 映射(扩展列或独立字典表)
        选项 2:对 allow 中每个 zoneId 调现有 Zone Feign 批量查名称(注意批量与超时)
        选项 3:若产品允许仅展示 zoneId,则 floorNames 可与 zoneId 同步占位(不推荐体验)

否则:
    保持现有原始 listByImageId 语义

result.setFloorList(...)
result.setFloorNames(...)

注意

  • defaultFloor / floorName(单人默认层展示)floorList(通行可达层) 语义不同,勿混写;参见 08 文档
  • 启用判定键:与《组织规格》一致,以 business_idHeader businessid / companyId)为主;若后续要 按机构细分,再扩展查询条件,不在本阶段默认实现。

阶段 C — 访客列表 page(isVisitor) 对齐(强烈建议)

文件:同一 ImgPersonServiceImpl,方法 page,分支 param.getIsVisitor() 非空

  • 现状:该分支内有 星河湾 40F/6F 等与 detail 不一致的展示逻辑。
  • 建议:在策略命中优先应用与 detail 相同的替代结果(或抽 私有方法 applyTenantVisitorFloorPolicy(resultRow, businessId, …)detailpage 共用),并 跳过与租户策略冲突的硬编码默认层块(参见《组织规格》§4.3)。
  • 避免:邀约走 detail、列表走 page 时出现两套楼层。

阶段 D — 电梯侧清理(收尾)

  1. 确认 PersonRuleServiceImpl TenantVisitorFloorPolicyDao 注入与 ∩ 逻辑(当前梳理版本已符合则仅做静态检查)。
  2. 删除或标注废弃cw-elevator-application-dataTenantVisitorFloorPolicyDao / Mapper / XML 若已不再被任何 Bean 引用 — 删除可减少歧义;若迁移脚本仍需参考表结构,可保留 DDL 文档到 docs/sql,代码删除前 grep 全仓引用。
  3. 电梯库表:迁移完成后由 DBA 删表或归档(按运维规范)。

阶段 E — UC-02 与集成(可选增强)

  • BFF:派梯前读取邀约单 floorIds,调用 detail 得到 floorList(已含替代),校验 floorIds ⊆ floorList(集合意义),失败则拒绝派梯并返回明确错误码。
  • 幂等:邀约单号 + 派梯状态机由业务系统保证,电梯接口本身不变。

阶段 F — 测试与验收

场景 期望
未配置策略 detail.floorList 与改造前 listByImageId 一致;UC-01 行为不变。
配置启用且 allow 非空 detail.floorList 等于 allow 列表(替代);UC-01 开通层与邀约页一致。
关闭策略 / JSON 无效 回退原始语义;无启动报错。
page(isVisitor) detail 策略表现一致(验收抽样)。

3. 风险与缓解

风险 缓解
floorNames 与 id 不对齐 替代后必须统一用 Zone 服务补全名称或扩展配置。
性能detail 每次多一次 DB + 可选批量 Zone 策略行缓存(短 TTL)或本地缓存按 business_id
跨楼栋首层(§4.8 产品确认单次 effective 是否允许多楼栋;否则约束邀约/UC-02 单层栋或拆分调用。

4. 推荐提交顺序(便于 Code Review

  1. 组织库 DDL + Mapper + PolicyService(单测解析 JSON)。
  2. detail 接入替代 + 单元/集成测试(可 Mock Feign)。
  3. page 分支对齐(若有)。
  4. 电梯侧删除死代码 + 文档更新(本文 + 《一致性梳理》§6)。
  5. 迁移脚本在生产前演练。

文档版本:与仓库实施同步更新;重大契约变更需同步修改《组织规格》并评审。