台桌统计报表

This commit is contained in:
Tankaikai 2025-04-02 13:25:56 +08:00
parent 6eb0a765c1
commit 84b7ac9e39
12 changed files with 314 additions and 38 deletions

View File

@ -1,7 +1,7 @@
server: server:
port: 9100 port: 9100
# servlet: servlet:
# context-path: /admin context-path: /account
spring: spring:
application: application:

View File

@ -2,17 +2,17 @@ package com.czg.controller;
import com.alibaba.fastjson2.JSONObject; import com.alibaba.fastjson2.JSONObject;
import com.czg.CzgPayUtils; import com.czg.CzgPayUtils;
import com.czg.account.service.MemberPointsService;
import com.czg.entity.CzgBaseRespParams; import com.czg.entity.CzgBaseRespParams;
import com.czg.mq.PrintMqListener; import com.czg.mq.PrintMqListener;
import com.czg.order.service.OrderInfoService; import com.czg.order.service.OrderInfoService;
import com.czg.order.service.ShopOrderStatisticService;
import com.czg.task.StatisticTask; import com.czg.task.StatisticTask;
import com.czg.utils.AssertUtil; import com.czg.utils.AssertUtil;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestBody; import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/** /**
* @author ww * @author ww
@ -30,18 +30,26 @@ public class NotifyController {
@Resource @Resource
private StatisticTask statisticTask; private StatisticTask statisticTask;
@DubboReference
private MemberPointsService pointsService;
@RequestMapping("/payCallBack") @Resource
public String notifyCallBack(@RequestBody CzgBaseRespParams respParams){ private ShopOrderStatisticService shopOrderStatisticService;
JSONObject czg = CzgPayUtils.getCzg(respParams);
AssertUtil.isNull(czg, "支付回调数据为空");
log.info("支付回调数据为:{}", czg); @GetMapping("/payCallBack")
orderInfoService.payCallBackOrder(czg.getString("mchOrderNo"), czg); public String notifyCallBack() {
shopOrderStatisticService.statistic();
//JSONObject czg = CzgPayUtils.getCzg(respParams);
//AssertUtil.isNull(czg, "支付回调数据为空");
//log.info("支付回调数据为:{}", czg);
//orderInfoService.payCallBackOrder(czg.getString("mchOrderNo"), czg);
return SUCCESS; return SUCCESS;
} }
@RequestMapping("/refundCallBack") @RequestMapping("/refundCallBack")
public String refundCallBack(@RequestBody CzgBaseRespParams respParams){ public String refundCallBack(@RequestBody CzgBaseRespParams respParams) {
JSONObject czg = CzgPayUtils.getCzg(respParams); JSONObject czg = CzgPayUtils.getCzg(respParams);
AssertUtil.isNull(czg, "退款回调数据为空"); AssertUtil.isNull(czg, "退款回调数据为空");
log.info("退款回调数据为:{}", czg); log.info("退款回调数据为:{}", czg);
@ -51,6 +59,7 @@ public class NotifyController {
@Resource @Resource
private PrintMqListener printMqListener; private PrintMqListener printMqListener;
@RequestMapping("/test") @RequestMapping("/test")
public void test(@RequestParam String id) { public void test(@RequestParam String id) {
printMqListener.orderPrint(id); printMqListener.orderPrint(id);

View File

@ -0,0 +1,151 @@
package com.czg.handel;
import cn.idev.excel.metadata.Head;
import cn.idev.excel.metadata.data.WriteCellData;
import cn.idev.excel.write.handler.CellWriteHandler;
import cn.idev.excel.write.metadata.holder.WriteSheetHolder;
import cn.idev.excel.write.metadata.holder.WriteTableHolder;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import java.util.List;
/**
* @author tankaikai
* @since 2025-04-01 18:41
*/
public class ExcelMergeHandler implements CellWriteHandler {
// 要合并的列索引数组
private int[] mergeColumnIndex = {0, 1, 2, 9, 10};
// 合并开始的行索引
private int mergeRowIndex = 1;
public ExcelMergeHandler() {
}
/**
* 构造函数
*
* @param mergeRowIndex 合并开始的行索引
* @param mergeColumnIndex 要合并的列索引数组
*/
public ExcelMergeHandler(int mergeRowIndex, int[] mergeColumnIndex) {
this.mergeRowIndex = mergeRowIndex;
this.mergeColumnIndex = mergeColumnIndex;
}
@Override
public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<WriteCellData<?>> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
// 当前行索引
int curRowIndex = cell.getRowIndex();
// 当前列索引
int curColIndex = cell.getColumnIndex();
// 如果当前行大于合并开始行且当前列在需要合并的列中
if (curRowIndex > mergeRowIndex && isMergeColumn(curColIndex)) {
// 进行合并操作
mergeWithPrevRow(writeSheetHolder, cell, curRowIndex, curColIndex);
}
}
/**
* 检查当前列是否在需要合并的列中
*
* @param curColIndex 当前列索引
* @return 如果是需要合并的列返回true否则返回false
*/
private boolean isMergeColumn(int curColIndex) {
for (int columnIndex : mergeColumnIndex) {
if (curColIndex == columnIndex) {
return true;
}
}
return false;
}
/**
* 当前单元格向上合并
*
* @param writeSheetHolder 当前工作表持有者
* @param cell 当前单元格
* @param curRowIndex 当前行索引
* @param curColIndex 当前列索引
*/
private void mergeWithPrevRow(WriteSheetHolder writeSheetHolder, Cell cell, int curRowIndex, int curColIndex) {
// 获取当前单元格的数据
Object curData = getCellData(cell);
// 获取前一个单元格的数据
Cell preCell = cell.getSheet().getRow(curRowIndex - 1).getCell(curColIndex);
Object preData = getCellData(preCell);
// 判断当前单元格和前一个单元格的数据以及主键是否相同
if (curData.equals(preData) && isSamePrimaryKey(cell, curRowIndex)) {
// 获取工作表
Sheet sheet = writeSheetHolder.getSheet();
// 合并单元格
mergeCells(sheet, curRowIndex, curColIndex);
CellStyle style = preCell.getCellStyle();
// 设置水平居中
style.setAlignment(HorizontalAlignment.CENTER);
// 设置垂直居中
style.setVerticalAlignment(VerticalAlignment.CENTER);
preCell.setCellStyle(style);
}
}
/**
* 获取单元格的数据
*
* @param cell 单元格
* @return 单元格数据
*/
private Object getCellData(Cell cell) {
return cell.getCellType() == CellType.STRING ? cell.getStringCellValue() : cell.getNumericCellValue();
}
/**
* 判断当前单元格和前一个单元格的主键是否相同
*
* @param cell 当前单元格
* @param curRowIndex 当前行索引
* @return 如果主键相同返回true否则返回false
*/
private boolean isSamePrimaryKey(Cell cell, int curRowIndex) {
String currentPrimaryKey = cell.getRow().getCell(0).getStringCellValue();
String previousPrimaryKey = cell.getSheet().getRow(curRowIndex - 1).getCell(0).getStringCellValue();
return currentPrimaryKey.equals(previousPrimaryKey);
}
/**
* 合并单元格
*
* @param sheet 工作表
* @param curRowIndex 当前行索引
* @param curColIndex 当前列索引
*/
private void mergeCells(Sheet sheet, int curRowIndex, int curColIndex) {
// 获取已合并的区域
List<CellRangeAddress> mergeRegions = sheet.getMergedRegions();
boolean isMerged = false;
// 检查前一个单元格是否已经被合并
for (int i = 0; i < mergeRegions.size() && !isMerged; i++) {
CellRangeAddress cellRangeAddr = mergeRegions.get(i);
if (cellRangeAddr.isInRange(curRowIndex - 1, curColIndex)) {
sheet.removeMergedRegion(i);
cellRangeAddr.setLastRow(curRowIndex);
sheet.addMergedRegion(cellRangeAddr);
isMerged = true;
}
}
// 如果前一个单元格未被合并则新增合并区域
if (!isMerged) {
CellRangeAddress cellRangeAddress = new CellRangeAddress(curRowIndex - 1, curRowIndex, curColIndex, curColIndex);
sheet.addMergedRegion(cellRangeAddress);
}
}
}

