# 访客楼层验证工具链 完整测试方案与计划见:`docs/testing/visitor-registration-floor-validation.md` **被访人(员工)与访客 ID、`personId`/`visitorId` 含义及楼层求交逻辑**:`docs/testing/visitor-registration-business-flow.md` **租户定制默认楼层与未配置租户隔离(业务边界 + 流程图)**:`docs/testing/tenant-visitor-default-floor-isolation.md` ## 一键验收(V2 程序) 需能访问 **MySQL**(组织库 + 电梯库)。联机时脚本会先检测 V2 是否可达;不可达则尝试自动启动 **Maven V2 电梯应用**(`cw-elevator-application-starter`)。 在同一目录创建 **`.env.visitor_verify`**(仅此文件名),填入 **`MYSQL_*`、`ELEVATOR_VERIFY_BASE`**,以及联机所需的 **`ELEVATOR_HEADER_AUTHORIZATION`**(等网关要求);**`ELEVATOR_HEADER_BUSINESSID` 可不写**——未设置时程序会从 `config/test_matrix.json` 的 **`tenant_primary_business_id`** 自动注入 HTTP 头 `businessid`。测**第二租户**时请加 **`--tenant secondary`**,或 **`--suite tenant_secondary_placeholder`**,或在 `.env` 中手写 `ELEVATOR_HEADER_BUSINESSID`。也可不设文件而在 shell 中 `export`。 **不同租户是否不同**:是。每个租户有独立的 **`business_id`**(组织/策略/人员数据隔离)。本矩阵中广发套件 `guangfa_fund_10` 与星河湾套件 `xinghewan_star_center` 当前配置为**同一** `business_id`(与 `tenant_primary_business_id` 一致);对照套件 **`tenant_secondary_placeholder`** 使用 **`tenant_secondary_business_id`**,与主租户不同。 一键脚本会优先加载 **`VISITOR_VERIFY_ENV_FILE`**(若设置),否则加载 **`./.env.visitor_verify`**。 | CLI / 环境 | 作用 | |------------|------| | (未设 `ELEVATOR_HEADER_BUSINESSID`) | 自动使用矩阵 **`tenant_primary_business_id`** | | **`--tenant primary`** / **`secondary`** | 显式使用矩阵顶层主/次租户 ID | | **`--suite `** 或 **`VISITOR_SUITE_ID`** | 按套件取该行的 **`business_id`**(适合只验某一业务块) | ```bash cd maven-cw-elevator-application/tools/visitor_floor_verification chmod +x run_v2_visitor_default_floor_verify.sh ./run_v2_visitor_default_floor_verify.sh ``` `.env.visitor_verify` 请保存为 **LF** 换行;若在 Windows 记事本编辑产生 CRLF,脚本已改为加载时自动剥除 `\r`,亦可在本目录执行 `sed -i 's/\r$//' .env.visitor_verify` 修复。 脚本顺序:`**export_catalog.py`** → `**run_visitor_floor_suite.py --phase all**`(静态校验 + 联机注册与 `passRule/image` 回读),报告写入 `report/visitor-floor-suite-*.md`。 若出现 **`Can't connect to MySQL server on '127.0.0.1'`**:说明未连上库(本机无 MySQL 或 `.env` 未加载)。请设置可达的 `MYSQL_HOST`/`MYSQL_PORT`,或已有快照时用 **`./run_v2_visitor_default_floor_verify.sh --skip-export`** 仅联机验证。 **部门员工不足 10 人**:静态报告仅**提示**;联机阶段对**该部门已有全部员工**逐人测试(仍受 `--max-employees-per-department` 上限约束)。**无员工**的部门会记为失败并 SKIP 联机。 | 脚本选项 | 含义 | | --------------- | -------------------------------------- | | `--skip-export` | 不跑导出,沿用现有 `data/catalog_snapshot.json` | | `--report-only` | 仅导出 + 静态 report,无联机(不需起 V2) | | `--smoke` | 联机极简:`--register-only` 且每部门 1 人 | | `--no-auto-start` | 关闭自动启动 V2(仅做探测,不拉起) | 环境变量:`**VISITOR_SKIP_HEALTH_PROBE**`、`**VISITOR_REQUIRE_HEALTH**`、`**VISITOR_SKIP_PIP_INSTALL**` 见 `run_v2_visitor_default_floor_verify.sh` 内注释。联机阶段若出现 **`Connection refused`**:默认会先尝试自动启动 V2。自动启动命令可用 `VISITOR_V2_START_CMD` 覆盖(默认 `mvn -pl cw-elevator-application-starter -am spring-boot:run -Dspring-boot.run.profiles=access-control`),等待上限 `VISITOR_V2_START_MAX_WAIT_SEC`(默认 180s),日志 `VISITOR_V2_START_LOG`。完全关闭自动拉起可用 `--no-auto-start` 或 `VISITOR_AUTO_START_V2=0`。`**VISITOR_SKIP_LIVE_PREFLIGHT=1**` 可跳过 `run_visitor_floor_suite` 的 TCP 预检(仍会在首条业务请求失败;默认开启预检以免报告刷屏)。 联机参数:`**--max-employees-per-department**`(默认 10;冒烟可设为 **1** 减少 API 次数)。 **验收口径(与业务一致)** - `POST /elevator/person/add/visitor`:完成访客派梯登记;请求里 `floorIds: []` 时由服务端取被访人 `floorList` 并与 `tenant_visitor_floor_policy` 求交后落库。 - **HTTP 响应为 `Boolean`,不含允许楼层列表**;要对「注册后实际可访问楼层」做断言,须在注册成功后用 `**POST /elevator/passRule/image`**(`personId` = 访客 `visitorId`)回读 zone 列表。这是与 `tools/elevator_api_parity/scripts/verify_gf_visitor_default_floor.py` 同一套验收路径。 - 若只做连通性/业务码冒烟(不测楼层):`**--register-only`**(不回读 passRule)。 ## 目录 | 路径 | 说明 | | ---------------------------------------- | ---------------------------------------------------------------- | | `config/test_matrix.json` | 套件与组织节点(广发10 + 星河湾/星中心代表 + 第二租户占位) | | `data/catalog_snapshot.json` | `scripts/export_catalog.py` 生成,含每部门样例被访人 ID | | `scripts/export_catalog.py` | 从 MySQL 拉取策略、人员锚点,合并矩阵 | | `run_v2_visitor_default_floor_verify.sh` | **一键**:导出 catalog + `--phase all`(推荐) | | `scripts/run_visitor_floor_suite.py` | `report` / `live` / `**all`**(静态 + 联机合并报告);`--register-only` 仅注册 | | `report/` | 运行后 Markdown 报告(默认生成于此) | ## 依赖 ```bash pip install -r requirements.txt ``` 联机阶段复用对拍请求头:`ELEVATOR_HEADER_BUSINESSID`、`ELEVATOR_HEADER_AUTHORIZATION` 等(见 `elevator_api_parity`)。 ## 典型命令 ```bash export MYSQL_HOST=192.168.3.12 MYSQL_PORT=3307 MYSQL_USER=root MYSQL_PASSWORD='***' export ELEVATOR_HEADER_BUSINESSID=2524639890ba4f2cba9ba1a4eeaa4015 export ELEVATOR_HEADER_AUTHORIZATION='Bearer ...' export VISITOR_TEST_PERSON_ID='<测试访客 personId>' # 推荐:一键(等同 export + --phase all;businessId 默认取矩阵主租户) ./run_v2_visitor_default_floor_verify.sh # 第二租户联机(businessId 取自 tenant_secondary_business_id;透传给 Python) ./run_v2_visitor_default_floor_verify.sh --tenant secondary python scripts/export_catalog.py python scripts/run_visitor_floor_suite.py --phase report --snapshot data/catalog_snapshot.json # 静态 + 联机合并为一份报告 python scripts/run_visitor_floor_suite.py --phase all --base-url http://127.0.0.1:18081 \ --visitor-person-id "$VISITOR_TEST_PERSON_ID" python scripts/run_visitor_floor_suite.py --phase live --base-url http://127.0.0.1:18081 \ --visitor-person-id "$VISITOR_TEST_PERSON_ID" # 仅访客注册(不测楼层明细) python scripts/run_visitor_floor_suite.py --phase live --base-url http://127.0.0.1:18081 \ --register-only --max-employees-per-department 1 ``` 第二租户联机需切换 `ELEVATOR_HEADER_BUSINESSID`(若现场无人员则套件自动 SKIP)。