孟苏慧

Merge branch 'dev/nx-20250526' into 'master'

农信停餐需求



See merge request !4
...@@ -6,10 +6,12 @@ import com.infoloop.tianting.mealorderservice.SingleMealOrderRpcResponse; ...@@ -6,10 +6,12 @@ import com.infoloop.tianting.mealorderservice.SingleMealOrderRpcResponse;
6 import com.infoloop.tianting.model.common.CreatedResult; 6 import com.infoloop.tianting.model.common.CreatedResult;
7 import com.infoloop.tianting.model.dto.MealOrderDTO; 7 import com.infoloop.tianting.model.dto.MealOrderDTO;
8 import com.infoloop.tianting.model.vo.DeliveryRuleVO; 8 import com.infoloop.tianting.model.vo.DeliveryRuleVO;
9 +import com.infoloop.tianting.model.vo.DinerMealSuspensionRecordVO;
9 import com.infoloop.tianting.model.vo.MealOrderVO; 10 import com.infoloop.tianting.model.vo.MealOrderVO;
10 import com.infoloop.tianting.service.MealOrderService; 11 import com.infoloop.tianting.service.MealOrderService;
11 import io.swagger.annotations.Api; 12 import io.swagger.annotations.Api;
12 import io.swagger.annotations.ApiOperation; 13 import io.swagger.annotations.ApiOperation;
14 +import io.swagger.annotations.ApiParam;
13 import lombok.RequiredArgsConstructor; 15 import lombok.RequiredArgsConstructor;
14 import lombok.extern.slf4j.Slf4j; 16 import lombok.extern.slf4j.Slf4j;
15 import org.springframework.beans.factory.annotation.Autowired; 17 import org.springframework.beans.factory.annotation.Autowired;
...@@ -20,6 +22,7 @@ import org.springframework.web.bind.annotation.PostMapping; ...@@ -20,6 +22,7 @@ import org.springframework.web.bind.annotation.PostMapping;
20 import org.springframework.web.bind.annotation.PutMapping; 22 import org.springframework.web.bind.annotation.PutMapping;
21 import org.springframework.web.bind.annotation.RequestAttribute; 23 import org.springframework.web.bind.annotation.RequestAttribute;
22 import org.springframework.web.bind.annotation.RequestBody; 24 import org.springframework.web.bind.annotation.RequestBody;
25 +import org.springframework.web.bind.annotation.RequestParam;
23 import org.springframework.web.bind.annotation.ResponseStatus; 26 import org.springframework.web.bind.annotation.ResponseStatus;
24 import org.springframework.web.bind.annotation.RestController; 27 import org.springframework.web.bind.annotation.RestController;
25 28
...@@ -67,4 +70,11 @@ public class MealOrderController { ...@@ -67,4 +70,11 @@ public class MealOrderController {
67 return mealOrderService.getDeliveryRule(); 70 return mealOrderService.getDeliveryRule();
68 } 71 }
69 72
73 + @ApiOperation(value = "查询停餐信息")
74 + @GetMapping("/dinermealsuspensionrecord")
75 + @ResponseStatus(HttpStatus.OK)
76 + public List<DinerMealSuspensionRecordVO> queryDinerMealSuspensionRecordsByCondition() {
77 + return mealOrderService.queryDinerMealSuspensionRecordsByCondition();
78 + }
79 +
70 } 80 }
......
...@@ -66,6 +66,8 @@ public enum ErrorCodeEnum implements BaseEnum { ...@@ -66,6 +66,8 @@ public enum ErrorCodeEnum implements BaseEnum {
66 66
67 MP_ACCOUNT_ALREADY_DISABLED(406000024, "账号已禁用"), 67 MP_ACCOUNT_ALREADY_DISABLED(406000024, "账号已禁用"),
68 68
69 + DINER_MEAL_SUSPENDED(406000025, "当前就餐人处于停餐状态")
70 +
69 71
70 ; 72 ;
71 private final int code; 73 private final int code;
......
...@@ -3,14 +3,7 @@ package com.infoloop.tianting.logic.task; ...@@ -3,14 +3,7 @@ package com.infoloop.tianting.logic.task;
3 import com.infoloop.tianting.clientinventoryservice.SingleClientRpcResponse; 3 import com.infoloop.tianting.clientinventoryservice.SingleClientRpcResponse;
4 import com.infoloop.tianting.context.LoginContextHolder; 4 import com.infoloop.tianting.context.LoginContextHolder;
5 import com.infoloop.tianting.enums.LoginSourceEnum; 5 import com.infoloop.tianting.enums.LoginSourceEnum;
6 -import com.infoloop.tianting.mealorderservice.MealOrderCreation; 6 +import com.infoloop.tianting.mealorderservice.*;
7 -import com.infoloop.tianting.mealorderservice.MealOrderOrderMethodEnum;
8 -import com.infoloop.tianting.mealorderservice.MenuSchedule;
9 -import com.infoloop.tianting.mealorderservice.SingleDinerRpcResponse;
10 -import com.infoloop.tianting.mealorderservice.SingleGradeClassRpcResponse;
11 -import com.infoloop.tianting.mealorderservice.SingleMealMenuRecordRpcResponse;
12 -import com.infoloop.tianting.mealorderservice.SingleMealOrderRpcResponse;
13 -import com.infoloop.tianting.mealorderservice.SingleMpAccountDinerRefRpcResponse;
14 import com.infoloop.tianting.service.client.ClientInventoryServiceRpcClient; 7 import com.infoloop.tianting.service.client.ClientInventoryServiceRpcClient;
15 import com.infoloop.tianting.service.client.DeliveryRuleServiceRpcClient; 8 import com.infoloop.tianting.service.client.DeliveryRuleServiceRpcClient;
16 import com.infoloop.tianting.service.client.MealOrderServiceRpcClient; 9 import com.infoloop.tianting.service.client.MealOrderServiceRpcClient;
...@@ -31,6 +24,7 @@ import java.time.temporal.TemporalAdjusters; ...@@ -31,6 +24,7 @@ import java.time.temporal.TemporalAdjusters;
31 import java.util.ArrayList; 24 import java.util.ArrayList;
32 import java.util.Collections; 25 import java.util.Collections;
33 import java.util.Comparator; 26 import java.util.Comparator;
27 +import java.util.HashMap;
34 import java.util.LinkedHashSet; 28 import java.util.LinkedHashSet;
35 import java.util.List; 29 import java.util.List;
36 import java.util.Map; 30 import java.util.Map;
...@@ -90,6 +84,24 @@ public class AutoCreateMealOrderTask { ...@@ -90,6 +84,24 @@ public class AutoCreateMealOrderTask {
90 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);
91 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);
92 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 +
93 // 查询本周已订餐学生 ID 105 // 查询本周已订餐学生 ID
94 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());
95 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));
...@@ -109,8 +121,86 @@ public class AutoCreateMealOrderTask { ...@@ -109,8 +121,86 @@ public class AutoCreateMealOrderTask {
109 final var clientMap = clientInventoryServiceRpcClient.getClientsByIds(enterpriseId, clientIds).getClientsList().stream().collect(Collectors.toMap(SingleClientRpcResponse::getId, Function.identity())); 121 final var clientMap = clientInventoryServiceRpcClient.getClientsByIds(enterpriseId, clientIds).getClientsList().stream().collect(Collectors.toMap(SingleClientRpcResponse::getId, Function.identity()));
110 final var gradeClassMap = mealOrderServiceRpcClient.getGradeClassesByIds(enterpriseId, classIds).stream().collect(Collectors.toMap(SingleGradeClassRpcResponse::getId, Function.identity())); 122 final var gradeClassMap = mealOrderServiceRpcClient.getGradeClassesByIds(enterpriseId, classIds).stream().collect(Collectors.toMap(SingleGradeClassRpcResponse::getId, Function.identity()));
111 final var latestMealMenuRecordMap = mealOrderServiceRpcClient.queryLatestMealMenuRecordsByClientIds(enterpriseId, clientIds).stream().collect(Collectors.toMap(SingleMealMenuRecordRpcResponse::getClientId, Function.identity())); 123 final var latestMealMenuRecordMap = mealOrderServiceRpcClient.queryLatestMealMenuRecordsByClientIds(enterpriseId, clientIds).stream().collect(Collectors.toMap(SingleMealMenuRecordRpcResponse::getClientId, Function.identity()));
124 +
125 + // 批量查询学校级别的停餐信息
126 + final var schoolSuspensionMap = new HashMap<Integer, SingleDinerMealSuspensionRecordRpcResponse>();
127 + var schoolSuspensionRecords = mealOrderServiceRpcClient.queryDinerMealSuspensionRecordsByCondition(
128 + enterpriseId,
129 + clientIds, // 使用0表示查询所有
130 + null,
131 + List.of(0)
132 + );
133 +
134 + if (schoolSuspensionRecords != null) {
135 + final var nextWeekStartTime = nextWeekStart.toInstant().toEpochMilli();
136 + final var nextWeekEndTime = nextWeekStart.plusDays(6).with(LocalTime.MAX).toInstant().toEpochMilli();
137 +
138 + schoolSuspensionRecords.stream()
139 + .filter(record -> clientIds.contains(record.getClientId()))
140 + .filter(record -> !(record.getEndAt() < nextWeekStartTime || record.getStartAt() > nextWeekEndTime))
141 + .collect(Collectors.groupingBy(
142 + SingleDinerMealSuspensionRecordRpcResponse::getClientId,
143 + Collectors.collectingAndThen(
144 + Collectors.maxBy((a, b) -> Long.compare(a.getCreatedAt(), b.getCreatedAt())),
145 + opt -> opt.orElse(null)
146 + )
147 + ))
148 + .forEach((clientId, record) -> {
149 + if (record != null) {
150 + schoolSuspensionMap.put(clientId, record);
151 + }
152 + });
153 + }
154 +
155 + // 批量查询学生级别的停餐信息
156 + final var studentSuspensionMap = new HashMap<Integer, SingleDinerMealSuspensionRecordRpcResponse>();
157 + var studentSuspensionRecords = mealOrderServiceRpcClient.queryDinerMealSuspensionRecordsByCondition(
158 + enterpriseId,
159 + null, // 使用0表示查询所有
160 + null,
161 + notReservedDiners.stream().map(SingleDinerRpcResponse::getId).toList()
162 + );
163 +
164 + if (studentSuspensionRecords != null) {
165 + final var nextWeekStartTime = nextWeekStart.toInstant().toEpochMilli();
166 + final var nextWeekEndTime = nextWeekStart.plusDays(6).with(LocalTime.MAX).toInstant().toEpochMilli();
167 + var dinerIdSet = notReservedDiners.stream()
168 + .map(SingleDinerRpcResponse::getId)
169 + .collect(Collectors.toSet());
170 +
171 + studentSuspensionRecords.stream()
172 + .filter(record -> dinerIdSet.contains(record.getDinerId()))
173 + .filter(record -> !(record.getEndAt() < nextWeekStartTime || record.getStartAt() > nextWeekEndTime))
174 + .collect(Collectors.groupingBy(
175 + SingleDinerMealSuspensionRecordRpcResponse::getDinerId,
176 + Collectors.collectingAndThen(
177 + Collectors.maxBy((a, b) -> Long.compare(a.getCreatedAt(), b.getCreatedAt())),
178 + opt -> opt.orElse(null)
179 + )
180 + ))
181 + .forEach((dinerId, record) -> {
182 + if (record != null) {
183 + studentSuspensionMap.put(dinerId, record);
184 + }
185 + });
186 + }
187 +
112 // 构建创建请求 188 // 构建创建请求
113 - final var creations = notReservedDiners.stream().map(diner -> toMealOrderCreation(diner, clientMap, gradeClassMap, latestMealMenuRecordMap, mpAccountDinerRefMap, nextWeekStart)).filter(Objects::nonNull).toList(); 189 + final var creations = notReservedDiners.stream()
190 + .map(diner -> toMealOrderCreation(
191 + diner,
192 + clientMap,
193 + gradeClassMap,
194 + latestMealMenuRecordMap,
195 + mpAccountDinerRefMap,
196 + nextWeekStart,
197 + schoolSuspensionMap,
198 + studentSuspensionMap,
199 + holidayMap
200 + ))
201 + .filter(Objects::nonNull)
202 + .toList();
203 +
114 if (creations.isEmpty()) { 204 if (creations.isEmpty()) {
115 return; 205 return;
116 } 206 }
...@@ -132,12 +222,25 @@ public class AutoCreateMealOrderTask { ...@@ -132,12 +222,25 @@ public class AutoCreateMealOrderTask {
132 Map<Integer, SingleGradeClassRpcResponse> classMap, 222 Map<Integer, SingleGradeClassRpcResponse> classMap,
133 Map<Integer, SingleMealMenuRecordRpcResponse> menuMap, 223 Map<Integer, SingleMealMenuRecordRpcResponse> menuMap,
134 Map<Integer, SingleMpAccountDinerRefRpcResponse> mpAccountDinerRefMap, 224 Map<Integer, SingleMpAccountDinerRefRpcResponse> mpAccountDinerRefMap,
135 - ZonedDateTime startOfNextWeek) { 225 + ZonedDateTime startOfNextWeek,
226 + Map<Integer, SingleDinerMealSuspensionRecordRpcResponse> schoolSuspensionMap,
227 + Map<Integer, SingleDinerMealSuspensionRecordRpcResponse> studentSuspensionMap,
228 + Map<String, Integer> holidayMap) {
136 final var menu = menuMap.get(diner.getClientId()); 229 final var menu = menuMap.get(diner.getClientId());
137 final var client = clientMap.get(diner.getClientId()); 230 final var client = clientMap.get(diner.getClientId());
138 final var gradeClass = classMap.get(diner.getClassId()); 231 final var gradeClass = classMap.get(diner.getClassId());
139 final var mpAccountDinerRef = mpAccountDinerRefMap.get(diner.getId()); 232 final var mpAccountDinerRef = mpAccountDinerRefMap.get(diner.getId());
140 if (menu == null || client == null || gradeClass == null) return null; 233 if (menu == null || client == null || gradeClass == null) return null;
234 +
235 + // 获取停餐信息,优先使用学校级别的
236 + SingleDinerMealSuspensionRecordRpcResponse suspensionRecord = schoolSuspensionMap.get(diner.getClientId());
237 + if (suspensionRecord == null) {
238 + suspensionRecord = studentSuspensionMap.get(diner.getId());
239 + }
240 +
241 + // 构建下周的餐食安排
242 + List<MenuSchedule> meals = buildNextWeekMeals(startOfNextWeek, suspensionRecord, holidayMap);
243 +
141 return MealOrderCreation.newBuilder() 244 return MealOrderCreation.newBuilder()
142 .setClientId(diner.getClientId()) 245 .setClientId(diner.getClientId())
143 .setMenuId(menu.getId()) 246 .setMenuId(menu.getId())
...@@ -150,24 +253,50 @@ public class AutoCreateMealOrderTask { ...@@ -150,24 +253,50 @@ public class AutoCreateMealOrderTask {
150 .setClassName(gradeClass.getClassName()) 253 .setClassName(gradeClass.getClassName())
151 .setStudentNo(diner.getStudentNo()) 254 .setStudentNo(diner.getStudentNo())
152 .setReserveDate(Instant.now().toEpochMilli()) 255 .setReserveDate(Instant.now().toEpochMilli())
153 - .addAllMeals(buildNextWeekMeals(startOfNextWeek)) 256 + .addAllMeals(meals)
154 .build(); 257 .build();
155 } 258 }
156 259
157 - private LocalDate getThisWeekDay(LocalDate now, DayOfWeek target) { 260 + private List<MenuSchedule> buildNextWeekMeals(ZonedDateTime nextWeekStart,
158 - LocalDate monday = now.with(DayOfWeek.MONDAY); 261 + SingleDinerMealSuspensionRecordRpcResponse suspensionRecord,
159 - return monday.plusDays(target.getValue() - 1L); 262 + Map<String, Integer> holidayMap) {
160 - } 263 + return IntStream.range(0, 7)
161 -
162 - private List<MenuSchedule> buildNextWeekMeals(ZonedDateTime nextWeekStart) {
163 - return IntStream.range(0, 5)
164 .mapToObj(i -> { 264 .mapToObj(i -> {
165 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 + // 如果是工作日且不在停餐时间内,返回正常菜单
166 return MenuSchedule.newBuilder() 289 return MenuSchedule.newBuilder()
167 .setDate(date.format(DateUtil.YYYY_MM_DD_LEFT_SYMBOL)) 290 .setDate(date.format(DateUtil.YYYY_MM_DD_LEFT_SYMBOL))
168 .setMenu("A") 291 .setMenu("A")
169 .build(); 292 .build();
170 }) 293 })
294 + .filter(Objects::nonNull) // 过滤掉null值
171 .toList(); 295 .toList();
172 } 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 + }
173 } 302 }
......
1 +package com.infoloop.tianting.model.vo;
2 +
3 +import io.swagger.annotations.ApiModel;
4 +import io.swagger.annotations.ApiModelProperty;
5 +import lombok.Builder;
6 +import lombok.Data;
7 +
8 +import java.util.Date;
9 +
10 +@Data
11 +@Builder
12 +@ApiModel("停餐记录VO")
13 +public class DinerMealSuspensionRecordVO {
14 + @ApiModelProperty("ID")
15 + private Long id;
16 +
17 + @ApiModelProperty("企业ID")
18 + private Long enterpriseId;
19 +
20 + @ApiModelProperty("客户ID")
21 + private Long clientId;
22 +
23 + @ApiModelProperty("班级ID")
24 + private Long classId;
25 +
26 + @ApiModelProperty("年级名称")
27 + private String gradeName;
28 +
29 + @ApiModelProperty("班级名称")
30 + private String className;
31 +
32 + @ApiModelProperty("用餐人ID")
33 + private Long dinerId;
34 +
35 + @ApiModelProperty("用餐人姓名")
36 + private String dinerName;
37 +
38 + @ApiModelProperty("学号")
39 + private String studentNo;
40 +
41 + @ApiModelProperty("开始时间")
42 + private Date startAt;
43 +
44 + @ApiModelProperty("结束时间")
45 + private Date endAt;
46 +
47 + @ApiModelProperty("备注")
48 + private String comment;
49 +}
...\ No newline at end of file ...\ No newline at end of file
...@@ -4,6 +4,7 @@ import com.infoloop.tianting.mealorderservice.SingleMealOrderRpcResponse; ...@@ -4,6 +4,7 @@ import com.infoloop.tianting.mealorderservice.SingleMealOrderRpcResponse;
4 import com.infoloop.tianting.model.common.CreatedResult; 4 import com.infoloop.tianting.model.common.CreatedResult;
5 import com.infoloop.tianting.model.dto.MealOrderDTO; 5 import com.infoloop.tianting.model.dto.MealOrderDTO;
6 import com.infoloop.tianting.model.vo.DeliveryRuleVO; 6 import com.infoloop.tianting.model.vo.DeliveryRuleVO;
7 +import com.infoloop.tianting.model.vo.DinerMealSuspensionRecordVO;
7 import com.infoloop.tianting.model.vo.MealOrderVO; 8 import com.infoloop.tianting.model.vo.MealOrderVO;
8 9
9 import java.util.List; 10 import java.util.List;
...@@ -17,4 +18,16 @@ public interface MealOrderService { ...@@ -17,4 +18,16 @@ public interface MealOrderService {
17 MealOrderVO getMealOrderById(SingleMealOrderRpcResponse mealOrder); 18 MealOrderVO getMealOrderById(SingleMealOrderRpcResponse mealOrder);
18 19
19 DeliveryRuleVO getDeliveryRule(); 20 DeliveryRuleVO getDeliveryRule();
21 +
22 + /**
23 + * 查询停餐信息
24 + * 先查询学校的停餐信息,再查询学生的停餐信息,学校的停餐信息优先级高于学生停餐信息
25 + *
26 + * @param enterpriseId 企业ID
27 + * @param clientId 客户ID
28 + * @param classId 班级ID
29 + * @param dinerId 用餐人ID
30 + * @return 停餐信息列表
31 + */
32 + List<DinerMealSuspensionRecordVO> queryDinerMealSuspensionRecordsByCondition();
20 } 33 }
......
...@@ -47,6 +47,8 @@ import com.infoloop.tianting.mealorderservice.UpdateDinerRpcRequest; ...@@ -47,6 +47,8 @@ import com.infoloop.tianting.mealorderservice.UpdateDinerRpcRequest;
47 import com.infoloop.tianting.mealorderservice.UpdateDinerRpcResponse; 47 import com.infoloop.tianting.mealorderservice.UpdateDinerRpcResponse;
48 import com.infoloop.tianting.mealorderservice.UpdateMpAccountRpcRequest; 48 import com.infoloop.tianting.mealorderservice.UpdateMpAccountRpcRequest;
49 import com.infoloop.tianting.mealorderservice.UpdateMpAccountRpcResponse; 49 import com.infoloop.tianting.mealorderservice.UpdateMpAccountRpcResponse;
50 +import com.infoloop.tianting.mealorderservice.QueryDinerMealSuspensionRecordsByConditionRpcRequest;
51 +import com.infoloop.tianting.mealorderservice.SingleDinerMealSuspensionRecordRpcResponse;
50 import lombok.RequiredArgsConstructor; 52 import lombok.RequiredArgsConstructor;
51 import org.apache.commons.collections4.CollectionUtils; 53 import org.apache.commons.collections4.CollectionUtils;
52 import org.apache.commons.lang3.StringUtils; 54 import org.apache.commons.lang3.StringUtils;
...@@ -274,4 +276,30 @@ public class MealOrderServiceRpcClient { ...@@ -274,4 +276,30 @@ public class MealOrderServiceRpcClient {
274 .setShouldFilterReserveDateEnd(reserveDateEnd != null).setReserveDateEnd(reserveDateEnd == null ? 0 : reserveDateEnd) 276 .setShouldFilterReserveDateEnd(reserveDateEnd != null).setReserveDateEnd(reserveDateEnd == null ? 0 : reserveDateEnd)
275 .build()).getResponsesList(); 277 .build()).getResponsesList();
276 } 278 }
279 +
280 + public List<SingleDinerMealSuspensionRecordRpcResponse> queryDinerMealSuspensionRecordsByCondition(
281 + int enterpriseId,
282 + @Nullable List<Integer> clientIds,
283 + @Nullable List<Integer> classIds,
284 + @Nullable List<Integer> dinerIds) {
285 + var request = QueryDinerMealSuspensionRecordsByConditionRpcRequest.newBuilder()
286 + .setEnterpriseId(enterpriseId);
287 +
288 + if (clientIds != null) {
289 + request.setShouldFilterClientIds(true)
290 + .addAllClientIds(clientIds);
291 + }
292 + if (classIds != null) {
293 + request.setShouldFilterClassIds(true)
294 + .addAllClassIds(classIds);
295 + }
296 +
297 + if (dinerIds != null) {
298 + request.setShouldFilterDinerIds(true)
299 + .addAllDinerIds(dinerIds);
300 + }
301 +
302 + return mealOrderServiceRpcBlockingStub.queryDinerMealSuspensionRecordsByCondition(request.build())
303 + .getResponsesList();
304 + }
277 } 305 }
......
...@@ -4,13 +4,11 @@ import com.infoloop.tianting.context.LoginContextHolder; ...@@ -4,13 +4,11 @@ import com.infoloop.tianting.context.LoginContextHolder;
4 import com.infoloop.tianting.enums.QueryMealOrderStatusEnum; 4 import com.infoloop.tianting.enums.QueryMealOrderStatusEnum;
5 import com.infoloop.tianting.exception.ClientEndExceptions; 5 import com.infoloop.tianting.exception.ClientEndExceptions;
6 import com.infoloop.tianting.exception.ErrorCodeEnum; 6 import com.infoloop.tianting.exception.ErrorCodeEnum;
7 -import com.infoloop.tianting.mealorderservice.MealOrderCreation; 7 +import com.infoloop.tianting.mealorderservice.*;
8 -import com.infoloop.tianting.mealorderservice.MealOrderOrderMethodEnum;
9 -import com.infoloop.tianting.mealorderservice.MenuSchedule;
10 -import com.infoloop.tianting.mealorderservice.SingleMealOrderRpcResponse;
11 import com.infoloop.tianting.model.common.CreatedResult; 8 import com.infoloop.tianting.model.common.CreatedResult;
12 import com.infoloop.tianting.model.dto.MealOrderDTO; 9 import com.infoloop.tianting.model.dto.MealOrderDTO;
13 import com.infoloop.tianting.model.vo.DeliveryRuleVO; 10 import com.infoloop.tianting.model.vo.DeliveryRuleVO;
11 +import com.infoloop.tianting.model.vo.DinerMealSuspensionRecordVO;
14 import com.infoloop.tianting.model.vo.MealOrderVO; 12 import com.infoloop.tianting.model.vo.MealOrderVO;
15 import com.infoloop.tianting.service.MealOrderService; 13 import com.infoloop.tianting.service.MealOrderService;
16 import com.infoloop.tianting.service.client.ClientInventoryServiceRpcClient; 14 import com.infoloop.tianting.service.client.ClientInventoryServiceRpcClient;
...@@ -23,12 +21,17 @@ import org.springframework.beans.factory.annotation.Autowired; ...@@ -23,12 +21,17 @@ import org.springframework.beans.factory.annotation.Autowired;
23 import org.springframework.stereotype.Service; 21 import org.springframework.stereotype.Service;
24 22
25 import java.time.DayOfWeek; 23 import java.time.DayOfWeek;
24 +import java.time.Instant;
26 import java.time.LocalDate; 25 import java.time.LocalDate;
27 import java.time.LocalDateTime; 26 import java.time.LocalDateTime;
28 import java.time.LocalTime; 27 import java.time.LocalTime;
29 import java.util.ArrayList; 28 import java.util.ArrayList;
30 import java.util.Collections; 29 import java.util.Collections;
30 +import java.util.Date;
31 import java.util.List; 31 import java.util.List;
32 +import java.util.Map;
33 +import java.util.Objects;
34 +import java.util.stream.Collectors;
32 35
33 @Slf4j 36 @Slf4j
34 @Service 37 @Service
...@@ -77,30 +80,86 @@ public class MealOrderServiceImpl implements MealOrderService { ...@@ -77,30 +80,86 @@ public class MealOrderServiceImpl implements MealOrderService {
77 if (!nowWithinRange) { 80 if (!nowWithinRange) {
78 throw ClientEndExceptions.IncorrectRequestValue.build(ErrorCodeEnum.MEAL_ORDER_TIME_NOT_IN_RANGE); 81 throw ClientEndExceptions.IncorrectRequestValue.build(ErrorCodeEnum.MEAL_ORDER_TIME_NOT_IN_RANGE);
79 } 82 }
83 +
84 + // 1. 获取订餐人信息
80 final var dinerById = mealOrderServiceRpcClient.getDinerById(loginInfo.getEnterpriseId(), createMealOrderDTO.getDinerId()); 85 final var dinerById = mealOrderServiceRpcClient.getDinerById(loginInfo.getEnterpriseId(), createMealOrderDTO.getDinerId());
81 if (dinerById == null) { 86 if (dinerById == null) {
82 throw ClientEndExceptions.IncorrectRequestValue.build(ErrorCodeEnum.DINER_NOT_FOUND); 87 throw ClientEndExceptions.IncorrectRequestValue.build(ErrorCodeEnum.DINER_NOT_FOUND);
83 } 88 }
89 +
90 + // 2. 校验订餐人关联关系
84 final var mpAccountDinerRefs = mealOrderServiceRpcClient.queryMpAccountDinerRefsByCondition(loginInfo.getEnterpriseId(), Collections.singletonList(loginInfo.getId()), Collections.singletonList(createMealOrderDTO.getDinerId())); 91 final var mpAccountDinerRefs = mealOrderServiceRpcClient.queryMpAccountDinerRefsByCondition(loginInfo.getEnterpriseId(), Collections.singletonList(loginInfo.getId()), Collections.singletonList(createMealOrderDTO.getDinerId()));
85 if (mpAccountDinerRefs.size() != 1) { 92 if (mpAccountDinerRefs.size() != 1) {
86 throw ClientEndExceptions.IncorrectRequestValue.build(ErrorCodeEnum.DINER_NOT_FOUND); 93 throw ClientEndExceptions.IncorrectRequestValue.build(ErrorCodeEnum.DINER_NOT_FOUND);
87 } 94 }
95 +
96 + // 3. 校验客户状态
88 final var clientById = clientInventoryServiceRpcClient.getClientById(loginInfo.getEnterpriseId(), dinerById.getClientId()); 97 final var clientById = clientInventoryServiceRpcClient.getClientById(loginInfo.getEnterpriseId(), dinerById.getClientId());
89 if (clientById.getClient().getStatus() != 1) { 98 if (clientById.getClient().getStatus() != 1) {
90 throw ClientEndExceptions.IncorrectRequestValue.build(ErrorCodeEnum.CLIENT_NOT_ENABLED); 99 throw ClientEndExceptions.IncorrectRequestValue.build(ErrorCodeEnum.CLIENT_NOT_ENABLED);
91 } 100 }
101 +
102 + // 4. 校验班级信息
92 final var gradeClassById = mealOrderServiceRpcClient.getGradeClassById(loginInfo.getEnterpriseId(), dinerById.getClassId()); 103 final var gradeClassById = mealOrderServiceRpcClient.getGradeClassById(loginInfo.getEnterpriseId(), dinerById.getClassId());
93 if (gradeClassById == null) { 104 if (gradeClassById == null) {
94 throw ClientEndExceptions.IncorrectRequestValue.build(ErrorCodeEnum.GRADE_CLASS_NOT_FOUND); 105 throw ClientEndExceptions.IncorrectRequestValue.build(ErrorCodeEnum.GRADE_CLASS_NOT_FOUND);
95 } 106 }
107 +
108 + // 5. 校验停餐记录
109 + var currentTime = System.currentTimeMillis();
110 + // 5.1 先查询学校级别的停餐信息
111 + var schoolSuspensionRecords = mealOrderServiceRpcClient.queryDinerMealSuspensionRecordsByCondition(
112 + loginInfo.getEnterpriseId(),
113 + List.of(dinerById.getClientId()),
114 + null,
115 + null
116 + );
117 +
118 + if (schoolSuspensionRecords != null && !schoolSuspensionRecords.isEmpty()) {
119 + var latestSchoolSuspension = schoolSuspensionRecords.stream()
120 + .max((a, b) -> Long.compare(a.getCreatedAt(), b.getCreatedAt()))
121 + .orElse(null);
122 +
123 + if (latestSchoolSuspension != null &&
124 + currentTime >= latestSchoolSuspension.getStartAt() &&
125 + currentTime <= latestSchoolSuspension.getEndAt()) {
126 + throw ClientEndExceptions.IncorrectRequestValue.build(ErrorCodeEnum.DINER_MEAL_SUSPENDED);
127 + }
128 + }
129 +
130 + // 5.2 再查询学生级别的停餐信息
131 + var studentSuspensionRecords = mealOrderServiceRpcClient.queryDinerMealSuspensionRecordsByCondition(
132 + loginInfo.getEnterpriseId(),
133 + List.of(dinerById.getClientId()),
134 + List.of(dinerById.getClassId()),
135 + List.of(dinerById.getId())
136 + );
137 +
138 + if (studentSuspensionRecords != null && !studentSuspensionRecords.isEmpty()) {
139 + var latestStudentSuspension = studentSuspensionRecords.stream()
140 + .max((a, b) -> Long.compare(a.getCreatedAt(), b.getCreatedAt()))
141 + .orElse(null);
142 +
143 + if (latestStudentSuspension != null &&
144 + currentTime >= latestStudentSuspension.getStartAt() &&
145 + currentTime <= latestStudentSuspension.getEndAt()) {
146 + throw ClientEndExceptions.IncorrectRequestValue.build(ErrorCodeEnum.DINER_MEAL_SUSPENDED);
147 + }
148 + }
149 +
150 + // 6. 校验菜单信息
96 final var latestMealMenuRecords = mealOrderServiceRpcClient.queryLatestMealMenuRecordsByClientIds(loginInfo.getEnterpriseId(), Collections.singletonList(dinerById.getClientId())); 151 final var latestMealMenuRecords = mealOrderServiceRpcClient.queryLatestMealMenuRecordsByClientIds(loginInfo.getEnterpriseId(), Collections.singletonList(dinerById.getClientId()));
97 if (latestMealMenuRecords.isEmpty()) { 152 if (latestMealMenuRecords.isEmpty()) {
98 // throw ClientEndExceptions.IncorrectRequestValue.build(ErrorCodeEnum.MEAL_MENU_NOT_FOUND); 153 // throw ClientEndExceptions.IncorrectRequestValue.build(ErrorCodeEnum.MEAL_MENU_NOT_FOUND);
99 } 154 }
155 +
156 + // 7. 校验是否已预订
100 final var reserveDinerMealOrders = mealOrderServiceRpcClient.queryReserveMealOrdersByDinerIds(loginInfo.getEnterpriseId(), Collections.singletonList(createMealOrderDTO.getDinerId())); 157 final var reserveDinerMealOrders = mealOrderServiceRpcClient.queryReserveMealOrdersByDinerIds(loginInfo.getEnterpriseId(), Collections.singletonList(createMealOrderDTO.getDinerId()));
101 if (!reserveDinerMealOrders.isEmpty()) { 158 if (!reserveDinerMealOrders.isEmpty()) {
102 throw ClientEndExceptions.IncorrectRequestValue.build(ErrorCodeEnum.DINER_ALREADY_RESERVED); 159 throw ClientEndExceptions.IncorrectRequestValue.build(ErrorCodeEnum.DINER_ALREADY_RESERVED);
103 } 160 }
161 +
162 + // 8. 创建订单
104 final var mealOrder = mealOrderServiceRpcClient.createMealOrder(loginInfo, MealOrderCreation.newBuilder() 163 final var mealOrder = mealOrderServiceRpcClient.createMealOrder(loginInfo, MealOrderCreation.newBuilder()
105 .setClientId(dinerById.getClientId()) 164 .setClientId(dinerById.getClientId())
106 .setMenuId(latestMealMenuRecords.isEmpty() ? 0 : latestMealMenuRecords.get(0).getId()) 165 .setMenuId(latestMealMenuRecords.isEmpty() ? 0 : latestMealMenuRecords.get(0).getId())
...@@ -180,7 +239,7 @@ public class MealOrderServiceImpl implements MealOrderService { ...@@ -180,7 +239,7 @@ public class MealOrderServiceImpl implements MealOrderService {
180 final var maxDay = Collections.max(enabledDays); 239 final var maxDay = Collections.max(enabledDays);
181 final var today = now.toLocalDate(); 240 final var today = now.toLocalDate();
182 final var startDateTime = getThisWeekDate(today, minDay).atTime(startTime); 241 final var startDateTime = getThisWeekDate(today, minDay).atTime(startTime);
183 - final var endDateTime = getThisWeekDate(today,maxDay).atTime(endTime); 242 + final var endDateTime = getThisWeekDate(today, maxDay).atTime(endTime);
184 return !now.isBefore(startDateTime) && !now.isAfter(endDateTime); 243 return !now.isBefore(startDateTime) && !now.isAfter(endDateTime);
185 } 244 }
186 245
...@@ -188,4 +247,136 @@ public class MealOrderServiceImpl implements MealOrderService { ...@@ -188,4 +247,136 @@ public class MealOrderServiceImpl implements MealOrderService {
188 LocalDate monday = now.with(DayOfWeek.MONDAY); 247 LocalDate monday = now.with(DayOfWeek.MONDAY);
189 return monday.plusDays(day.getValue() - 1L); // MONDAY 是 1,SUNDAY 是 7 248 return monday.plusDays(day.getValue() - 1L); // MONDAY 是 1,SUNDAY 是 7
190 } 249 }
250 +
251 + @Override
252 + public List<DinerMealSuspensionRecordVO> queryDinerMealSuspensionRecordsByCondition() {
253 + final var loginInfo = LoginContextHolder.getLoginInfo();
254 +
255 + // 1. 获取当前登录用户关联的所有订餐人
256 + var mpAccountDinerRefs = mealOrderServiceRpcClient.queryMpAccountDinerRefsByCondition(
257 + loginInfo.getEnterpriseId(),
258 + Collections.singletonList(loginInfo.getId()),
259 + Collections.emptyList()
260 + );
261 +
262 + if (mpAccountDinerRefs.isEmpty()) {
263 + return Collections.emptyList();
264 + }
265 +
266 + // 2. 获取所有订餐人ID
267 + var dinerIds = mpAccountDinerRefs.stream()
268 + .map(SingleMpAccountDinerRefRpcResponse::getDinerId)
269 + .toList();
270 +
271 + // 3. 获取所有订餐人信息
272 + var diners = mealOrderServiceRpcClient.getDinersByIds(loginInfo.getEnterpriseId(), dinerIds);
273 + var dinerById = diners.stream().collect(Collectors.toMap(SingleDinerRpcResponse::getId, diner -> diner));
274 +
275 + // 4. 获取所有不重复的clientId
276 + var uniqueClientIds = diners.stream()
277 + .map(diner -> Long.valueOf(diner.getClientId()))
278 + .distinct()
279 + .toList();
280 +
281 + // 5. 批量获取所有学校的停餐信息
282 + final var now = Instant.now();
283 + var schoolSuspensionRecords = mealOrderServiceRpcClient.queryDinerMealSuspensionRecordsByCondition(
284 + loginInfo.getEnterpriseId(),
285 + null,
286 + null,
287 + null
288 + ).stream().filter(r -> r.getClassId() == 0).filter(r -> r.getEndAt() > now.toEpochMilli()).toList();
289 +
290 + // 6. 批量获取所有学生的停餐信息
291 + var studentSuspensionRecords = mealOrderServiceRpcClient.queryDinerMealSuspensionRecordsByCondition(
292 + loginInfo.getEnterpriseId(),
293 + null,
294 + null,
295 + dinerIds
296 + ).stream().filter(r -> r.getEndAt() > now.toEpochMilli()).toList();
297 +
298 + // 7. 构建学校停餐信息Map
299 + var schoolSuspensionMap = schoolSuspensionRecords.stream()
300 + .collect(Collectors.groupingBy(
301 + SingleDinerMealSuspensionRecordRpcResponse::getClientId,
302 + Collectors.collectingAndThen(
303 + Collectors.maxBy((a, b) -> Long.compare(a.getCreatedAt(), b.getCreatedAt())),
304 + opt -> opt.map(o -> convertToVO(o, dinerById)).orElse(null)
305 + )
306 + ));
307 +
308 + // 8. 构建学生停餐信息Map
309 + var studentSuspensionMap = studentSuspensionRecords.stream()
310 + .collect(Collectors.groupingBy(
311 + SingleDinerMealSuspensionRecordRpcResponse::getDinerId,
312 + Collectors.collectingAndThen(
313 + Collectors.maxBy((a, b) -> Long.compare(a.getCreatedAt(), b.getCreatedAt())),
314 + opt -> opt.map(o -> convertToVO(o, dinerById)).orElse(null)
315 + )
316 + ));
317 +
318 + // 9. 获取每个订餐人的停餐信息
319 + return diners.stream()
320 + .map(diner -> {
321 + // 获取学校级别的停餐信息
322 + var schoolSuspension = schoolSuspensionMap.get(Long.valueOf(diner.getClientId()).intValue());
323 + // 获取学生级别的停餐信息
324 + var studentSuspension = studentSuspensionMap.get(Long.valueOf(diner.getId()).intValue());
325 +
326 + // 如果两个都没有停餐信息,返回null
327 + if (schoolSuspension == null && studentSuspension == null) {
328 + return null;
329 + }
330 +
331 + // 如果只有学校级别的停餐信息
332 + if (schoolSuspension != null && studentSuspension == null) {
333 + return schoolSuspension;
334 + }
335 +
336 + // 如果只有学生级别的停餐信息
337 + if (schoolSuspension == null && studentSuspension != null) {
338 + return studentSuspension;
339 + }
340 +
341 + // 如果两个都有停餐信息,合并时间范围
342 + return DinerMealSuspensionRecordVO.builder()
343 + .id(schoolSuspension.getId())
344 + .enterpriseId(schoolSuspension.getEnterpriseId())
345 + .clientId(schoolSuspension.getClientId())
346 + .classId(studentSuspension.getClassId())
347 + .dinerId(studentSuspension.getDinerId())
348 + .dinerName(studentSuspension.getDinerName())
349 + .studentNo(studentSuspension.getStudentNo())
350 + .startAt(new Date(Math.min(schoolSuspension.getStartAt().getTime(), studentSuspension.getStartAt().getTime())))
351 + .endAt(new Date(Math.max(schoolSuspension.getEndAt().getTime(), studentSuspension.getEndAt().getTime())))
352 + .comment("")
353 + .build();
354 + })
355 + .filter(Objects::nonNull)
356 + .distinct()
357 + .toList();
358 + }
359 +
360 + /**
361 + * 将RPC响应转换为VO对象
362 + */
363 + private DinerMealSuspensionRecordVO convertToVO(SingleDinerMealSuspensionRecordRpcResponse response,
364 + Map<Integer, SingleDinerRpcResponse> dinerById) {
365 + if (response == null) {
366 + return null;
367 + }
368 +
369 + return DinerMealSuspensionRecordVO.builder()
370 + .id(Long.valueOf(response.getId()))
371 + .enterpriseId(Long.valueOf(response.getEnterpriseId()))
372 + .clientId(Long.valueOf(response.getClientId()))
373 + .classId(Long.valueOf(response.getClassId()))
374 + .dinerId(Long.valueOf(response.getDinerId()))
375 + .dinerName(dinerById.get(response.getDinerId()) != null ? dinerById.get(response.getDinerId()).getName() : null)
376 + .studentNo(dinerById.get(response.getDinerId()) != null ? dinerById.get(response.getDinerId()).getStudentNo() : null)
377 + .startAt(new Date(response.getStartAt()))
378 + .endAt(new Date(response.getEndAt()))
379 + .comment(response.getComment())
380 + .build();
381 + }
191 } 382 }
......
...@@ -31,6 +31,7 @@ service MealOrderServiceRpc { ...@@ -31,6 +31,7 @@ service MealOrderServiceRpc {
31 rpc UpdateDiner (UpdateDinerRpcRequest) returns (UpdateDinerRpcResponse) {} 31 rpc UpdateDiner (UpdateDinerRpcRequest) returns (UpdateDinerRpcResponse) {}
32 rpc BatchSaveOrUpdateDiners (BatchSaveOrUpdateDinersRpcRequest) returns (BatchSaveOrUpdateDinersRpcResponse) {} 32 rpc BatchSaveOrUpdateDiners (BatchSaveOrUpdateDinersRpcRequest) returns (BatchSaveOrUpdateDinersRpcResponse) {}
33 rpc DeleteDinersByIds (DeleteDinersByIdsRpcRequest) returns (DeleteDinersRpcResponse) {} 33 rpc DeleteDinersByIds (DeleteDinersByIdsRpcRequest) returns (DeleteDinersRpcResponse) {}
34 + rpc DeleteGraduationDinersByClassIds (DeleteGraduationDinersByClassIdsRpcRequest) returns (DeleteGraduationDinersByClassIdsRpcResponse) {}
34 35
35 rpc GetMpAccountDinerRefsByIds (GetMpAccountDinerRefsByIdsRpcRequest) returns (GetMpAccountDinerRefsByIdsRpcResponse) {} 36 rpc GetMpAccountDinerRefsByIds (GetMpAccountDinerRefsByIdsRpcRequest) returns (GetMpAccountDinerRefsByIdsRpcResponse) {}
36 rpc QueryMpAccountDinerRefsByCondition (QueryMpAccountDinerRefsByConditionRpcRequest) returns (QueryMpAccountDinerRefsByConditionRpcResponse) {} 37 rpc QueryMpAccountDinerRefsByCondition (QueryMpAccountDinerRefsByConditionRpcRequest) returns (QueryMpAccountDinerRefsByConditionRpcResponse) {}
...@@ -46,12 +47,22 @@ service MealOrderServiceRpc { ...@@ -46,12 +47,22 @@ service MealOrderServiceRpc {
46 rpc BatchSaveOrUpdateGradeClasses (BatchSaveOrUpdateGradeClassesRpcRequest) returns (BatchSaveOrUpdateGradeClassesRpcResponse) {} 47 rpc BatchSaveOrUpdateGradeClasses (BatchSaveOrUpdateGradeClassesRpcRequest) returns (BatchSaveOrUpdateGradeClassesRpcResponse) {}
47 rpc DeleteGradeClassesByIds (DeleteGradeClassesByIdsRpcRequest) returns (DeleteGradeClassesRpcResponse) {} 48 rpc DeleteGradeClassesByIds (DeleteGradeClassesByIdsRpcRequest) returns (DeleteGradeClassesRpcResponse) {}
48 rpc DeleteGradeClassesAndDinersByClientIds (DeleteGradeClassesAndDinersByClientIdsRpcRequest) returns (DeleteGradeClassesAndDinersByClientIdsRpcResponse) {} 49 rpc DeleteGradeClassesAndDinersByClientIds (DeleteGradeClassesAndDinersByClientIdsRpcRequest) returns (DeleteGradeClassesAndDinersByClientIdsRpcResponse) {}
50 + rpc DeleteGradeClassesAndDinersByClassIds (DeleteGradeClassesAndDinersByClassIdsRpcRequest) returns (DeleteGradeClassesAndDinersByClassIdsRpcResponse) {}
49 51
50 rpc GetMealMenuRecordById (GetMealMenuRecordByIdRpcRequest) returns (GetMealMenuRecordByIdRpcResponse) {} 52 rpc GetMealMenuRecordById (GetMealMenuRecordByIdRpcRequest) returns (GetMealMenuRecordByIdRpcResponse) {}
51 rpc GetMealMenuRecordsByIds (GetMealMenuRecordsByIdsRpcRequest) returns (GetMealMenuRecordsByIdsRpcResponse) {} 53 rpc GetMealMenuRecordsByIds (GetMealMenuRecordsByIdsRpcRequest) returns (GetMealMenuRecordsByIdsRpcResponse) {}
52 rpc QueryMealMenuRecordsByCondition (QueryMealMenuRecordsByConditionRpcRequest) returns (QueryMealMenuRecordsByConditionRpcResponse) {} 54 rpc QueryMealMenuRecordsByCondition (QueryMealMenuRecordsByConditionRpcRequest) returns (QueryMealMenuRecordsByConditionRpcResponse) {}
53 rpc CreateMealMenuRecord (CreateMealMenuRecordRpcRequest) returns (CreateMealMenuRecordRpcResponse) {} 55 rpc CreateMealMenuRecord (CreateMealMenuRecordRpcRequest) returns (CreateMealMenuRecordRpcResponse) {}
54 rpc QueryLatestMealMenuRecordsByClientIds (QueryLatestMealMenuRecordsByClientIdsRpcRequest) returns (QueryLatestMealMenuRecordsByClientIdsRpcResponse) {} 56 rpc QueryLatestMealMenuRecordsByClientIds (QueryLatestMealMenuRecordsByClientIdsRpcRequest) returns (QueryLatestMealMenuRecordsByClientIdsRpcResponse) {}
57 +
58 + // 停餐记录相关服务
59 + rpc getDinerMealSuspensionRecordById(GetDinerMealSuspensionRecordByIdRpcRequest) returns (GetDinerMealSuspensionRecordByIdRpcResponse);
60 + rpc getDinerMealSuspensionRecordsByIds(GetDinerMealSuspensionRecordsByIdsRpcRequest) returns (GetDinerMealSuspensionRecordsByIdsRpcResponse);
61 + rpc queryDinerMealSuspensionRecordsByCondition(QueryDinerMealSuspensionRecordsByConditionRpcRequest) returns (QueryDinerMealSuspensionRecordsByConditionRpcResponse);
62 + rpc createDinerMealSuspensionRecord(CreateDinerMealSuspensionRecordRpcRequest) returns (CreateDinerMealSuspensionRecordRpcResponse);
63 + rpc batchCreateDinerMealSuspensionRecords(BatchCreateDinerMealSuspensionRecordsRpcRequest) returns (BatchCreateDinerMealSuspensionRecordsRpcResponse);
64 + rpc updateDinerMealSuspensionRecord(UpdateDinerMealSuspensionRecordRpcRequest) returns (UpdateDinerMealSuspensionRecordRpcResponse);
65 + rpc deleteDinerMealSuspensionRecordsByIds(DeleteDinerMealSuspensionRecordsByIdsRpcRequest) returns (DeleteDinerMealSuspensionRecordsRpcResponse);
55 } 66 }
56 67
57 enum MealOrderOrderMethodEnum { 68 enum MealOrderOrderMethodEnum {
...@@ -357,6 +368,17 @@ message DeleteDinersRpcResponse { ...@@ -357,6 +368,17 @@ message DeleteDinersRpcResponse {
357 bool isDeleted = 1; 368 bool isDeleted = 1;
358 } 369 }
359 370
371 +message DeleteGraduationDinersByClassIdsRpcRequest {
372 + repeated int32 classIds = 1;
373 + int32 enterpriseId = 2;
374 + int32 updatedBy = 3;
375 + int32 updateSource = 4;
376 +}
377 +
378 +message DeleteGraduationDinersByClassIdsRpcResponse {
379 + bool isDeleted = 1;
380 +}
381 +
360 enum MpAccountGenderEnum { 382 enum MpAccountGenderEnum {
361 MP_ACCOUNT_GENDER_MAN = 0; 383 MP_ACCOUNT_GENDER_MAN = 0;
362 MP_ACCOUNT_GENDER_WOMAN = 1; 384 MP_ACCOUNT_GENDER_WOMAN = 1;
...@@ -613,8 +635,8 @@ message QueryGradeClassesByConditionRpcRequest { ...@@ -613,8 +635,8 @@ message QueryGradeClassesByConditionRpcRequest {
613 int32 enterpriseId = 1; 635 int32 enterpriseId = 1;
614 bool shouldFilterClientIds = 2; 636 bool shouldFilterClientIds = 2;
615 repeated int32 clientIds = 3; 637 repeated int32 clientIds = 3;
616 - bool shouldFilterGradeName = 4; 638 + bool shouldFilterGradeNames = 4;
617 - string gradeName = 5; 639 + repeated string gradeName = 5;
618 bool includeDeleted = 6; 640 bool includeDeleted = 6;
619 } 641 }
620 642
...@@ -721,6 +743,18 @@ message DeleteGradeClassesAndDinersByClientIdsRpcResponse { ...@@ -721,6 +743,18 @@ message DeleteGradeClassesAndDinersByClientIdsRpcResponse {
721 bool isDeleted = 1; 743 bool isDeleted = 1;
722 } 744 }
723 745
746 +message DeleteGradeClassesAndDinersByClassIdsRpcRequest {
747 + repeated int32 classIds = 1;
748 + int32 enterpriseId = 2;
749 + int32 updatedBy = 3;
750 + int32 updateSource = 4;
751 +}
752 +
753 +message DeleteGradeClassesAndDinersByClassIdsRpcResponse {
754 + bool isDeleted = 1;
755 +}
756 +
757 +
724 message SingleMealMenuRecordRpcResponse { 758 message SingleMealMenuRecordRpcResponse {
725 int32 id = 1; 759 int32 id = 1;
726 int32 enterpriseId = 2; 760 int32 enterpriseId = 2;
...@@ -734,6 +768,7 @@ message SingleMealMenuRecordRpcResponse { ...@@ -734,6 +768,7 @@ message SingleMealMenuRecordRpcResponse {
734 int64 updatedAt = 10; 768 int64 updatedAt = 10;
735 int32 updateSource = 11; 769 int32 updateSource = 11;
736 bool isDeleted = 12; 770 bool isDeleted = 12;
771 + string operatorName = 13;
737 } 772 }
738 773
739 message GetMealMenuRecordByIdRpcRequest { 774 message GetMealMenuRecordByIdRpcRequest {
...@@ -781,6 +816,7 @@ message CreateMealMenuRecordRpcRequest { ...@@ -781,6 +816,7 @@ message CreateMealMenuRecordRpcRequest {
781 int32 enterpriseId = 2; 816 int32 enterpriseId = 2;
782 int32 createdBy = 3; 817 int32 createdBy = 3;
783 int32 creationSource = 4; 818 int32 creationSource = 4;
819 + string operatorName = 5;
784 } 820 }
785 821
786 message CreateMealMenuRecordRpcResponse { 822 message CreateMealMenuRecordRpcResponse {
...@@ -796,3 +832,126 @@ message QueryLatestMealMenuRecordsByClientIdsRpcRequest { ...@@ -796,3 +832,126 @@ message QueryLatestMealMenuRecordsByClientIdsRpcRequest {
796 message QueryLatestMealMenuRecordsByClientIdsRpcResponse { 832 message QueryLatestMealMenuRecordsByClientIdsRpcResponse {
797 repeated SingleMealMenuRecordRpcResponse responses = 1; 833 repeated SingleMealMenuRecordRpcResponse responses = 1;
798 } 834 }
835 +
836 +// 停餐记录相关消息定义
837 +message SingleDinerMealSuspensionRecordRpcResponse {
838 + int32 id = 1;
839 + int32 enterpriseId = 2;
840 + int32 clientId = 3;
841 + int32 classId = 4;
842 + int32 dinerId = 5;
843 + int64 startAt = 6;
844 + int64 endAt = 7;
845 + string comment = 8;
846 + int64 createdAt = 9;
847 + int32 createdBy = 10;
848 + int32 creationSource = 11;
849 + int64 updatedAt = 12;
850 + int32 updatedBy = 13;
851 + int32 updateSource = 14;
852 +}
853 +
854 +message GetDinerMealSuspensionRecordByIdRpcRequest {
855 + int64 id = 1;
856 +}
857 +
858 +message GetDinerMealSuspensionRecordByIdRpcResponse {
859 + SingleDinerMealSuspensionRecordRpcResponse response = 1;
860 +}
861 +
862 +message GetDinerMealSuspensionRecordsByIdsRpcRequest {
863 + repeated int32 ids = 1;
864 +}
865 +
866 +message GetDinerMealSuspensionRecordsByIdsRpcResponse {
867 + repeated SingleDinerMealSuspensionRecordRpcResponse responses = 1;
868 +}
869 +
870 +message QueryDinerMealSuspensionRecordsByConditionRpcRequest {
871 + int32 enterpriseId = 1;
872 + bool shouldFilterClientIds = 2;
873 + repeated int32 clientIds = 3;
874 + bool shouldFilterClassIds = 4;
875 + repeated int32 classIds = 5;
876 + bool shouldFilterDinerIds = 6;
877 + repeated int32 dinerIds = 7;
878 + bool shouldFilterStartAt = 8;
879 + int64 startAt = 9;
880 + bool shouldFilterEndAt = 10;
881 + int64 endAt = 11;
882 +}
883 +
884 +message QueryDinerMealSuspensionRecordsByConditionRpcResponse {
885 + repeated SingleDinerMealSuspensionRecordRpcResponse responses = 1;
886 +}
887 +
888 +message CreateDinerMealSuspensionRecordRpcRequest {
889 + int32 enterpriseId = 1;
890 + int32 createdBy = 2;
891 + int32 creationSource = 3;
892 + DinerMealSuspensionRecordCreation creation = 4;
893 +}
894 +
895 +message DinerMealSuspensionRecordCreation {
896 + int32 clientId = 1;
897 + int32 classId = 2;
898 + int32 dinerId = 3;
899 + int64 startAt = 4;
900 + int64 endAt = 5;
901 + string comment = 6;
902 +}
903 +
904 +message CreateDinerMealSuspensionRecordRpcResponse {
905 + bool isCreated = 1;
906 + int32 id = 2;
907 +}
908 +
909 +message UpdateDinerMealSuspensionRecordRpcRequest {
910 + int32 enterpriseId = 1;
911 + int32 updatedBy = 2;
912 + int32 updateSource = 3;
913 + DinerMealSuspensionRecordModification modification = 4;
914 +}
915 +
916 +message DinerMealSuspensionRecordModification {
917 + int32 id = 1;
918 + bool shouldUpdateClientId = 2;
919 + int32 clientId = 3;
920 + bool shouldUpdateClassId = 4;
921 + int32 classId = 5;
922 + bool shouldUpdateDinerId = 6;
923 + int32 dinerId = 7;
924 + bool shouldUpdateStartAt = 8;
925 + int64 startAt = 9;
926 + bool shouldUpdateEndAt = 10;
927 + int64 endAt = 11;
928 + bool shouldUpdateComment = 12;
929 + string comment = 13;
930 +}
931 +
932 +message UpdateDinerMealSuspensionRecordRpcResponse {
933 + bool isUpdated = 1;
934 +}
935 +
936 +message DeleteDinerMealSuspensionRecordsByIdsRpcRequest {
937 + repeated int32 ids = 1;
938 + int32 enterpriseId = 2;
939 + int32 updatedBy = 3;
940 + int32 updateSource = 4;
941 +}
942 +
943 +message DeleteDinerMealSuspensionRecordsRpcResponse {
944 + bool isDeleted = 1;
945 +}
946 +
947 +message BatchCreateDinerMealSuspensionRecordsRpcRequest {
948 + int32 enterpriseId = 1;
949 + int32 createdBy = 2;
950 + int32 creationSource = 3;
951 + repeated DinerMealSuspensionRecordCreation creations = 4;
952 +}
953 +
954 +message BatchCreateDinerMealSuspensionRecordsRpcResponse {
955 + bool isCreated = 1;
956 + repeated int32 ids = 2;
957 +}
......