diff --git a/eladmin-common/src/main/java/cn/ysk/cashier/utils/FileUtil.java b/eladmin-common/src/main/java/cn/ysk/cashier/utils/FileUtil.java index 0f2fcacc..74b22ffa 100644 --- a/eladmin-common/src/main/java/cn/ysk/cashier/utils/FileUtil.java +++ b/eladmin-common/src/main/java/cn/ysk/cashier/utils/FileUtil.java @@ -32,9 +32,11 @@ import java.io.*; import java.security.MessageDigest; import java.text.DecimalFormat; import java.text.SimpleDateFormat; +import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Map; +import java.util.concurrent.ConcurrentLinkedQueue; /** * File工具类,扩展 hutool 工具包 @@ -231,6 +233,36 @@ public class FileUtil extends cn.hutool.core.io.FileUtil { IoUtil.close(out); } + public static void downloadExcelAndMerge(ConcurrentLinkedQueue> list, int colSize, HttpServletResponse response, ArrayList mergeRowIndex) throws IOException { + String tempPath = SYS_TEM_DIR + IdUtil.fastSimpleUUID() + ".xlsx"; + File file = new File(tempPath); + BigExcelWriter writer = ExcelUtil.getBigWriter(file); + + // 合并单元格后的标题行,使用默认标题样式. + for (int i = 0; i < mergeRowIndex.size(); i++) { + for (int i1 = 0; i1 < colSize; i1++) { + writer.merge(i == 0 ? 0 : mergeRowIndex.get(i - 1) + 1, mergeRowIndex.get(i), i1, i1, "", true); + } + } + // 一次性写出内容,使用默认样式,强制输出标题 + writer.write(list, true); + SXSSFSheet sheet = (SXSSFSheet)writer.getSheet(); + //上面需要强转SXSSFSheet 不然没有trackAllColumnsForAutoSizing方法 + sheet.trackAllColumnsForAutoSizing(); + //列宽自适应 + writer.autoSizeColumnAll(); + //response为HttpServletResponse对象 + response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8"); + //test.xls是弹出下载对话框的文件名,不能为中文,中文请自行编码 + response.setHeader("Content-Disposition", "attachment;filename=file.xlsx"); + ServletOutputStream out = response.getOutputStream(); + // 终止后删除临时文件 + file.deleteOnExit(); + writer.flush(out, true); + //此处记得关闭输出Servlet流 + IoUtil.close(out); + } + public static String getFileType(String type) { String documents = "txt doc pdf ppt pps xlsx xls docx"; String music = "mp3 wav wma mpa ram ra aac aif m4a"; @@ -353,4 +385,6 @@ public class FileUtil extends cn.hutool.core.io.FileUtil { public static String getMd5(File file) { return getMd5(getByte(file)); } + + } diff --git a/eladmin-system/src/main/java/cn/ysk/cashier/repository/order/TbOrderDetailRepository.java b/eladmin-system/src/main/java/cn/ysk/cashier/repository/order/TbOrderDetailRepository.java index e8cdda21..6de46a4b 100644 --- a/eladmin-system/src/main/java/cn/ysk/cashier/repository/order/TbOrderDetailRepository.java +++ b/eladmin-system/src/main/java/cn/ysk/cashier/repository/order/TbOrderDetailRepository.java @@ -3,6 +3,7 @@ package cn.ysk.cashier.repository.order; import cn.ysk.cashier.dto.product.StockCountDTO; import cn.ysk.cashier.pojo.order.TbOrderDetail; import cn.ysk.cashier.vo.TbOrderPayCountVo; +import cn.ysk.cashier.vo.TbOrderSaleVO; import cn.ysk.cashier.vo.TbOrderSalesCountByDayVo; import org.apache.ibatis.annotations.Param; import org.springframework.data.domain.Page; @@ -77,6 +78,7 @@ public interface TbOrderDetailRepository extends JpaRepository findOrderIdsByProductNameLike(@Param("productName") String productName, @Param("shop_id") String shopId, @Param("startTime") Date startTime, @Param("endTime") Date endTime); + @Query(value = "SELECT\n" + + "od.num,\n" + + "od.price AS price,\n" + + "od.status, oi.orderNo \n" + + "FROM\n" + + "TbOrderInfo oi\n" + + "LEFT JOIN TbOrderDetail od ON oi.id = od.orderId \n" + + "WHERE\n" + + "od.shopId = :shopId \n" + + "AND ( od.status = 'closed' OR od.status = 'refund' ) \n" + + "AND oi.createdAt > :startTime \n" + + "AND oi.createdAt < :endTime \n" + + "AND od.productId = :productId\n" + + "AND od.productSkuId = :productSkuId") + List querySaleOrderInfo(Date startTime, Date endTime, Integer productId, Integer productSkuId, String shopId); } diff --git a/eladmin-system/src/main/java/cn/ysk/cashier/service/impl/SummaryServiceImpl.java b/eladmin-system/src/main/java/cn/ysk/cashier/service/impl/SummaryServiceImpl.java index a8bf5b37..6588408b 100644 --- a/eladmin-system/src/main/java/cn/ysk/cashier/service/impl/SummaryServiceImpl.java +++ b/eladmin-system/src/main/java/cn/ysk/cashier/service/impl/SummaryServiceImpl.java @@ -37,6 +37,7 @@ import java.time.Instant; import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.util.*; +import java.util.concurrent.ConcurrentLinkedQueue; @Service @RequiredArgsConstructor @@ -403,10 +404,13 @@ public class SummaryServiceImpl implements SummaryService { @Override public void download(ShopSummaryDto summaryDto, HttpServletResponse response) throws IOException { - List> list = new ArrayList<>(); +// List> list = new ArrayList<>(); + ConcurrentLinkedQueue> list = new ConcurrentLinkedQueue(); if(StringUtils.isBlank(summaryDto.getCateId())){ summaryDto.setCateId(null); } + + ArrayList mergeRowIndex = new ArrayList<>(); if (summaryDto.getType() != null && summaryDto.getType() == 1) {//金额 Long start = 1704038400000L; Long end = Instant.now().toEpochMilli(); @@ -430,23 +434,39 @@ public class SummaryServiceImpl implements SummaryService { summaryDto.setStartTime(DateUtil.toDate(DateUtil.fromTimeStamp(1704038400L))); summaryDto.setEndTime(new Date()); } - List tbOrderSalesCountByDayVos = detailRepository.queryTbOrderSalesCountByDay(Integer.valueOf(summaryDto.getShopId()),summaryDto.getCateId(),summaryDto.getProName(), summaryDto.getStartTime(), summaryDto.getEndTime()); - for (TbOrderSalesCountByDayVo all : tbOrderSalesCountByDayVos) { - Map map = new LinkedHashMap<>(); - map.put("商品分类", all.getCateName()); - map.put("商品名称", all.getProductName()); - map.put("单 位", all.getUnitName()); - map.put("商品规格", StringUtils.isBlank(all.getProductSkuName()) ? "" : all.getProductSkuName()); - map.put("销 售 额", all.getSalesAmount()); - map.put("销 量", all.getSalesNum()); - map.put("单 价", all.getPrice()); - map.put("退 单 量", all.getRefNum()); - map.put("退 单 额", all.getRefAmount().compareTo(BigDecimal.ZERO)==0?all.getRefAmount():"-"+all.getRefAmount()); - map.put("总 量", all.getNum()-all.getRefNum()); - list.add(map); - } + List tbOrderSalesCountByDayVos = detailRepository + .queryTbOrderSalesCountByDay(Integer.valueOf(summaryDto.getShopId()),summaryDto.getCateId(),summaryDto.getProName(), summaryDto.getStartTime(), summaryDto.getEndTime()); + tbOrderSalesCountByDayVos.stream().parallel().forEach(all -> { + List tbOrderSaleVOS = detailRepository.querySaleOrderInfo(summaryDto.getStartTime(), + summaryDto.getEndTime(), all.getProductId(), all.getProductSkuId(), summaryDto.getShopId()); + for (TbOrderSaleVO tbOrderSaleVO : tbOrderSaleVOS) { + Map map = new LinkedHashMap<>(); + map.put("商品分类", all.getCateName()); + map.put("商品名称", all.getProductName()); + map.put("单 位", all.getUnitName()); + map.put("商品规格", StringUtils.isBlank(all.getProductSkuName()) ? "" : all.getProductSkuName()); + map.put("销 售 额", all.getSalesAmount()); + map.put("销 量", all.getSalesNum()); + map.put("单 价", all.getPrice()); + map.put("退 单 量", all.getRefNum()); + map.put("退 单 额", all.getRefAmount().compareTo(BigDecimal.ZERO)==0?all.getRefAmount():"-"+all.getRefAmount()); + map.put("总 量", all.getNum()-all.getRefNum()); + map.put("订单编号", tbOrderSaleVO.getOrderNo()); + map.put("售出数量", tbOrderSaleVO.getNum()); + list.add(map); + } + if (!tbOrderSaleVOS.isEmpty()) { + if (mergeRowIndex.isEmpty()) { + mergeRowIndex.add(tbOrderSaleVOS.size()); + }else { + mergeRowIndex.add(mergeRowIndex.get(mergeRowIndex.size() - 1) + tbOrderSaleVOS.size()); + } + } + + }); + } - FileUtil.downloadExcel(list, response); + FileUtil.downloadExcelAndMerge(list, 12, response, mergeRowIndex); } @Override diff --git a/eladmin-system/src/main/java/cn/ysk/cashier/vo/TbOrderSalesCountByDayVo.java b/eladmin-system/src/main/java/cn/ysk/cashier/vo/TbOrderSalesCountByDayVo.java index f2644496..b48d86c7 100644 --- a/eladmin-system/src/main/java/cn/ysk/cashier/vo/TbOrderSalesCountByDayVo.java +++ b/eladmin-system/src/main/java/cn/ysk/cashier/vo/TbOrderSalesCountByDayVo.java @@ -14,6 +14,24 @@ public class TbOrderSalesCountByDayVo { private BigDecimal salesAmount; private BigDecimal refAmount; private Long num; + private Integer productId; + private Integer productSkuId; + + public Integer getProductId() { + return productId; + } + + public void setProductId(Integer productId) { + this.productId = productId; + } + + public Integer getProductSkuId() { + return productSkuId; + } + + public void setProductSkuId(Integer productSkuId) { + this.productSkuId = productSkuId; + } public String getProductName() { return productName;