lutong пре 3 недеља
родитељ
комит
65f38ebed5

+ 72 - 10
alien-dining/src/main/java/shop/alien/dining/service/impl/DiningWalkInReservationServiceImpl.java

@@ -49,6 +49,8 @@ public class DiningWalkInReservationServiceImpl extends ServiceImpl<UserReservat
     /** 未填结束时间时,按 N 小时作为占用窗口做冲突判断(与订金预订「结束时间」空值场景对齐) */
     private static final int DEFAULT_BLOCK_HOURS_WHEN_NO_END = 4;
     private static final DateTimeFormatter HM = DateTimeFormatter.ofPattern("HH:mm");
+    /** 与订桌/库内既有数据一致:varchar 存 yyyy-MM-dd HH:mm */
+    private static final DateTimeFormatter STORE_DATE_TIME = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
 
     @Override
     @Transactional(rollbackFor = Exception.class)
@@ -67,21 +69,24 @@ public class DiningWalkInReservationServiceImpl extends ServiceImpl<UserReservat
         }
 
         LocalDate day = reservationDate.toInstant().atZone(SHANGHAI).toLocalDate();
-        LocalTime newStartLt = parseHm(dto.getStartTime());
+        LocalTime newStartLt = parseTimeOfDayOnly(dto.getStartTime());
         if (newStartLt == null) {
             throw new RuntimeException("开始时间格式不正确,请使用 HH:mm");
         }
-        LocalTime newEndLt = parseHm(dto.getEndTime());
+        LocalTime newEndLt = parseTimeOfDayOnly(dto.getEndTime());
         assertNoTableBookingConflict(table.getId(), table.getStoreId(), day, newStartLt, newEndLt);
 
+        LocalDateTime startLdt = LocalDateTime.of(day, newStartLt);
+        LocalDateTime endLdt = windowEnd(day, newStartLt, newEndLt);
+
         Date now = new Date();
         UserReservation entity = new UserReservation();
         entity.setReservationNo(generateReservationNo());
         entity.setUserId(userId);
         entity.setStoreId(table.getStoreId());
         entity.setReservationDate(reservationDate);
-        entity.setStartTime(trimOrNull(dto.getStartTime()));
-        entity.setEndTime(trimOrNull(dto.getEndTime()));
+        entity.setStartTime(startLdt.format(STORE_DATE_TIME));
+        entity.setEndTime(endLdt.format(STORE_DATE_TIME));
         entity.setGuestCount(dto.getGuestCount());
         entity.setCategoryId(table.getCategoryId());
         entity.setStatus(STATUS_ARRIVED);
@@ -168,13 +173,11 @@ public class DiningWalkInReservationServiceImpl extends ServiceImpl<UserReservat
             if (otherDay == null || !day.equals(otherDay)) {
                 continue;
             }