View File

@ -0,0 +1,55 @@
package com.czg.handel;
import cn.hutool.core.util.ArrayUtil;
import cn.idev.excel.metadata.Head;
import cn.idev.excel.metadata.data.WriteCellData;
import cn.idev.excel.write.handler.CellWriteHandler;
import cn.idev.excel.write.metadata.holder.WriteSheetHolder;
import cn.idev.excel.write.metadata.holder.WriteTableHolder;
import org.apache.poi.ss.usermodel.*;
import java.util.List;
/**
* 台桌统计退单单元格处理器
*
* @author tankaikai
* @since 2025-04-02 09:50
*/
public class TableRefundCellHandel implements CellWriteHandler {
// 要处理的列索引数组
private int[] yellowColumnIndex = {11, 12};
public TableRefundCellHandel() {
}
@Override
public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<WriteCellData<?>> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
// 当前行索引
int curRowIndex = cell.getRowIndex();
// 当前列索引
int curColIndex = cell.getColumnIndex();
if (curRowIndex == 0) {
return;
}
// 如果是指定要处理的列则要进行加黄操作
if (ArrayUtil.contains(yellowColumnIndex, curColIndex)) {
Cell preCell = cell.getSheet().getRow(curRowIndex - 1).getCell(curColIndex);
if (preCell.getCellType() == CellType.NUMERIC) {
if (preCell.getNumericCellValue() < 0) {
//System.out.println("设置黄色背景:" + curRowIndex + "行," + curColIndex + "" + preCell.getNumericCellValue());
CellStyle style = preCell.getSheet().getWorkbook().createCellStyle();
style.cloneStyleFrom(preCell.getCellStyle());
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
style.setFillForegroundColor(IndexedColors.YELLOW.getIndex());
// 设置水平居中
style.setAlignment(HorizontalAlignment.CENTER);
// 设置垂直居中
style.setVerticalAlignment(VerticalAlignment.CENTER);
preCell.setCellStyle(style);
}
}
}
}
}

