8.6 KiB
8.6 KiB
ISSUE-01-05 宿舍房间与楼宇基础数据维护开发验收文档
1. 任务概述与环境基线
- 任务 ID:
ISSUE-01-05 - 任务名称: 宿舍房间与楼宇基础数据维护
- 所属 Epic:
EPIC-01 基础主数据必要集合 - 优先级: P0
- 工作区目录:
/Users/wzb/Desktop/项目/RailwaySystem-worktrees/issue-01-05-dormitory - 当前分支:
feat/issue-01-05-dormitory - 正确基线 Commit:
4682df03c566776562b693ed5cb48fd98cda2472(integration/wave1a-foundation)- 基线祖先校验状态:
PASS(当前分支直接派生自该正式基线)
- 基线祖先校验状态:
- API 契约基准:
docs/api-v2/02_module_a_base_resource_api.md4.4 节、docs/api-v2/06_dto_vo_catalog.md、docs/api-v2/10_permission_and_error_codes.md - 数据库基线: Database V2 (
train_dormitory_info) - Generator 冻结策略:
YES (单表结构)(依据docs/issues-v1/02_p0_issue_backlog.md与docs/issues-v1/05_agent_assignment.md) - 本轮 Generator 实际执行:
Generator actually executed = NO(骨架已在此前生成,本次按 V2 契约与手写逻辑完成重构与对齐,未重新执行 Generator) - 核心业务目标: 建立宿舍物理房间主数据台账(楼栋、楼层、房间号、核定容量、适用性别、门锁SN),提供同楼栋房号查重与防重、实时在住人数与剩余床位只读动态聚合、当前入住学员列表回显以及楼栋-楼层-房间三级结构化级联下拉选项。
2. HTTP Endpoint 最终收口与物理映射
严格依照冻结契约收口 Controller 公开接口,非冻结接口全部从 Controller 移除,不再对外公开:
- 彻底移除历史
/train/dorminfo路由及 Alias; - 彻底移除
PUT /train/dormitory、DELETE /train/dormitory/{dormIds}、POST /train/dormitory/export等非 P0 接口。
2.1 最终公开物理 Endpoint 完整列表(共且仅有 4 个正式 P0)
| 优先级 | HTTP Method | URI 路径 | Controller 方法 | 权限字符 | 适用角色 | 功能说明与契约对齐 |
|---|---|---|---|---|---|---|
| P0 | GET |
/train/dormitory/list |
list(TrainDormitoryInfo) |
train:dormitory:list |
管理员, 宿管 | 分页查询宿舍列表,附带 capacity、usedCount、remainingBeds |
| P0 | GET |
/train/dormitory/{dormId} |
getInfo(@PathVariable) |
train:dormitory:list |
管理员, 宿管 | 获取指定房间详情及当前入住人员列表 (occupants) |
| P0 | POST |
/train/dormitory |
add(@Validated @RequestBody) |
train:dormitory:edit |
管理员, 宿管 | 新增房间(前置查重与底层唯一约束冲突均转换为 40006) |
| P0 | GET |
/train/dormitory/options |
options() |
train:dormitory:list |
管理员, 宿管 | 获取结构化的楼栋 -> 楼层 -> 房间层级树(分房弹窗必需) |
- Contract-extra Endpoint 数量: 0 个。
3. DTO 与 VO 设计规范
3.1 DormitoryCreateDTO
dormBuilding(String,@NotBlank,@Size(max = 50)): 宿舍楼栋dormFloor(String,@NotBlank,@Size(max = 20)): 所在楼层dormRoom(String,@NotBlank,@Size(max = 30)): 房间号capacity(Integer,@NotNull,@Min(1),@Max(8)): 核定床位容量 (1~8)genderType(Integer,@NotNull): 适用性别 (0:不限, 1:男, 2:女)lockDeviceSn(String,@Size(max = 64)): 智能门锁设备序列号 (可选)remark(String,@Size(max = 500)): 备注 (可选)
3.2 DormitoryItemVO
dormId(String): 宿舍ID主键dormBuilding(String): 宿舍楼栋dormFloor(String): 所在楼层dormRoom(String): 房间号capacity(Integer): 核定床位容量usedCount(Integer): 已住人数 (动态聚合自train_accommodation)remainingBeds(Integer): 剩余床位 (capacity - usedCount)genderType(Integer): 适用性别 (0:不限, 1:男, 2:女)lockDeviceSn(String): 智能门锁SNdormStatus(Integer): 状态 (0:禁用, 1:可用)remark(String): 备注createTime(Date): 创建时间
3.3 DormitoryOccupantVO
enrollmentId(Long): 参训档案IDstudentId(String): 学员主档IDstudentName(String): 学员姓名gender(String): 性别orgName(String): 所属单位bedNo(String): 分配床位号 (可选)assignedTime(Date): 分配入住时间accommodationStatus(Integer): 住宿状态 (0:预分配, 1:已入住)
3.4 DormitoryDetailVO
- 包含房间基础信息与动态统计 (
dormId,dormBuilding,dormFloor,dormRoom,capacity,usedCount,remainingBeds,genderType,lockDeviceSn,dormStatus,remark,createTime); occupants(List<DormitoryOccupantVO>): 当前入住学员列表(空房时返回[],严禁返回null)。
3.5 DormOptionsVO
- 楼栋 -> 楼层 -> 房间三级树节点,包含
value,label,type("building"/"floor"/"room"),children; - 叶子节点(房间)挂载
capacity,usedCount,remainingBeds,genderType,lockDeviceSn元数据,方便前端分房弹窗直接消费。
4. 业务规则与边界约束
4.1 容量与性别规则
- 容量范围: 严格限定在
1 \le \text{capacity} \le 8之间,非正数或大于 8 抛出业务校验异常。 - 适用性别: 必须为合法枚举值(0: 不限, 1: 男, 2: 女)。
4.2 动态房态聚合口径
- 依据:
RuoYi-Vue/sql/train/v2/007_dicts.sql中train_accommodation_status字典定义:0: 预分配 (报到前系统预先分配)1: 已入住 (报到确认并已入住)2: 已退宿 (培训结束已离宿)
- 实际占用定义: 仅处于“预分配”与“已入住”状态的记录占用床位,退宿后释放。
- 实际 SQL 过滤条件:
SELECT dorm_id, COUNT(1) AS used_count FROM train_accommodation WHERE accommodation_status IN (0, 1) GROUP BY dorm_idremaining_beds = (capacity - COALESCE(acc.used_count, 0))。
4.3 UNIQUE 并发语义保证
- 数据库约束:
uq_dorm_building_room UNIQUE (dorm_building, dorm_room)。 - 并发保护机制:
- 应用层前置查重:查询
train_dormitory_info是否存在同楼栋同房号未删除记录,存在即抛出ServiceException("同一楼栋下该宿舍房号已存在", 40006); - 底层并发冲突兜底:高并发场景下两请求同时绕过前置查重时,底层 INSERT 触发唯一约束冲突抛出
DuplicateKeyException,Service 层显式捕获并转换为 40006 业务异常,杜绝 500 裸异常泄漏。
- 应用层前置查重:查询
4.4 业务边界铁律
- Dormitory 仅代表物理房间基础资源: 负责房间基础资产的维护与只读聚合。
- 无独立 DormBed 实体: Phase 1 阶段严禁引入
train_dorm_bed表;bed_no仅为train_accommodation的可空业务字段。 - 禁止 Accommodation 写操作: 本 Issue 严禁分房、调房、退宿、门禁下发与同步、报到入住办理以及级联物理删除。
5. 验证结果与质量达标记录
-
单元测试:
- 执行测试:
DormitoryServiceTest包含 6 个测试用例:testAddAndDuplicateInterception: 前置防重与 40006 拦截testConcurrentInsertDuplicateKeyConversion: 高并发DuplicateKeyException转换为 40006testCapacityAndGenderValidation: 容量 (1~8) 与性别枚举合法性testList: 动态聚合usedCount与remainingBedstestGet: 房间详情与occupants列表回显testOptions: 楼栋-楼层-房间三级树结构组装
- 运行结果:
Tests run: 6, Failures: 0, Errors: 0, Skipped: 0全部通过。
- 执行测试:
-
模块依赖测试:
- 命令:
mvn test -pl ruoyi-train -am -f RuoYi-Vue/pom.xml - 运行结果:
Tests run: 20, Failures: 0, Errors: 0, Skipped: 0全部通过。
- 命令:
-
后端 Reactor 编译:
- 命令:
mvn compile -DskipTests -f RuoYi-Vue/pom.xml - 运行结果:8 个子模块全部
SUCCESS。
- 命令:
-
前端 ESLint 检查:
- 命令:
./node_modules/.bin/eslint --no-ignore src/api/train/dormitory.js src/views/train/dormitory/index.vue - 运行结果:0 errors, 0 warnings。
- 命令:
-
前端生产打包 (build:prod):
- 命令:
npm run build:prod - 运行结果:
Build complete. The dist directory is ready to be deployed.构建成功。构建完成后已彻底清理临时产物与软链接。
- 命令:
-
格式检查 (git diff --check):
- 命令:
git diff --check - 运行结果:无任何 trailing whitespace,洁净通过。
- 命令:
-
Commit 状态:
- 本地暂存区与工作区保留全部修改,未执行 git commit,等待评审。