-            LocalTime oStart = parseHm(other.getStartTime());
-            if (oStart == null) {
+            LocalDateTime oStartLdt = parseStoredStartLdt(otherDay, other.getStartTime());
+            if (oStartLdt == null) {
                 continue;
             }
-            LocalTime oEnd = parseHm(other.getEndTime());
-            LocalDateTime oStartLdt = LocalDateTime.of(otherDay, oStart);
-            LocalDateTime oEndLdt = windowEnd(otherDay, oStart, oEnd);
+            LocalDateTime oEndLdt = parseStoredEndLdt(oStartLdt, other.getEndTime());
             if (newStartLdt.isBefore(oEndLdt) && oStartLdt.isBefore(newEndLdt)) {
                 log.warn("到店就餐信息与既有预订冲突 tableId={} day={} new=[{} - {}] otherResId={} other=[{} - {}]",
                         tableId, day, newStartLdt, newEndLdt, other.getId(), oStartLdt, oEndLdt);
@@ -195,11 +198,15 @@ public class DiningWalkInReservationServiceImpl extends ServiceImpl<UserReservat
         return d.toInstant().atZone(SHANGHAI).toLocalDate();
     }
 
-    private static LocalTime parseHm(String raw) {
+    /** 仅时分:HH:mm / H:mm */
+    private static LocalTime parseTimeOfDayOnly(String raw) {
         if (!StringUtils.hasText(raw)) {
             return null;
         }
         String s = raw.trim();
+        if (s.contains(" ")) {
+            s = s.substring(s.lastIndexOf(' ') + 1).trim();
+        }
         try {
             return LocalTime.parse(s, HM);
         } catch (DateTimeParseException e) {
@@ -211,6 +218,61 @@ public class DiningWalkInReservationServiceImpl extends ServiceImpl<UserReservat
         }
     }
 
+    private static LocalDateTime tryParseFullDateTime(String raw) {
+        if (!StringUtils.hasText(raw) || !raw.trim().contains(" ")) {
+            return null;
+        }
+        String s = raw.trim();
+        DateTimeFormatter[] fmps = new DateTimeFormatter[]{
+                DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"),
+                DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"),
+                DateTimeFormatter.ofPattern("yyyy-MM-dd H:mm:ss"),
+                DateTimeFormatter.ofPattern("yyyy-MM-dd H:mm")
+        };
+        for (DateTimeFormatter f : fmps) {
+            try {
+                return LocalDateTime.parse(s, f);
+            } catch (DateTimeParseException ignored) {
+            }
+        }
+        return null;
+    }
+
+    private static LocalDateTime parseStoredStartLdt(LocalDate reservationDay, String raw) {
+        if (!StringUtils.hasText(raw)) {
+            return null;
+        }
+        String s = raw.trim();
+        LocalDateTime full = tryParseFullDateTime(s);
+        if (full != null) {
+            return full;
+        }
+        LocalTime t = parseTimeOfDayOnly(s);
+        if (t == null) {
+            return null;
+        }
+        return LocalDateTime.of(reservationDay, t);
+    }
+
+    private static LocalDateTime parseStoredEndLdt(LocalDateTime startLdt, String endRaw) {
+        if (startLdt == null) {
+            return null;
+        }
+        if (!StringUtils.hasText(endRaw)) {
+            return windowEnd(startLdt.toLocalDate(), startLdt.toLocalTime(), null);
+        }
+        String s = endRaw.trim();
+        LocalDateTime full = tryParseFullDateTime(s);
+        if (full != null) {
+            return full;
+        }
+        LocalTime endT = parseTimeOfDayOnly(s);
+        if (endT == null) {
+            return windowEnd(startLdt.toLocalDate(), startLdt.toLocalTime(), null);
+        }
+        return windowEnd(startLdt.toLocalDate(), startLdt.toLocalTime(), endT);
+    }
+
     /**
      * 预约结束时刻:结束早于或等于开始(同一张日历日上的钟点)则视为跨日至次日;结束时间为空则用默认时长。
      */

+ 2 - 2
alien-entity/src/main/java/shop/alien/entity/store/UserReservation.java

@@ -41,11 +41,11 @@ public class UserReservation {
     @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
     private Date reservationDate;
 
-    @ApiModelProperty(value = "预约开始时间 HH:mm")
+    @ApiModelProperty(value = "预约开始时间:存库为 yyyy-MM-dd HH:mm(与订桌数据一致);历史数据可能仅有 HH:mm")
     @TableField("start_time")
     private String startTime;
 
-    @ApiModelProperty(value = "预约结束时间 HH:mm(可往后延续)")
+    @ApiModelProperty(value = "预约结束时间:存库为 yyyy-MM-dd HH:mm;历史数据可能仅有 HH:mm")
     @TableField("end_time")
     private String endTime;
 

+ 2 - 2
alien-entity/src/main/java/shop/alien/entity/store/dto/DiningWalkInReservationDTO.java

@@ -31,11 +31,11 @@ public class DiningWalkInReservationDTO {
     @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
     private Date reservationDate;
 
-    @ApiModelProperty(value = "开始时间 HH:mm", required = true)
+    @ApiModelProperty(value = "开始时间 HH:mm(与 reservation_date 组合;入库为 yyyy-MM-dd HH:mm)", required = true)
     @NotBlank(message = "开始时间不能为空")
     private String startTime;
 
-    @ApiModelProperty(value = "结束时间 HH:mm;若早于开始时间则视为次日结束。选填,不填则按4小时占用窗口参与冲突校验")
+    @ApiModelProperty(value = "结束时间 HH:mm;若早于当日开始钟点则视为次日结束。选填;入库为 yyyy-MM-dd HH:mm,不填则按占位规则写出结束时刻")
     private String endTime;
 
     @ApiModelProperty(value = "就餐人姓名")

+ 2 - 2
alien-entity/src/main/java/shop/alien/entity/store/dto/UserReservationDTO.java

@@ -30,10 +30,10 @@ public class UserReservationDTO {
     @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
     private Date reservationDate;
 
-    @ApiModelProperty(value = "预约开始时间 HH:mm", example = "09:00")
+    @ApiModelProperty(value = "预约开始时间:建议 yyyy-MM-dd HH:mm;兼容 HH:mm(按预约日拼接)", example = "2026-03-28 09:00")
     private String startTime;
 
-    @ApiModelProperty(value = "预约结束时间 HH:mm", example = "12:00")
+    @ApiModelProperty(value = "预约结束时间:建议 yyyy-MM-dd HH:mm;兼容 HH:mm", example = "2026-03-28 12:00")
     private String endTime;
 
     @ApiModelProperty(value = "预约人数", required = true)

+ 2 - 2
alien-entity/src/main/java/shop/alien/entity/store/vo/UserReservationVo.java

@@ -33,10 +33,10 @@ public class UserReservationVo {
     @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
     private Date reservationDate;
 
-    @ApiModelProperty(value = "预约开始时间 HH:mm")
+    @ApiModelProperty(value = "预约开始时间,一般为 yyyy-MM-dd HH:mm")
     private String startTime;
 
-    @ApiModelProperty(value = "预约结束时间 HH:mm")
+    @ApiModelProperty(value = "预约结束时间,一般为 yyyy-MM-dd HH:mm")
     private String endTime;
 
     @ApiModelProperty(value = "预约人数")