Merge branch 'refs/heads/gyj' into dev

This commit is contained in:
GYJ
2024-10-31 09:34:11 +08:00
5 changed files with 210 additions and 199 deletions

View File

@@ -248,7 +248,18 @@ public class FileUtil extends cn.hutool.core.io.FileUtil {
Row row = sheet.createRow(i + 1); Row row = sheet.createRow(i + 1);
for (int j = 0; j < keyList.size(); j++) { for (int j = 0; j < keyList.size(); j++) {
Cell cell = row.createCell(j); Cell cell = row.createCell(j);
cell.setCellValue(map.get(keyList.get(j)) == null ? "" : map.get(keyList.get(j)).toString()); String value = map.get(keyList.get(j)) == null ? "" : map.get(keyList.get(j)).toString();
cell.setCellValue(value);
if (j == 11 && !"0".equals(value)) {
cell.setCellValue("-" + value);
setCellBackground(cell, IndexedColors.YELLOW, workbook);
}
if (j == 12 && !"0.00".equals(value)) {
cell.setCellValue("-" + value);
setCellBackground(cell, IndexedColors.YELLOW, workbook);
}
} }
} }
@@ -268,6 +279,13 @@ public class FileUtil extends cn.hutool.core.io.FileUtil {
} }
} }
private static void setCellBackground(Cell cell, IndexedColors color, Workbook workbook) {
CellStyle style = workbook.createCellStyle();
style.setFillForegroundColor(color.getIndex());
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
cell.setCellStyle(style);
}
/** /**
* 输入标题到excel * 输入标题到excel
* *

View File

@@ -1,6 +1,5 @@
package cn.ysk.cashier.controller.shop; package cn.ysk.cashier.controller.shop;
import cn.ysk.cashier.annotation.rest.AnonymousGetMapping;
import cn.ysk.cashier.annotation.rest.AnonymousPostMapping; import cn.ysk.cashier.annotation.rest.AnonymousPostMapping;
import cn.ysk.cashier.dto.BaseQueryDto; import cn.ysk.cashier.dto.BaseQueryDto;
import cn.ysk.cashier.dto.shop.ShopTableSaleInfoDto; import cn.ysk.cashier.dto.shop.ShopTableSaleInfoDto;

View File

@@ -1,18 +0,0 @@
package cn.ysk.cashier.dto.shop;
import lombok.Data;
import java.util.List;
import java.util.Map;
/**
* @author yijiegong
*/
@Data
public class ExportTableStsDataDto {
private String dateStr;
private List<Map<String, Object>> data;
private List<List<Integer>> mergeCells;
}

View File