View File

@ -27,8 +27,8 @@ public class StatisticTask {
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
log.info("定时任务执行,开始统计数据"); log.info("定时任务执行,开始统计数据");
shopOrderStatisticService.statistic(); shopOrderStatisticService.statistic();
shopProdStatisticService.statistic(); //shopProdStatisticService.statistic();
shopTableOrderStatisticService.statistic(); //shopTableOrderStatisticService.statistic();
log.info("定时任务执行完毕,耗时:{}ms", start - System.currentTimeMillis()); log.info("定时任务执行完毕,耗时:{}ms", start - System.currentTimeMillis());
} }
} }

View File

@ -1,5 +1,7 @@
server: server:
port: 9200 port: 9200
servlet:
context-path: /order
spring: spring:
application: application:

View File

@ -18,6 +18,7 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
public class ProductApplication { public class ProductApplication {
public static void main(String[] args) { public static void main(String[] args) {
SpringApplication.run(ProductApplication.class, args); SpringApplication.run(ProductApplication.class, args);
} }

View File

@ -1,5 +1,7 @@
server: server:
port: 9300 port: 9300
servlet:
context-path: /product
spring: spring:
application: application:
@ -14,6 +16,7 @@ wx:
operationMsgTmpId: wFdoUG-dUT7bDRHq8bMJD9CF5TjyH9x_uJQgQByZqHg operationMsgTmpId: wFdoUG-dUT7bDRHq8bMJD9CF5TjyH9x_uJQgQByZqHg
warnMsgTmpId: C08OUr80x6wGmUN1zpFhSQ3Sv7VF5vksdZigiEx2pD0 warnMsgTmpId: C08OUr80x6wGmUN1zpFhSQ3Sv7VF5vksdZigiEx2pD0
logging: logging:
config: classpath:logback.xml config: classpath:logback.xml
@ -28,4 +31,6 @@ pagehelper:
helper-dialect: mysql helper-dialect: mysql
support-methods-arguments: true support-methods-arguments: true
dubbo:
consumer:
check: false

View File

@ -18,4 +18,27 @@ public class DemoTest {
System.out.println(password); System.out.println(password);
} }
public static void main(String[] args) {
//System.out.println(StrUtil.sub("下架商品:情人节固",0,20));
/*Map<String, Object> data = new HashMap<String, Object>() {{
put("thing19", new HashMap<String, Object>() {{
put("value", "张三");
}});
put("thing8", new HashMap<String, Object>() {{
put("value", "财务票据");
}});
put("time21", new HashMap<String, Object>() {{
put("value", DateUtil.format(DateUtil.date(), "yyyy-MM-dd HH:mm:ss"));
}});
}};
JSONObject req = new JSONObject();
req.put("template_id", "wFdoUG-dUT7bDRHq8bMJD9CF5TjyH9x_uJQgQByZqHg");
req.put("touser", "ojC-S6iKBL7sHUb-E0UYq-Q1J4AA");
req.put("data", data);
String accessToken = "90_zBsyBkkK9cYx3GpbydWV97yPr-2WkRYqc2ESQKLGbr_IxqWgb3t9MZO-9jFNUlJoQCYyKyR1-tHOh_e5GKYPWdSY9wGSzEvC_uNM_MaHHbG1IiI0A0nzDrJmDNgEXBbAJAVOS";
String post = HttpUtil.post("https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=".concat(accessToken), req.toString());
System.out.println(post);*/
}
} }

View File

@ -1,5 +1,7 @@
server: server:
port: 9400 port: 9400
servlet:
context-path: /system
spring: spring:
application: application:

View File

