fix(order): optimize dish replacement logic and update payment transaction ID
Showing
11 changed files
with
995 additions
and
852 deletions
| ... | @@ -60,4 +60,5 @@ public class PayController { | ... | @@ -60,4 +60,5 @@ public class PayController { |
| 60 | public String cancel(@Valid @RequestBody PayDTO.PayRefundRequestDto payRefundRequestDto) { | 60 | public String cancel(@Valid @RequestBody PayDTO.PayRefundRequestDto payRefundRequestDto) { |
| 61 | return payServiceClient.orderPayRefund(payRefundRequestDto); | 61 | return payServiceClient.orderPayRefund(payRefundRequestDto); |
| 62 | } | 62 | } |
| 63 | + | ||
| 63 | } | 64 | } |
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
| 1 | +package com.infoloop.tianting.model.bo; | ||
| 2 | + | ||
| 3 | +import com.infoloop.tianting.clientcustomerorderservice.ServeStatusEnum; | ||
| 4 | +import lombok.Data; | ||
| 5 | + | ||
| 6 | +@Data | ||
| 7 | +public class OrderDetailBO { | ||
| 8 | + | ||
| 9 | + private int id; | ||
| 10 | + | ||
| 11 | + public int skuId; | ||
| 12 | + | ||
| 13 | + private String skuName; | ||
| 14 | + | ||
| 15 | + private Integer price; | ||
| 16 | + | ||
| 17 | + private int count; | ||
| 18 | + | ||
| 19 | + private String adjustSkuRemark; | ||
| 20 | + | ||
| 21 | + private ServeStatusEnum serveStatus; | ||
| 22 | +} |
| ... | @@ -520,6 +520,7 @@ public class OrderDbDTO { | ... | @@ -520,6 +520,7 @@ public class OrderDbDTO { |
| 520 | private Integer count; | 520 | private Integer count; |
| 521 | private String adjustSkuRemark; | 521 | private String adjustSkuRemark; |
| 522 | private String serveStatus; | 522 | private String serveStatus; |
| 523 | + private Integer price; | ||
| 523 | } | 524 | } |
| 524 | 525 | ||
| 525 | 526 | ||
| ... | @@ -730,6 +731,10 @@ public class OrderDbDTO { | ... | @@ -730,6 +731,10 @@ public class OrderDbDTO { |
| 730 | @Builder.Default | 731 | @Builder.Default |
| 731 | private Boolean shouldUpdateServeStatus = false; | 732 | private Boolean shouldUpdateServeStatus = false; |
| 732 | 733 | ||
| 734 | + @ApiModelProperty(value = "价格") | ||
| 735 | + @Builder.Default | ||
| 736 | + private Integer price = null; | ||
| 737 | + | ||
| 733 | @ApiModelProperty(value = "出餐状态: 默认未出餐=1; 不出餐=2; 已出餐=3") | 738 | @ApiModelProperty(value = "出餐状态: 默认未出餐=1; 不出餐=2; 已出餐=3") |
| 734 | @Builder.Default | 739 | @Builder.Default |
| 735 | private ServeStatusEnum serveStatus = ServeStatusEnum.SERVE_NOT_START; | 740 | private ServeStatusEnum serveStatus = ServeStatusEnum.SERVE_NOT_START; | ... | ... |
| ... | @@ -9,6 +9,8 @@ import lombok.Builder; | ... | @@ -9,6 +9,8 @@ import lombok.Builder; |
| 9 | import lombok.Data; | 9 | import lombok.Data; |
| 10 | import lombok.NoArgsConstructor; | 10 | import lombok.NoArgsConstructor; |
| 11 | 11 | ||
| 12 | +import java.util.List; | ||
| 13 | + | ||
| 12 | @Data | 14 | @Data |
| 13 | @ApiModel(description = "支付DTO") | 15 | @ApiModel(description = "支付DTO") |
| 14 | public class PayDTO { | 16 | public class PayDTO { |
| ... | @@ -31,6 +33,7 @@ public class PayDTO { | ... | @@ -31,6 +33,7 @@ public class PayDTO { |
| 31 | @AllArgsConstructor | 33 | @AllArgsConstructor |
| 32 | public static class PayRefundRequestDto { | 34 | public static class PayRefundRequestDto { |
| 33 | private Integer orderId; | 35 | private Integer orderId; |
| 36 | + private List<Integer> orderDetailIds; | ||
| 34 | private String hospitalCode; | 37 | private String hospitalCode; |
| 35 | } | 38 | } |
| 36 | 39 | ... | ... |
| ... | @@ -18,6 +18,9 @@ public class PaymentCallbackResult { | ... | @@ -18,6 +18,9 @@ public class PaymentCallbackResult { |
| 18 | @JacksonXmlProperty(localName = "TransSN") | 18 | @JacksonXmlProperty(localName = "TransSN") |
| 19 | private String transSN; | 19 | private String transSN; |
| 20 | 20 | ||
| 21 | + @JacksonXmlProperty(localName = "TradeReferenceNo") | ||
| 22 | + private String tradeReferenceNo; | ||
| 23 | + | ||
| 21 | @JacksonXmlProperty(localName = "TransType") | 24 | @JacksonXmlProperty(localName = "TransType") |
| 22 | private String transType; | 25 | private String transType; |
| 23 | 26 | ... | ... |
| ... | @@ -103,6 +103,8 @@ public class SettlementDTO { | ... | @@ -103,6 +103,8 @@ public class SettlementDTO { |
| 103 | private String remark; | 103 | private String remark; |
| 104 | private String avoidRemark; | 104 | private String avoidRemark; |
| 105 | private String onlinePay; | 105 | private String onlinePay; |
| 106 | + private String operationType; | ||
| 107 | + private String transactionId; | ||
| 106 | } | 108 | } |
| 107 | 109 | ||
| 108 | @Data | 110 | @Data | ... | ... |
| ... | @@ -22,6 +22,8 @@ import com.infoloop.tianting.clientcustomerorderservice.GetClientCustomerOrderBy | ... | @@ -22,6 +22,8 @@ import com.infoloop.tianting.clientcustomerorderservice.GetClientCustomerOrderBy |
| 22 | import com.infoloop.tianting.clientcustomerorderservice.GetClientCustomerOrderDetailsByIdsRpcRequest; | 22 | import com.infoloop.tianting.clientcustomerorderservice.GetClientCustomerOrderDetailsByIdsRpcRequest; |
| 23 | import com.infoloop.tianting.clientcustomerorderservice.GetClientCustomerOrderDetailsByOrderIdsRpcRequest; | 23 | import com.infoloop.tianting.clientcustomerorderservice.GetClientCustomerOrderDetailsByOrderIdsRpcRequest; |
| 24 | import com.infoloop.tianting.clientcustomerorderservice.GetClientCustomerOrdersByCustomerIdRpcRequest; | 24 | import com.infoloop.tianting.clientcustomerorderservice.GetClientCustomerOrdersByCustomerIdRpcRequest; |
| 25 | +import com.infoloop.tianting.clientcustomerorderservice.GetOrderOperationRecordsByOrderIdsRequest; | ||
| 26 | +import com.infoloop.tianting.clientcustomerorderservice.GetOrderOperationRecordsByOrderIdsResponse; | ||
| 25 | import com.infoloop.tianting.clientcustomerorderservice.MealDetail; | 27 | import com.infoloop.tianting.clientcustomerorderservice.MealDetail; |
| 26 | import com.infoloop.tianting.clientcustomerorderservice.OnlinePayEnum; | 28 | import com.infoloop.tianting.clientcustomerorderservice.OnlinePayEnum; |
| 27 | import com.infoloop.tianting.clientcustomerorderservice.OrderOperationRecordCreation; | 29 | import com.infoloop.tianting.clientcustomerorderservice.OrderOperationRecordCreation; |
| ... | @@ -240,8 +242,10 @@ public class OrderServiceRpcClient { | ... | @@ -240,8 +242,10 @@ public class OrderServiceRpcClient { |
| 240 | final var operator = operatorServiceRpcClient.getCOperatorById(operatorLoginInfo.getId()); | 242 | final var operator = operatorServiceRpcClient.getCOperatorById(operatorLoginInfo.getId()); |
| 241 | final var idsOfNeedUpdateMenuDetails = new ArrayList<Integer>(); | 243 | final var idsOfNeedUpdateMenuDetails = new ArrayList<Integer>(); |
| 242 | final var idsOfAddCount = new ArrayList<Integer>(); | 244 | final var idsOfAddCount = new ArrayList<Integer>(); |
| 245 | + final var idsOfNoReject = new ArrayList<Integer>(); | ||
| 243 | List<OrderDetailDto> originalOrderDetails = new ArrayList<>(); | 246 | List<OrderDetailDto> originalOrderDetails = new ArrayList<>(); |
| 244 | List<OrderDetailDto> newOrderDetails; | 247 | List<OrderDetailDto> newOrderDetails; |
| 248 | + final var orderDetailsMap = orderDetailBatchUpdateDto.getDetails().stream().collect(Collectors.toMap(OrderDbDTO.OrderDetailUpdateDto::getId, Function.identity())); | ||
| 245 | final var modifications = orderDetailBatchUpdateDto.getDetails().stream().map(d -> { | 249 | final var modifications = orderDetailBatchUpdateDto.getDetails().stream().map(d -> { |
| 246 | var mealDetail = MealDetail.newBuilder().build(); | 250 | var mealDetail = MealDetail.newBuilder().build(); |
| 247 | Integer menuDetailId = 0; | 251 | Integer menuDetailId = 0; |
| ... | @@ -280,9 +284,11 @@ public class OrderServiceRpcClient { | ... | @@ -280,9 +284,11 @@ public class OrderServiceRpcClient { |
| 280 | .build(); | 284 | .build(); |
| 281 | } | 285 | } |
| 282 | } | 286 | } |
| 283 | - | ||
| 284 | ServeStatusEnum serveStatus = ServeStatusEnum.UNKNOWN_SERVE_STATUS; | 287 | ServeStatusEnum serveStatus = ServeStatusEnum.UNKNOWN_SERVE_STATUS; |
| 285 | if (d.getShouldUpdateServeStatus()) { | 288 | if (d.getShouldUpdateServeStatus()) { |
| 289 | + if (d.getServeStatus() == ServeStatusEnum.SERVE_REJECT) { | ||
| 290 | + idsOfNoReject.add(d.getId()); | ||
| 291 | + } | ||
| 286 | serveStatus = d.getServeStatus(); | 292 | serveStatus = d.getServeStatus(); |
| 287 | } | 293 | } |
| 288 | Integer count = 0; | 294 | Integer count = 0; |
| ... | @@ -319,7 +325,8 @@ public class OrderServiceRpcClient { | ... | @@ -319,7 +325,8 @@ public class OrderServiceRpcClient { |
| 319 | .build(); | 325 | .build(); |
| 320 | final var totalIds = new ArrayList<>(idsOfNeedUpdateMenuDetails); | 326 | final var totalIds = new ArrayList<>(idsOfNeedUpdateMenuDetails); |
| 321 | totalIds.addAll(idsOfAddCount); | 327 | totalIds.addAll(idsOfAddCount); |
| 322 | - if (!idsOfNeedUpdateMenuDetails.isEmpty() || !idsOfAddCount.isEmpty()) { | 328 | + totalIds.addAll(idsOfNoReject); |
| 329 | + if (!totalIds.isEmpty()) { | ||
| 323 | final var orgionalResponseList = getClientCustomerOrderDetailsByIds(totalIds); | 330 | final var orgionalResponseList = getClientCustomerOrderDetailsByIds(totalIds); |
| 324 | originalOrderDetails = orgionalResponseList.stream().map(d -> OrderDetailDto.builder() | 331 | originalOrderDetails = orgionalResponseList.stream().map(d -> OrderDetailDto.builder() |
| 325 | .id(d.getId()) | 332 | .id(d.getId()) |
| ... | @@ -357,7 +364,7 @@ public class OrderServiceRpcClient { | ... | @@ -357,7 +364,7 @@ public class OrderServiceRpcClient { |
| 357 | } | 364 | } |
| 358 | final var res = orderServiceRpcBlockingStub.batchUpdateClientCustomerOrderDetails(request); | 365 | final var res = orderServiceRpcBlockingStub.batchUpdateClientCustomerOrderDetails(request); |
| 359 | if (res.getIsUpdated()) { | 366 | if (res.getIsUpdated()) { |
| 360 | - if (!idsOfNeedUpdateMenuDetails.isEmpty() || !idsOfAddCount.isEmpty()) { | 367 | + if (!totalIds.isEmpty()) { |
| 361 | final var newResponseList = getClientCustomerOrderDetailsByIds(totalIds); | 368 | final var newResponseList = getClientCustomerOrderDetailsByIds(totalIds); |
| 362 | newOrderDetails = newResponseList.stream().map(d -> | 369 | newOrderDetails = newResponseList.stream().map(d -> |
| 363 | OrderDetailDto.builder() | 370 | OrderDetailDto.builder() |
| ... | @@ -392,15 +399,21 @@ public class OrderServiceRpcClient { | ... | @@ -392,15 +399,21 @@ public class OrderServiceRpcClient { |
| 392 | .updateSource(d.getUpdateSource().getNumber()) | 399 | .updateSource(d.getUpdateSource().getNumber()) |
| 393 | .updatedAt(DateUtil.formatDate(d.getUpdatedAt())) | 400 | .updatedAt(DateUtil.formatDate(d.getUpdatedAt())) |
| 394 | .updatedBy(d.getUpdatedBy()) | 401 | .updatedBy(d.getUpdatedBy()) |
| 395 | - .build()).collect(Collectors.toList()); | 402 | + .build()).toList(); |
| 396 | // 替换菜品的操作记录 | 403 | // 替换菜品的操作记录 |
| 397 | List<SingleOperationDto> operations = new ArrayList<>(); | 404 | List<SingleOperationDto> operations = new ArrayList<>(); |
| 398 | for (OrderDetailDto originalDetail : originalOrderDetails) { | 405 | for (OrderDetailDto originalDetail : originalOrderDetails) { |
| 406 | + if (!totalIds.contains(originalDetail.getId())) { | ||
| 407 | + continue; | ||
| 408 | + } | ||
| 409 | + final var orderDetailUpdateDto = orderDetailsMap.get(originalDetail.getId()); | ||
| 399 | OrderOperationType orderOperationType = OrderOperationType.UNKNOWN_OPERATION_TYPE; | 410 | OrderOperationType orderOperationType = OrderOperationType.UNKNOWN_OPERATION_TYPE; |
| 400 | if (idsOfNeedUpdateMenuDetails.contains(originalDetail.getId())) { | 411 | if (idsOfNeedUpdateMenuDetails.contains(originalDetail.getId())) { |
| 401 | orderOperationType = OrderOperationType.REPLACE_DISHES; | 412 | orderOperationType = OrderOperationType.REPLACE_DISHES; |
| 402 | } else if (idsOfAddCount.contains(originalDetail.getId())) { | 413 | } else if (idsOfAddCount.contains(originalDetail.getId())) { |
| 403 | orderOperationType = OrderOperationType.ADD_DISHES; | 414 | orderOperationType = OrderOperationType.ADD_DISHES; |
| 415 | + } else if (idsOfNoReject.contains(originalDetail.getId())) { | ||
| 416 | + orderOperationType = OrderOperationType.NOT_SERVE; | ||
| 404 | } | 417 | } |
| 405 | String originalDetailStr; | 418 | String originalDetailStr; |
| 406 | String newDetailStr = ""; | 419 | String newDetailStr = ""; |
| ... | @@ -413,6 +426,7 @@ public class OrderServiceRpcClient { | ... | @@ -413,6 +426,7 @@ public class OrderServiceRpcClient { |
| 413 | .count(newDetail.get().getCount()) | 426 | .count(newDetail.get().getCount()) |
| 414 | .adjustSkuRemark(newDetail.get().getAdjustSkuRemark()) | 427 | .adjustSkuRemark(newDetail.get().getAdjustSkuRemark()) |
| 415 | .serveStatus(newDetail.get().getServeStatus().name()) | 428 | .serveStatus(newDetail.get().getServeStatus().name()) |
| 429 | + .price(orderDetailUpdateDto.getPrice() == null ? newDetail.get().getPrice() : orderDetailUpdateDto.getPrice()) | ||
| 416 | .build(); | 430 | .build(); |
| 417 | newDetailStr = JsonUtil.writeAsJson(List.of(newOrderDetailOperation)); | 431 | newDetailStr = JsonUtil.writeAsJson(List.of(newOrderDetailOperation)); |
| 418 | } | 432 | } |
| ... | @@ -423,6 +437,7 @@ public class OrderServiceRpcClient { | ... | @@ -423,6 +437,7 @@ public class OrderServiceRpcClient { |
| 423 | .count(originalDetail.getCount()) | 437 | .count(originalDetail.getCount()) |
| 424 | .adjustSkuRemark(originalDetail.getAdjustSkuRemark()) | 438 | .adjustSkuRemark(originalDetail.getAdjustSkuRemark()) |
| 425 | .serveStatus(originalDetail.getServeStatus().name()) | 439 | .serveStatus(originalDetail.getServeStatus().name()) |
| 440 | + .price(originalDetail.getPrice()) | ||
| 426 | .build(); | 441 | .build(); |
| 427 | originalDetailStr = JsonUtil.writeAsJson(List.of(originalOrderDetailOperation)); | 442 | originalDetailStr = JsonUtil.writeAsJson(List.of(originalOrderDetailOperation)); |
| 428 | final var operation = SingleOperationDto.builder() | 443 | final var operation = SingleOperationDto.builder() |
| ... | @@ -471,7 +486,6 @@ public class OrderServiceRpcClient { | ... | @@ -471,7 +486,6 @@ public class OrderServiceRpcClient { |
| 471 | .setCreationSource(batchOperationDto.getCreationSource()) | 486 | .setCreationSource(batchOperationDto.getCreationSource()) |
| 472 | .build(); | 487 | .build(); |
| 473 | return orderServiceRpcBlockingStub.batchCreateOrderOperationRecords(request); | 488 | return orderServiceRpcBlockingStub.batchCreateOrderOperationRecords(request); |
| 474 | - | ||
| 475 | } | 489 | } |
| 476 | 490 | ||
| 477 | public QueryClientCustomerOrdersByPaginationRpcResponse queryClientCustomerOrdersByPagination(QueryOrderByPaginationDto queryOrderDto) { | 491 | public QueryClientCustomerOrdersByPaginationRpcResponse queryClientCustomerOrdersByPagination(QueryOrderByPaginationDto queryOrderDto) { |
| ... | @@ -489,6 +503,14 @@ public class OrderServiceRpcClient { | ... | @@ -489,6 +503,14 @@ public class OrderServiceRpcClient { |
| 489 | return orderServiceRpcBlockingStub.queryClientCustomerOrdersByPagination(request); | 503 | return orderServiceRpcBlockingStub.queryClientCustomerOrdersByPagination(request); |
| 490 | } | 504 | } |
| 491 | 505 | ||
| 506 | + public GetOrderOperationRecordsByOrderIdsResponse getOrderOperationRecordsByOrderIds(int enterpriseId, List<Integer> orderIds) { | ||
| 507 | + final var request = GetOrderOperationRecordsByOrderIdsRequest.newBuilder() | ||
| 508 | + .setEnterpriseId(enterpriseId) | ||
| 509 | + .addAllOrderIds(orderIds) | ||
| 510 | + .build(); | ||
| 511 | + return orderServiceRpcBlockingStub.getOrderOperationRecordsByOrderIds(request); | ||
| 512 | + } | ||
| 513 | + | ||
| 492 | public QueryClientCustomerOrdersByConditionRpcResponse queryClientCustomerOrdersByCondition(OrderDbDTO.QueryOrderDto queryOrderDto) { | 514 | public QueryClientCustomerOrdersByConditionRpcResponse queryClientCustomerOrdersByCondition(OrderDbDTO.QueryOrderDto queryOrderDto) { |
| 493 | final var request = QueryClientCustomerOrdersByConditionRpcRequest.newBuilder() | 515 | final var request = QueryClientCustomerOrdersByConditionRpcRequest.newBuilder() |
| 494 | .setShouldFilterStatus(true) | 516 | .setShouldFilterStatus(true) | ... | ... |
| ... | @@ -38,6 +38,7 @@ import lombok.RequiredArgsConstructor; | ... | @@ -38,6 +38,7 @@ import lombok.RequiredArgsConstructor; |
| 38 | import lombok.extern.slf4j.Slf4j; | 38 | import lombok.extern.slf4j.Slf4j; |
| 39 | import org.apache.commons.codec.binary.Base64; | 39 | import org.apache.commons.codec.binary.Base64; |
| 40 | import org.apache.commons.codec.digest.DigestUtils; | 40 | import org.apache.commons.codec.digest.DigestUtils; |
| 41 | +import org.apache.commons.collections4.CollectionUtils; | ||
| 41 | import org.springframework.beans.factory.annotation.Autowired; | 42 | import org.springframework.beans.factory.annotation.Autowired; |
| 42 | import org.springframework.http.HttpEntity; | 43 | import org.springframework.http.HttpEntity; |
| 43 | import org.springframework.http.HttpHeaders; | 44 | import org.springframework.http.HttpHeaders; |
| ... | @@ -66,333 +67,338 @@ import java.util.stream.Collectors; | ... | @@ -66,333 +67,338 @@ import java.util.stream.Collectors; |
| 66 | @RequiredArgsConstructor(onConstructor = @__(@Autowired)) | 67 | @RequiredArgsConstructor(onConstructor = @__(@Autowired)) |
| 67 | public class PayServiceClient { | 68 | public class PayServiceClient { |
| 68 | 69 | ||
| 69 | - private final RestTemplate restTemplate; | 70 | + private final RestTemplate restTemplate; |
| 70 | 71 | ||
| 71 | - private final BusinessConfig businessConfig; | 72 | + private final BusinessConfig businessConfig; |
| 72 | 73 | ||
| 73 | - private final OrderServiceRpcClient orderServiceRpcClient; | 74 | + private final OrderServiceRpcClient orderServiceRpcClient; |
| 74 | 75 | ||
| 75 | - private final ClientResourceTagServiceRpcClient clientResourceTagServiceRpcClient; | 76 | + private final ClientResourceTagServiceRpcClient clientResourceTagServiceRpcClient; |
| 76 | 77 | ||
| 77 | - private final EnterpriseResourceServiceRpcClient enterpriseResourceServiceRpcClient; | 78 | + private final EnterpriseResourceServiceRpcClient enterpriseResourceServiceRpcClient; |
| 78 | 79 | ||
| 79 | - private final XmlMapper xmlMapper = new XmlMapper(); | 80 | + private final XmlMapper xmlMapper = new XmlMapper(); |
| 80 | 81 | ||
| 81 | - public PayResponseDto payInform(PayInformRequestDto payRequestDto) { | 82 | + public PayResponseDto payInform(PayInformRequestDto payRequestDto) { |
| 82 | - final var orderById = | 83 | + final var orderById = |
| 83 | - orderServiceRpcClient.getOrderById(Integer.valueOf(payRequestDto.getOrderId())); | 84 | + orderServiceRpcClient.getOrderById(Integer.valueOf(payRequestDto.getOrderId())); |
| 84 | - if (orderById == null | 85 | + if (orderById == null |
| 85 | - || orderById.getPayStatus() == PayStatusEnum.PAY_CANCELED | 86 | + || orderById.getPayStatus() == PayStatusEnum.PAY_CANCELED |
| 86 | - || orderById.getStatus() == OrderStatusEnum.ORDER_CANCELED) { | 87 | + || orderById.getStatus() == OrderStatusEnum.ORDER_CANCELED) { |
| 87 | - log.info("Order {} not found or canceled, skipping.", payRequestDto.getOrderId()); | 88 | + log.info("Order {} not found or canceled, skipping.", payRequestDto.getOrderId()); |
| 88 | - throw ClientEndExceptions.BusinessException.build(ErrorCodeEnum.ORDER_CANCEL); | 89 | + throw ClientEndExceptions.BusinessException.build(ErrorCodeEnum.ORDER_CANCEL); |
| 89 | - } | 90 | + } |
| 90 | - String url = MessageFormat.format(businessConfig.getPayUrl(), businessConfig.getPayClientId()); | 91 | + String url = MessageFormat.format(businessConfig.getPayUrl(), businessConfig.getPayClientId()); |
| 91 | - String requestDate = DateUtil.formatDate(LocalDateTime.now(), DateUtil.YMDHMS); | 92 | + String requestDate = DateUtil.formatDate(LocalDateTime.now(), DateUtil.YMDHMS); |
| 92 | - ThirdPartyPayInformRequestDto jsonData = buildRequestData(payRequestDto, requestDate); | 93 | + ThirdPartyPayInformRequestDto jsonData = buildRequestData(payRequestDto, requestDate); |
| 93 | - String jsonDataString; | 94 | + String jsonDataString; |
| 94 | - try { | 95 | + try { |
| 95 | - ObjectMapper objectMapper = new ObjectMapper(); | 96 | + ObjectMapper objectMapper = new ObjectMapper(); |
| 96 | - objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); | 97 | + objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); |
| 97 | - objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); | 98 | + objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); |
| 98 | - objectMapper.setPropertyNamingStrategy(new PropertyNamingStrategies.UpperCamelCaseStrategy()); | 99 | + objectMapper.setPropertyNamingStrategy(new PropertyNamingStrategies.UpperCamelCaseStrategy()); |
| 99 | - jsonDataString = objectMapper.writeValueAsString(jsonData); | 100 | + jsonDataString = objectMapper.writeValueAsString(jsonData); |
| 100 | - } catch (JsonProcessingException e) { | 101 | + } catch (JsonProcessingException e) { |
| 101 | - log.error("Failed to serialize request data", e); | 102 | + log.error("Failed to serialize request data", e); |
| 102 | - throw new IllegalArgumentException("支付信息获取失败: JSON 解析错误"); | 103 | + throw new IllegalArgumentException("支付信息获取失败: JSON 解析错误"); |
| 104 | + } | ||
| 105 | + HttpEntity<String> requestEntity = new HttpEntity<>(jsonDataString, createHeaders()); | ||
| 106 | + log.info("payInform request: {}", jsonDataString); | ||
| 107 | + ResponseEntity<String> responseEntity = | ||
| 108 | + restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class); | ||
| 109 | + return processResponse(responseEntity); | ||
| 103 | } | 110 | } |
| 104 | - HttpEntity<String> requestEntity = new HttpEntity<>(jsonDataString, createHeaders()); | ||
| 105 | - log.info("payInform request: {}", jsonDataString); | ||
| 106 | - ResponseEntity<String> responseEntity = | ||
| 107 | - restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class); | ||
| 108 | - return processResponse(responseEntity); | ||
| 109 | - } | ||
| 110 | - | ||
| 111 | - private ThirdPartyPayInformRequestDto buildRequestData( | ||
| 112 | - PayInformRequestDto payRequestDto, String requestDate) { | ||
| 113 | - ThirdPartyPayInformRequestDto jsonData = new ThirdPartyPayInformRequestDto(); | ||
| 114 | - jsonData.setClientId(businessConfig.getPayClientId()); | ||
| 115 | - jsonData.setTradeId(payRequestDto.getOrderId()); | ||
| 116 | - jsonData.setRequestDate(requestDate); | ||
| 117 | - jsonData.setRequestSource("OFWXApplet"); | ||
| 118 | - jsonData.setPayerOpenId(LoginContextHolder.getOpenId()); | ||
| 119 | - jsonData.setHospitalCode(payRequestDto.getHospitalCode()); | ||
| 120 | - jsonData.setPID(LoginContextHolder.getOpenId()); | ||
| 121 | - jsonData.setRemark(""); | ||
| 122 | - jsonData.setTransAmount(payRequestDto.getPrice()); | ||
| 123 | - jsonData.setTradeDesc(""); | ||
| 124 | - jsonData.setSign( | ||
| 125 | - EncryptionUtil.sha1Encryption( | ||
| 126 | - businessConfig.getPayClientId() | ||
| 127 | - + payRequestDto.getOrderId() | ||
| 128 | - + requestDate | ||
| 129 | - + businessConfig.getPayClientId())); | ||
| 130 | - return jsonData; | ||
| 131 | - } | ||
| 132 | 111 | ||
| 133 | - private HttpHeaders createHeaders() { | 112 | + private ThirdPartyPayInformRequestDto buildRequestData( |
| 134 | - HttpHeaders headers = new HttpHeaders(); | 113 | + PayInformRequestDto payRequestDto, String requestDate) { |
| 135 | - headers.setContentType(MediaType.APPLICATION_JSON); | 114 | + ThirdPartyPayInformRequestDto jsonData = new ThirdPartyPayInformRequestDto(); |
| 136 | - return headers; | 115 | + jsonData.setClientId(businessConfig.getPayClientId()); |
| 137 | - } | 116 | + jsonData.setTradeId(payRequestDto.getOrderId()); |
| 138 | - | 117 | + jsonData.setRequestDate(requestDate); |
| 139 | - private PayResponseDto processResponse(ResponseEntity<String> responseEntity) { | 118 | + jsonData.setRequestSource("OFWXApplet"); |
| 140 | - if (!responseEntity.getStatusCode().is2xxSuccessful() || responseEntity.getBody() == null) { | 119 | + jsonData.setPayerOpenId(LoginContextHolder.getOpenId()); |
| 141 | - log.error("payInform failed with response: {}", responseEntity.getBody()); | 120 | + jsonData.setHospitalCode(payRequestDto.getHospitalCode()); |
| 142 | - throw new IllegalArgumentException("支付信息获取失败"); | 121 | + jsonData.setPID(LoginContextHolder.getOpenId()); |
| 143 | - } | 122 | + jsonData.setRemark(""); |
| 144 | - try { | 123 | + jsonData.setTransAmount(payRequestDto.getPrice()); |
| 145 | - log.info("processResponse response: {}", responseEntity.getBody()); | 124 | + jsonData.setTradeDesc(""); |
| 146 | - return xmlMapper.readValue(responseEntity.getBody(), PayResponseDto.class); | 125 | + jsonData.setSign( |
| 147 | - } catch (Exception e) { | 126 | + EncryptionUtil.sha1Encryption( |
| 148 | - log.error("Failed to parse XML response", e); | 127 | + businessConfig.getPayClientId() |
| 149 | - throw new RuntimeException("支付信息结果解析失败", e); | 128 | + + payRequestDto.getOrderId() |
| 129 | + + requestDate | ||
| 130 | + + businessConfig.getPayClientId())); | ||
| 131 | + return jsonData; | ||
| 150 | } | 132 | } |
| 151 | - } | ||
| 152 | 133 | ||
| 153 | - public boolean callback(PaymentCallbackDTO paymentCallbackDTO) { | 134 | + private HttpHeaders createHeaders() { |
| 154 | - log.info("callback request received: {}", paymentCallbackDTO); | 135 | + HttpHeaders headers = new HttpHeaders(); |
| 155 | - try { | 136 | + headers.setContentType(MediaType.APPLICATION_JSON); |
| 156 | - final var paymentCallbackResult = | 137 | + return headers; |
| 157 | - xmlMapper.readValue(paymentCallbackDTO.getPayResult(), PaymentCallbackResult.class); | 138 | + } |
| 158 | - log.info("Parsed paymentCallbackResult: {}", paymentCallbackResult); | ||
| 159 | - final var orderId = Integer.parseInt(paymentCallbackResult.getTradeId()); | ||
| 160 | - final var orderById = orderServiceRpcClient.getOrderById(orderId); | ||
| 161 | - if (orderById == null) { | ||
| 162 | - log.error("Order not found, orderId: {}", orderId); | ||
| 163 | - return false; | ||
| 164 | - } | ||
| 165 | - log.info("Order callback, orderId: {}", orderId); | ||
| 166 | 139 | ||
| 167 | - final var transType = paymentCallbackResult.getTransType(); | 140 | + private PayResponseDto processResponse(ResponseEntity<String> responseEntity) { |
| 168 | - if (transType.equals("00")) { | 141 | + if (!responseEntity.getStatusCode().is2xxSuccessful() || responseEntity.getBody() == null) { |
| 169 | - if (orderById.getPayStatus() != PayStatusEnum.TO_PAY | 142 | + log.error("payInform failed with response: {}", responseEntity.getBody()); |
| 170 | - && orderById.getPayStatus() != PayStatusEnum.IN_PROGRESS) { | 143 | + throw new IllegalArgumentException("支付信息获取失败"); |
| 171 | - log.error("Order status is not TO_PAY or IN_PROGRESS, orderId: {}", orderId); | ||
| 172 | - return true; | ||
| 173 | } | 144 | } |
| 174 | - long payTime; | ||
| 175 | try { | 145 | try { |
| 176 | - payTime = | 146 | + log.info("processResponse response: {}", responseEntity.getBody()); |
| 177 | - DateUtil.parseDate(paymentCallbackResult.getTransDate(), "yyyyMMddHHmmss").getTime(); | 147 | + return xmlMapper.readValue(responseEntity.getBody(), PayResponseDto.class); |
| 178 | - } catch (ParseException e) { | 148 | + } catch (Exception e) { |
| 179 | - log.error("Failed to parse TransDate: {}", paymentCallbackResult.getTransDate(), e); | 149 | + log.error("Failed to parse XML response", e); |
| 180 | - throw new IllegalArgumentException("支付时间格式错误: " + paymentCallbackResult.getTransDate(), e); | 150 | + throw new RuntimeException("支付信息结果解析失败", e); |
| 181 | } | 151 | } |
| 182 | - BigDecimal realAmount; | 152 | + } |
| 153 | + | ||
| 154 | + public boolean callback(PaymentCallbackDTO paymentCallbackDTO) { | ||
| 155 | + log.info("callback request received: {}", paymentCallbackDTO); | ||
| 183 | try { | 156 | try { |
| 184 | - realAmount = Convert.toBigDecimal(paymentCallbackResult.getRealAmount()); | 157 | + final var paymentCallbackResult = |
| 185 | - if (realAmount == null) { | 158 | + xmlMapper.readValue(paymentCallbackDTO.getPayResult(), PaymentCallbackResult.class); |
| 186 | - throw new NumberFormatException("RealAmount is null or empty"); | 159 | + log.info("Parsed paymentCallbackResult: {}", paymentCallbackResult); |
| 187 | - } | 160 | + final var orderId = Integer.parseInt(paymentCallbackResult.getTradeId()); |
| 188 | - } catch (NumberFormatException e) { | 161 | + final var orderById = orderServiceRpcClient.getOrderById(orderId); |
| 189 | - log.error("Invalid RealAmount value: {}", paymentCallbackResult.getRealAmount(), e); | 162 | + if (orderById == null) { |
| 190 | - throw new IllegalArgumentException("支付金额错误: " + paymentCallbackResult.getRealAmount(), e); | 163 | + log.error("Order not found, orderId: {}", orderId); |
| 191 | - } | 164 | + return false; |
| 192 | - final var build = | ||
| 193 | - ClientCustomerOrderModification.newBuilder() | ||
| 194 | - .setId(orderId) | ||
| 195 | - .setShouldUpdatePayTime(true) | ||
| 196 | - .setPayTime(payTime) | ||
| 197 | - .setShouldUpdatePayPrice(true) | ||
| 198 | - .setPayPrice(realAmount.multiply(new BigDecimal("100")).intValue()) | ||
| 199 | - .setShouldUpdatePayStatus(true) | ||
| 200 | - .setPayStatus(PayStatusEnum.SUCCEED) | ||
| 201 | - .setShouldUpdateStatus(true) | ||
| 202 | - .setStatus(OrderStatusEnum.PREPARING) | ||
| 203 | - .setShouldUpdateTransactionId(true) | ||
| 204 | - .setTransactionId(paymentCallbackResult.getTransSN()) | ||
| 205 | - .build(); | ||
| 206 | - final var updateResponse = | ||
| 207 | - orderServiceRpcClient.updateClientCustomerOrderPaymentResult(orderById, build); | ||
| 208 | - log.info("callback updateClientCustomerOrder result: {}", updateResponse.getIsUpdated()); | ||
| 209 | - if (updateResponse.getIsUpdated()) { | ||
| 210 | - String createdAt = Instant.ofEpochMilli(orderById.getCreatedAt()) | ||
| 211 | - .atZone(DateUtil.CHINA_ZONE) | ||
| 212 | - .minusHours(8) | ||
| 213 | - .format(DateUtil.Y_M_D_H_M_S); | ||
| 214 | - String payTimed = Instant.ofEpochMilli(orderById.getPayTime()) | ||
| 215 | - .atZone(DateUtil.CHINA_ZONE) | ||
| 216 | - .minusHours(8) | ||
| 217 | - .format(DateUtil.Y_M_D_H_M_S); | ||
| 218 | - final var orderPaymentSuccessData = | ||
| 219 | - OrderPaymentSuccessData.builder() | ||
| 220 | - .orderId(orderById.getId()) | ||
| 221 | - .orderCode(orderById.getOrderCode()) | ||
| 222 | - .createTime(createdAt) | ||
| 223 | - .payTime(payTimed) | ||
| 224 | - .build(); | ||
| 225 | - final var data = | ||
| 226 | - SocketMessage.<OrderPaymentSuccessData>builder() | ||
| 227 | - .type(MessageTypeEnum.ORDER) | ||
| 228 | - .noticeType(NoticeTypeEnum.ORDER_PAYMENT_SUCCESS) | ||
| 229 | - .subject(NoticeTypeEnum.ORDER_PAYMENT_SUCCESS.getDescription()) | ||
| 230 | - .message("您的订单:" + orderById.getOrderCode() + " 支付成功啦,快去查看吧~") | ||
| 231 | - .data(orderPaymentSuccessData) | ||
| 232 | - .build(); | ||
| 233 | - WebSocketServer.sendMessageToUser( | ||
| 234 | - UserSessionKey.builder() | ||
| 235 | - .userId(orderById.getOpenId()) | ||
| 236 | - .userType(UserTypeEnum.MICRO) | ||
| 237 | - .build(), | ||
| 238 | - data); | ||
| 239 | - if (LocalDate.now().equals(DateUtil.toLocalDate(orderById.getMealTime()))) { | ||
| 240 | - final var orderCreateSuccessData = | ||
| 241 | - OrderCreateSuccessData.builder().orderId(orderById.getId()).build(); | ||
| 242 | - final var createOrderData = | ||
| 243 | - SocketMessage.<OrderCreateSuccessData>builder() | ||
| 244 | - .type(MessageTypeEnum.ORDER) | ||
| 245 | - .noticeType(NoticeTypeEnum.ORDER_CREATED) | ||
| 246 | - .subject(NoticeTypeEnum.ORDER_CREATED.getDescription()) | ||
| 247 | - .message("有新的订单下单成功啦,快去查看吧~") | ||
| 248 | - .data(orderCreateSuccessData) | ||
| 249 | - .build(); | ||
| 250 | - final var clientOperatorIds = | ||
| 251 | - clientResourceTagServiceRpcClient | ||
| 252 | - .getOperatorIdsByStallIds(List.of(orderById.getStallId())).stream() | ||
| 253 | - .map(SingleResourceLabelEntityRefsResponse::getEntityId) | ||
| 254 | - .distinct() | ||
| 255 | - .collect(Collectors.toList()); | ||
| 256 | - final var enterpriseOperatorIds = | ||
| 257 | - enterpriseResourceServiceRpcClient.getOperatorIdsByStallId( | ||
| 258 | - orderById.getEnterpriseId(), orderById.getStallId()); | ||
| 259 | - final var userAuthData = new ArrayList<UserAuthData>(); | ||
| 260 | - userAuthData.addAll( | ||
| 261 | - clientOperatorIds.stream() | ||
| 262 | - .map( | ||
| 263 | - e -> | ||
| 264 | - UserAuthData.builder() | ||
| 265 | - .operatorId(e) | ||
| 266 | - .userType(UserTypeEnum.CLIENT) | ||
| 267 | - .build()) | ||
| 268 | - .collect(Collectors.toList())); | ||
| 269 | - userAuthData.addAll( | ||
| 270 | - enterpriseOperatorIds.stream() | ||
| 271 | - .map(e -> UserAuthData.builder().operatorId(e).userType(UserTypeEnum.KDS).build()) | ||
| 272 | - .collect(Collectors.toList())); | ||
| 273 | - log.info("received userAuthData:{}", JsonUtil.writeAsJson(userAuthData)); | ||
| 274 | - try { | ||
| 275 | - WebSocketServer.sendMessageByUserTypes( | ||
| 276 | - List.of(UserTypeEnum.CLIENT, UserTypeEnum.KDS), userAuthData, createOrderData); | ||
| 277 | - } catch (IOException e) { | ||
| 278 | - log.error("Failed to send message to user", e); | ||
| 279 | } | 165 | } |
| 280 | - } | 166 | + log.info("Order callback, orderId: {}", orderId); |
| 167 | + | ||
| 168 | + final var transType = paymentCallbackResult.getTransType(); | ||
| 169 | + if (transType.equals("00")) { | ||
| 170 | + if (orderById.getPayStatus() != PayStatusEnum.TO_PAY | ||
| 171 | + && orderById.getPayStatus() != PayStatusEnum.IN_PROGRESS) { | ||
| 172 | + log.error("Order status is not TO_PAY or IN_PROGRESS, orderId: {}", orderId); | ||
| 173 | + return true; | ||
| 174 | + } | ||
| 175 | + long payTime; | ||
| 176 | + try { | ||
| 177 | + payTime = | ||
| 178 | + DateUtil.parseDate(paymentCallbackResult.getTransDate(), "yyyyMMddHHmmss").getTime(); | ||
| 179 | + } catch (ParseException e) { | ||
| 180 | + log.error("Failed to parse TransDate: {}", paymentCallbackResult.getTransDate(), e); | ||
| 181 | + throw new IllegalArgumentException("支付时间格式错误: " + paymentCallbackResult.getTransDate(), e); | ||
| 182 | + } | ||
| 183 | + BigDecimal realAmount; | ||
| 184 | + try { | ||
| 185 | + realAmount = Convert.toBigDecimal(paymentCallbackResult.getRealAmount()); | ||
| 186 | + if (realAmount == null) { | ||
| 187 | + throw new NumberFormatException("RealAmount is null or empty"); | ||
| 188 | + } | ||
| 189 | + } catch (NumberFormatException e) { | ||
| 190 | + log.error("Invalid RealAmount value: {}", paymentCallbackResult.getRealAmount(), e); | ||
| 191 | + throw new IllegalArgumentException("支付金额错误: " + paymentCallbackResult.getRealAmount(), e); | ||
| 192 | + } | ||
| 193 | + final var build = | ||
| 194 | + ClientCustomerOrderModification.newBuilder() | ||
| 195 | + .setId(orderId) | ||
| 196 | + .setShouldUpdatePayTime(true) | ||
| 197 | + .setPayTime(payTime) | ||
| 198 | + .setShouldUpdatePayPrice(true) | ||
| 199 | + .setPayPrice(realAmount.multiply(new BigDecimal("100")).intValue()) | ||
| 200 | + .setShouldUpdatePayStatus(true) | ||
| 201 | + .setPayStatus(PayStatusEnum.SUCCEED) | ||
| 202 | + .setShouldUpdateStatus(true) | ||
| 203 | + .setStatus(OrderStatusEnum.PREPARING) | ||
| 204 | + .setShouldUpdateTransactionId(true) | ||
| 205 | + .setTransactionId(paymentCallbackResult.getTradeReferenceNo()) | ||
| 206 | + .build(); | ||
| 207 | + final var updateResponse = | ||
| 208 | + orderServiceRpcClient.updateClientCustomerOrderPaymentResult(orderById, build); | ||
| 209 | + log.info("callback updateClientCustomerOrder result: {}", updateResponse.getIsUpdated()); | ||
| 210 | + if (updateResponse.getIsUpdated()) { | ||
| 211 | + String createdAt = Instant.ofEpochMilli(orderById.getCreatedAt()) | ||
| 212 | + .atZone(DateUtil.CHINA_ZONE) | ||
| 213 | + .minusHours(8) | ||
| 214 | + .format(DateUtil.Y_M_D_H_M_S); | ||
| 215 | + String payTimed = Instant.ofEpochMilli(orderById.getPayTime()) | ||
| 216 | + .atZone(DateUtil.CHINA_ZONE) | ||
| 217 | + .minusHours(8) | ||
| 218 | + .format(DateUtil.Y_M_D_H_M_S); | ||
| 219 | + final var orderPaymentSuccessData = | ||
| 220 | + OrderPaymentSuccessData.builder() | ||
| 221 | + .orderId(orderById.getId()) | ||
| 222 | + .orderCode(orderById.getOrderCode()) | ||
| 223 | + .createTime(createdAt) | ||
| 224 | + .payTime(payTimed) | ||
| 225 | + .build(); | ||
| 226 | + final var data = | ||
| 227 | + SocketMessage.<OrderPaymentSuccessData>builder() | ||
| 228 | + .type(MessageTypeEnum.ORDER) | ||
| 229 | + .noticeType(NoticeTypeEnum.ORDER_PAYMENT_SUCCESS) | ||
| 230 | + .subject(NoticeTypeEnum.ORDER_PAYMENT_SUCCESS.getDescription()) | ||
| 231 | + .message("您的订单:" + orderById.getOrderCode() + " 支付成功啦,快去查看吧~") | ||
| 232 | + .data(orderPaymentSuccessData) | ||
| 233 | + .build(); | ||
| 234 | + WebSocketServer.sendMessageToUser( | ||
| 235 | + UserSessionKey.builder() | ||
| 236 | + .userId(orderById.getOpenId()) | ||
| 237 | + .userType(UserTypeEnum.MICRO) | ||
| 238 | + .build(), | ||
| 239 | + data); | ||
| 240 | + if (LocalDate.now().equals(DateUtil.toLocalDate(orderById.getMealTime()))) { | ||
| 241 | + final var orderCreateSuccessData = | ||
| 242 | + OrderCreateSuccessData.builder().orderId(orderById.getId()).build(); | ||
| 243 | + final var createOrderData = | ||
| 244 | + SocketMessage.<OrderCreateSuccessData>builder() | ||
| 245 | + .type(MessageTypeEnum.ORDER) | ||
| 246 | + .noticeType(NoticeTypeEnum.ORDER_CREATED) | ||
| 247 | + .subject(NoticeTypeEnum.ORDER_CREATED.getDescription()) | ||
| 248 | + .message("有新的订单下单成功啦,快去查看吧~") | ||
| 249 | + .data(orderCreateSuccessData) | ||
| 250 | + .build(); | ||
| 251 | + final var clientOperatorIds = | ||
| 252 | + clientResourceTagServiceRpcClient | ||
| 253 | + .getOperatorIdsByStallIds(List.of(orderById.getStallId())).stream() | ||
| 254 | + .map(SingleResourceLabelEntityRefsResponse::getEntityId) | ||
| 255 | + .distinct() | ||
| 256 | + .collect(Collectors.toList()); | ||
| 257 | + final var enterpriseOperatorIds = | ||
| 258 | + enterpriseResourceServiceRpcClient.getOperatorIdsByStallId( | ||
| 259 | + orderById.getEnterpriseId(), orderById.getStallId()); | ||
| 260 | + final var userAuthData = new ArrayList<UserAuthData>(); | ||
| 261 | + userAuthData.addAll( | ||
| 262 | + clientOperatorIds.stream() | ||
| 263 | + .map( | ||
| 264 | + e -> | ||
| 265 | + UserAuthData.builder() | ||
| 266 | + .operatorId(e) | ||
| 267 | + .userType(UserTypeEnum.CLIENT) | ||
| 268 | + .build()) | ||
| 269 | + .collect(Collectors.toList())); | ||
| 270 | + userAuthData.addAll( | ||
| 271 | + enterpriseOperatorIds.stream() | ||
| 272 | + .map(e -> UserAuthData.builder().operatorId(e).userType(UserTypeEnum.KDS).build()) | ||
| 273 | + .collect(Collectors.toList())); | ||
| 274 | + log.info("received userAuthData:{}", JsonUtil.writeAsJson(userAuthData)); | ||
| 275 | + try { | ||
| 276 | + WebSocketServer.sendMessageByUserTypes( | ||
| 277 | + List.of(UserTypeEnum.CLIENT, UserTypeEnum.KDS), userAuthData, createOrderData); | ||
| 278 | + } catch (IOException e) { | ||
| 279 | + log.error("Failed to send message to user", e); | ||
| 280 | + } | ||
| 281 | + } | ||
| 282 | + } | ||
| 283 | + return updateResponse.getIsUpdated(); | ||
| 284 | + } else { | ||
| 285 | + final var build = | ||
| 286 | + ClientCustomerOrderModification.newBuilder() | ||
| 287 | + .setId(orderId) | ||
| 288 | + .setShouldUpdatePayStatus(true) | ||
| 289 | + .setPayStatus(PayStatusEnum.REFUND) | ||
| 290 | + .build(); | ||
| 291 | + final var updateResponse = | ||
| 292 | + orderServiceRpcClient.updateClientCustomerOrderPaymentResult(orderById, build); | ||
| 293 | + log.info("callback updateClientCustomerOrder result: {}", updateResponse.getIsUpdated()); | ||
| 294 | + return updateResponse.getIsUpdated(); | ||
| 295 | + } | ||
| 296 | + } catch (JsonProcessingException e) { | ||
| 297 | + log.error("Failed to parse XML response, raw XML: {}", paymentCallbackDTO.getPayResult(), e); | ||
| 298 | + throw new RuntimeException("支付/退款通知结果解析失败", e); | ||
| 299 | + } catch (Exception e) { | ||
| 300 | + log.error("Unexpected error in callback, request: {}", paymentCallbackDTO, e); | ||
| 301 | + throw new RuntimeException("支付/退款通知处理失败", e); | ||
| 302 | + } | ||
| 303 | + } | ||
| 304 | + | ||
| 305 | + public boolean waiting(Integer orderId) { | ||
| 306 | + final var orderById = orderServiceRpcClient.getOrderById(orderId); | ||
| 307 | + if (orderById == null) { | ||
| 308 | + log.error("waiting Order not found, orderId: {}", orderId); | ||
| 309 | + return false; | ||
| 310 | + } | ||
| 311 | + if (orderById.getPayStatus() != PayStatusEnum.TO_PAY) { | ||
| 312 | + log.info("waiting Order {} already processed, skipping.", orderId); | ||
| 313 | + return false; | ||
| 281 | } | 314 | } |
| 282 | - return updateResponse.getIsUpdated(); | ||
| 283 | - } else { | ||
| 284 | final var build = | 315 | final var build = |
| 285 | - ClientCustomerOrderModification.newBuilder() | 316 | + ClientCustomerOrderModification.newBuilder() |
| 286 | - .setId(orderId) | 317 | + .setId(orderId) |
| 287 | - .setShouldUpdatePayStatus(true) | 318 | + .setShouldUpdatePayStatus(true) |
| 288 | - .setPayStatus(PayStatusEnum.REFUND) | 319 | + .setPayStatus(PayStatusEnum.IN_PROGRESS) |
| 289 | - .build(); | 320 | + .build(); |
| 290 | final var updateResponse = | 321 | final var updateResponse = |
| 291 | - orderServiceRpcClient.updateClientCustomerOrderPaymentResult(orderById, build); | 322 | + orderServiceRpcClient.updateClientCustomerOrderPaymentResult(orderById, build); |
| 292 | - log.info("callback updateClientCustomerOrder result: {}", updateResponse.getIsUpdated()); | 323 | + log.info("waiting updateClientCustomerOrder result: {}", updateResponse.getIsUpdated()); |
| 293 | return updateResponse.getIsUpdated(); | 324 | return updateResponse.getIsUpdated(); |
| 294 | - } | ||
| 295 | - } catch (JsonProcessingException e) { | ||
| 296 | - log.error("Failed to parse XML response, raw XML: {}", paymentCallbackDTO.getPayResult(), e); | ||
| 297 | - throw new RuntimeException("支付/退款通知结果解析失败", e); | ||
| 298 | - } catch (Exception e) { | ||
| 299 | - log.error("Unexpected error in callback, request: {}", paymentCallbackDTO, e); | ||
| 300 | - throw new RuntimeException("支付/退款通知处理失败", e); | ||
| 301 | } | 325 | } |
| 302 | - } | ||
| 303 | 326 | ||
| 304 | - public boolean waiting(Integer orderId) { | 327 | + public String orderPayRefund(PayRefundRequestDto payRefundRequestDto) { |
| 305 | - final var orderById = orderServiceRpcClient.getOrderById(orderId); | 328 | + Integer orderId = payRefundRequestDto.getOrderId(); |
| 306 | - if (orderById == null) { | 329 | + final var orderById = orderServiceRpcClient.getOrderById(orderId); |
| 307 | - log.error("waiting Order not found, orderId: {}", orderId); | 330 | + if (orderById == null) { |
| 308 | - return false; | 331 | + log.error("Order not found, orderId: {}", orderId); |
| 309 | - } | 332 | + throw ClientEndExceptions.BusinessException.build(ErrorCodeEnum.ORDER_NOT_FOUND); |
| 310 | - if (orderById.getPayStatus() != PayStatusEnum.TO_PAY) { | 333 | + } |
| 311 | - log.info("waiting Order {} already processed, skipping.", orderId); | 334 | + if (orderById.getOnlinePay() != OnlinePayEnum.ONLINE) { |
| 312 | - return false; | 335 | + log.info("Order {} is not online pay.", orderId); |
| 313 | - } | 336 | + throw ClientEndExceptions.BusinessException.build(ErrorCodeEnum.ORDER_NOT_ONLINE_PAY); |
| 314 | - final var build = | 337 | + } |
| 315 | - ClientCustomerOrderModification.newBuilder() | 338 | + if (orderById.getPayStatus() != PayStatusEnum.SUCCEED) { |
| 316 | - .setId(orderId) | 339 | + log.info("Order {} pay is not succeed.", orderId); |
| 317 | - .setShouldUpdatePayStatus(true) | 340 | + throw ClientEndExceptions.BusinessException.build(ErrorCodeEnum.ORDER_NOT_SUCCESS); |
| 318 | - .setPayStatus(PayStatusEnum.IN_PROGRESS) | 341 | + } |
| 319 | - .build(); | 342 | + LocalDate today = LocalDate.now(); |
| 320 | - final var updateResponse = | 343 | + LocalDate tomorrow = today.plusDays(1); |
| 321 | - orderServiceRpcClient.updateClientCustomerOrderPaymentResult(orderById, build); | 344 | + LocalDateTime tomorrowZero = tomorrow.atStartOfDay(); |
| 322 | - log.info("waiting updateClientCustomerOrder result: {}", updateResponse.getIsUpdated()); | 345 | + LocalDateTime orderPayTime = DateUtil.toLocalDateTime(orderById.getPayTime()).minusHours(8); |
| 323 | - return updateResponse.getIsUpdated(); | 346 | + if (!orderPayTime.isBefore(tomorrowZero)) { |
| 324 | - } | 347 | + log.info("Order {} pay is beyond cancel time.", orderId); |
| 325 | - | 348 | + throw ClientEndExceptions.BusinessException.build(ErrorCodeEnum.ORDER_PAY_REFUND_FAILED); |
| 326 | - public String orderPayRefund(PayRefundRequestDto payRefundRequestDto) { | 349 | + } |
| 327 | - Integer orderId = payRefundRequestDto.getOrderId(); | 350 | + BigDecimal detailPrice = BigDecimal.ZERO; |
| 328 | - final var orderById = orderServiceRpcClient.getOrderById(orderId); | 351 | + if (CollectionUtils.isNotEmpty(payRefundRequestDto.getOrderDetailIds())) { |
| 329 | - if (orderById == null) { | 352 | + final var orderDetails = orderServiceRpcClient.getClientCustomerOrderDetailsByIds(payRefundRequestDto.getOrderDetailIds()); |
| 330 | - log.error("Order not found, orderId: {}", orderId); | 353 | + detailPrice = orderDetails.stream().filter(e -> e.getPrice() > 0).map(e -> new BigDecimal(e.getPrice()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP)).reduce(BigDecimal.ZERO, BigDecimal::add); |
| 331 | - throw ClientEndExceptions.BusinessException.build(ErrorCodeEnum.ORDER_NOT_FOUND); | 354 | + } |
| 332 | - } | ||
| 333 | - if (orderById.getOnlinePay() != OnlinePayEnum.ONLINE) { | ||
| 334 | - log.info("Order {} is not online pay.", orderId); | ||
| 335 | - throw ClientEndExceptions.BusinessException.build(ErrorCodeEnum.ORDER_NOT_ONLINE_PAY); | ||
| 336 | - } | ||
| 337 | - if (orderById.getPayStatus() != PayStatusEnum.SUCCEED) { | ||
| 338 | - log.info("Order {} pay is not succeed.", orderId); | ||
| 339 | - throw ClientEndExceptions.BusinessException.build(ErrorCodeEnum.ORDER_NOT_SUCCESS); | ||
| 340 | - } | ||
| 341 | - LocalDate today = LocalDate.now(); | ||
| 342 | - LocalDate tomorrow = today.plusDays(1); | ||
| 343 | - LocalDateTime tomorrowZero = tomorrow.atStartOfDay(); | ||
| 344 | - LocalDateTime orderPayTime = DateUtil.toLocalDateTime(orderById.getPayTime()).minusHours(8); | ||
| 345 | - if (!orderPayTime.isBefore(tomorrowZero)) { | ||
| 346 | - log.info("Order {} pay is beyond cancel time.", orderId); | ||
| 347 | - throw ClientEndExceptions.BusinessException.build(ErrorCodeEnum.ORDER_PAY_REFUND_FAILED); | ||
| 348 | - } | ||
| 349 | 355 | ||
| 350 | - String appId = businessConfig.getPayClientId(); | 356 | + String appId = businessConfig.getPayClientId(); |
| 351 | 357 | ||
| 352 | - // 构建paycontent | 358 | + // 构建paycontent |
| 353 | - String payTime = Instant.ofEpochMilli(orderById.getPayTime()) | 359 | + String payTime = Instant.ofEpochMilli(orderById.getPayTime()) |
| 354 | - .atZone(DateUtil.CHINA_ZONE) | 360 | + .atZone(DateUtil.CHINA_ZONE) |
| 355 | - .minusHours(8) | 361 | + .minusHours(8) |
| 356 | - .format(DateUtil.YMDHMS); | 362 | + .format(DateUtil.YMDHMS); |
| 357 | 363 | ||
| 358 | - BigDecimal price = | 364 | + BigDecimal price = detailPrice.compareTo(BigDecimal.ZERO) == 0 ? |
| 359 | - new BigDecimal(orderById.getPayPrice()) | 365 | + new BigDecimal(orderById.getPayPrice()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP).negate() |
| 360 | - .divide(new BigDecimal(100), 2, RoundingMode.HALF_UP).negate(); | 366 | + : detailPrice.negate(); |
| 361 | 367 | ||
| 362 | - String payContentStr = | 368 | + String payContentStr = |
| 363 | - orderById.getId() | 369 | + orderById.getId() |
| 364 | - + "^" | 370 | + + "^" |
| 365 | - + "01" | 371 | + + "01" |
| 366 | - + "^" | 372 | + + "^" |
| 367 | - + "^" | 373 | + + "^" |
| 368 | - + orderById.getOpenId() | 374 | + + orderById.getOpenId() |
| 369 | - + "^" | 375 | + + "^" |
| 370 | - + orderById.getOrderCode() | 376 | + + orderById.getOrderCode() |
| 371 | - + "^" | 377 | + + "^" |
| 372 | - + price | 378 | + + price |
| 373 | - + "^" | 379 | + + "^" |
| 374 | - + payTime | 380 | + + payTime |
| 375 | - + "^" | 381 | + + "^" |
| 376 | - + orderById.getTransactionId() | 382 | + + orderById.getTransactionId() |
| 377 | - + "^" | 383 | + + "^" |
| 378 | - + payRefundRequestDto.getHospitalCode() | 384 | + + payRefundRequestDto.getHospitalCode() |
| 379 | - + "^" | 385 | + + "^" |
| 380 | - + "^" | 386 | + + "^" |
| 381 | - + LoginContextHolder.getId() | 387 | + + LoginContextHolder.getId() |
| 382 | - + "^" | 388 | + + "^" |
| 383 | - + LoginContextHolder.getName(); | 389 | + + LoginContextHolder.getName(); |
| 384 | - String payContent = | 390 | + String payContent = |
| 385 | - URLEncoder.encode( | 391 | + URLEncoder.encode( |
| 386 | - Base64.encodeBase64String(payContentStr.getBytes()), StandardCharsets.UTF_8); | 392 | + Base64.encodeBase64String(payContentStr.getBytes()), StandardCharsets.UTF_8); |
| 387 | 393 | ||
| 388 | - // 构建signinfo | 394 | + // 构建signinfo |
| 389 | - String signInfoStr = appId + orderById.getId() + payTime + businessConfig.getRefundSecurityKey(); | 395 | + String signInfoStr = appId + orderById.getId() + payTime + businessConfig.getRefundSecurityKey(); |
| 390 | - String signInfo = DigestUtils.sha1Hex(signInfoStr.getBytes()); | 396 | + String signInfo = DigestUtils.sha1Hex(signInfoStr.getBytes()); |
| 391 | 397 | ||
| 392 | - // 构建请求 | 398 | + // 构建请求 |
| 393 | - try { | 399 | + try { |
| 394 | - String url = businessConfig.getCancelPayUrl() + "?" + "appid=" + appId + "&paycontent=" + payContent + "&signinfo=" + signInfo; | 400 | + String url = businessConfig.getCancelPayUrl() + "?" + "appid=" + appId + "&paycontent=" + payContent + "&signinfo=" + signInfo; |
| 395 | - log.info("cancel order pay url:{}", url); | 401 | + log.info("cancel order pay url:{}", url); |
| 396 | // Request request = | 402 | // Request request = |
| 397 | // new Request.Builder().url(url).get().build(); | 403 | // new Request.Builder().url(url).get().build(); |
| 398 | // Response payResponse = client.newCall(request).execute(); | 404 | // Response payResponse = client.newCall(request).execute(); |
| ... | @@ -400,10 +406,10 @@ public class PayServiceClient { | ... | @@ -400,10 +406,10 @@ public class PayServiceClient { |
| 400 | // throw ClientEndExceptions.BusinessException.build(ErrorCodeEnum.ORDER_PAY_REFUND_FAILED); | 406 | // throw ClientEndExceptions.BusinessException.build(ErrorCodeEnum.ORDER_PAY_REFUND_FAILED); |
| 401 | // } | 407 | // } |
| 402 | // String htmlContent = payResponse.body().string(); | 408 | // String htmlContent = payResponse.body().string(); |
| 403 | - return url; | 409 | + return url; |
| 404 | - } catch (Exception e) { | 410 | + } catch (Exception e) { |
| 405 | - log.error(e.getMessage()); | 411 | + log.error(e.getMessage()); |
| 406 | - throw ClientEndExceptions.BusinessException.build(ErrorCodeEnum.ORDER_PAY_REFUND_FAILED); | 412 | + throw ClientEndExceptions.BusinessException.build(ErrorCodeEnum.ORDER_PAY_REFUND_FAILED); |
| 413 | + } | ||
| 407 | } | 414 | } |
| 408 | - } | ||
| 409 | } | 415 | } | ... | ... |
| ... | @@ -2,8 +2,11 @@ package com.infoloop.tianting.service.impl; | ... | @@ -2,8 +2,11 @@ package com.infoloop.tianting.service.impl; |
| 2 | 2 | ||
| 3 | import cn.hutool.core.collection.CollectionUtil; | 3 | import cn.hutool.core.collection.CollectionUtil; |
| 4 | import cn.hutool.core.date.LocalDateTimeUtil; | 4 | import cn.hutool.core.date.LocalDateTimeUtil; |
| 5 | +import com.fasterxml.jackson.core.type.TypeReference; | ||
| 5 | import com.infoloop.tianting.SingleDishSkuByIdsRpcResponse; | 6 | import com.infoloop.tianting.SingleDishSkuByIdsRpcResponse; |
| 6 | import com.infoloop.tianting.clientcustomerorderservice.OnlinePayEnum; | 7 | import com.infoloop.tianting.clientcustomerorderservice.OnlinePayEnum; |
| 8 | +import com.infoloop.tianting.clientcustomerorderservice.OrderOperationRecord; | ||
| 9 | +import com.infoloop.tianting.clientcustomerorderservice.OrderOperationType; | ||
| 7 | import com.infoloop.tianting.clientcustomerorderservice.OrderStatusEnum; | 10 | import com.infoloop.tianting.clientcustomerorderservice.OrderStatusEnum; |
| 8 | import com.infoloop.tianting.clientcustomerorderservice.PayStatusEnum; | 11 | import com.infoloop.tianting.clientcustomerorderservice.PayStatusEnum; |
| 9 | import com.infoloop.tianting.clientcustomerorderservice.ServeStatusEnum; | 12 | import com.infoloop.tianting.clientcustomerorderservice.ServeStatusEnum; |
| ... | @@ -17,6 +20,7 @@ import com.infoloop.tianting.exception.ClientEndExceptions.BusinessException; | ... | @@ -17,6 +20,7 @@ import com.infoloop.tianting.exception.ClientEndExceptions.BusinessException; |
| 17 | import com.infoloop.tianting.exception.ErrorCodeEnum; | 20 | import com.infoloop.tianting.exception.ErrorCodeEnum; |
| 18 | import com.infoloop.tianting.menuservice.SingleMenuDetailRpcResponse; | 21 | import com.infoloop.tianting.menuservice.SingleMenuDetailRpcResponse; |
| 19 | import com.infoloop.tianting.menuservice.SingleMenuRpcResponse; | 22 | import com.infoloop.tianting.menuservice.SingleMenuRpcResponse; |
| 23 | +import com.infoloop.tianting.model.bo.OrderDetailBO; | ||
| 20 | import com.infoloop.tianting.model.dto.OrderDbDTO.QueryOrderByConditionDto; | 24 | import com.infoloop.tianting.model.dto.OrderDbDTO.QueryOrderByConditionDto; |
| 21 | import com.infoloop.tianting.model.dto.OrderDbDTO.QueryOrderDto; | 25 | import com.infoloop.tianting.model.dto.OrderDbDTO.QueryOrderDto; |
| 22 | import com.infoloop.tianting.model.dto.SettlementDTO; | 26 | import com.infoloop.tianting.model.dto.SettlementDTO; |
| ... | @@ -39,8 +43,10 @@ import com.infoloop.tianting.service.client.OrderServiceRpcClient; | ... | @@ -39,8 +43,10 @@ import com.infoloop.tianting.service.client.OrderServiceRpcClient; |
| 39 | import com.infoloop.tianting.service.client.SkuServiceRpcClient; | 43 | import com.infoloop.tianting.service.client.SkuServiceRpcClient; |
| 40 | import com.infoloop.tianting.setmealscheduleservice.SingleMealRpcResponse; | 44 | import com.infoloop.tianting.setmealscheduleservice.SingleMealRpcResponse; |
| 41 | import com.infoloop.tianting.utils.DateUtil; | 45 | import com.infoloop.tianting.utils.DateUtil; |
| 46 | +import com.infoloop.tianting.utils.JsonUtil; | ||
| 42 | import lombok.RequiredArgsConstructor; | 47 | import lombok.RequiredArgsConstructor; |
| 43 | import lombok.extern.slf4j.Slf4j; | 48 | import lombok.extern.slf4j.Slf4j; |
| 49 | +import org.apache.commons.lang3.StringUtils; | ||
| 44 | import org.apache.poi.ss.usermodel.BorderStyle; | 50 | import org.apache.poi.ss.usermodel.BorderStyle; |
| 45 | import org.apache.poi.ss.usermodel.Cell; | 51 | import org.apache.poi.ss.usermodel.Cell; |
| 46 | import org.apache.poi.ss.usermodel.CellStyle; | 52 | import org.apache.poi.ss.usermodel.CellStyle; |
| ... | @@ -71,7 +77,9 @@ import java.util.HashMap; | ... | @@ -71,7 +77,9 @@ import java.util.HashMap; |
| 71 | import java.util.List; | 77 | import java.util.List; |
| 72 | import java.util.Map; | 78 | import java.util.Map; |
| 73 | import java.util.Objects; | 79 | import java.util.Objects; |
| 80 | +import java.util.function.Function; | ||
| 74 | import java.util.stream.Collectors; | 81 | import java.util.stream.Collectors; |
| 82 | +import java.util.stream.Stream; | ||
| 75 | 83 | ||
| 76 | @Slf4j | 84 | @Slf4j |
| 77 | @Service | 85 | @Service |
| ... | @@ -295,6 +303,408 @@ public class SettlementServiceImpl implements SettlementService { | ... | @@ -295,6 +303,408 @@ public class SettlementServiceImpl implements SettlementService { |
| 295 | return dateList; | 303 | return dateList; |
| 296 | } | 304 | } |
| 297 | 305 | ||
| 306 | + /** | ||
| 307 | + * 按订单维度生成Excel | ||
| 308 | + */ | ||
| 309 | + private static ByteArrayOutputStream writeToExcelByOrder(SettlementDTO.SettlementDataByOrderDto settlementDataDto) | ||
| 310 | + throws IOException { | ||
| 311 | + Workbook workbook = new XSSFWorkbook(); | ||
| 312 | + Sheet sheet = workbook.createSheet("客人结算"); | ||
| 313 | + | ||
| 314 | + // 创建表头样式(黑色边框) | ||
| 315 | + CellStyle headerStyle = workbook.createCellStyle(); | ||
| 316 | + headerStyle.setBorderTop(BorderStyle.THIN); | ||
| 317 | + headerStyle.setBorderBottom(BorderStyle.THIN); | ||
| 318 | + headerStyle.setBorderLeft(BorderStyle.THIN); | ||
| 319 | + headerStyle.setBorderRight(BorderStyle.THIN); | ||
| 320 | + headerStyle.setTopBorderColor(IndexedColors.BLACK.getIndex()); | ||
| 321 | + headerStyle.setBottomBorderColor(IndexedColors.BLACK.getIndex()); | ||
| 322 | + headerStyle.setLeftBorderColor(IndexedColors.BLACK.getIndex()); | ||
| 323 | + headerStyle.setRightBorderColor(IndexedColors.BLACK.getIndex()); | ||
| 324 | + | ||
| 325 | + // 创建数据行样式(浅灰色边框) | ||
| 326 | + CellStyle dataStyle = workbook.createCellStyle(); | ||
| 327 | + dataStyle.setBorderTop(BorderStyle.THIN); | ||
| 328 | + dataStyle.setBorderBottom(BorderStyle.THIN); | ||
| 329 | + dataStyle.setBorderLeft(BorderStyle.THIN); | ||
| 330 | + dataStyle.setBorderRight(BorderStyle.THIN); | ||
| 331 | + dataStyle.setTopBorderColor(IndexedColors.GREY_25_PERCENT.getIndex()); | ||
| 332 | + dataStyle.setBottomBorderColor(IndexedColors.GREY_25_PERCENT.getIndex()); | ||
| 333 | + dataStyle.setLeftBorderColor(IndexedColors.GREY_25_PERCENT.getIndex()); | ||
| 334 | + dataStyle.setRightBorderColor(IndexedColors.GREY_25_PERCENT.getIndex()); | ||
| 335 | + | ||
| 336 | + int rowNum = 0; | ||
| 337 | + | ||
| 338 | + // 创建表头 | ||
| 339 | + Row titleRow = sheet.createRow(rowNum++); | ||
| 340 | + int columnNum = 0; | ||
| 341 | + | ||
| 342 | + Cell cell0 = titleRow.createCell(columnNum++); | ||
| 343 | + cell0.setCellValue("用餐时间"); | ||
| 344 | + cell0.setCellStyle(headerStyle); | ||
| 345 | + | ||
| 346 | + Cell cell1 = titleRow.createCell(columnNum++); | ||
| 347 | + cell1.setCellValue("订单号"); | ||
| 348 | + cell1.setCellStyle(headerStyle); | ||
| 349 | + | ||
| 350 | + Cell cell2 = titleRow.createCell(columnNum++); | ||
| 351 | + cell2.setCellValue("餐别"); | ||
| 352 | + cell2.setCellStyle(headerStyle); | ||
| 353 | + | ||
| 354 | + Cell cell3 = titleRow.createCell(columnNum++); | ||
| 355 | + cell3.setCellValue("房间号"); | ||
| 356 | + cell3.setCellStyle(headerStyle); | ||
| 357 | + | ||
| 358 | + Cell cell4 = titleRow.createCell(columnNum++); | ||
| 359 | + cell4.setCellValue("客户姓名"); | ||
| 360 | + cell4.setCellStyle(headerStyle); | ||
| 361 | + | ||
| 362 | + Cell cell5 = titleRow.createCell(columnNum++); | ||
| 363 | + cell5.setCellValue("客户腕带号"); | ||
| 364 | + cell5.setCellStyle(headerStyle); | ||
| 365 | + | ||
| 366 | + Cell cell6 = titleRow.createCell(columnNum++); | ||
| 367 | + cell6.setCellValue("忌口信息"); | ||
| 368 | + cell6.setCellStyle(headerStyle); | ||
| 369 | + | ||
| 370 | + Cell cell7 = titleRow.createCell(columnNum++); | ||
| 371 | + cell7.setCellValue("医嘱信息"); | ||
| 372 | + cell7.setCellStyle(headerStyle); | ||
| 373 | + | ||
| 374 | + Cell cell8 = titleRow.createCell(columnNum++); | ||
| 375 | + cell8.setCellValue("餐单名称"); | ||
| 376 | + cell8.setCellStyle(headerStyle); | ||
| 377 | + | ||
| 378 | + Cell cell9 = titleRow.createCell(columnNum++); | ||
| 379 | + cell9.setCellValue("菜品名称"); | ||
| 380 | + cell9.setCellStyle(headerStyle); | ||
| 381 | + | ||
| 382 | + Cell cell10 = titleRow.createCell(columnNum++); | ||
| 383 | + cell10.setCellValue("菜品份数"); | ||
| 384 | + cell10.setCellStyle(headerStyle); | ||
| 385 | + | ||
| 386 | + Cell cell11 = titleRow.createCell(columnNum++); | ||
| 387 | + cell11.setCellValue("菜品单价"); | ||
| 388 | + cell11.setCellStyle(headerStyle); | ||
| 389 | + | ||
| 390 | + Cell cell12 = titleRow.createCell(columnNum++); | ||
| 391 | + cell12.setCellValue("菜品金额"); | ||
| 392 | + cell12.setCellStyle(headerStyle); | ||
| 393 | + | ||
| 394 | + Cell cell13 = titleRow.createCell(columnNum++); | ||
| 395 | + cell13.setCellValue("菜品状态"); | ||
| 396 | + cell13.setCellStyle(headerStyle); | ||
| 397 | + | ||
| 398 | + Cell cell14 = titleRow.createCell(columnNum++); | ||
| 399 | + cell14.setCellValue("交易码"); | ||
| 400 | + cell14.setCellStyle(headerStyle); | ||
| 401 | + | ||
| 402 | + Cell cell15 = titleRow.createCell(columnNum++); | ||
| 403 | + cell15.setCellValue("备注"); | ||
| 404 | + cell15.setCellStyle(headerStyle); | ||
| 405 | + | ||
| 406 | + Cell cell16 = titleRow.createCell(columnNum++); | ||
| 407 | + cell16.setCellValue("支付方式"); | ||
| 408 | + cell16.setCellStyle(headerStyle); | ||
| 409 | + | ||
| 410 | + // 填充数据 | ||
| 411 | + final var classifyOrders = settlementDataDto.getClassifyOrders(); | ||
| 412 | + if (classifyOrders != null) { | ||
| 413 | + for (SettlementDTO.SettlementOrderDetail orderDetail : classifyOrders) { | ||
| 414 | + Row dataRow = sheet.createRow(rowNum++); | ||
| 415 | + columnNum = 0; | ||
| 416 | + | ||
| 417 | + Cell dataCell0 = dataRow.createCell(columnNum++); | ||
| 418 | + dataCell0.setCellValue(orderDetail.getMealTime() != null ? orderDetail.getMealTime() : ""); | ||
| 419 | + dataCell0.setCellStyle(dataStyle); | ||
| 420 | + | ||
| 421 | + Cell dataCell1 = dataRow.createCell(columnNum++); | ||
| 422 | + dataCell1.setCellValue(orderDetail.getCode() != null ? orderDetail.getCode() : ""); | ||
| 423 | + dataCell1.setCellStyle(dataStyle); | ||
| 424 | + | ||
| 425 | + Cell dataCell2 = dataRow.createCell(columnNum++); | ||
| 426 | + dataCell2.setCellValue(orderDetail.getMealName() != null ? orderDetail.getMealName() : ""); | ||
| 427 | + dataCell2.setCellStyle(dataStyle); | ||
| 428 | + | ||
| 429 | + Cell dataCell3 = dataRow.createCell(columnNum++); | ||
| 430 | + dataCell3.setCellValue(orderDetail.getRoomNo() != null ? orderDetail.getRoomNo() : ""); | ||
| 431 | + dataCell3.setCellStyle(dataStyle); | ||
| 432 | + | ||
| 433 | + Cell dataCell4 = dataRow.createCell(columnNum++); | ||
| 434 | + dataCell4.setCellValue(orderDetail.getCustomerName() != null ? orderDetail.getCustomerName() : ""); | ||
| 435 | + dataCell4.setCellStyle(dataStyle); | ||
| 436 | + | ||
| 437 | + Cell dataCell5 = dataRow.createCell(columnNum++); | ||
| 438 | + dataCell5.setCellValue(orderDetail.getHISCustomerNo() != null ? orderDetail.getHISCustomerNo() : ""); | ||
| 439 | + dataCell5.setCellStyle(dataStyle); | ||
| 440 | + | ||
| 441 | + // 忌口列表转字符串 | ||
| 442 | + String avoidsStr = orderDetail.getAvoids() != null ? String.join(", ", orderDetail.getAvoids()) : ""; | ||
| 443 | + Cell dataCell6 = dataRow.createCell(columnNum++); | ||
| 444 | + dataCell6.setCellValue(avoidsStr); | ||
| 445 | + dataCell6.setCellStyle(dataStyle); | ||
| 446 | + | ||
| 447 | + // 医嘱列表转字符串 | ||
| 448 | + String doctorsStr = orderDetail.getDoctors() != null ? String.join(", ", orderDetail.getDoctors()) : ""; | ||
| 449 | + Cell dataCell7 = dataRow.createCell(columnNum++); | ||
| 450 | + dataCell7.setCellValue(doctorsStr); | ||
| 451 | + dataCell7.setCellStyle(dataStyle); | ||
| 452 | + | ||
| 453 | + Cell dataCell8 = dataRow.createCell(columnNum++); | ||
| 454 | + dataCell8.setCellValue(orderDetail.getMenuName() != null ? orderDetail.getMenuName() : ""); | ||
| 455 | + dataCell8.setCellStyle(dataStyle); | ||
| 456 | + | ||
| 457 | + Cell dataCell9 = dataRow.createCell(columnNum++); | ||
| 458 | + dataCell9.setCellValue(orderDetail.getSkuName() != null ? orderDetail.getSkuName() : ""); | ||
| 459 | + dataCell9.setCellStyle(dataStyle); | ||
| 460 | + | ||
| 461 | + Cell dataCell10 = dataRow.createCell(columnNum++); | ||
| 462 | + dataCell10.setCellValue(orderDetail.getCount() != null ? orderDetail.getCount() : 0); | ||
| 463 | + dataCell10.setCellStyle(dataStyle); | ||
| 464 | + | ||
| 465 | + // 价格 | ||
| 466 | + Cell dataCell11 = dataRow.createCell(columnNum++); | ||
| 467 | + if (orderDetail.getPrice() != null) { | ||
| 468 | + dataCell11.setCellValue(orderDetail.getPrice().doubleValue()); | ||
| 469 | + } else { | ||
| 470 | + dataCell11.setCellValue(0.0); | ||
| 471 | + } | ||
| 472 | + dataCell11.setCellStyle(dataStyle); | ||
| 473 | + | ||
| 474 | + // 总价 | ||
| 475 | + Cell dataCell12 = dataRow.createCell(columnNum++); | ||
| 476 | + if (orderDetail.getTotalPrice() != null) { | ||
| 477 | + dataCell12.setCellValue(orderDetail.getTotalPrice().doubleValue()); | ||
| 478 | + } else { | ||
| 479 | + dataCell12.setCellValue(0.0); | ||
| 480 | + } | ||
| 481 | + dataCell12.setCellStyle(dataStyle); | ||
| 482 | + | ||
| 483 | + // 状态 | ||
| 484 | + Cell dataCell13 = dataRow.createCell(columnNum++); | ||
| 485 | + dataCell13.setCellValue(orderDetail.getOperationType()); | ||
| 486 | + dataCell13.setCellStyle(dataStyle); | ||
| 487 | + | ||
| 488 | + Cell dataCell14 = dataRow.createCell(columnNum++); | ||
| 489 | + dataCell14.setCellValue(orderDetail.getTransactionId() != null ? orderDetail.getTransactionId() : ""); | ||
| 490 | + dataCell14.setCellStyle(dataStyle); | ||
| 491 | + | ||
| 492 | + // 合并备注和忌口备注,用分号分割,备注在前 | ||
| 493 | + String remark = orderDetail.getRemark() != null ? orderDetail.getRemark() : ""; | ||
| 494 | + String avoidRemark = orderDetail.getAvoidRemark() != null ? orderDetail.getAvoidRemark() : ""; | ||
| 495 | + String combinedRemark = ""; | ||
| 496 | + if (!remark.isEmpty() && !avoidRemark.isEmpty()) { | ||
| 497 | + combinedRemark = remark + ";" + avoidRemark; | ||
| 498 | + } else if (!remark.isEmpty()) { | ||
| 499 | + combinedRemark = remark; | ||
| 500 | + } else if (!avoidRemark.isEmpty()) { | ||
| 501 | + combinedRemark = avoidRemark; | ||
| 502 | + } | ||
| 503 | + Cell dataCell15 = dataRow.createCell(columnNum++); | ||
| 504 | + dataCell15.setCellValue(combinedRemark); | ||
| 505 | + dataCell15.setCellStyle(dataStyle); | ||
| 506 | + | ||
| 507 | + Cell dataCell16 = dataRow.createCell(columnNum++); | ||
| 508 | + dataCell16.setCellValue(orderDetail.getOnlinePay() != null ? orderDetail.getOnlinePay() : ""); | ||
| 509 | + dataCell16.setCellStyle(dataStyle); | ||
| 510 | + } | ||
| 511 | + } | ||
| 512 | + | ||
| 513 | + // 自动调整列宽 | ||
| 514 | + for (int i = 0; i < 17; i++) { | ||
| 515 | + sheet.autoSizeColumn(i); | ||
| 516 | + } | ||
| 517 | + | ||
| 518 | + // 将工作簿内容写入字节数组输出流 | ||
| 519 | + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); | ||
| 520 | + workbook.write(outputStream); | ||
| 521 | + workbook.close(); | ||
| 522 | + | ||
| 523 | + return outputStream; | ||
| 524 | + } | ||
| 525 | + | ||
| 526 | + /** | ||
| 527 | + * 生成分餐表Excel | ||
| 528 | + */ | ||
| 529 | + private static ByteArrayOutputStream writeToExcelBySeparateMeal(SeparateMealDataDto separateMealDataDto) | ||
| 530 | + throws IOException { | ||
| 531 | + Workbook workbook = new XSSFWorkbook(); | ||
| 532 | + Sheet sheet = workbook.createSheet("分餐表"); | ||
| 533 | + | ||
| 534 | + // 创建标题样式(合并单元格标题) | ||
| 535 | + CellStyle titleStyle = workbook.createCellStyle(); | ||
| 536 | + titleStyle.setAlignment(HorizontalAlignment.CENTER); | ||
| 537 | + titleStyle.setVerticalAlignment(VerticalAlignment.CENTER); | ||
| 538 | + titleStyle.setBorderTop(BorderStyle.THIN); | ||
| 539 | + titleStyle.setBorderBottom(BorderStyle.THIN); | ||
| 540 | + titleStyle.setBorderLeft(BorderStyle.THIN); | ||
| 541 | + titleStyle.setBorderRight(BorderStyle.THIN); | ||
| 542 | + titleStyle.setTopBorderColor(IndexedColors.BLACK.getIndex()); | ||
| 543 | + titleStyle.setBottomBorderColor(IndexedColors.BLACK.getIndex()); | ||
| 544 | + titleStyle.setLeftBorderColor(IndexedColors.BLACK.getIndex()); | ||
| 545 | + titleStyle.setRightBorderColor(IndexedColors.BLACK.getIndex()); | ||
| 546 | + Font titleFont = workbook.createFont(); | ||
| 547 | + titleFont.setBold(true); | ||
| 548 | + titleFont.setFontHeightInPoints((short) 16); | ||
| 549 | + titleStyle.setFont(titleFont); | ||
| 550 | + | ||
| 551 | + // 创建表头样式(黑色边框) | ||
| 552 | + CellStyle headerStyle = workbook.createCellStyle(); | ||
| 553 | + headerStyle.setBorderTop(BorderStyle.THIN); | ||
| 554 | + headerStyle.setBorderBottom(BorderStyle.THIN); | ||
| 555 | + headerStyle.setBorderLeft(BorderStyle.THIN); | ||
| 556 | + headerStyle.setBorderRight(BorderStyle.THIN); | ||
| 557 | + headerStyle.setTopBorderColor(IndexedColors.BLACK.getIndex()); | ||
| 558 | + headerStyle.setBottomBorderColor(IndexedColors.BLACK.getIndex()); | ||
| 559 | + headerStyle.setLeftBorderColor(IndexedColors.BLACK.getIndex()); | ||
| 560 | + headerStyle.setRightBorderColor(IndexedColors.BLACK.getIndex()); | ||
| 561 | + | ||
| 562 | + // 创建数据行样式(浅灰色边框) | ||
| 563 | + CellStyle dataStyle = workbook.createCellStyle(); | ||
| 564 | + dataStyle.setBorderTop(BorderStyle.THIN); | ||
| 565 | + dataStyle.setBorderBottom(BorderStyle.THIN); | ||
| 566 | + dataStyle.setBorderLeft(BorderStyle.THIN); | ||
| 567 | + dataStyle.setBorderRight(BorderStyle.THIN); | ||
| 568 | + dataStyle.setTopBorderColor(IndexedColors.GREY_25_PERCENT.getIndex()); | ||
| 569 | + dataStyle.setBottomBorderColor(IndexedColors.GREY_25_PERCENT.getIndex()); | ||
| 570 | + dataStyle.setLeftBorderColor(IndexedColors.GREY_25_PERCENT.getIndex()); | ||
| 571 | + dataStyle.setRightBorderColor(IndexedColors.GREY_25_PERCENT.getIndex()); | ||
| 572 | + | ||
| 573 | + int rowNum = 0; | ||
| 574 | + | ||
| 575 | + // 第一行:创建合并单元格标题 | ||
| 576 | + Row mainTitleRow = sheet.createRow(rowNum++); | ||
| 577 | + Cell mainTitleCell = mainTitleRow.createCell(0); | ||
| 578 | + mainTitleCell.setCellValue("住院客户分餐表"); | ||
| 579 | + mainTitleCell.setCellStyle(titleStyle); | ||
| 580 | + | ||
| 581 | + // 合并第一行的8列 | ||
| 582 | + CellRangeAddress titleRegion = new CellRangeAddress(0, 0, 0, 8); | ||
| 583 | + sheet.addMergedRegion(titleRegion); | ||
| 584 | + | ||
| 585 | + // 为合并区域设置边框 | ||
| 586 | + RegionUtil.setBorderTop(BorderStyle.THIN, titleRegion, sheet); | ||
| 587 | + RegionUtil.setBorderBottom(BorderStyle.THIN, titleRegion, sheet); | ||
| 588 | + RegionUtil.setBorderLeft(BorderStyle.THIN, titleRegion, sheet); | ||
| 589 | + RegionUtil.setBorderRight(BorderStyle.THIN, titleRegion, sheet); | ||
| 590 | + RegionUtil.setTopBorderColor(IndexedColors.BLACK.getIndex(), titleRegion, sheet); | ||
| 591 | + RegionUtil.setBottomBorderColor(IndexedColors.BLACK.getIndex(), titleRegion, sheet); | ||
| 592 | + RegionUtil.setLeftBorderColor(IndexedColors.BLACK.getIndex(), titleRegion, sheet); | ||
| 593 | + RegionUtil.setRightBorderColor(IndexedColors.BLACK.getIndex(), titleRegion, sheet); | ||
| 594 | + | ||
| 595 | + // 第二行:创建表头 | ||
| 596 | + Row titleRow = sheet.createRow(rowNum++); | ||
| 597 | + int columnNum = 0; | ||
| 598 | + | ||
| 599 | + Cell cell0 = titleRow.createCell(columnNum++); | ||
| 600 | + cell0.setCellValue("餐别"); | ||
| 601 | + cell0.setCellStyle(headerStyle); | ||
| 602 | + | ||
| 603 | + Cell cell1 = titleRow.createCell(columnNum++); | ||
| 604 | + cell1.setCellValue("房间号"); | ||
| 605 | + cell1.setCellStyle(headerStyle); | ||
| 606 | + | ||
| 607 | + Cell cell2 = titleRow.createCell(columnNum++); | ||
| 608 | + cell2.setCellValue("客户姓名"); | ||
| 609 | + cell2.setCellStyle(headerStyle); | ||
| 610 | + | ||
| 611 | + Cell cell3 = titleRow.createCell(columnNum++); | ||
| 612 | + cell3.setCellValue("医嘱信息"); | ||
| 613 | + cell3.setCellStyle(headerStyle); | ||
| 614 | + | ||
| 615 | + Cell cell4 = titleRow.createCell(columnNum++); | ||
| 616 | + cell4.setCellValue("餐单名称"); | ||
| 617 | + cell4.setCellStyle(headerStyle); | ||
| 618 | + | ||
| 619 | + Cell cell5 = titleRow.createCell(columnNum++); | ||
| 620 | + cell5.setCellValue("菜品名称"); | ||
| 621 | + cell5.setCellStyle(headerStyle); | ||
| 622 | + | ||
| 623 | + Cell cell6 = titleRow.createCell(columnNum++); | ||
| 624 | + cell6.setCellValue("菜品数量"); | ||
| 625 | + cell6.setCellStyle(headerStyle); | ||
| 626 | + | ||
| 627 | + Cell cell7 = titleRow.createCell(columnNum++); | ||
| 628 | + cell7.setCellValue("忌口信息"); | ||
| 629 | + cell7.setCellStyle(headerStyle); | ||
| 630 | + | ||
| 631 | + Cell cell8 = titleRow.createCell(columnNum++); | ||
| 632 | + cell8.setCellValue("备注"); | ||
| 633 | + cell8.setCellStyle(headerStyle); | ||
| 634 | + | ||
| 635 | + // 填充数据 | ||
| 636 | + final var mealDetails = separateMealDataDto.getMealDetails(); | ||
| 637 | + if (mealDetails != null) { | ||
| 638 | + for (SeparateMealDetail mealDetail : mealDetails) { | ||
| 639 | + Row dataRow = sheet.createRow(rowNum++); | ||
| 640 | + columnNum = 0; | ||
| 641 | + | ||
| 642 | + Cell dataCell0 = dataRow.createCell(columnNum++); | ||
| 643 | + dataCell0.setCellValue(mealDetail.getMealName() != null ? mealDetail.getMealName() : ""); | ||
| 644 | + dataCell0.setCellStyle(dataStyle); | ||
| 645 | + | ||
| 646 | + Cell dataCell1 = dataRow.createCell(columnNum++); | ||
| 647 | + dataCell1.setCellValue(mealDetail.getRoomNo() != null ? mealDetail.getRoomNo() : ""); | ||
| 648 | + dataCell1.setCellStyle(dataStyle); | ||
| 649 | + | ||
| 650 | + Cell dataCell2 = dataRow.createCell(columnNum++); | ||
| 651 | + dataCell2.setCellValue(mealDetail.getCustomerName() != null ? mealDetail.getCustomerName() : ""); | ||
| 652 | + dataCell2.setCellStyle(dataStyle); | ||
| 653 | + | ||
| 654 | + Cell dataCell3 = dataRow.createCell(columnNum++); | ||
| 655 | + dataCell3.setCellValue(mealDetail.getDoctors() != null ? mealDetail.getDoctors() : ""); | ||
| 656 | + dataCell3.setCellStyle(dataStyle); | ||
| 657 | + | ||
| 658 | + Cell dataCell4 = dataRow.createCell(columnNum++); | ||
| 659 | + dataCell4.setCellValue(mealDetail.getMenuName() != null ? mealDetail.getMenuName() : ""); | ||
| 660 | + dataCell4.setCellStyle(dataStyle); | ||
| 661 | + | ||
| 662 | + Cell dataCell5 = dataRow.createCell(columnNum++); | ||
| 663 | + dataCell5.setCellValue(mealDetail.getSkuName() != null ? mealDetail.getSkuName() : ""); | ||
| 664 | + dataCell5.setCellStyle(dataStyle); | ||
| 665 | + | ||
| 666 | + Cell dataCell6 = dataRow.createCell(columnNum++); | ||
| 667 | + dataCell6.setCellValue(mealDetail.getCount() != null ? mealDetail.getCount() : 0); | ||
| 668 | + dataCell6.setCellStyle(dataStyle); | ||
| 669 | + | ||
| 670 | + Cell dataCell7 = dataRow.createCell(columnNum++); | ||
| 671 | + dataCell7.setCellValue(mealDetail.getAvoids() != null ? mealDetail.getAvoids() : ""); | ||
| 672 | + dataCell7.setCellStyle(dataStyle); | ||
| 673 | + | ||
| 674 | + Cell dataCell8 = dataRow.createCell(columnNum++); | ||
| 675 | + dataCell8.setCellValue(mealDetail.getRemark() != null ? mealDetail.getRemark() : ""); | ||
| 676 | + dataCell8.setCellStyle(dataStyle); | ||
| 677 | + } | ||
| 678 | + } | ||
| 679 | + | ||
| 680 | + // 自动调整列宽 | ||
| 681 | + for (int i = 0; i < 9; i++) { | ||
| 682 | + sheet.autoSizeColumn(i); | ||
| 683 | + } | ||
| 684 | + | ||
| 685 | + // 将工作簿内容写入字节数组输出流 | ||
| 686 | + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); | ||
| 687 | + workbook.write(outputStream); | ||
| 688 | + workbook.close(); | ||
| 689 | + | ||
| 690 | + return outputStream; | ||
| 691 | + } | ||
| 692 | + | ||
| 693 | + /** | ||
| 694 | + * 创建空的分餐表Excel(无数据) | ||
| 695 | + */ | ||
| 696 | + private static ByteArrayOutputStream createEmptyExcelBySeparateMeal() { | ||
| 697 | + try { | ||
| 698 | + SeparateMealDataDto emptyData = SeparateMealDataDto.builder() | ||
| 699 | + .mealDetails(new ArrayList<>()) | ||
| 700 | + .build(); | ||
| 701 | + return writeToExcelBySeparateMeal(emptyData); | ||
| 702 | + } catch (IOException e) { | ||
| 703 | + log.error("创建空分餐表Excel失败", e); | ||
| 704 | + throw BusinessException.build(ErrorCodeEnum.GENERATE_EXCEL_ERROR); | ||
| 705 | + } | ||
| 706 | + } | ||
| 707 | + | ||
| 298 | @Override | 708 | @Override |
| 299 | public ByteArrayOutputStream generateOrderSettlementExcel(SettlementRequestDto settlementRequest) { | 709 | public ByteArrayOutputStream generateOrderSettlementExcel(SettlementRequestDto settlementRequest) { |
| 300 | if (settlementRequest.getDimension().equals(SettlementDimensionEnum.BY_SKU)) { | 710 | if (settlementRequest.getDimension().equals(SettlementDimensionEnum.BY_SKU)) { |
| ... | @@ -369,13 +779,11 @@ public class SettlementServiceImpl implements SettlementService { | ... | @@ -369,13 +779,11 @@ public class SettlementServiceImpl implements SettlementService { |
| 369 | .collect(Collectors.toList()); | 779 | .collect(Collectors.toList()); |
| 370 | 780 | ||
| 371 | if (orderIds.isEmpty()) { | 781 | if (orderIds.isEmpty()) { |
| 372 | - log.warn("筛选后无有效订单,enterpriseId: {}", enterpriseId); | ||
| 373 | return createEmptyExcelByOrder(); | 782 | return createEmptyExcelByOrder(); |
| 374 | } | 783 | } |
| 375 | 784 | ||
| 376 | // 构建订单映射 | 785 | // 构建订单映射 |
| 377 | - final var orderMap = orderList.stream() | 786 | + final var orderMap = orderList.stream().filter(o -> o.getId() != 0) |
| 378 | - .filter(o -> o.getId() != 0) | ||
| 379 | .collect(Collectors.toMap(SingleClientCustomerOrderRpcResponse::getId, o -> o, (o1, o2) -> o1)); | 787 | .collect(Collectors.toMap(SingleClientCustomerOrderRpcResponse::getId, o -> o, (o1, o2) -> o1)); |
| 380 | 788 | ||
| 381 | // 查询订单详情 | 789 | // 查询订单详情 |
| ... | @@ -384,86 +792,60 @@ public class SettlementServiceImpl implements SettlementService { | ... | @@ -384,86 +792,60 @@ public class SettlementServiceImpl implements SettlementService { |
| 384 | log.warn("未查询到订单详情数据,orderIds: {}", orderIds); | 792 | log.warn("未查询到订单详情数据,orderIds: {}", orderIds); |
| 385 | return createEmptyExcelByOrder(); | 793 | return createEmptyExcelByOrder(); |
| 386 | } | 794 | } |
| 387 | - | ||
| 388 | // 订单详情按订单ID分组 | 795 | // 订单详情按订单ID分组 |
| 389 | - final var orderDetailGroupByOrderId = orderDetailList.stream() | 796 | + final var orderDetailGroupByOrderId = orderDetailList.stream().filter(Objects::nonNull).collect(Collectors.groupingBy(SingleClientCustomerOrderDetailRpcResponse::getOrderId)); |
| 390 | - .filter(Objects::nonNull) | 797 | + |
| 391 | - .filter(d -> !d.getServeStatus().equals(ServeStatusEnum.SERVE_REJECT)) | 798 | + final var orderOperationRecordsByOrderIds = orderServiceRpcClient.getOrderOperationRecordsByOrderIds(LoginContextHolder.getEnterpriseId(), orderIds).getResponsesList(); |
| 392 | - .collect(Collectors.groupingBy(SingleClientCustomerOrderDetailRpcResponse::getOrderId)); | 799 | + |
| 393 | - | 800 | + // 订单操作记录按订单ID分组 |
| 394 | - // 获取SKU数据 | 801 | + final var orderOperationRecordByOrderId = orderOperationRecordsByOrderIds.stream().filter(Objects::nonNull).collect(Collectors.groupingBy(OrderOperationRecord::getOrderId)); |
| 395 | - List<Integer> skuIds = orderDetailList.stream() | 802 | + |
| 396 | - .filter(Objects::nonNull) | 803 | + List<Integer> skuIds = Stream.concat( |
| 397 | - .filter(d -> !d.getServeStatus().equals(ServeStatusEnum.SERVE_REJECT)) | 804 | + orderOperationRecordsByOrderIds.stream() |
| 398 | - .map(SingleClientCustomerOrderDetailRpcResponse::getSkuId) | 805 | + .filter(e -> StringUtils.isNoneBlank(e.getOriginalOrderDetailJson())) |
| 806 | + .flatMap(e -> JsonUtil.readJsonAs(e.getOriginalOrderDetailJson(), new TypeReference<List<OrderDetailBO>>() {}).stream()) | ||
| 807 | + .map(OrderDetailBO::getSkuId), | ||
| 808 | + orderDetailList.stream() | ||
| 809 | + .filter(Objects::nonNull) | ||
| 810 | + .map(SingleClientCustomerOrderDetailRpcResponse::getSkuId) | ||
| 811 | + ) | ||
| 399 | .distinct() | 812 | .distinct() |
| 400 | .collect(Collectors.toList()); | 813 | .collect(Collectors.toList()); |
| 401 | 814 | ||
| 402 | final var skuResponse = skuServiceRpcClient.getDishSkusByIds(skuIds); | 815 | final var skuResponse = skuServiceRpcClient.getDishSkusByIds(skuIds); |
| 403 | - final List<SingleDishSkuByIdsRpcResponse> skus = skuResponse != null ? skuResponse.getResponseList() : new ArrayList<>(); | 816 | + final List<SingleDishSkuByIdsRpcResponse> skus = skuResponse.getResponseList(); |
| 404 | - final var skuMap = skus.stream() | 817 | + final var skuMap = skus.stream().collect(Collectors.toMap(SingleDishSkuByIdsRpcResponse::getId, s -> s, (s1, s2) -> s1)); |
| 405 | - .filter(Objects::nonNull) | ||
| 406 | - .filter(s -> s.getId() != 0) | ||
| 407 | - .collect(Collectors.toMap(SingleDishSkuByIdsRpcResponse::getId, s -> s, (s1, s2) -> s1)); | ||
| 408 | 818 | ||
| 409 | // 获取餐别数据 | 819 | // 获取餐别数据 |
| 410 | final var mealResponse = mealServiceRpcClient.getAllMeals(enterpriseId); | 820 | final var mealResponse = mealServiceRpcClient.getAllMeals(enterpriseId); |
| 411 | final List<SingleMealRpcResponse> meals = mealResponse != null ? mealResponse.getResponsesList() : new ArrayList<>(); | 821 | final List<SingleMealRpcResponse> meals = mealResponse != null ? mealResponse.getResponsesList() : new ArrayList<>(); |
| 412 | - final var mealMap = meals.stream() | 822 | + final var mealMap = meals.stream().collect(Collectors.toMap(SingleMealRpcResponse::getId, m -> m, (m1, m2) -> m1)); |
| 413 | - .filter(Objects::nonNull) | ||
| 414 | - .filter(m -> m.getId() != 0) | ||
| 415 | - .collect(Collectors.toMap(SingleMealRpcResponse::getId, m -> m, (m1, m2) -> m1)); | ||
| 416 | 823 | ||
| 417 | // 获取菜单数据 | 824 | // 获取菜单数据 |
| 418 | - List<Integer> menuIds = orderList.stream() | 825 | + List<Integer> menuIds = orderList.stream().map(SingleClientCustomerOrderRpcResponse::getMenuId).distinct().collect(Collectors.toList()); |
| 419 | - .filter(Objects::nonNull) | ||
| 420 | - .map(SingleClientCustomerOrderRpcResponse::getMenuId) | ||
| 421 | - .filter(id -> id != 0) | ||
| 422 | - .distinct() | ||
| 423 | - .collect(Collectors.toList()); | ||
| 424 | - | ||
| 425 | final var menuResponse = menuServiceRpcClient.getMenusByIds(enterpriseId, menuIds); | 826 | final var menuResponse = menuServiceRpcClient.getMenusByIds(enterpriseId, menuIds); |
| 426 | final List<SingleMenuRpcResponse> menuList = menuResponse != null ? menuResponse.getResponsesList() : new ArrayList<>(); | 827 | final List<SingleMenuRpcResponse> menuList = menuResponse != null ? menuResponse.getResponsesList() : new ArrayList<>(); |
| 427 | - final var menuMap = menuList.stream() | 828 | + final var menuMap = menuList.stream().collect(Collectors.toMap(SingleMenuRpcResponse::getId, m -> m, (m1, m2) -> m1)); |
| 428 | - .filter(Objects::nonNull) | ||
| 429 | - .filter(m -> m.getId() != 0) | ||
| 430 | - .collect(Collectors.toMap(SingleMenuRpcResponse::getId, m -> m, (m1, m2) -> m1)); | ||
| 431 | 829 | ||
| 432 | // 获取菜单详情数据 | 830 | // 获取菜单详情数据 |
| 433 | final var menuDetailResponse = menuServiceRpcClient.queryMenuDetailsByMenuIds(enterpriseId, menuIds); | 831 | final var menuDetailResponse = menuServiceRpcClient.queryMenuDetailsByMenuIds(enterpriseId, menuIds); |
| 434 | - final List<SingleMenuDetailRpcResponse> menuDetailList = menuDetailResponse != null ? menuDetailResponse.getResponsesList() : new ArrayList<>(); | 832 | + final List<SingleMenuDetailRpcResponse> menuDetailList = menuDetailResponse.getResponsesList(); |
| 435 | - final var menuDetailMap = menuDetailList.stream() | 833 | + final var menuDetailMap = menuDetailList.stream().collect(Collectors.toMap(SingleMenuDetailRpcResponse::getId, m -> m, (m1, m2) -> m1)); |
| 436 | - .filter(Objects::nonNull) | ||
| 437 | - .filter(m -> m.getId() != 0) | ||
| 438 | - .collect(Collectors.toMap(SingleMenuDetailRpcResponse::getId, m -> m, (m1, m2) -> m1)); | ||
| 439 | 834 | ||
| 440 | // 获取客户数据 | 835 | // 获取客户数据 |
| 441 | - List<Integer> customerIds = orderList.stream() | 836 | + List<Integer> customerIds = orderList.stream().map(SingleClientCustomerOrderRpcResponse::getCustomerId).distinct().collect(Collectors.toList()); |
| 442 | - .filter(Objects::nonNull) | ||
| 443 | - .map(SingleClientCustomerOrderRpcResponse::getCustomerId) | ||
| 444 | - .filter(id -> id != 0) | ||
| 445 | - .distinct() | ||
| 446 | - .collect(Collectors.toList()); | ||
| 447 | - | ||
| 448 | final var customerResponse = clientCustomerServiceRpcClient.getClientCustomersByIds(enterpriseId, customerIds); | 837 | final var customerResponse = clientCustomerServiceRpcClient.getClientCustomersByIds(enterpriseId, customerIds); |
| 449 | - final List<SingleClientCustomerRpcResponse> customers = customerResponse != null ? customerResponse.getResponsesList() : new ArrayList<>(); | 838 | + final List<SingleClientCustomerRpcResponse> customers = customerResponse.getResponsesList(); |
| 450 | - final var customerMap = customers.stream() | 839 | + final var customerMap = customers.stream().collect(Collectors.toMap(SingleClientCustomerRpcResponse::getId, c -> c, (c1, c2) -> c1)); |
| 451 | - .filter(Objects::nonNull) | ||
| 452 | - .filter(c -> c.getId() != 0) | ||
| 453 | - .collect(Collectors.toMap(SingleClientCustomerRpcResponse::getId, c -> c, (c1, c2) -> c1)); | ||
| 454 | 840 | ||
| 455 | // 构建结算订单明细 | 841 | // 构建结算订单明细 |
| 456 | final var classifyOrders = new ArrayList<SettlementDTO.SettlementOrderDetail>(); | 842 | final var classifyOrders = new ArrayList<SettlementDTO.SettlementOrderDetail>(); |
| 457 | for (Integer orderId : orderIds) { | 843 | for (Integer orderId : orderIds) { |
| 458 | final var orderDetails = orderDetailGroupByOrderId.getOrDefault(orderId, Collections.emptyList()); | 844 | final var orderDetails = orderDetailGroupByOrderId.getOrDefault(orderId, Collections.emptyList()); |
| 459 | final var order = orderMap.get(orderId); | 845 | final var order = orderMap.get(orderId); |
| 460 | - | ||
| 461 | - // 订单为空则跳过 | ||
| 462 | if (order == null) { | 846 | if (order == null) { |
| 463 | - log.warn("订单不存在,orderId: {}", orderId); | ||
| 464 | continue; | 847 | continue; |
| 465 | } | 848 | } |
| 466 | - | ||
| 467 | // 获取菜单信息 | 849 | // 获取菜单信息 |
| 468 | final var menu = menuMap.get(order.getMenuId()); | 850 | final var menu = menuMap.get(order.getMenuId()); |
| 469 | final String menuName = menu != null ? menu.getName() : ""; | 851 | final String menuName = menu != null ? menu.getName() : ""; |
| ... | @@ -473,52 +855,76 @@ public class SettlementServiceImpl implements SettlementService { | ... | @@ -473,52 +855,76 @@ public class SettlementServiceImpl implements SettlementService { |
| 473 | final String customerName = customer != null ? customer.getName() : ""; | 855 | final String customerName = customer != null ? customer.getName() : ""; |
| 474 | final String hisCustomerNo = customer != null ? customer.getHISCustomerNo() : ""; | 856 | final String hisCustomerNo = customer != null ? customer.getHISCustomerNo() : ""; |
| 475 | 857 | ||
| 476 | - // 处理每个订单详情 | 858 | + final var orderOperationRecords = orderOperationRecordByOrderId.getOrDefault(orderId, Collections.emptyList()); |
| 477 | - for (SingleClientCustomerOrderDetailRpcResponse orderDetail : orderDetails) { | ||
| 478 | - if (orderDetail == null) { | ||
| 479 | - continue; | ||
| 480 | - } | ||
| 481 | 859 | ||
| 482 | - // 安全获取餐别名称 | 860 | + Map<Integer, OrderDetailBO> addOriginalDetailMap = orderOperationRecords.stream() |
| 483 | - String mealName = getMealNameSafely(orderDetail, menuDetailMap, mealMap); | 861 | + .filter(e -> e.getType() == OrderOperationType.ADD_DISHES) |
| 862 | + .flatMap(e -> JsonUtil.readJsonAs(e.getOriginalOrderDetailJson(), new TypeReference<List<OrderDetailBO>>() { | ||
| 863 | + }).stream()) | ||
| 864 | + .collect(Collectors.toMap(OrderDetailBO::getId, Function.identity(), (a, b) -> a)); | ||
| 484 | 865 | ||
| 485 | - // 安全获取SKU名称 | 866 | + Map<Integer, OrderDetailBO> replaceOriginalDetailMap = orderOperationRecords.stream() |
| 486 | - String skuName = getSkuNameSafely(orderDetail, skuMap); | 867 | + .filter(e -> e.getType() == OrderOperationType.REPLACE_DISHES) |
| 868 | + .flatMap(e -> JsonUtil.readJsonAs(e.getOriginalOrderDetailJson(), new TypeReference<List<OrderDetailBO>>() { | ||
| 869 | + }).stream()) | ||
| 870 | + .collect(Collectors.toMap(OrderDetailBO::getId, Function.identity(), (a, b) -> a)); | ||
| 487 | 871 | ||
| 488 | - // 安全获取房间号 | 872 | + Map<Integer, OrderDetailBO> replaceAdjustDetailMap = orderOperationRecords.stream() |
| 489 | - String roomNo = getRoomNoSafely(order); | 873 | + .filter(e -> e.getType() == OrderOperationType.REPLACE_DISHES) |
| 874 | + .flatMap(e -> JsonUtil.readJsonAs(e.getAdjustOrderDetailJson(), new TypeReference<List<OrderDetailBO>>() { | ||
| 875 | + }).stream()) | ||
| 876 | + .collect(Collectors.toMap(OrderDetailBO::getId, Function.identity(), (a, b) -> a)); | ||
| 490 | 877 | ||
| 491 | - // 安全获取忌口和医嘱 | 878 | + for (SingleClientCustomerOrderDetailRpcResponse orderDetail : orderDetails) { |
| 492 | - List<String> avoids = getAvoidsSafely(order); | 879 | + // 1. 先处理加餐 |
| 493 | - List<String> doctors = getDoctorsSafely(order); | 880 | + if (addOriginalDetailMap.containsKey(orderDetail.getId()) |
| 881 | + && addOriginalDetailMap.get(orderDetail.getId()).getCount() != orderDetail.getCount()) { | ||
| 882 | + final var orderDetailBO = addOriginalDetailMap.get(orderDetail.getId()); | ||
| 883 | + SettlementDTO.SettlementOrderDetail beforeChange = buildSettlementOrderDetail( | ||
| 884 | + order, orderDetail.getMenuDetailId(), orderDetailBO.getSkuId(), orderDetailBO.getCount(), orderDetail.getPrice(), "订餐", menuName, customerName, hisCustomerNo, menuDetailMap, mealMap, skuMap); | ||
| 885 | + classifyOrders.add(beforeChange); | ||
| 886 | + SettlementDTO.SettlementOrderDetail afterChange = buildSettlementOrderDetail( | ||
| 887 | + order, orderDetail.getMenuDetailId(), orderDetailBO.getSkuId(), orderDetail.getCount() - orderDetailBO.getCount(), orderDetail.getPrice(), "加餐", menuName, customerName, hisCustomerNo, menuDetailMap, mealMap, skuMap); | ||
| 888 | + classifyOrders.add(afterChange); | ||
| 889 | + } | ||
| 494 | 890 | ||
| 495 | - // 安全获取在线支付描述 | 891 | + // 2. 再处理换菜 |
| 496 | - String onlinePayDesc = getOnlinePayDescSafely(order); | 892 | + if (replaceOriginalDetailMap.containsKey(orderDetail.getId()) |
| 893 | + && !Objects.equals(replaceOriginalDetailMap.get(orderDetail.getId()).getSkuId(), orderDetail.getSkuId())) { | ||
| 894 | + final var orderDetailBO = replaceOriginalDetailMap.get(orderDetail.getId()); | ||
| 895 | + final var orderDetailAdjustBO = replaceAdjustDetailMap.get(orderDetail.getId()); | ||
| 896 | + SettlementDTO.SettlementOrderDetail beforeChange = buildSettlementOrderDetail( | ||
| 897 | + order, orderDetail.getMenuDetailId(), orderDetailBO.getSkuId(), orderDetailBO.getCount(), orderDetailBO.getPrice(), "换菜前", menuName, customerName, hisCustomerNo, menuDetailMap, mealMap, skuMap); | ||
| 898 | + classifyOrders.add(beforeChange); | ||
| 899 | + SettlementDTO.SettlementOrderDetail afterChange = buildSettlementOrderDetail( | ||
| 900 | + order, orderDetail.getMenuDetailId(), orderDetail.getSkuId(), orderDetail.getCount(), orderDetailAdjustBO.getPrice(), "换菜后", menuName, customerName, hisCustomerNo, menuDetailMap, mealMap, skuMap); | ||
| 901 | + classifyOrders.add(afterChange); | ||
| 902 | + } | ||
| 497 | 903 | ||
| 498 | - // 构建订单详情 | 904 | + // 3. 判断已退款 |
| 499 | - order.getOrderCode(); | 905 | + if (orderDetail.getServeStatus() == ServeStatusEnum.SERVE_REJECT) { |
| 500 | - order.getRemark(); | 906 | + SettlementDTO.SettlementOrderDetail refundRecord1 = buildSettlementOrderDetail( |
| 501 | - order.getAvoidRemark(); | 907 | + order, orderDetail.getMenuDetailId(), orderDetail.getSkuId(), orderDetail.getCount(), orderDetail.getPrice(), "订餐", menuName, customerName, hisCustomerNo, menuDetailMap, mealMap, skuMap); |
| 502 | - SettlementDTO.SettlementOrderDetail settlementOrderDetail = SettlementDTO.SettlementOrderDetail.builder() | 908 | + classifyOrders.add(refundRecord1); |
| 503 | - .mealTime(order.getMealTime() != 0L ? LocalDateTimeUtil.of(order.getMealTime()).format(DateUtil.YYYY_MM_DD_LEFT_SYMBOL) : "") | 909 | + SettlementDTO.SettlementOrderDetail refundRecord2 = buildSettlementOrderDetail( |
| 504 | - .code(order.getOrderCode()) | 910 | + order, orderDetail.getMenuDetailId(), orderDetail.getSkuId(), -orderDetail.getCount(), orderDetail.getPrice(), "已退款", menuName, customerName, hisCustomerNo, menuDetailMap, mealMap, skuMap); |
| 505 | - .mealName(mealName) | 911 | + classifyOrders.add(refundRecord2); |
| 506 | - .roomNo(roomNo) | 912 | + } |
| 507 | - .customerName(customerName) | 913 | + |
| 508 | - .HISCustomerNo(hisCustomerNo) | 914 | + // 4. 如果既不是加餐,也不是换菜,也不是退款,才记录“订餐” |
| 509 | - .avoids(avoids) | 915 | + boolean isNormal = !(addOriginalDetailMap.containsKey(orderDetail.getId()) |
| 510 | - .doctors(doctors) | 916 | + && addOriginalDetailMap.get(orderDetail.getId()).getCount() != orderDetail.getCount()) |
| 511 | - .menuName(menuName) | 917 | + && !(replaceOriginalDetailMap.containsKey(orderDetail.getId()) |
| 512 | - .skuName(skuName) | 918 | + && !Objects.equals(replaceOriginalDetailMap.get(orderDetail.getId()).getSkuId(), orderDetail.getSkuId())) |
| 513 | - .count(orderDetail.getCount() != 0 ? orderDetail.getCount() : 0) | 919 | + && orderDetail.getServeStatus() != ServeStatusEnum.SERVE_REJECT; |
| 514 | - .price(calculatePrice(orderDetail.getPrice())) | 920 | + |
| 515 | - .totalPrice(calculateTotalPrice(orderDetail.getPrice(), orderDetail.getCount())) | 921 | + if (isNormal) { |
| 516 | - .remark(order.getRemark()) | 922 | + SettlementDTO.SettlementOrderDetail normalRecord = buildSettlementOrderDetail( |
| 517 | - .avoidRemark(order.getAvoidRemark()) | 923 | + order, orderDetail.getMenuDetailId(), orderDetail.getSkuId(), orderDetail.getCount(), orderDetail.getPrice(), "订餐", menuName, customerName, hisCustomerNo, menuDetailMap, mealMap, skuMap); |
| 518 | - .onlinePay(onlinePayDesc) | 924 | + classifyOrders.add(normalRecord); |
| 519 | - .build(); | 925 | + } |
| 520 | - classifyOrders.add(settlementOrderDetail); | ||
| 521 | } | 926 | } |
| 927 | + | ||
| 522 | } | 928 | } |
| 523 | 929 | ||
| 524 | // 构建结算数据 | 930 | // 构建结算数据 |
| ... | @@ -535,17 +941,57 @@ public class SettlementServiceImpl implements SettlementService { | ... | @@ -535,17 +941,57 @@ public class SettlementServiceImpl implements SettlementService { |
| 535 | } | 941 | } |
| 536 | } | 942 | } |
| 537 | 943 | ||
| 944 | + private SettlementDTO.SettlementOrderDetail buildSettlementOrderDetail(SingleClientCustomerOrderRpcResponse order, | ||
| 945 | + int menuDetailId, | ||
| 946 | + int skuId, | ||
| 947 | + int count, | ||
| 948 | + Integer price, | ||
| 949 | + String operationType, | ||
| 950 | + String menuName, | ||
| 951 | + String customerName, | ||
| 952 | + String hisCustomerNo, | ||
| 953 | + Map<Integer, SingleMenuDetailRpcResponse> menuDetailMap, | ||
| 954 | + Map<Integer, SingleMealRpcResponse> mealMap, | ||
| 955 | + Map<Integer, SingleDishSkuByIdsRpcResponse> skuMap) { | ||
| 956 | + String mealName = getMealNameSafely(menuDetailId, menuDetailMap, mealMap); | ||
| 957 | + String skuName = getSkuNameSafely(skuId, skuMap); | ||
| 958 | + String roomNo = getRoomNoSafely(order); | ||
| 959 | + List<String> avoids = getAvoidsSafely(order); | ||
| 960 | + List<String> doctors = getDoctorsSafely(order); | ||
| 961 | + String onlinePayDesc = getOnlinePayDescSafely(order); | ||
| 962 | + return SettlementDTO.SettlementOrderDetail.builder() | ||
| 963 | + .mealTime(order.getMealTime() != 0L ? LocalDateTimeUtil.of(order.getMealTime()).format(DateUtil.YYYY_MM_DD_LEFT_SYMBOL) : "") | ||
| 964 | + .code(order.getOrderCode()) | ||
| 965 | + .mealName(mealName) | ||
| 966 | + .roomNo(roomNo) | ||
| 967 | + .customerName(customerName) | ||
| 968 | + .HISCustomerNo(hisCustomerNo) | ||
| 969 | + .avoids(avoids) | ||
| 970 | + .doctors(doctors) | ||
| 971 | + .menuName(menuName) | ||
| 972 | + .skuName(skuName) | ||
| 973 | + .count(count) | ||
| 974 | + .price(calculatePrice(price)) | ||
| 975 | + .totalPrice(calculateTotalPrice(price, count)) | ||
| 976 | + .remark(order.getRemark()) | ||
| 977 | + .avoidRemark(order.getAvoidRemark()) | ||
| 978 | + .onlinePay(onlinePayDesc) | ||
| 979 | + .operationType(operationType) | ||
| 980 | + .transactionId(operationType.equals("已退款") ? "" : order.getTransactionId()) | ||
| 981 | + .build(); | ||
| 982 | + } | ||
| 983 | + | ||
| 538 | /** | 984 | /** |
| 539 | * 安全获取餐别名称 | 985 | * 安全获取餐别名称 |
| 540 | */ | 986 | */ |
| 541 | - private String getMealNameSafely(SingleClientCustomerOrderDetailRpcResponse orderDetail, | 987 | + private String getMealNameSafely(int menuDetailId, |
| 542 | - Map<Integer, SingleMenuDetailRpcResponse> menuDetailMap, | 988 | + Map<Integer, SingleMenuDetailRpcResponse> menuDetailMap, |
| 543 | - Map<Integer, SingleMealRpcResponse> mealMap) { | 989 | + Map<Integer, SingleMealRpcResponse> mealMap) { |
| 544 | - if (orderDetail == null || orderDetail.getMenuDetailId() == 0) { | 990 | + if (menuDetailId == 0) { |
| 545 | return ""; | 991 | return ""; |
| 546 | } | 992 | } |
| 547 | 993 | ||
| 548 | - final var menuDetail = menuDetailMap.get(orderDetail.getMenuDetailId()); | 994 | + final var menuDetail = menuDetailMap.get(menuDetailId); |
| 549 | if (menuDetail == null || menuDetail.getMealId() == 0) { | 995 | if (menuDetail == null || menuDetail.getMealId() == 0) { |
| 550 | return ""; | 996 | return ""; |
| 551 | } | 997 | } |
| ... | @@ -557,13 +1003,12 @@ public class SettlementServiceImpl implements SettlementService { | ... | @@ -557,13 +1003,12 @@ public class SettlementServiceImpl implements SettlementService { |
| 557 | /** | 1003 | /** |
| 558 | * 安全获取SKU名称 | 1004 | * 安全获取SKU名称 |
| 559 | */ | 1005 | */ |
| 560 | - private String getSkuNameSafely(SingleClientCustomerOrderDetailRpcResponse orderDetail, | 1006 | + private String getSkuNameSafely(int skuId, |
| 561 | - Map<Integer, SingleDishSkuByIdsRpcResponse> skuMap) { | 1007 | + Map<Integer, SingleDishSkuByIdsRpcResponse> skuMap) { |
| 562 | - if (orderDetail == null || orderDetail.getSkuId() == 0) { | 1008 | + if (skuId == 0) { |
| 563 | return ""; | 1009 | return ""; |
| 564 | } | 1010 | } |
| 565 | - | 1011 | + final var sku = skuMap.get(skuId); |
| 566 | - final var sku = skuMap.get(orderDetail.getSkuId()); | ||
| 567 | return sku != null ? sku.getName() : ""; | 1012 | return sku != null ? sku.getName() : ""; |
| 568 | } | 1013 | } |
| 569 | 1014 | ||
| ... | @@ -598,268 +1043,65 @@ public class SettlementServiceImpl implements SettlementService { | ... | @@ -598,268 +1043,65 @@ public class SettlementServiceImpl implements SettlementService { |
| 598 | * 安全获取医嘱列表 | 1043 | * 安全获取医嘱列表 |
| 599 | */ | 1044 | */ |
| 600 | private List<String> getDoctorsSafely(SingleClientCustomerOrderRpcResponse order) { | 1045 | private List<String> getDoctorsSafely(SingleClientCustomerOrderRpcResponse order) { |
| 601 | - if (order == null) { | 1046 | + if (order == null) { |
| 602 | - return Collections.emptyList(); | 1047 | + return Collections.emptyList(); |
| 603 | - } | 1048 | + } |
| 604 | - | ||
| 605 | - return order.getCustomerNoticeJson().getDoctorsList(); | ||
| 606 | - } | ||
| 607 | - | ||
| 608 | - /** | ||
| 609 | - * 安全获取在线支付描述 | ||
| 610 | - */ | ||
| 611 | - private String getOnlinePayDescSafely(SingleClientCustomerOrderRpcResponse order) { | ||
| 612 | - if (order == null) { | ||
| 613 | - return ""; | ||
| 614 | - } | ||
| 615 | - | ||
| 616 | - try { | ||
| 617 | - String desc = BaseProtoDescEnum.getDescByProtoEnum(order.getOnlinePay(), OnlinePayDescEnum.class); | ||
| 618 | - return desc != null ? desc : ""; | ||
| 619 | - } catch (Exception e) { | ||
| 620 | - log.warn("获取在线支付描述失败,orderId: {}", order.getId(), e); | ||
| 621 | - return ""; | ||
| 622 | - } | ||
| 623 | - } | ||
| 624 | - | ||
| 625 | - /** | ||
| 626 | - * 计算单价 | ||
| 627 | - */ | ||
| 628 | - private BigDecimal calculatePrice(Integer price) { | ||
| 629 | - if (price == null) { | ||
| 630 | - return BigDecimal.ZERO; | ||
| 631 | - } | ||
| 632 | - return new BigDecimal(price).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP); | ||
| 633 | - } | ||
| 634 | - | ||
| 635 | - /** | ||
| 636 | - * 计算总价 | ||
| 637 | - */ | ||
| 638 | - private BigDecimal calculateTotalPrice(Integer price, Integer count) { | ||
| 639 | - if (price == null || count == null) { | ||
| 640 | - return BigDecimal.ZERO; | ||
| 641 | - } | ||
| 642 | - return new BigDecimal(price) | ||
| 643 | - .multiply(new BigDecimal(count)) | ||
| 644 | - .divide(new BigDecimal(100), 2, RoundingMode.HALF_UP); | ||
| 645 | - } | ||
| 646 | - | ||
| 647 | - /** | ||
| 648 | - * 创建空的订单Excel | ||
| 649 | - */ | ||
| 650 | - private ByteArrayOutputStream createEmptyExcelByOrder() { | ||
| 651 | - try { | ||
| 652 | - final var emptyData = SettlementDTO.SettlementDataByOrderDto.builder() | ||
| 653 | - .classifyOrders(Collections.emptyList()) | ||
| 654 | - .build(); | ||
| 655 | - return writeToExcelByOrder(emptyData); | ||
| 656 | - } catch (IOException e) { | ||
| 657 | - log.error("创建空Excel失败", e); | ||
| 658 | - throw BusinessException.build(ErrorCodeEnum.GENERATE_EXCEL_ERROR); | ||
| 659 | - } | ||
| 660 | - } | ||
| 661 | - | ||
| 662 | - /** | ||
| 663 | - * 按订单维度生成Excel | ||
| 664 | - */ | ||
| 665 | - private static ByteArrayOutputStream writeToExcelByOrder(SettlementDTO.SettlementDataByOrderDto settlementDataDto) | ||
| 666 | - throws IOException { | ||
| 667 | - Workbook workbook = new XSSFWorkbook(); | ||
| 668 | - Sheet sheet = workbook.createSheet("客人结算"); | ||
| 669 | - | ||
| 670 | - // 创建表头样式(黑色边框) | ||
| 671 | - CellStyle headerStyle = workbook.createCellStyle(); | ||
| 672 | - headerStyle.setBorderTop(BorderStyle.THIN); | ||
| 673 | - headerStyle.setBorderBottom(BorderStyle.THIN); | ||
| 674 | - headerStyle.setBorderLeft(BorderStyle.THIN); | ||
| 675 | - headerStyle.setBorderRight(BorderStyle.THIN); | ||
| 676 | - headerStyle.setTopBorderColor(IndexedColors.BLACK.getIndex()); | ||
| 677 | - headerStyle.setBottomBorderColor(IndexedColors.BLACK.getIndex()); | ||
| 678 | - headerStyle.setLeftBorderColor(IndexedColors.BLACK.getIndex()); | ||
| 679 | - headerStyle.setRightBorderColor(IndexedColors.BLACK.getIndex()); | ||
| 680 | - | ||
| 681 | - // 创建数据行样式(浅灰色边框) | ||
| 682 | - CellStyle dataStyle = workbook.createCellStyle(); | ||
| 683 | - dataStyle.setBorderTop(BorderStyle.THIN); | ||
| 684 | - dataStyle.setBorderBottom(BorderStyle.THIN); | ||
| 685 | - dataStyle.setBorderLeft(BorderStyle.THIN); | ||
| 686 | - dataStyle.setBorderRight(BorderStyle.THIN); | ||
| 687 | - dataStyle.setTopBorderColor(IndexedColors.GREY_25_PERCENT.getIndex()); | ||
| 688 | - dataStyle.setBottomBorderColor(IndexedColors.GREY_25_PERCENT.getIndex()); | ||
| 689 | - dataStyle.setLeftBorderColor(IndexedColors.GREY_25_PERCENT.getIndex()); | ||
| 690 | - dataStyle.setRightBorderColor(IndexedColors.GREY_25_PERCENT.getIndex()); | ||
| 691 | - | ||
| 692 | - int rowNum = 0; | ||
| 693 | - | ||
| 694 | - // 创建表头 | ||
| 695 | - Row titleRow = sheet.createRow(rowNum++); | ||
| 696 | - int columnNum = 0; | ||
| 697 | - | ||
| 698 | - Cell cell0 = titleRow.createCell(columnNum++); | ||
| 699 | - cell0.setCellValue("用餐时间"); | ||
| 700 | - cell0.setCellStyle(headerStyle); | ||
| 701 | - | ||
| 702 | - Cell cell1 = titleRow.createCell(columnNum++); | ||
| 703 | - cell1.setCellValue("订单号"); | ||
| 704 | - cell1.setCellStyle(headerStyle); | ||
| 705 | - | ||
| 706 | - Cell cell2 = titleRow.createCell(columnNum++); | ||
| 707 | - cell2.setCellValue("餐别"); | ||
| 708 | - cell2.setCellStyle(headerStyle); | ||
| 709 | - | ||
| 710 | - Cell cell3 = titleRow.createCell(columnNum++); | ||
| 711 | - cell3.setCellValue("房间号"); | ||
| 712 | - cell3.setCellStyle(headerStyle); | ||
| 713 | - | ||
| 714 | - Cell cell4 = titleRow.createCell(columnNum++); | ||
| 715 | - cell4.setCellValue("客户姓名"); | ||
| 716 | - cell4.setCellStyle(headerStyle); | ||
| 717 | - | ||
| 718 | - Cell cell5 = titleRow.createCell(columnNum++); | ||
| 719 | - cell5.setCellValue("客户腕带号"); | ||
| 720 | - cell5.setCellStyle(headerStyle); | ||
| 721 | - | ||
| 722 | - Cell cell6 = titleRow.createCell(columnNum++); | ||
| 723 | - cell6.setCellValue("忌口信息"); | ||
| 724 | - cell6.setCellStyle(headerStyle); | ||
| 725 | - | ||
| 726 | - Cell cell7 = titleRow.createCell(columnNum++); | ||
| 727 | - cell7.setCellValue("医嘱信息"); | ||
| 728 | - cell7.setCellStyle(headerStyle); | ||
| 729 | - | ||
| 730 | - Cell cell8 = titleRow.createCell(columnNum++); | ||
| 731 | - cell8.setCellValue("餐单名称"); | ||
| 732 | - cell8.setCellStyle(headerStyle); | ||
| 733 | - | ||
| 734 | - Cell cell9 = titleRow.createCell(columnNum++); | ||
| 735 | - cell9.setCellValue("菜品名称"); | ||
| 736 | - cell9.setCellStyle(headerStyle); | ||
| 737 | - | ||
| 738 | - Cell cell10 = titleRow.createCell(columnNum++); | ||
| 739 | - cell10.setCellValue("菜品份数"); | ||
| 740 | - cell10.setCellStyle(headerStyle); | ||
| 741 | - | ||
| 742 | - Cell cell11 = titleRow.createCell(columnNum++); | ||
| 743 | - cell11.setCellValue("菜品单价"); | ||
| 744 | - cell11.setCellStyle(headerStyle); | ||
| 745 | - | ||
| 746 | - Cell cell12 = titleRow.createCell(columnNum++); | ||
| 747 | - cell12.setCellValue("菜品金额"); | ||
| 748 | - cell12.setCellStyle(headerStyle); | ||
| 749 | - | ||
| 750 | - Cell cell13 = titleRow.createCell(columnNum++); | ||
| 751 | - cell13.setCellValue("备注"); | ||
| 752 | - cell13.setCellStyle(headerStyle); | ||
| 753 | - | ||
| 754 | - Cell cell14 = titleRow.createCell(columnNum++); | ||
| 755 | - cell14.setCellValue("支付方式"); | ||
| 756 | - cell14.setCellStyle(headerStyle); | ||
| 757 | - | ||
| 758 | - // 填充数据 | ||
| 759 | - final var classifyOrders = settlementDataDto.getClassifyOrders(); | ||
| 760 | - if (classifyOrders != null) { | ||
| 761 | - for (SettlementDTO.SettlementOrderDetail orderDetail : classifyOrders) { | ||
| 762 | - Row dataRow = sheet.createRow(rowNum++); | ||
| 763 | - columnNum = 0; | ||
| 764 | - | ||
| 765 | - Cell dataCell0 = dataRow.createCell(columnNum++); | ||
| 766 | - dataCell0.setCellValue(orderDetail.getMealTime() != null ? orderDetail.getMealTime() : ""); | ||
| 767 | - dataCell0.setCellStyle(dataStyle); | ||
| 768 | - | ||
| 769 | - Cell dataCell1 = dataRow.createCell(columnNum++); | ||
| 770 | - dataCell1.setCellValue(orderDetail.getCode() != null ? orderDetail.getCode() : ""); | ||
| 771 | - dataCell1.setCellStyle(dataStyle); | ||
| 772 | - | ||
| 773 | - Cell dataCell2 = dataRow.createCell(columnNum++); | ||
| 774 | - dataCell2.setCellValue(orderDetail.getMealName() != null ? orderDetail.getMealName() : ""); | ||
| 775 | - dataCell2.setCellStyle(dataStyle); | ||
| 776 | - | ||
| 777 | - Cell dataCell3 = dataRow.createCell(columnNum++); | ||
| 778 | - dataCell3.setCellValue(orderDetail.getRoomNo() != null ? orderDetail.getRoomNo() : ""); | ||
| 779 | - dataCell3.setCellStyle(dataStyle); | ||
| 780 | - | ||
| 781 | - Cell dataCell4 = dataRow.createCell(columnNum++); | ||
| 782 | - dataCell4.setCellValue(orderDetail.getCustomerName() != null ? orderDetail.getCustomerName() : ""); | ||
| 783 | - dataCell4.setCellStyle(dataStyle); | ||
| 784 | - | ||
| 785 | - Cell dataCell5 = dataRow.createCell(columnNum++); | ||
| 786 | - dataCell5.setCellValue(orderDetail.getHISCustomerNo() != null ? orderDetail.getHISCustomerNo() : ""); | ||
| 787 | - dataCell5.setCellStyle(dataStyle); | ||
| 788 | - | ||
| 789 | - // 忌口列表转字符串 | ||
| 790 | - String avoidsStr = orderDetail.getAvoids() != null ? String.join(", ", orderDetail.getAvoids()) : ""; | ||
| 791 | - Cell dataCell6 = dataRow.createCell(columnNum++); | ||
| 792 | - dataCell6.setCellValue(avoidsStr); | ||
| 793 | - dataCell6.setCellStyle(dataStyle); | ||
| 794 | - | ||
| 795 | - // 医嘱列表转字符串 | ||
| 796 | - String doctorsStr = orderDetail.getDoctors() != null ? String.join(", ", orderDetail.getDoctors()) : ""; | ||
| 797 | - Cell dataCell7 = dataRow.createCell(columnNum++); | ||
| 798 | - dataCell7.setCellValue(doctorsStr); | ||
| 799 | - dataCell7.setCellStyle(dataStyle); | ||
| 800 | - | ||
| 801 | - Cell dataCell8 = dataRow.createCell(columnNum++); | ||
| 802 | - dataCell8.setCellValue(orderDetail.getMenuName() != null ? orderDetail.getMenuName() : ""); | ||
| 803 | - dataCell8.setCellStyle(dataStyle); | ||
| 804 | - | ||
| 805 | - Cell dataCell9 = dataRow.createCell(columnNum++); | ||
| 806 | - dataCell9.setCellValue(orderDetail.getSkuName() != null ? orderDetail.getSkuName() : ""); | ||
| 807 | - dataCell9.setCellStyle(dataStyle); | ||
| 808 | - | ||
| 809 | - Cell dataCell10 = dataRow.createCell(columnNum++); | ||
| 810 | - dataCell10.setCellValue(orderDetail.getCount() != null ? orderDetail.getCount() : 0); | ||
| 811 | - dataCell10.setCellStyle(dataStyle); | ||
| 812 | - | ||
| 813 | - // 价格 | ||
| 814 | - Cell dataCell11 = dataRow.createCell(columnNum++); | ||
| 815 | - if (orderDetail.getPrice() != null) { | ||
| 816 | - dataCell11.setCellValue(orderDetail.getPrice().doubleValue()); | ||
| 817 | - } else { | ||
| 818 | - dataCell11.setCellValue(0.0); | ||
| 819 | - } | ||
| 820 | - dataCell11.setCellStyle(dataStyle); | ||
| 821 | - | ||
| 822 | - // 总价 | ||
| 823 | - Cell dataCell12 = dataRow.createCell(columnNum++); | ||
| 824 | - if (orderDetail.getTotalPrice() != null) { | ||
| 825 | - dataCell12.setCellValue(orderDetail.getTotalPrice().doubleValue()); | ||
| 826 | - } else { | ||
| 827 | - dataCell12.setCellValue(0.0); | ||
| 828 | - } | ||
| 829 | - dataCell12.setCellStyle(dataStyle); | ||
| 830 | 1049 | ||
| 831 | - // 合并备注和忌口备注,用分号分割,备注在前 | 1050 | + return order.getCustomerNoticeJson().getDoctorsList(); |
| 832 | - String remark = orderDetail.getRemark() != null ? orderDetail.getRemark() : ""; | 1051 | + } |
| 833 | - String avoidRemark = orderDetail.getAvoidRemark() != null ? orderDetail.getAvoidRemark() : ""; | ||
| 834 | - String combinedRemark = ""; | ||
| 835 | - if (!remark.isEmpty() && !avoidRemark.isEmpty()) { | ||
| 836 | - combinedRemark = remark + ";" + avoidRemark; | ||
| 837 | - } else if (!remark.isEmpty()) { | ||
| 838 | - combinedRemark = remark; | ||
| 839 | - } else if (!avoidRemark.isEmpty()) { | ||
| 840 | - combinedRemark = avoidRemark; | ||
| 841 | - } | ||
| 842 | - Cell dataCell13 = dataRow.createCell(columnNum++); | ||
| 843 | - dataCell13.setCellValue(combinedRemark); | ||
| 844 | - dataCell13.setCellStyle(dataStyle); | ||
| 845 | 1052 | ||
| 846 | - Cell dataCell14 = dataRow.createCell(columnNum++); | 1053 | + /** |
| 847 | - dataCell14.setCellValue(orderDetail.getOnlinePay() != null ? orderDetail.getOnlinePay() : ""); | 1054 | + * 安全获取在线支付描述 |
| 848 | - dataCell14.setCellStyle(dataStyle); | 1055 | + */ |
| 849 | - } | 1056 | + private String getOnlinePayDescSafely(SingleClientCustomerOrderRpcResponse order) { |
| 1057 | + if (order == null) { | ||
| 1058 | + return ""; | ||
| 850 | } | 1059 | } |
| 851 | 1060 | ||
| 852 | - // 自动调整列宽 | 1061 | + try { |
| 853 | - for (int i = 0; i < 15; i++) { | 1062 | + String desc = BaseProtoDescEnum.getDescByProtoEnum(order.getOnlinePay(), OnlinePayDescEnum.class); |
| 854 | - sheet.autoSizeColumn(i); | 1063 | + return desc != null ? desc : ""; |
| 1064 | + } catch (Exception e) { | ||
| 1065 | + log.warn("获取在线支付描述失败,orderId: {}", order.getId(), e); | ||
| 1066 | + return ""; | ||
| 855 | } | 1067 | } |
| 1068 | + } | ||
| 856 | 1069 | ||
| 857 | - // 将工作簿内容写入字节数组输出流 | 1070 | + /** |
| 858 | - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); | 1071 | + * 计算单价 |
| 859 | - workbook.write(outputStream); | 1072 | + */ |
| 860 | - workbook.close(); | 1073 | + private BigDecimal calculatePrice(Integer price) { |
| 1074 | + if (price == null) { | ||
| 1075 | + return BigDecimal.ZERO; | ||
| 1076 | + } | ||
| 1077 | + return new BigDecimal(price).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP); | ||
| 1078 | + } | ||
| 861 | 1079 | ||
| 862 | - return outputStream; | 1080 | + /** |
| 1081 | + * 计算总价 | ||
| 1082 | + */ | ||
| 1083 | + private BigDecimal calculateTotalPrice(Integer price, Integer count) { | ||
| 1084 | + if (price == null || count == null) { | ||
| 1085 | + return BigDecimal.ZERO; | ||
| 1086 | + } | ||
| 1087 | + return new BigDecimal(price) | ||
| 1088 | + .multiply(new BigDecimal(count)) | ||
| 1089 | + .divide(new BigDecimal(100), 2, RoundingMode.HALF_UP); | ||
| 1090 | + } | ||
| 1091 | + | ||
| 1092 | + /** | ||
| 1093 | + * 创建空的订单Excel | ||
| 1094 | + */ | ||
| 1095 | + private ByteArrayOutputStream createEmptyExcelByOrder() { | ||
| 1096 | + try { | ||
| 1097 | + final var emptyData = SettlementDTO.SettlementDataByOrderDto.builder() | ||
| 1098 | + .classifyOrders(Collections.emptyList()) | ||
| 1099 | + .build(); | ||
| 1100 | + return writeToExcelByOrder(emptyData); | ||
| 1101 | + } catch (IOException e) { | ||
| 1102 | + log.error("创建空Excel失败", e); | ||
| 1103 | + throw BusinessException.build(ErrorCodeEnum.GENERATE_EXCEL_ERROR); | ||
| 1104 | + } | ||
| 863 | } | 1105 | } |
| 864 | 1106 | ||
| 865 | public ByteArrayOutputStream generateOrderSettlementExcelBySku(SettlementRequestDto settlementRequest) { | 1107 | public ByteArrayOutputStream generateOrderSettlementExcelBySku(SettlementRequestDto settlementRequest) { |
| ... | @@ -1249,10 +1491,10 @@ public class SettlementServiceImpl implements SettlementService { | ... | @@ -1249,10 +1491,10 @@ public class SettlementServiceImpl implements SettlementService { |
| 1249 | } | 1491 | } |
| 1250 | 1492 | ||
| 1251 | // 安全获取餐别名称 | 1493 | // 安全获取餐别名称 |
| 1252 | - String mealName = getMealNameSafely(orderDetail, menuDetailMap, mealMap); | 1494 | + String mealName = getMealNameSafely(orderDetail.getMenuDetailId(), menuDetailMap, mealMap); |
| 1253 | 1495 | ||
| 1254 | // 安全获取SKU名称 | 1496 | // 安全获取SKU名称 |
| 1255 | - String skuName = getSkuNameSafely(orderDetail, skuMap); | 1497 | + String skuName = getSkuNameSafely(orderDetail.getSkuId(), skuMap); |
| 1256 | 1498 | ||
| 1257 | // 安全获取忌口信息(列表转字符串) | 1499 | // 安全获取忌口信息(列表转字符串) |
| 1258 | List<String> avoidsList = getAvoidsSafely(order); | 1500 | List<String> avoidsList = getAvoidsSafely(order); |
| ... | @@ -1304,186 +1546,4 @@ public class SettlementServiceImpl implements SettlementService { | ... | @@ -1304,186 +1546,4 @@ public class SettlementServiceImpl implements SettlementService { |
| 1304 | } | 1546 | } |
| 1305 | } | 1547 | } |
| 1306 | 1548 | ||
| 1307 | - /** | ||
| 1308 | - * 生成分餐表Excel | ||
| 1309 | - */ | ||
| 1310 | - private static ByteArrayOutputStream writeToExcelBySeparateMeal(SeparateMealDataDto separateMealDataDto) | ||
| 1311 | - throws IOException { | ||
| 1312 | - Workbook workbook = new XSSFWorkbook(); | ||
| 1313 | - Sheet sheet = workbook.createSheet("分餐表"); | ||
| 1314 | - | ||
| 1315 | - // 创建标题样式(合并单元格标题) | ||
| 1316 | - CellStyle titleStyle = workbook.createCellStyle(); | ||
| 1317 | - titleStyle.setAlignment(HorizontalAlignment.CENTER); | ||
| 1318 | - titleStyle.setVerticalAlignment(VerticalAlignment.CENTER); | ||
| 1319 | - titleStyle.setBorderTop(BorderStyle.THIN); | ||
| 1320 | - titleStyle.setBorderBottom(BorderStyle.THIN); | ||
| 1321 | - titleStyle.setBorderLeft(BorderStyle.THIN); | ||
| 1322 | - titleStyle.setBorderRight(BorderStyle.THIN); | ||
| 1323 | - titleStyle.setTopBorderColor(IndexedColors.BLACK.getIndex()); | ||
| 1324 | - titleStyle.setBottomBorderColor(IndexedColors.BLACK.getIndex()); | ||
| 1325 | - titleStyle.setLeftBorderColor(IndexedColors.BLACK.getIndex()); | ||
| 1326 | - titleStyle.setRightBorderColor(IndexedColors.BLACK.getIndex()); | ||
| 1327 | - Font titleFont = workbook.createFont(); | ||
| 1328 | - titleFont.setBold(true); | ||
| 1329 | - titleFont.setFontHeightInPoints((short) 16); | ||
| 1330 | - titleStyle.setFont(titleFont); | ||
| 1331 | - | ||
| 1332 | - // 创建表头样式(黑色边框) | ||
| 1333 | - CellStyle headerStyle = workbook.createCellStyle(); | ||
| 1334 | - headerStyle.setBorderTop(BorderStyle.THIN); | ||
| 1335 | - headerStyle.setBorderBottom(BorderStyle.THIN); | ||
| 1336 | - headerStyle.setBorderLeft(BorderStyle.THIN); | ||
| 1337 | - headerStyle.setBorderRight(BorderStyle.THIN); | ||
| 1338 | - headerStyle.setTopBorderColor(IndexedColors.BLACK.getIndex()); | ||
| 1339 | - headerStyle.setBottomBorderColor(IndexedColors.BLACK.getIndex()); | ||
| 1340 | - headerStyle.setLeftBorderColor(IndexedColors.BLACK.getIndex()); | ||
| 1341 | - headerStyle.setRightBorderColor(IndexedColors.BLACK.getIndex()); | ||
| 1342 | - | ||
| 1343 | - // 创建数据行样式(浅灰色边框) | ||
| 1344 | - CellStyle dataStyle = workbook.createCellStyle(); | ||
| 1345 | - dataStyle.setBorderTop(BorderStyle.THIN); | ||
| 1346 | - dataStyle.setBorderBottom(BorderStyle.THIN); | ||
| 1347 | - dataStyle.setBorderLeft(BorderStyle.THIN); | ||
| 1348 | - dataStyle.setBorderRight(BorderStyle.THIN); | ||
| 1349 | - dataStyle.setTopBorderColor(IndexedColors.GREY_25_PERCENT.getIndex()); | ||
| 1350 | - dataStyle.setBottomBorderColor(IndexedColors.GREY_25_PERCENT.getIndex()); | ||
| 1351 | - dataStyle.setLeftBorderColor(IndexedColors.GREY_25_PERCENT.getIndex()); | ||
| 1352 | - dataStyle.setRightBorderColor(IndexedColors.GREY_25_PERCENT.getIndex()); | ||
| 1353 | - | ||
| 1354 | - int rowNum = 0; | ||
| 1355 | - | ||
| 1356 | - // 第一行:创建合并单元格标题 | ||
| 1357 | - Row mainTitleRow = sheet.createRow(rowNum++); | ||
| 1358 | - Cell mainTitleCell = mainTitleRow.createCell(0); | ||
| 1359 | - mainTitleCell.setCellValue("住院客户分餐表"); | ||
| 1360 | - mainTitleCell.setCellStyle(titleStyle); | ||
| 1361 | - | ||
| 1362 | - // 合并第一行的8列 | ||
| 1363 | - CellRangeAddress titleRegion = new CellRangeAddress(0, 0, 0, 8); | ||
| 1364 | - sheet.addMergedRegion(titleRegion); | ||
| 1365 | - | ||
| 1366 | - // 为合并区域设置边框 | ||
| 1367 | - RegionUtil.setBorderTop(BorderStyle.THIN, titleRegion, sheet); | ||
| 1368 | - RegionUtil.setBorderBottom(BorderStyle.THIN, titleRegion, sheet); | ||
| 1369 | - RegionUtil.setBorderLeft(BorderStyle.THIN, titleRegion, sheet); | ||
| 1370 | - RegionUtil.setBorderRight(BorderStyle.THIN, titleRegion, sheet); | ||
| 1371 | - RegionUtil.setTopBorderColor(IndexedColors.BLACK.getIndex(), titleRegion, sheet); | ||
| 1372 | - RegionUtil.setBottomBorderColor(IndexedColors.BLACK.getIndex(), titleRegion, sheet); | ||
| 1373 | - RegionUtil.setLeftBorderColor(IndexedColors.BLACK.getIndex(), titleRegion, sheet); | ||
| 1374 | - RegionUtil.setRightBorderColor(IndexedColors.BLACK.getIndex(), titleRegion, sheet); | ||
| 1375 | - | ||
| 1376 | - // 第二行:创建表头 | ||
| 1377 | - Row titleRow = sheet.createRow(rowNum++); | ||
| 1378 | - int columnNum = 0; | ||
| 1379 | - | ||
| 1380 | - Cell cell0 = titleRow.createCell(columnNum++); | ||
| 1381 | - cell0.setCellValue("餐别"); | ||
| 1382 | - cell0.setCellStyle(headerStyle); | ||
| 1383 | - | ||
| 1384 | - Cell cell1 = titleRow.createCell(columnNum++); | ||
| 1385 | - cell1.setCellValue("房间号"); | ||
| 1386 | - cell1.setCellStyle(headerStyle); | ||
| 1387 | - | ||
| 1388 | - Cell cell2 = titleRow.createCell(columnNum++); | ||
| 1389 | - cell2.setCellValue("客户姓名"); | ||
| 1390 | - cell2.setCellStyle(headerStyle); | ||
| 1391 | - | ||
| 1392 | - Cell cell3 = titleRow.createCell(columnNum++); | ||
| 1393 | - cell3.setCellValue("医嘱信息"); | ||
| 1394 | - cell3.setCellStyle(headerStyle); | ||
| 1395 | - | ||
| 1396 | - Cell cell4 = titleRow.createCell(columnNum++); | ||
| 1397 | - cell4.setCellValue("餐单名称"); | ||
| 1398 | - cell4.setCellStyle(headerStyle); | ||
| 1399 | - | ||
| 1400 | - Cell cell5 = titleRow.createCell(columnNum++); | ||
| 1401 | - cell5.setCellValue("菜品名称"); | ||
| 1402 | - cell5.setCellStyle(headerStyle); | ||
| 1403 | - | ||
| 1404 | - Cell cell6 = titleRow.createCell(columnNum++); | ||
| 1405 | - cell6.setCellValue("菜品数量"); | ||
| 1406 | - cell6.setCellStyle(headerStyle); | ||
| 1407 | - | ||
| 1408 | - Cell cell7 = titleRow.createCell(columnNum++); | ||
| 1409 | - cell7.setCellValue("忌口信息"); | ||
| 1410 | - cell7.setCellStyle(headerStyle); | ||
| 1411 | - | ||
| 1412 | - Cell cell8 = titleRow.createCell(columnNum++); | ||
| 1413 | - cell8.setCellValue("备注"); | ||
| 1414 | - cell8.setCellStyle(headerStyle); | ||
| 1415 | - | ||
| 1416 | - // 填充数据 | ||
| 1417 | - final var mealDetails = separateMealDataDto.getMealDetails(); | ||
| 1418 | - if (mealDetails != null) { | ||
| 1419 | - for (SeparateMealDetail mealDetail : mealDetails) { | ||
| 1420 | - Row dataRow = sheet.createRow(rowNum++); | ||
| 1421 | - columnNum = 0; | ||
| 1422 | - | ||
| 1423 | - Cell dataCell0 = dataRow.createCell(columnNum++); | ||
| 1424 | - dataCell0.setCellValue(mealDetail.getMealName() != null ? mealDetail.getMealName() : ""); | ||
| 1425 | - dataCell0.setCellStyle(dataStyle); | ||
| 1426 | - | ||
| 1427 | - Cell dataCell1 = dataRow.createCell(columnNum++); | ||
| 1428 | - dataCell1.setCellValue(mealDetail.getRoomNo() != null ? mealDetail.getRoomNo() : ""); | ||
| 1429 | - dataCell1.setCellStyle(dataStyle); | ||
| 1430 | - | ||
| 1431 | - Cell dataCell2 = dataRow.createCell(columnNum++); | ||
| 1432 | - dataCell2.setCellValue(mealDetail.getCustomerName() != null ? mealDetail.getCustomerName() : ""); | ||
| 1433 | - dataCell2.setCellStyle(dataStyle); | ||
| 1434 | - | ||
| 1435 | - Cell dataCell3 = dataRow.createCell(columnNum++); | ||
| 1436 | - dataCell3.setCellValue(mealDetail.getDoctors() != null ? mealDetail.getDoctors() : ""); | ||
| 1437 | - dataCell3.setCellStyle(dataStyle); | ||
| 1438 | - | ||
| 1439 | - Cell dataCell4 = dataRow.createCell(columnNum++); | ||
| 1440 | - dataCell4.setCellValue(mealDetail.getMenuName() != null ? mealDetail.getMenuName() : ""); | ||
| 1441 | - dataCell4.setCellStyle(dataStyle); | ||
| 1442 | - | ||
| 1443 | - Cell dataCell5 = dataRow.createCell(columnNum++); | ||
| 1444 | - dataCell5.setCellValue(mealDetail.getSkuName() != null ? mealDetail.getSkuName() : ""); | ||
| 1445 | - dataCell5.setCellStyle(dataStyle); | ||
| 1446 | - | ||
| 1447 | - Cell dataCell6 = dataRow.createCell(columnNum++); | ||
| 1448 | - dataCell6.setCellValue(mealDetail.getCount() != null ? mealDetail.getCount() : 0); | ||
| 1449 | - dataCell6.setCellStyle(dataStyle); | ||
| 1450 | - | ||
| 1451 | - Cell dataCell7 = dataRow.createCell(columnNum++); | ||
| 1452 | - dataCell7.setCellValue(mealDetail.getAvoids() != null ? mealDetail.getAvoids() : ""); | ||
| 1453 | - dataCell7.setCellStyle(dataStyle); | ||
| 1454 | - | ||
| 1455 | - Cell dataCell8 = dataRow.createCell(columnNum++); | ||
| 1456 | - dataCell8.setCellValue(mealDetail.getRemark() != null ? mealDetail.getRemark() : ""); | ||
| 1457 | - dataCell8.setCellStyle(dataStyle); | ||
| 1458 | - } | ||
| 1459 | - } | ||
| 1460 | - | ||
| 1461 | - // 自动调整列宽 | ||
| 1462 | - for (int i = 0; i < 9; i++) { | ||
| 1463 | - sheet.autoSizeColumn(i); | ||
| 1464 | - } | ||
| 1465 | - | ||
| 1466 | - // 将工作簿内容写入字节数组输出流 | ||
| 1467 | - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); | ||
| 1468 | - workbook.write(outputStream); | ||
| 1469 | - workbook.close(); | ||
| 1470 | - | ||
| 1471 | - return outputStream; | ||
| 1472 | - } | ||
| 1473 | - | ||
| 1474 | - /** | ||
| 1475 | - * 创建空的分餐表Excel(无数据) | ||
| 1476 | - */ | ||
| 1477 | - private static ByteArrayOutputStream createEmptyExcelBySeparateMeal() { | ||
| 1478 | - try { | ||
| 1479 | - SeparateMealDataDto emptyData = SeparateMealDataDto.builder() | ||
| 1480 | - .mealDetails(new ArrayList<>()) | ||
| 1481 | - .build(); | ||
| 1482 | - return writeToExcelBySeparateMeal(emptyData); | ||
| 1483 | - } catch (IOException e) { | ||
| 1484 | - log.error("创建空分餐表Excel失败", e); | ||
| 1485 | - throw BusinessException.build(ErrorCodeEnum.GENERATE_EXCEL_ERROR); | ||
| 1486 | - } | ||
| 1487 | - } | ||
| 1488 | - | ||
| 1489 | } | 1549 | } | ... | ... |
| ... | @@ -2,6 +2,7 @@ package com.infoloop.tianting.utils; | ... | @@ -2,6 +2,7 @@ package com.infoloop.tianting.utils; |
| 2 | 2 | ||
| 3 | import com.fasterxml.jackson.annotation.JsonInclude; | 3 | import com.fasterxml.jackson.annotation.JsonInclude; |
| 4 | import com.fasterxml.jackson.core.JsonProcessingException; | 4 | import com.fasterxml.jackson.core.JsonProcessingException; |
| 5 | +import com.fasterxml.jackson.core.type.TypeReference; | ||
| 5 | import com.fasterxml.jackson.databind.DeserializationFeature; | 6 | import com.fasterxml.jackson.databind.DeserializationFeature; |
| 6 | import com.fasterxml.jackson.databind.JsonNode; | 7 | import com.fasterxml.jackson.databind.JsonNode; |
| 7 | import com.fasterxml.jackson.databind.ObjectMapper; | 8 | import com.fasterxml.jackson.databind.ObjectMapper; |
| ... | @@ -41,6 +42,14 @@ public class JsonUtil { | ... | @@ -41,6 +42,14 @@ public class JsonUtil { |
| 41 | } | 42 | } |
| 42 | } | 43 | } |
| 43 | 44 | ||
| 45 | + public static <T> T readJsonAs(final String json, final TypeReference<T> typeRef) { | ||
| 46 | + try { | ||
| 47 | + return OBJECT_MAPPER.readValue(json, typeRef); | ||
| 48 | + } catch (IOException e) { | ||
| 49 | + throw new RuntimeException(e); | ||
| 50 | + } | ||
| 51 | + } | ||
| 52 | + | ||
| 44 | public static <T> T convertValue(final Object object, final Class<T> clazz) { | 53 | public static <T> T convertValue(final Object object, final Class<T> clazz) { |
| 45 | return OBJECT_MAPPER.convertValue(object, clazz); | 54 | return OBJECT_MAPPER.convertValue(object, clazz); |
| 46 | } | 55 | } | ... | ... |
| ... | @@ -32,6 +32,7 @@ service ClientCustomerOrderServiceRpc { | ... | @@ -32,6 +32,7 @@ service ClientCustomerOrderServiceRpc { |
| 32 | 32 | ||
| 33 | // 操作记录 | 33 | // 操作记录 |
| 34 | rpc GetOrderOperationRecordsByOrderId (GetOrderOperationRecordsByOrderIdRequest) returns (GetOrderOperationRecordsByOrderIdResponse) {} | 34 | rpc GetOrderOperationRecordsByOrderId (GetOrderOperationRecordsByOrderIdRequest) returns (GetOrderOperationRecordsByOrderIdResponse) {} |
| 35 | + rpc GetOrderOperationRecordsByOrderIds (GetOrderOperationRecordsByOrderIdsRequest) returns (GetOrderOperationRecordsByOrderIdsResponse) {} | ||
| 35 | rpc BatchCreateOrderOperationRecords (BatchCreateOrderOperationRecordsRequest) returns (BatchCreateOrderOperationRecordsResponse) {} | 36 | rpc BatchCreateOrderOperationRecords (BatchCreateOrderOperationRecordsRequest) returns (BatchCreateOrderOperationRecordsResponse) {} |
| 36 | 37 | ||
| 37 | 38 | ||
| ... | @@ -624,6 +625,15 @@ message GetOrderOperationRecordsByOrderIdResponse { | ... | @@ -624,6 +625,15 @@ message GetOrderOperationRecordsByOrderIdResponse { |
| 624 | repeated OrderOperationRecord responses = 1; | 625 | repeated OrderOperationRecord responses = 1; |
| 625 | } | 626 | } |
| 626 | 627 | ||
| 628 | +message GetOrderOperationRecordsByOrderIdsRequest { | ||
| 629 | + int32 enterpriseId = 1; | ||
| 630 | + repeated int32 orderIds = 2; | ||
| 631 | +} | ||
| 632 | + | ||
| 633 | +message GetOrderOperationRecordsByOrderIdsResponse { | ||
| 634 | + repeated OrderOperationRecord responses = 1; | ||
| 635 | +} | ||
| 636 | + | ||
| 627 | message OrderOperationRecordCreation { | 637 | message OrderOperationRecordCreation { |
| 628 | int32 orderId = 1; | 638 | int32 orderId = 1; |
| 629 | OrderOperationType type = 2; | 639 | OrderOperationType type = 2; | ... | ... |
-
Please register or login to post a comment