@@ -1,8 +1,9 @@
package cn.ysk.cashier.service.impl; package cn.ysk.cashier.service.impl;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import cn.ysk.cashier.dto.ShopSummaryDto;
import cn.ysk.cashier.dto.BaseQueryDto; import cn.ysk.cashier.dto.BaseQueryDto;
import cn.ysk.cashier.dto.ShopSummaryDto;
import cn.ysk.cashier.dto.shop.ShopTableSaleInfoDto; import cn.ysk.cashier.dto.shop.ShopTableSaleInfoDto;
import cn.ysk.cashier.enums.PayTypeEnum; import cn.ysk.cashier.enums.PayTypeEnum;
import cn.ysk.cashier.exception.BadRequestException; import cn.ysk.cashier.exception.BadRequestException;
@@ -35,6 +36,7 @@ import java.time.Instant;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.*; import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@@ -179,7 +181,6 @@ public class SummaryServiceImpl implements SummaryService {
} }
@Override @Override
public Map<String, Object> productSaleDate(Integer shopId, Integer day, Integer page, Integer size) { public Map<String, Object> productSaleDate(Integer shopId, Integer day, Integer page, Integer size) {
Pageable pageable = PageRequest.of(page, size); Pageable pageable = PageRequest.of(page, size);
@@ -438,56 +439,119 @@ public class SummaryServiceImpl implements SummaryService {
@Override @Override
public void downloadTableSaleInfo(ShopTableSaleInfoDto shopTableSaleInfoDto, HttpServletResponse response) throws IOException { public void downloadTableSaleInfo(ShopTableSaleInfoDto shopTableSaleInfoDto, HttpServletResponse response) throws IOException {
if (shopTableSaleInfoDto.getStartTime() == null) { if (shopTableSaleInfoDto.getStartTime() == null) {
shopTableSaleInfoDto.setStartTime(DateUtil.toDate(DateUtil.fromTimeStamp(1704038400L))); // 设置开始时间为30天前
shopTableSaleInfoDto.setStartTime(cn.hutool.core.date.DateUtil.offsetDay(new Date(), -30));
} }
if (shopTableSaleInfoDto.getEndTime() == null) { if (shopTableSaleInfoDto.getEndTime() == null) {
shopTableSaleInfoDto.setEndTime(new Date()); shopTableSaleInfoDto.setEndTime(new Date());
} }
List<ShopTableSaleInfoVo> infoVos = selectSummaryTable(shopTableSaleInfoDto.getShopId(), shopTableSaleInfoDto.getStartTime(), shopTableSaleInfoDto.getEndTime()); // 计算开始时间和结束时间相差天数
long diff = shopTableSaleInfoDto.getEndTime().getTime() - shopTableSaleInfoDto.getStartTime().getTime();
infoVos.add(new ShopTableSaleInfoVo(99999, shopTableSaleInfoDto.getShopId(), null, "", "收银台", null, null, null, null)); long day = diff / (1000 * 60 * 60 * 24) + 1;
if (day > 31) {
List<TbOrderSalesCountByTable> countByTables = tbOrderDetailRepository.queryTbOrderSalesCountByTable(shopTableSaleInfoDto.getShopId(), shopTableSaleInfoDto.getStartTime(), shopTableSaleInfoDto.getEndTime()); throw new BadRequestException("时间范围不能超过31天");
Map<String, List<TbOrderSalesCountByTable>> countByTableMap = countByTables.stream()
.collect(Collectors.groupingBy(TbOrderSalesCountByTable::getTableId));
// 比较 shopTableSaleInfoDto 的 startTime 和 endTime 是不是同一天
boolean sameDay = cn.hutool.core.date.DateUtil.isSameDay(shopTableSaleInfoDto.getStartTime(), shopTableSaleInfoDto.getEndTime());
String queryDate = cn.hutool.core.date.DateUtil.format(shopTableSaleInfoDto.getStartTime(), "yyyy-MM-dd");
if (!sameDay) {
queryDate += "" + cn.hutool.core.date.DateUtil.format(shopTableSaleInfoDto.getEndTime(), "yyyy-MM-dd");
} }
List<Map<String, Object>> list = new ArrayList<>(); ThreadGroup threadGroup = new ThreadGroup("MyThreadGroup");
CountDownLatch countDownLatch = new CountDownLatch((int) day);
Map<String, List<ShopTableSaleInfoVo>> infoVoMap = new HashMap<>();
Map<String, List<TbOrderSalesCountByTable>> countByTableMap = new HashMap<>();
Set<String> tableCodeSet = new HashSet<>();
for (int i = 0; i < day; i++) {
DateTime date = cn.hutool.core.date.DateUtil.offsetDay(shopTableSaleInfoDto.getStartTime(), i);
Thread thread = new Thread(threadGroup, () -> {
try {
String dateKey = cn.hutool.core.date.DateUtil.format(date, "yyyy-MM-dd");
DateTime start = cn.hutool.core.date.DateUtil.beginOfDay(date);
DateTime end = cn.hutool.core.date.DateUtil.endOfDay(date);
List<ShopTableSaleInfoVo> infoVos = selectSummaryTable(shopTableSaleInfoDto.getShopId(),
start, end);
infoVos.add(new ShopTableSaleInfoVo(99999, shopTableSaleInfoDto.getShopId(), null, "", "收银台", null, null, null, null));
infoVoMap.put(dateKey, infoVos);
List<TbOrderSalesCountByTable> countByTables = tbOrderDetailRepository.queryTbOrderSalesCountByTable(
shopTableSaleInfoDto.getShopId(),
start, end);
Map<String, List<TbOrderSalesCountByTable>> ctMap = countByTables.stream()
.collect(Collectors.groupingBy(TbOrderSalesCountByTable::getTableId));
ctMap.forEach((k, v) -> {
countByTableMap.put(dateKey + "-" + k, v);
});
for (ShopTableSaleInfoVo infoVo : infoVos) {
tableCodeSet.add(infoVo.getTableCode());
}
countDownLatch.countDown();
} catch (Exception e) {
e.printStackTrace();
}
});
thread.start();
}
// 等待所有线程完成
try {
countDownLatch.await();
System.out.println("所有线程执行完成");
} catch (InterruptedException e) {
e.printStackTrace();
}
List<Map<String, Object>> finalDataList = new ArrayList<>();
List<List<Integer>> mergeList = new ArrayList<>(); List<List<Integer>> mergeList = new ArrayList<>();
Map<String, Integer> tableStartIndexMap = new HashMap<>();
// 桌子 --- list【天--- list【商品】】
Map<String, Map<String, List<Map<String, Object>>>> dataList = new HashMap<>();
int rowIndex = 1; int rowIndex = 1;
for (ShopTableSaleInfoVo all : infoVos) { // 用于记录每个日期首次出现的行索引
List<TbOrderSalesCountByTable> tables = countByTableMap.get(all.getTableCode()); Map<String, Integer> dateFirstRowIndex = new HashMap<>();
if (tables == null) { for (String tableCode : tableCodeSet) {
Map<String, List<Map<String, Object>>> dayMap = new HashMap<>();
BigDecimal totalAmount = BigDecimal.ZERO;
List<Map<String, Object>> totalList = new ArrayList<>();
for (int i = 0; i < day; i++) {
DateTime date = cn.hutool.core.date.DateUtil.offsetDay(shopTableSaleInfoDto.getStartTime(), i);
String queryDate = cn.hutool.core.date.DateUtil.format(date, "yyyy-MM-dd");
List<Map<String, Object>> maps = dayMap.computeIfAbsent(queryDate, k -> new ArrayList<>());
List<ShopTableSaleInfoVo> infoVos = infoVoMap.get(queryDate);
if (infoVos == null) {
continue;
}
for (ShopTableSaleInfoVo infoVo : infoVos) {
String valueKey = queryDate + "-" + infoVo.getTableCode();
List<TbOrderSalesCountByTable> countByTables = countByTableMap.get(valueKey);
if (countByTables == null) {
continue;
}
if (!tableCode.equals(infoVo.getTableCode())) {
continue; continue;
} }
BigDecimal total = BigDecimal.ZERO; BigDecimal total = BigDecimal.ZERO;
for (TbOrderSalesCountByTable table : tables) { for (TbOrderSalesCountByTable table : countByTables) {
total = total.add(table.getSalesAmount().abs()); total = total.add(table.getSalesAmount().abs());
} }
String tableCode = all.getTableName().toString(); totalAmount = totalAmount.add(total);
if (!tableStartIndexMap.containsKey(tableCode)) {
tableStartIndexMap.put(tableCode, rowIndex);
}
for (TbOrderSalesCountByTable table : tables) { String dateRowKey = queryDate + tableCode;
for (TbOrderSalesCountByTable table : countByTables) {
Map<String, Object> map = new LinkedHashMap<>(); Map<String, Object> map = new LinkedHashMap<>();
map.put("台桌", infoVo.getTableName());
map.put("日期", queryDate); map.put("日期", queryDate);
map.put("台桌", all.getTableName());
map.put("商品分类", table.getCateName()); map.put("商品分类", table.getCateName());
map.put("商品名称", table.getProductName()); map.put("商品名称", table.getProductName());
map.put("单位", table.getUnitName()); map.put("单位", table.getUnitName());
@@ -498,22 +562,47 @@ public class SummaryServiceImpl implements SummaryService {
map.put("销售额", total); map.put("销售额", total);
map.put("退单量", table.getRefNum()); map.put("退单量", table.getRefNum());
map.put("退单额", table.getRefAmount()); map.put("退单额", table.getRefAmount());
list.add(map); maps.add(map);
rowIndex++; totalList.add(map);
finalDataList.add(map);
// 记录每个日期首次出现的行索引
if (!dateFirstRowIndex.containsKey(dateRowKey)) {
dateFirstRowIndex.put(dateRowKey, finalDataList.size());
}
} }
int start = tableStartIndexMap.get(tableCode); // 确定日期列的合并区域范围
int end = rowIndex - 1; if (dateFirstRowIndex.containsKey(dateRowKey)) {
if (end - start > 0) { int startRow = dateFirstRowIndex.get(dateRowKey);
mergeList.add(Arrays.asList(start, end, 0, 0)); int endRow = finalDataList.size();
mergeList.add(Arrays.asList(start, end, 1, 1)); if (endRow - startRow > 0) {
mergeList.add(Arrays.asList(start, end, 9, 9)); mergeList.add(Arrays.asList(startRow, endRow, 1, 1));
mergeList.add(Arrays.asList(startRow, endRow, 9, 9));
} }
} }
}
}
if (finalDataList.size() - rowIndex > 0) {
mergeList.add(Arrays.asList(rowIndex, finalDataList.size(), 0, 0));
mergeList.add(Arrays.asList(rowIndex, finalDataList.size(), 10, 10));
}
rowIndex = finalDataList.size() + 1;
for (Map<String, Object> map : totalList) {
map.put("总销售额", totalAmount);
}
dataList.put(tableCode, dayMap);
}
List<String> keyList = new ArrayList<>(); List<String> keyList = new ArrayList<>();
keyList.add("日期");
keyList.add("台桌"); keyList.add("台桌");
keyList.add("日期");
keyList.add("商品分类"); keyList.add("商品分类");
keyList.add("商品名称"); keyList.add("商品名称");
keyList.add("单位"); keyList.add("单位");
@@ -522,9 +611,10 @@ public class SummaryServiceImpl implements SummaryService {
keyList.add("单价"); keyList.add("单价");
keyList.add("金额"); keyList.add("金额");
keyList.add("销售额"); keyList.add("销售额");
keyList.add("总销售额");
keyList.add("退单量"); keyList.add("退单量");
keyList.add("退单额"); keyList.add("退单额");
FileUtil.downloadAndMergeExcel(list, mergeList, keyList, response); FileUtil.downloadAndMergeExcel(finalDataList, mergeList, keyList, response);
} }
} }

View File

@@ -1,78 +0,0 @@
package cn.ysk.cashier.utils;
import cn.ysk.cashier.dto.shop.ExportTableStsDataDto;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Map;
/**
* @author yijiegong
*/
public class FileUtils {
/**
* 该方法用于导出台桌数据统计,不通用
*/
public static void downloadTableDataStsToExcel(List<ExportTableStsDataDto> dataList, List<String> keyList, HttpServletResponse response) throws IOException {
// String tempPath = SYS_TEM_DIR + IdUtil.fastSimpleUUID() + ".xlsx";
// 创建工作簿
Workbook workbook = new XSSFWorkbook();
for (ExportTableStsDataDto exportTableStsDataDto : dataList) {
Sheet sheet = workbook.createSheet(exportTableStsDataDto.getDateStr());
for (List<Integer> mergeDatum : exportTableStsDataDto.getMergeCells()) {
sheet.addMergedRegion(new CellRangeAddress(mergeDatum.get(0), mergeDatum.get(1), mergeDatum.get(2), mergeDatum.get(3)));
}
Row row0 = sheet.createRow(0);
for (int i = 0; i < keyList.size(); i++) {
Cell cell = row0.createCell(i);
cell.setCellValue(keyList.get(i));
}
for (int i = 0; i < exportTableStsDataDto.getData().size(); i++) {
Map<String, Object> map = exportTableStsDataDto.getData().get(i);
Row row = sheet.createRow(i + 1);
for (int j = 0; j < keyList.size(); j++) {
Cell cell = row.createCell(j);
String value = map.get(keyList.get(j)) == null ? "" : map.get(keyList.get(j)).toString();
cell.setCellValue(value);
if (j == 10 && !"0".equals(value)) {
cell.setCellValue("-" + value);
setCellBackground(cell, IndexedColors.YELLOW, workbook);
}
if (j == 11 && !"0.00".equals(value)) {
cell.setCellValue("-" + value);
setCellBackground(cell, IndexedColors.YELLOW, workbook);
}
}
}
}
// response为HttpServletResponse对象
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
response.setHeader("Content-Disposition", "attachment;filename=file.xlsx");
try (ServletOutputStream out = response.getOutputStream()) {
workbook.write(out);
out.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
private static void setCellBackground(Cell cell, IndexedColors color, Workbook workbook) {
CellStyle style = workbook.createCellStyle();
style.setFillForegroundColor(color.getIndex());
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
cell.setCellStyle(style);
}
}