diff --git a/RuoYi-Vue/ruoyi-train/src/main/java/com/ruoyi/train/service/impl/TrainAccommodationServiceImpl.java b/RuoYi-Vue/ruoyi-train/src/main/java/com/ruoyi/train/service/impl/TrainAccommodationServiceImpl.java index dfcb6373e..6c87518a1 100644 --- a/RuoYi-Vue/ruoyi-train/src/main/java/com/ruoyi/train/service/impl/TrainAccommodationServiceImpl.java +++ b/RuoYi-Vue/ruoyi-train/src/main/java/com/ruoyi/train/service/impl/TrainAccommodationServiceImpl.java @@ -186,6 +186,12 @@ public class TrainAccommodationServiceImpl implements ITrainAccommodationService { accommodation.setAccommodationStatus(TrainAccommodation.STATUS_PREALLOCATED); } + // FIX-04: 住宿生命周期状态白名单守卫,杜绝非法整数与伪造状态落库 + assertStatusInLifecycleWhitelist(accommodation.getAccommodationStatus()); + if (TrainAccommodation.STATUS_CHECKED_OUT.equals(accommodation.getAccommodationStatus())) + { + throw new ServiceException("新增住宿安排不能直接置为已退宿状态,退宿请使用专属退宿业务操作"); + } int rows = trainAccommodationMapper.insertTrainAccommodation(accommodation); if (rows > 0 && accessAuthorizationOrchestrator != null) { @@ -223,6 +229,16 @@ public class TrainAccommodationServiceImpl implements ITrainAccommodationService throw new ServiceException("变更宿舍请使用专属调房换房流程 (transfer),禁止直接修改住宿记录的宿舍ID"); } + // FIX-04: 住宿生命周期状态只能通过办理入住/办理退宿/调房等专属业务操作改变, + // 通用 update 一律不得写 accommodation_status,避免绕过状态机与门禁撤权联动。 + if (accommodation.getAccommodationStatus() != null + && !accommodation.getAccommodationStatus().equals(exist.getAccommodationStatus())) + { + throw new ServiceException("变更住宿状态请使用办理入住、办理退宿或调房等专属业务操作,禁止直接修改住宿记录状态"); + } + // 与现状一致时同样不下发该字段,杜绝通用更新路径触碰生命周期状态列 + accommodation.setAccommodationStatus(null); + String targetDormId = accommodation.getDormId() != null ? accommodation.getDormId() : exist.getDormId(); String targetBedNo = accommodation.getBedNo() != null ? accommodation.getBedNo() : exist.getBedNo(); @@ -403,6 +419,24 @@ public class TrainAccommodationServiceImpl implements ITrainAccommodationService return trainAccommodationMapper.deleteTrainAccommodationByAccommodationId(accommodationId); } + /** + * FIX-04: 住宿生命周期状态白名单校验。 + *
+ * 数据库与业务只承认三个状态:0 预分配、1 已入住、2 已退宿。
+ * 不存在"已调房"等第四种状态,调房是业务操作而非住宿状态。
+ *
+ * @param status 待校验的住宿状态
+ */
+ private void assertStatusInLifecycleWhitelist(Integer status)
+ {
+ if (!TrainAccommodation.STATUS_PREALLOCATED.equals(status)
+ && !TrainAccommodation.STATUS_CHECKED_IN.equals(status)
+ && !TrainAccommodation.STATUS_CHECKED_OUT.equals(status))
+ {
+ throw new ServiceException("住宿状态不合法,仅支持预分配、已入住、已退宿三种状态");
+ }
+ }
+
/**
* Model C: 校验床位在开班计划时间窗口内的占用情况 (Fail Closed)
*
diff --git a/build_ui/src/views/train/accommodation/index.vue b/build_ui/src/views/train/accommodation/index.vue
index e0efb76b2..0cb313219 100644
--- a/build_ui/src/views/train/accommodation/index.vue
+++ b/build_ui/src/views/train/accommodation/index.vue
@@ -30,7 +30,6 @@