Showing
1 changed file
with
70 additions
and
24 deletions
| ... | @@ -84,6 +84,24 @@ public class AutoCreateMealOrderTask { | ... | @@ -84,6 +84,24 @@ public class AutoCreateMealOrderTask { |
| 84 | final var thisWeekEnd = today.with(DayOfWeek.SUNDAY).atTime(LocalTime.MAX).atZone(DateUtil.CHINA_ZONE); | 84 | final var thisWeekEnd = today.with(DayOfWeek.SUNDAY).atTime(LocalTime.MAX).atZone(DateUtil.CHINA_ZONE); |
| 85 | final var nextWeekStart = today.with(TemporalAdjusters.next(DayOfWeek.MONDAY)).atStartOfDay().atZone(DateUtil.CHINA_ZONE); | 85 | final var nextWeekStart = today.with(TemporalAdjusters.next(DayOfWeek.MONDAY)).atStartOfDay().atZone(DateUtil.CHINA_ZONE); |
| 86 | 86 | ||
| 87 | + // 获取下周每天的节假日信息 | ||
| 88 | + final var holidayMap = new HashMap<String, Integer>(); | ||
| 89 | + for (int i = 0; i < 7; i++) { | ||
| 90 | + final var date = nextWeekStart.plusDays(i); | ||
| 91 | + final var dateStr = date.format(DateUtil.YYYY_MM_DD); | ||
| 92 | + try { | ||
| 93 | + final var url = String.format("https://api.haoshenqi.top/holiday?date=%s", dateStr); | ||
| 94 | + final var response = new java.net.URL(url).openConnection(); | ||
| 95 | + final var reader = new java.io.BufferedReader(new java.io.InputStreamReader(response.getInputStream())); | ||
| 96 | + final var jsonResponse = reader.readLine(); | ||
| 97 | + final var jsonNode = new com.fasterxml.jackson.databind.ObjectMapper().readTree(jsonResponse); | ||
| 98 | + final var status = jsonNode.get(0).get("status").asInt(); | ||
| 99 | + holidayMap.put(dateStr, status); | ||
| 100 | + } catch (Exception e) { | ||
| 101 | + log.error("检查节假日失败: {}", dateStr, e); | ||
| 102 | + } | ||
| 103 | + } | ||
| 104 | + | ||
| 87 | // 查询本周已订餐学生 ID | 105 | // 查询本周已订餐学生 ID |
| 88 | final var mealOrders = mealOrderServiceRpcClient.queryMealOrdersByCondition(enterpriseId, null, thisWeekStart.toInstant().toEpochMilli(), thisWeekEnd.toInstant().toEpochMilli()); | 106 | final var mealOrders = mealOrderServiceRpcClient.queryMealOrdersByCondition(enterpriseId, null, thisWeekStart.toInstant().toEpochMilli(), thisWeekEnd.toInstant().toEpochMilli()); |
| 89 | final var dinerIds = mealOrders.stream().map(SingleMealOrderRpcResponse::getDinerId).sorted(Comparator.comparingInt(Integer::intValue)).collect(Collectors.toCollection(LinkedHashSet::new)); | 107 | final var dinerIds = mealOrders.stream().map(SingleMealOrderRpcResponse::getDinerId).sorted(Comparator.comparingInt(Integer::intValue)).collect(Collectors.toCollection(LinkedHashSet::new)); |
| ... | @@ -110,14 +128,16 @@ public class AutoCreateMealOrderTask { | ... | @@ -110,14 +128,16 @@ public class AutoCreateMealOrderTask { |
| 110 | enterpriseId, | 128 | enterpriseId, |
| 111 | clientIds, // 使用0表示查询所有 | 129 | clientIds, // 使用0表示查询所有 |
| 112 | null, | 130 | null, |
| 113 | - null | 131 | + List.of(0) |
| 114 | ); | 132 | ); |
| 115 | 133 | ||
| 116 | if (schoolSuspensionRecords != null) { | 134 | if (schoolSuspensionRecords != null) { |
| 117 | - var currentTime = System.currentTimeMillis(); | 135 | + final var nextWeekStartTime = nextWeekStart.toInstant().toEpochMilli(); |
| 136 | + final var nextWeekEndTime = nextWeekStart.plusDays(6).with(LocalTime.MAX).toInstant().toEpochMilli(); | ||
| 137 | + | ||
| 118 | schoolSuspensionRecords.stream() | 138 | schoolSuspensionRecords.stream() |
| 119 | .filter(record -> clientIds.contains(record.getClientId())) | 139 | .filter(record -> clientIds.contains(record.getClientId())) |
| 120 | - .filter(record -> currentTime >= record.getStartAt() && currentTime <= record.getEndAt()) | 140 | + .filter(record -> !(record.getEndAt() < nextWeekStartTime || record.getStartAt() > nextWeekEndTime)) |
| 121 | .collect(Collectors.groupingBy( | 141 | .collect(Collectors.groupingBy( |
| 122 | SingleDinerMealSuspensionRecordRpcResponse::getClientId, | 142 | SingleDinerMealSuspensionRecordRpcResponse::getClientId, |
| 123 | Collectors.collectingAndThen( | 143 | Collectors.collectingAndThen( |
| ... | @@ -142,14 +162,15 @@ public class AutoCreateMealOrderTask { | ... | @@ -142,14 +162,15 @@ public class AutoCreateMealOrderTask { |
| 142 | ); | 162 | ); |
| 143 | 163 | ||
| 144 | if (studentSuspensionRecords != null) { | 164 | if (studentSuspensionRecords != null) { |
| 145 | - var currentTime = System.currentTimeMillis(); | 165 | + final var nextWeekStartTime = nextWeekStart.toInstant().toEpochMilli(); |
| 166 | + final var nextWeekEndTime = nextWeekStart.plusDays(6).with(LocalTime.MAX).toInstant().toEpochMilli(); | ||
| 146 | var dinerIdSet = notReservedDiners.stream() | 167 | var dinerIdSet = notReservedDiners.stream() |
| 147 | .map(SingleDinerRpcResponse::getId) | 168 | .map(SingleDinerRpcResponse::getId) |
| 148 | .collect(Collectors.toSet()); | 169 | .collect(Collectors.toSet()); |
| 149 | 170 | ||
| 150 | studentSuspensionRecords.stream() | 171 | studentSuspensionRecords.stream() |
| 151 | .filter(record -> dinerIdSet.contains(record.getDinerId())) | 172 | .filter(record -> dinerIdSet.contains(record.getDinerId())) |
| 152 | - .filter(record -> currentTime >= record.getStartAt() && currentTime <= record.getEndAt()) | 173 | + .filter(record -> !(record.getEndAt() < nextWeekStartTime || record.getStartAt() > nextWeekEndTime)) |
| 153 | .collect(Collectors.groupingBy( | 174 | .collect(Collectors.groupingBy( |
| 154 | SingleDinerMealSuspensionRecordRpcResponse::getDinerId, | 175 | SingleDinerMealSuspensionRecordRpcResponse::getDinerId, |
| 155 | Collectors.collectingAndThen( | 176 | Collectors.collectingAndThen( |
| ... | @@ -174,7 +195,8 @@ public class AutoCreateMealOrderTask { | ... | @@ -174,7 +195,8 @@ public class AutoCreateMealOrderTask { |
| 174 | mpAccountDinerRefMap, | 195 | mpAccountDinerRefMap, |
| 175 | nextWeekStart, | 196 | nextWeekStart, |
| 176 | schoolSuspensionMap, | 197 | schoolSuspensionMap, |
| 177 | - studentSuspensionMap | 198 | + studentSuspensionMap, |
| 199 | + holidayMap | ||
| 178 | )) | 200 | )) |
| 179 | .filter(Objects::nonNull) | 201 | .filter(Objects::nonNull) |
| 180 | .toList(); | 202 | .toList(); |
| ... | @@ -202,24 +224,22 @@ public class AutoCreateMealOrderTask { | ... | @@ -202,24 +224,22 @@ public class AutoCreateMealOrderTask { |
| 202 | Map<Integer, SingleMpAccountDinerRefRpcResponse> mpAccountDinerRefMap, | 224 | Map<Integer, SingleMpAccountDinerRefRpcResponse> mpAccountDinerRefMap, |
| 203 | ZonedDateTime startOfNextWeek, | 225 | ZonedDateTime startOfNextWeek, |
| 204 | Map<Integer, SingleDinerMealSuspensionRecordRpcResponse> schoolSuspensionMap, | 226 | Map<Integer, SingleDinerMealSuspensionRecordRpcResponse> schoolSuspensionMap, |
| 205 | - Map<Integer, SingleDinerMealSuspensionRecordRpcResponse> studentSuspensionMap) { | 227 | + Map<Integer, SingleDinerMealSuspensionRecordRpcResponse> studentSuspensionMap, |
| 228 | + Map<String, Integer> holidayMap) { | ||
| 206 | final var menu = menuMap.get(diner.getClientId()); | 229 | final var menu = menuMap.get(diner.getClientId()); |
| 207 | final var client = clientMap.get(diner.getClientId()); | 230 | final var client = clientMap.get(diner.getClientId()); |
| 208 | final var gradeClass = classMap.get(diner.getClassId()); | 231 | final var gradeClass = classMap.get(diner.getClassId()); |
| 209 | final var mpAccountDinerRef = mpAccountDinerRefMap.get(diner.getId()); | 232 | final var mpAccountDinerRef = mpAccountDinerRefMap.get(diner.getId()); |
| 210 | if (menu == null || client == null || gradeClass == null) return null; | 233 | if (menu == null || client == null || gradeClass == null) return null; |
| 211 | 234 | ||
| 212 | - // 检查学校级别的停餐信息 | 235 | + // 获取停餐信息,优先使用学校级别的 |
| 213 | - if (schoolSuspensionMap.containsKey(diner.getClientId())) { | 236 | + SingleDinerMealSuspensionRecordRpcResponse suspensionRecord = schoolSuspensionMap.get(diner.getClientId()); |
| 214 | - log.info("学校 {} 当前处于停餐状态,跳过自动订餐", client.getName()); | 237 | + if (suspensionRecord == null) { |
| 215 | - return null; | 238 | + suspensionRecord = studentSuspensionMap.get(diner.getId()); |
| 216 | } | 239 | } |
| 217 | 240 | ||
| 218 | - // 检查学生级别的停餐信息 | 241 | + // 构建下周的餐食安排 |
| 219 | - if (studentSuspensionMap.containsKey(diner.getId())) { | 242 | + List<MenuSchedule> meals = buildNextWeekMeals(startOfNextWeek, suspensionRecord, holidayMap); |
| 220 | - log.info("学生 {} 当前处于停餐状态,跳过自动订餐", diner.getName()); | ||
| 221 | - return null; | ||
| 222 | - } | ||
| 223 | 243 | ||
| 224 | return MealOrderCreation.newBuilder() | 244 | return MealOrderCreation.newBuilder() |
| 225 | .setClientId(diner.getClientId()) | 245 | .setClientId(diner.getClientId()) |
| ... | @@ -233,24 +253,50 @@ public class AutoCreateMealOrderTask { | ... | @@ -233,24 +253,50 @@ public class AutoCreateMealOrderTask { |
| 233 | .setClassName(gradeClass.getClassName()) | 253 | .setClassName(gradeClass.getClassName()) |
| 234 | .setStudentNo(diner.getStudentNo()) | 254 | .setStudentNo(diner.getStudentNo()) |
| 235 | .setReserveDate(Instant.now().toEpochMilli()) | 255 | .setReserveDate(Instant.now().toEpochMilli()) |
| 236 | - .addAllMeals(buildNextWeekMeals(startOfNextWeek)) | 256 | + .addAllMeals(meals) |
| 237 | .build(); | 257 | .build(); |
| 238 | } | 258 | } |
| 239 | 259 | ||
| 240 | - private LocalDate getThisWeekDay(LocalDate now, DayOfWeek target) { | 260 | + private List<MenuSchedule> buildNextWeekMeals(ZonedDateTime nextWeekStart, |
| 241 | - LocalDate monday = now.with(DayOfWeek.MONDAY); | 261 | + SingleDinerMealSuspensionRecordRpcResponse suspensionRecord, |
| 242 | - return monday.plusDays(target.getValue() - 1L); | 262 | + Map<String, Integer> holidayMap) { |
| 243 | - } | 263 | + return IntStream.range(0, 7) |
| 244 | - | ||
| 245 | - private List<MenuSchedule> buildNextWeekMeals(ZonedDateTime nextWeekStart) { | ||
| 246 | - return IntStream.range(0, 5) | ||
| 247 | .mapToObj(i -> { | 264 | .mapToObj(i -> { |
| 248 | final var date = nextWeekStart.plusDays(i); | 265 | final var date = nextWeekStart.plusDays(i); |
| 266 | + final var dateStr = date.format(DateUtil.YYYY_MM_DD); | ||
| 267 | + | ||
| 268 | + // 检查是否为节假日 | ||
| 269 | + final var status = holidayMap.get(dateStr); | ||
| 270 | + if (status != null && status != 0 && status != 2) { | ||
| 271 | + // 如果不是工作日,返回null | ||
| 272 | + return null; | ||
| 273 | + } | ||
| 274 | + | ||
| 275 | + // 如果有停餐信息,检查当前循环的日期是否在停餐时间范围内 | ||
| 276 | + if (suspensionRecord != null) { | ||
| 277 | + final var dateStart = date.with(LocalTime.MIN).toInstant().toEpochMilli(); | ||
| 278 | + final var dateEnd = date.with(LocalTime.MAX).toInstant().toEpochMilli(); | ||
| 279 | + final var suspensionStart = suspensionRecord.getStartAt(); | ||
| 280 | + final var suspensionEnd = suspensionRecord.getEndAt(); | ||
| 281 | + | ||
| 282 | + // 如果停餐时间范围与当前日期有重叠,返回null | ||
| 283 | + if (!(dateEnd < suspensionStart || dateStart > suspensionEnd)) { | ||
| 284 | + return null; | ||
| 285 | + } | ||
| 286 | + } | ||
| 287 | + | ||
| 288 | + // 如果是工作日且不在停餐时间内,返回正常菜单 | ||
| 249 | return MenuSchedule.newBuilder() | 289 | return MenuSchedule.newBuilder() |
| 250 | .setDate(date.format(DateUtil.YYYY_MM_DD_LEFT_SYMBOL)) | 290 | .setDate(date.format(DateUtil.YYYY_MM_DD_LEFT_SYMBOL)) |
| 251 | .setMenu("A") | 291 | .setMenu("A") |
| 252 | .build(); | 292 | .build(); |
| 253 | }) | 293 | }) |
| 294 | + .filter(Objects::nonNull) // 过滤掉null值 | ||
| 254 | .toList(); | 295 | .toList(); |
| 255 | } | 296 | } |
| 297 | + | ||
| 298 | + private LocalDate getThisWeekDay(LocalDate now, DayOfWeek target) { | ||
| 299 | + LocalDate monday = now.with(DayOfWeek.MONDAY); | ||
| 300 | + return monday.plusDays(target.getValue() - 1L); | ||
| 301 | + } | ||
| 256 | } | 302 | } | ... | ... |
-
Please register or login to post a comment