@ -61,15 +61,17 @@ public class SaTokenConfigure implements WebMvcConfigurer {
SaRouter.match("/user/**").notMatch("/user/login", "/user/test", "/user/geo/**", "/user/home/**", "/user/home/**", "/user/dict/**", "/user/openId") SaRouter.match("/user/**").notMatch("/user/login", "/user/test", "/user/geo/**", "/user/home/**", "/user/home/**", "/user/dict/**", "/user/openId")
.notMatch("/pay/**") .notMatch("/pay/**")
.notMatch("/notify/**") .notMatch("/order/notify/**")
.notMatch("/user/product/**")
.check(r -> MyStpLogic.CLIENT_LOGIC.checkLogin()) .check(r -> MyStpLogic.CLIENT_LOGIC.checkLogin())
.setHit(true) .setHit(true)
// .match("/**") // .match("/**")
.notMatch("/user/**") .notMatch("/user/**")
.notMatch("/pay/**") .notMatch("/pay/**")
.notMatch("/notify/**") .notMatch("/order/notify/**")
.notMatch("/admin/auth/**") .notMatch("/account/admin/auth/**")
.notMatch("/admin/shopMsgPush/subscribe/**") .notMatch("/user/product/**")
.notMatch("/account/admin/shopMsgPush/subscribe/**")
.check(r -> MyStpLogic.ADMIN_LOGIC.checkLogin()); .check(r -> MyStpLogic.ADMIN_LOGIC.checkLogin());
})).addPathPatterns("/**"); })).addPathPatterns("/**");

View File

@ -1,8 +1,7 @@
package com.czg.service.order.service.impl; package com.czg.service.order.service.impl;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime; import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.date.DateUtil;
import com.czg.order.entity.ShopOrderStatistic; import com.czg.order.entity.ShopOrderStatistic;
import com.czg.order.param.DataSummaryTradeParam; import com.czg.order.param.DataSummaryTradeParam;
import com.czg.order.service.DataSummaryService; import com.czg.order.service.DataSummaryService;
@ -12,9 +11,11 @@ import com.mybatisflex.spring.service.impl.ServiceImpl;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List; import java.util.List;
import java.util.stream.Stream;
/** /**
* 服务层实现 * 服务层实现
@ -30,27 +31,52 @@ public class ShopOrderStatisticServiceImpl extends ServiceImpl<ShopOrderStatisti
@Override @Override
public void statistic() { public void statistic() {
// 获取前一天
DateTime yesterday = DateUtil.yesterday();
// 获取前一天的开始时间00:00:00
DateTime startOfDay = DateUtil.beginOfDay(yesterday);
// 获取前一天的结束时间23:59:59
DateTime endOfDay = DateUtil.endOfDay(yesterday);
List<Long> shopIdList = dataSummaryService.getShopIdList(); List<Long> shopIdList = dataSummaryService.getShopIdList();
if (CollUtil.isEmpty(shopIdList)) { if (CollUtil.isEmpty(shopIdList)) {
return; return;
} }
shopIdList.parallelStream().forEach(shopId -> {
DataSummaryTradeParam param = new DataSummaryTradeParam(); LocalDate startDate = LocalDate.of(2024, 3, 12);
param.setShopId(shopId); LocalDate endDate = LocalDate.of(2025, 3, 25);
param.setBeginDate(startOfDay.toStringDefaultTimeZone());
param.setEndDate(endOfDay.toStringDefaultTimeZone()); // 生成日期流
ShopOrderStatistic statistic = dataSummaryService.getTradeData(param); Stream<LocalDate> dateStream = startDate.datesUntil(endDate);
statistic.setShopId(shopId);
statistic.setCreateDay(LocalDate.now()); // 遍历日期流
statistic.setUpdateTime(LocalDateTime.now()); dateStream.forEach(date -> {
saveOrUpdate(statistic); String cur = date.toString();
String a = cur + " 00:00:00";
String b = cur + " 23:59:59";
shopIdList.parallelStream().forEach(shopId -> {
DataSummaryTradeParam param = new DataSummaryTradeParam();
param.setShopId(shopId);
param.setBeginDate(a);
param.setEndDate(b);
ShopOrderStatistic statistic = dataSummaryService.getTradeData(param);
if (NumberUtil.isGreater(statistic.getSaleAmount(), BigDecimal.ZERO)) {
statistic.setShopId(shopId);
statistic.setCreateDay(LocalDate.now());
statistic.setUpdateTime(LocalDateTime.now());
saveOrUpdate(statistic);
}
});
}); });
} }
public static void main(String[] args) {
LocalDate startDate = LocalDate.of(2024, 3, 12);
LocalDate endDate = LocalDate.of(2025, 3, 25);
// 生成日期流
Stream<LocalDate> dateStream = startDate.datesUntil(endDate);
// 遍历日期流
dateStream.forEach(date -> {
String cur = date.toString();
String a = cur + "00:00:00";
String b = cur + "23:59:59";
System.out.println(date.toString());
});
}
} }