SettlementServiceImpl.java 8.6 KB
package com.infoloop.tianting.service.impl;

import com.infoloop.tianting.clientcustomerorderservice.SingleClientCustomerOrderDetailRpcResponse;
import com.infoloop.tianting.clientcustomerorderservice.SingleClientCustomerOrderRpcResponse;
import com.infoloop.tianting.context.LoginContextHolder;
import com.infoloop.tianting.exception.ClientEndExceptions.BusinessException;
import com.infoloop.tianting.exception.ErrorCodeEnum;
import com.infoloop.tianting.menuservice.SingleMenuDetailRpcResponse;
import com.infoloop.tianting.menuservice.SingleMenuRpcResponse;
import com.infoloop.tianting.model.dto.OrderDbDTO.QueryOrderByConditionDto;
import com.infoloop.tianting.model.dto.SettlementDTO.SettlementMenuSkuDto;
import com.infoloop.tianting.model.dto.SettlementDTO.SettlementRequestDto;
import com.infoloop.tianting.service.OrderService;
import com.infoloop.tianting.service.SettlementService;
import com.infoloop.tianting.service.client.MenuServiceRpcClient;
import com.infoloop.tianting.service.client.OrderServiceRpcClient;
import com.infoloop.tianting.utils.DateUtil;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Slf4j
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class SettlementServiceImpl implements SettlementService {
  private final OrderServiceRpcClient orderServiceRpcClient;
  private final MenuServiceRpcClient menuServiceRpcClient;

  @Override
  public ByteArrayOutputStream generateOrderSettlementExcel(SettlementRequestDto settlementRequest) {

    final var operatorLoginInfo = LoginContextHolder.getLoginInfo();
    final var queryOrderDto = QueryOrderByConditionDto.builder()
        .enterpriseId(operatorLoginInfo.getEnterpriseId())
        .shouldFilterCreatedAtTimeStart(true)
        .createdAtTimeStart(settlementRequest.getTimeStart())
        .shouldFilterCreatedAtTimeEnd(true)
        .createdAtTimeEnd(settlementRequest.getTimeEnd())
        .build();
    final var orderList = orderServiceRpcClient.getOrdersByCondition(queryOrderDto);
    List<Integer> orderIds = orderList.stream().map(
        SingleClientCustomerOrderRpcResponse::getId).distinct()
        .collect(Collectors.toList());
    final var orderDetailList = orderServiceRpcClient.getOrderDetailsByOrderIds(orderIds);

    List<Integer> menuIds = orderList.stream().map(
        SingleClientCustomerOrderRpcResponse::getMenuId).distinct()
        .collect(Collectors.toList());
    final var menuList = menuServiceRpcClient.getMenusByIds(operatorLoginInfo.getEnterpriseId(), menuIds);
    final var menuDetailList = menuServiceRpcClient.queryMenuDetailsByMenuIds(
        operatorLoginInfo.getEnterpriseId(), menuIds).getResponsesList();
    Map<String, Map<Integer, List<SettlementMenuSkuDto>>> classifyOrders = new HashMap<>();

    //找出所有需要的日期
    final var dates = orderList.stream()
        .map(o -> DateUtil.formatDate(o.getCreatedAt(), DateUtil.YYYY_MM_DD))
        .collect(Collectors.toList());
    for(String date: dates) {

      if (!classifyOrders.containsKey(date)) {
        classifyOrders.put(date, new HashMap<>());
      }
      final var menusMap = classifyOrders.get(date);

      // 找出当天所有的订单
      final var curOrderList = orderList.stream()
          .filter(o -> DateUtil.formatDate(o.getCreatedAt(), DateUtil.YYYY_MM_DD).equals(date))
          .collect(Collectors.toList());
      final var curOrderIds = curOrderList.stream()
          .map(SingleClientCustomerOrderRpcResponse::getId)
          .collect(Collectors.toList());

      // 找出当天已点的所有餐单
      final var curMenuIds = curOrderList.stream()
          .map(SingleClientCustomerOrderRpcResponse::getMenuId)
          .collect(Collectors.toList());
      for (Integer curMenuId: curMenuIds) {
        if (!menusMap.containsKey(curMenuId)) {
          menusMap.put(curMenuId, new ArrayList<>());
        }
        final var menuSkuList = new ArrayList<SettlementMenuSkuDto>();
        // 找出当天餐单所有的菜品
        final var curMenuDetails = menuDetailList.stream()
            .filter(md -> md.getMenuId() == curMenuId)
            .collect(Collectors.toList());

        final var curMenuDetailIds = curMenuDetails.stream()
            .map(SingleMenuDetailRpcResponse::getId)
            .collect(Collectors.toList());

        //找出当天所有已点的菜品明细
        final var curOrderDetails = orderDetailList.stream()
            .filter(d -> curOrderIds.contains(d.getOrderId()))
            .collect(Collectors.toList());

        for (SingleMenuDetailRpcResponse m: curMenuDetails) {
          // 找出该餐单下该sku所点菜品的明细
          final var curSkuOrderDetails = curOrderDetails.stream()
              .filter(rd-> rd.getMenuDetailId() == m.getId())
              .collect(Collectors.toList());
          final var countList = curSkuOrderDetails.stream()
              .map(SingleClientCustomerOrderDetailRpcResponse::getCount)
              .collect(Collectors.toList());
          int countTotal = countList.stream().mapToInt(Integer::intValue).sum();
          final var settlementMenuSku = SettlementMenuSkuDto.builder()
              .count(countTotal)
              .showName(m.getShowName())
              .price(m.getPrice())
              .totalPrice(m.getPrice() * countTotal)
              .build();
          menuSkuList.add(settlementMenuSku);

        }
        menusMap.get(curMenuId).addAll(menuSkuList);


      }
    }

    try {
       final var bytes = writeToExcel(classifyOrders);
       return bytes;
    } catch (IOException e) {
      throw BusinessException.build(ErrorCodeEnum.GENERATE_EXCEL_ERROR);
    }

  }

  public static ByteArrayOutputStream writeToExcel(Map<String, Map<Integer, List<SettlementMenuSkuDto>>> classifyOrders)
      throws IOException {
    Workbook workbook = new XSSFWorkbook();
    Sheet sheet = workbook.createSheet("订单数据");

    int rowNum = 0;
    for (Map.Entry<String, Map<Integer, List<SettlementMenuSkuDto>>> outerEntry : classifyOrders.entrySet()) {
      String orderDate = outerEntry.getKey();
      Map<Integer, List<SettlementMenuSkuDto>> innerMap = outerEntry.getValue();

      // 写入日期列并合并单元格
      int startRowForDate = rowNum;
      for (int i = 0; i < innerMap.size() * 2; i++) {
        Row dateRow = sheet.createRow(rowNum++);
        Cell dateCell = dateRow.createCell(0);
        dateCell.setCellValue(orderDate);
      }
      int endRowForDate = rowNum - 1;
      if (endRowForDate >= startRowForDate) {
        CellRangeAddress region = new CellRangeAddress(startRowForDate, endRowForDate, 0, 0);
        sheet.addMergedRegion(region);
      }

      for (Map.Entry<Integer, List<SettlementMenuSkuDto>> innerEntry : innerMap.entrySet()) {
        int menuId = innerEntry.getKey();
        List<SettlementMenuSkuDto> skuList = innerEntry.getValue();

        // 写入菜单ID列并合并单元格
        int startRowForMenu = rowNum;
        for (int i = 0; i < skuList.size(); i++) {
          Row menuRow = sheet.createRow(rowNum++);
          Cell menuCell = menuRow.createCell(1);
          menuCell.setCellValue(menuId);
        }
        int endRowForMenu = rowNum - 1;
        if (endRowForMenu >= startRowForMenu) {
          CellRangeAddress region = new CellRangeAddress(startRowForMenu, endRowForMenu, 1, 1);
          sheet.addMergedRegion(region);
        }

        // 写入SKU列
        for (SettlementMenuSkuDto skuDto : skuList) {
          Row skuRow = sheet.createRow(rowNum++);
          Cell skuCell = skuRow.createCell(2);
          skuCell.setCellValue(skuDto.getShowName());
          skuCell.setCellValue(skuDto.getPrice());
          skuCell.setCellValue(skuDto.getCount());
          skuCell.setCellValue(skuDto.getTotalPrice());
        }
      }
    }

    // 自动调整列宽
    for (int i = 0; i < 6; i++) {
      sheet.autoSizeColumn(i);
    }

    // 将工作簿内容写入字节数组输出流
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    workbook.write(outputStream);
    workbook.close();

    return outputStream;
  }

}