mirror of
https://github.com/hpd840321/starRiverProperty.git
synced 2026-06-11 01:10:29 +08:00
docs: mark elevator-side tenant policy SQL as deprecated, add guangfa visitor floor design
- Deprecate elevator-side tenant_visitor_floor_policy SQL files (V2 queries only component-organization library) - Add guangfa 28F visitor floor design spec (table-driven approach A) - Add complete database ER diagram (14 DBs, 537 tables) - Add implementation plan for guangfa visitor floor policy - Code walkthrough docs for visitor floor policy analysis
This commit is contained in:
@@ -0,0 +1,296 @@
|
||||
# 广发基金 28F 硬编码方案 — 组件/模块/位置细化设计
|
||||
|
||||
**日期**: 2026-05-09
|
||||
**分支**: `feature/guangfa-28f-hardcoded`
|
||||
**状态**: 方案细化完成,待实施
|
||||
|
||||
---
|
||||
|
||||
## 1. 涉及组件与模块总览
|
||||
|
||||
```
|
||||
source/backend/
|
||||
├── ninca-common-component-organization/ ★ 唯一变更组件
|
||||
│ ├── cwos-component-organization-service/ ★ 代码变更
|
||||
│ │ └── src/main/java/cn/cloudwalk/service/organization/service/
|
||||
│ │ └── ImgPersonServiceImpl.java ★ 唯一变更 Java 文件
|
||||
│ │
|
||||
│ ├── cwos-component-organization-starter/ ★ 配置变更
|
||||
│ │ └── deploy/run-verify/
|
||||
│ │ └── application.properties ★ 唯一变更配置文件
|
||||
│ │
|
||||
│ └── (其余模块不变: data, interface, web)
|
||||
│
|
||||
├── cw-elevator-application/ ☆ 仅增强日志
|
||||
│ └── cw-elevator-application-service/
|
||||
│ └── .../impl/PersonRuleServiceImpl.java ☆ +2 行日志
|
||||
│
|
||||
└── intelligent-cwoscomponent/ 不变 (仅 Feign 接口定义)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. 变更点详细定位
|
||||
|
||||
### 2.1 模块: `cwos-component-organization-service`
|
||||
|
||||
**文件**: `backend/ninca-common-component-organization/cwos-component-organization-service/src/main/java/cn/cloudwalk/service/organization/service/ImgPersonServiceImpl.java`
|
||||
|
||||
**包**: `cn.cloudwalk.service.organization.service`
|
||||
**类**: `ImgPersonServiceImpl` (1414 行)
|
||||
|
||||
#### 位置 A — 依赖注入区 (第 157-158 行后,新增 2 行)
|
||||
|
||||
**原代码**:
|
||||
```java
|
||||
157: @Value("${xhwSixFloorId}")
|
||||
158: private String xhwSixFloorId;
|
||||
159:
|
||||
160: private static final String imageBase64 =
|
||||
```
|
||||
|
||||
**改为**:
|
||||
```java
|
||||
157: @Value("${xhwSixFloorId}")
|
||||
158: private String xhwSixFloorId;
|
||||
159:
|
||||
160: @Value("${gfOrgId}")
|
||||
161: private String gfOrgId;
|
||||
162:
|
||||
163: @Value("${gfDefaultFloorId}")
|
||||
164: private String gfDefaultFloorId;
|
||||
165:
|
||||
166: private static final String imageBase64 =
|
||||
```
|
||||
|
||||
#### 位置 B — `listByPage()` 访客列表分支 (第 354-370 行,插入 else-if)
|
||||
|
||||
**当前代码** (精确):
|
||||
```java
|
||||
354: if (imgStorePersonResult.getOrganizationIds().contains(this.xhwId)) {
|
||||
355: imgStorePersonResult.setDefaultChooseFloor(this.xhwDefaultFloorId);
|
||||
356: List<AcsPassRuleImageResultDto> floorInfoList = new ArrayList<>();
|
||||
357: AcsPassRuleImageResultDto resultDto = new AcsPassRuleImageResultDto();
|
||||
358: resultDto.setZoneId(this.xhwDefaultFloorId);
|
||||
359: resultDto.setZoneName("40F");
|
||||
360: floorInfoList.add(resultDto);
|
||||
361: imgStorePersonResult.setFloorInfoList(floorInfoList);
|
||||
362: } else {
|
||||
363: imgStorePersonResult.setDefaultChooseFloor(this.xhwSixFloorId);
|
||||
364: List<AcsPassRuleImageResultDto> floorInfoList = new ArrayList<>();
|
||||
365: AcsPassRuleImageResultDto resultDto = new AcsPassRuleImageResultDto();
|
||||
366: resultDto.setZoneId(this.xhwSixFloorId);
|
||||
367: resultDto.setZoneName("6F");
|
||||
368: floorInfoList.add(resultDto);
|
||||
369: imgStorePersonResult.setFloorInfoList(floorInfoList);
|
||||
370: }
|
||||
```
|
||||
|
||||
**改为**:
|
||||
```java
|
||||
354: if (imgStorePersonResult.getOrganizationIds().contains(this.xhwId)) {
|
||||
355: imgStorePersonResult.setDefaultChooseFloor(this.xhwDefaultFloorId);
|
||||
356: List<AcsPassRuleImageResultDto> floorInfoList = new ArrayList<>();
|
||||
357: AcsPassRuleImageResultDto resultDto = new AcsPassRuleImageResultDto();
|
||||
358: resultDto.setZoneId(this.xhwDefaultFloorId);
|
||||
359: resultDto.setZoneName("40F");
|
||||
360: floorInfoList.add(resultDto);
|
||||
361: imgStorePersonResult.setFloorInfoList(floorInfoList);
|
||||
362: } else if (imgStorePersonResult.getOrganizationIds().contains(this.gfOrgId)) {
|
||||
363: imgStorePersonResult.setDefaultChooseFloor(this.gfDefaultFloorId);
|
||||
364: List<AcsPassRuleImageResultDto> floorInfoList = new ArrayList<>();
|
||||
365: AcsPassRuleImageResultDto resultDto = new AcsPassRuleImageResultDto();
|
||||
366: resultDto.setZoneId(this.gfDefaultFloorId);
|
||||
367: resultDto.setZoneName("28F");
|
||||
368: floorInfoList.add(resultDto);
|
||||
369: imgStorePersonResult.setFloorInfoList(floorInfoList);
|
||||
370: imgStorePersonResult.setIsAcrossDay(Integer.valueOf(0));
|
||||
371: this.logger.info("[GF-28F] listByPage MATCH orgId={} in orgIds={} → default 28F",
|
||||
372: this.gfOrgId, imgStorePersonResult.getOrganizationIds());
|
||||
373: } else {
|
||||
374: imgStorePersonResult.setDefaultChooseFloor(this.xhwSixFloorId);
|
||||
375: List<AcsPassRuleImageResultDto> floorInfoList = new ArrayList<>();
|
||||
376: AcsPassRuleImageResultDto resultDto = new AcsPassRuleImageResultDto();
|
||||
377: resultDto.setZoneId(this.xhwSixFloorId);
|
||||
378: resultDto.setZoneName("6F");
|
||||
379: floorInfoList.add(resultDto);
|
||||
380: imgStorePersonResult.setFloorInfoList(floorInfoList);
|
||||
381: }
|
||||
```
|
||||
|
||||
**注意**: 行号偏移 (+5 行,因上方注入区新增)。实际编辑以内容匹配为准。
|
||||
|
||||
#### 位置 C — `detail()` 邀约+派梯核心路径 (第 643-651 行,在策略替代块后插入)
|
||||
|
||||
**当前代码** (精确):
|
||||
```java
|
||||
643: Optional<List<String>> replacementFloors =
|
||||
644: this.tenantVisitorFloorPolicyService.replacementZoneIdsIfPolicyActive(
|
||||
645: result.getOrganizationIds());
|
||||
646: if (replacementFloors.isPresent()) {
|
||||
647: floorList = new ArrayList<>(replacementFloors.get());
|
||||
648: zoneNames = buildCommaSeparatedFloorNames(businessId, floorList);
|
||||
649: }
|
||||
650: result.setFloorNames(zoneNames);
|
||||
651: result.setFloorList(floorList);
|
||||
```
|
||||
|
||||
**改为**:
|
||||
```java
|
||||
643: Optional<List<String>> replacementFloors =
|
||||
644: this.tenantVisitorFloorPolicyService.replacementZoneIdsIfPolicyActive(
|
||||
645: result.getOrganizationIds());
|
||||
646: if (replacementFloors.isPresent()) {
|
||||
647: floorList = new ArrayList<>(replacementFloors.get());
|
||||
648: zoneNames = buildCommaSeparatedFloorNames(businessId, floorList);
|
||||
649: }
|
||||
650: // 广发基金: 邀约 + UC-01 派梯 floorList 限制为 28F
|
||||
651: if (!CollectionUtils.isEmpty(result.getOrganizationIds())
|
||||
652: && result.getOrganizationIds().contains(this.gfOrgId)) {
|
||||
653: List<String> originalFloors = new ArrayList<>(floorList);
|
||||
654: floorList = Collections.singletonList(this.gfDefaultFloorId);
|
||||
655: zoneNames = "28F";
|
||||
656: this.logger.info("[GF-28F] detail MATCH orgId={} in orgIds={} → floor restricted: {}→[28F]",
|
||||
657: this.gfOrgId, result.getOrganizationIds(), originalFloors);
|
||||
658: } else {
|
||||
659: this.logger.debug("[GF-28F] detail NO-MATCH orgId={} not in orgIds={}",
|
||||
660: this.gfOrgId, result.getOrganizationIds());
|
||||
661: }
|
||||
662: result.setFloorNames(zoneNames);
|
||||
663: result.setFloorList(floorList);
|
||||
```
|
||||
|
||||
**注意**: `Collections.singletonList` 需要 `import java.util.Collections;` — 检查是否已存在(当前代码 `listByPage` 中使用了 `Collections.singletonList`,import 应已存在)。
|
||||
|
||||
#### 位置 D — `detail()` 入口日志 (在第 600 行附近,`detail()` 方法体内)
|
||||
|
||||
在 `detail()` 方法体的早期(如第 570-600 行区间,根据实际方法体定位),新增:
|
||||
|
||||
```java
|
||||
this.logger.info("[GF-DETAIL] entry personId={} businessId={} orgIds={}",
|
||||
param.getId(), businessId, result.getOrganizationIds());
|
||||
```
|
||||
|
||||
#### 位置 E — `detail()` listByImageId 返回日志 (在第 630 行附近)
|
||||
|
||||
在 `listByImageId` 调用成功后、循环组装 `floorList` 前:
|
||||
|
||||
```java
|
||||
this.logger.info("[GF-DETAIL] listByImageId returned {} zones: {}",
|
||||
acsPassRuleImageResultDtoList.size(),
|
||||
acsPassRuleImageResultDtoList.stream()
|
||||
.map(AcsPassRuleImageResultDto::getZoneId).collect(Collectors.toList()));
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2.2 模块: `cw-elevator-application-service`
|
||||
|
||||
**文件**: `backend/cw-elevator-application/cw-elevator-application-service/src/main/java/cn/cloudwalk/elevator/person/impl/PersonRuleServiceImpl.java`
|
||||
|
||||
**包**: `cn.cloudwalk.elevator.person.impl`
|
||||
**类**: `PersonRuleServiceImpl`
|
||||
|
||||
#### 位置 F — addVisitor() 日志增强 (第 187-194 行附近)
|
||||
|
||||
**当前代码** (精确):
|
||||
```java
|
||||
187: boolean callerProvidedFloors = !CollectionUtils.isEmpty(param.getFloorIds());
|
||||
188: if (callerProvidedFloors) {
|
||||
189: effective = param.getFloorIds();
|
||||
190: this.logger.info("UC-02:调用方显式楼层 effective={}", effective);
|
||||
191: } else {
|
||||
192: effective = personResult.getFloorList();
|
||||
193: if (CollectionUtils.isEmpty(effective)) {
|
||||
194: this.logger.warn("UC-01:被访人 detail.floorList 为空 personId={}", param.getPersonId());
|
||||
```
|
||||
|
||||
**改为**:
|
||||
```java
|
||||
187: boolean callerProvidedFloors = !CollectionUtils.isEmpty(param.getFloorIds());
|
||||
188: if (callerProvidedFloors) {
|
||||
189: effective = param.getFloorIds();
|
||||
190: this.logger.info("[GF-ADDV] UC-02 effective={}", effective);
|
||||
191: } else {
|
||||
192: effective = personResult.getFloorList();
|
||||
193: if (CollectionUtils.isEmpty(effective)) {
|
||||
194: this.logger.warn("[GF-ADDV] UC-01 floorList empty personId={}", param.getPersonId());
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2.3 模块: `cwos-component-organization-starter` (配置)
|
||||
|
||||
**文件**: `backend/ninca-common-component-organization/cwos-component-organization-starter/deploy/run-verify/application.properties`
|
||||
|
||||
**位置**: 第 172 行后(`xhwSixFloorId` 之后),新增 2 行:
|
||||
|
||||
```properties
|
||||
# 第 170-172 行 (现有):
|
||||
xhwId=21474e012cd14e26bc62771873b22562
|
||||
xhwDefaultFloorId=605560547135455232
|
||||
xhwSixFloorId=605560541473144832
|
||||
|
||||
# 第 173-174 行 (新增):
|
||||
gfOrgId=488b8ad049bb43408a6fbcc50bcb89ac
|
||||
gfDefaultFloorId=605560545117995008
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2.4 数据层: 禁用原表驱动策略
|
||||
|
||||
**数据库**: `component-organization` (组织库)
|
||||
**表**: `tenant_visitor_floor_policy`
|
||||
|
||||
```sql
|
||||
UPDATE tenant_visitor_floor_policy
|
||||
SET enabled = 0,
|
||||
remark = CONCAT(remark, ' [DISABLED 2026-05-09: migrated to hardcoded 28F in ImgPersonServiceImpl]'),
|
||||
updated_at = UNIX_TIMESTAMP(NOW()) * 1000
|
||||
WHERE id = 'gf_vstr_policy_guangfa_fund_001x'
|
||||
AND enabled = 1;
|
||||
```
|
||||
|
||||
**数据库**: `cw-elevator-application` (电梯库,如果存在同步表)
|
||||
```sql
|
||||
-- 仅当电梯库也有 tenant_visitor_floor_policy 表时执行
|
||||
UPDATE tenant_visitor_floor_policy
|
||||
SET enabled = 0
|
||||
WHERE id = 'gf_vstr_policy_guangfa_fund_001x'
|
||||
AND enabled = 1;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 不变更清单
|
||||
|
||||
| 组件 | 模块 | 文件 | 原因 |
|
||||
|------|------|------|------|
|
||||
| intelligent-cwoscomponent | interface | PersonService.java | Feign 接口定义,不变 |
|
||||
| intelligent-cwoscomponent | rest | PersonFeignClient.java | HTTP 路径映射,不变 |
|
||||
| ninca-common-component-organization | data | TenantVisitorFloorPolicyMapper.java | 仍服务物业策略,不删 |
|
||||
| ninca-common-component-organization | service | TenantVisitorFloorPolicyService.java | 仍服务物业策略,不删 |
|
||||
| ninca-common-component-organization | web | PersonController.java | REST 入口,不变 |
|
||||
| ninca-common-component-organization | starter | bootstrap.properties | 启动配置,不变 |
|
||||
| cw-elevator-application | web | AcsPersonController.java | REST 入口,不变 |
|
||||
| cw-elevator-application | data | ImageRuleRefDao.java | DAO 层,不变 |
|
||||
| scripts/test-env | config | component-org.properties | 测试模板(最小配置),不变 |
|
||||
| ninca-common-component-organization | releases/ | 所有 `releases/` 下文件 | 历史发布快照,不变 |
|
||||
|
||||
---
|
||||
|
||||
## 4. 汇总
|
||||
|
||||
| # | 组件 | Maven 模块 | 文件 | 变更类型 | 行数 |
|
||||
|---|------|-----------|------|---------|------|
|
||||
| A | component-org | cwos-component-organization-**service** | `ImgPersonServiceImpl.java` | 注入 `@Value` ×2 | +4 |
|
||||
| B | component-org | cwos-component-organization-**service** | `ImgPersonServiceImpl.java` | `listByPage` else-if 分支 | +11 |
|
||||
| C | component-org | cwos-component-organization-**service** | `ImgPersonServiceImpl.java` | `detail()` floorList 截断 | +13 |
|
||||
| D | component-org | cwos-component-organization-**service** | `ImgPersonServiceImpl.java` | `detail()` 入口日志 | +2 |
|
||||
| E | component-org | cwos-component-organization-**service** | `ImgPersonServiceImpl.java` | listByImageId 返回日志 | +3 |
|
||||
| F | elevator-app | cw-elevator-application-**service** | `PersonRuleServiceImpl.java` | addVisitor 日志前缀 | ~0 (替换) |
|
||||
| — | component-org | cwos-component-organization-**starter** | `application.properties` | 配置 ×2 | +2 |
|
||||
| — | (数据库) | — | `tenant_visitor_floor_policy` | UPDATE enabled=0 | 1 行 |
|
||||
|
||||
**总计: 2 个组件, 3 个模块, 3 个文件, ~35 行新增**
|
||||
Reference in New Issue
Block a user