打印数据

This commit is contained in:
2026-04-16 14:38:14 +08:00
parent 710cca65d6
commit cef7e5315a
27 changed files with 467 additions and 86 deletions

View File

@@ -37,6 +37,7 @@ public class VipPayParamDTO {
private BigDecimal amount;
private String buyerRemark;
private String operator;
/**
* 跳转地址
*/

View File

@@ -0,0 +1,14 @@
package com.czg.service.order.mapper;
import com.mybatisflex.core.BaseMapper;
import com.czg.order.entity.SysPrintData;
/**
* 数据打印表 映射层。
*
* @author ww
* @since 2026-04-16
*/
public interface SysPrintDataMapper extends BaseMapper<SysPrintData> {
}

View File

@@ -62,26 +62,8 @@ public class PrintConfig implements ApplicationRunner {
public static final Map<String, PrinterHandler> PRINTER_MAP = new ConcurrentHashMap<>();
// @PostConstruct
// 直接使用实例变量,不需要静态
// private Map<String, PrinterHandler> printerMap;
// public void init() {
// Map<String, PrinterHandler> printers = applicationContext.getBeansOfType(PrinterHandler.class);
// printerMap = new ConcurrentHashMap<>();
//
// printers.forEach((beanName, printer) -> {
// String brand = printer.printerBrand;
// if (brand != null && !brand.trim().isEmpty()) {
// printerMap.put(brand, printer);
// }
// });
//
// log.info("已注册打印机: {}", printerMap.keySet());
// }
@Override
public void run(ApplicationArguments args) throws Exception {
// 🔥 这里是 Spring 容器完全启动成功后才执行!
// 🔥 所有 feiPrinter、yxyPrinter 都已经加载好了!
Map<String, PrinterHandler> beans = applicationContext.getBeansOfType(PrinterHandler.class);

View File

@@ -364,7 +364,7 @@ public abstract class PrinterHandler {
String codeUrl, LocalDateTime takeTime, String shopNote);
/**
* 出入库打印单
* 出入库打印单
*/
protected abstract void stockPrint(PrintMachine machine, String shopName, StockPrintDTO record);
@@ -379,12 +379,12 @@ public abstract class PrinterHandler {
protected abstract void productReportPrint(PrintMachine machine, String shopName, ProductReportPrintDTO record);
/**
* 储值单打印
* 储值单打印
*/
protected abstract void rechargePrint(PrintMachine machine, String shopName, RechargePrintDTO record);
/**
* 库存盘点打印
* 库存盘点打印
*/
protected abstract void stockCheckPrint(PrintMachine machine, String shopName, StockCheckPrintDTO record);

View File

@@ -17,7 +17,6 @@ import lombok.experimental.Accessors;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/**
@@ -668,37 +667,25 @@ public interface PrinterImpl {
builder.append(getFormatLabel(header, signLabelInfo.s)).append(signLabelInfo.br);
// 遍历分类+商品明细
Map<String, List<ProductReportPrintDTO.ProductItem>> itemsMap = record.getItems();
if (CollUtil.isNotEmpty(itemsMap)) {
for (Map.Entry<String, List<ProductReportPrintDTO.ProductItem>> entry : itemsMap.entrySet()) {
String categoryName = entry.getKey();
List<ProductReportPrintDTO.ProductItem> productList = entry.getValue();
// 先打印分类名称行(分类名称+该分类汇总数量/实收/销售额,和示例图一致)
// 分类汇总:遍历该分类下所有商品,求和
BigDecimal categoryTotalNum = BigDecimal.ZERO;
BigDecimal categoryTotalActual = BigDecimal.ZERO;
BigDecimal categoryTotalSales = BigDecimal.ZERO;
for (ProductReportPrintDTO.ProductItem item : productList) {
categoryTotalNum = categoryTotalNum.add(item.getNumber());
categoryTotalActual = categoryTotalActual.add(item.getActualAmount());
categoryTotalSales = categoryTotalSales.add(item.getSalesAmount());
}
List<ProductReportPrintDTO.CategoryItem> items = record.getItems();
if (CollUtil.isNotEmpty(items)) {
for (ProductReportPrintDTO.CategoryItem item : items) {
List<ProductReportPrintDTO.ProductItem> productList = item.getProductItems();
// 打印分类行缩进0和表头对齐
String categoryLine = key4(categoryName,
categoryTotalNum.stripTrailingZeros().toPlainString(),
categoryTotalActual.stripTrailingZeros().toPlainString(),
categoryTotalSales.stripTrailingZeros().toPlainString(),
String categoryLine = key4(item.getCategoryName(),
item.getNumber().stripTrailingZeros().toPlainString(),
item.getActualAmount().stripTrailingZeros().toPlainString(),
item.getSalesAmount().stripTrailingZeros().toPlainString(),
12, 8, 8);
builder.append(getFormatLabel(categoryLine, signLabelInfo.s)).append(signLabelInfo.br);
// 再打印该分类下的商品明细缩进2个空格和示例图一致
for (ProductReportPrintDTO.ProductItem item : productList) {
String numStr = item.getNumber().stripTrailingZeros().toPlainString();
String actualStr = item.getActualAmount().stripTrailingZeros().toPlainString();
String salesStr = item.getSalesAmount().stripTrailingZeros().toPlainString();
for (ProductReportPrintDTO.ProductItem pro : productList) {
String numStr = pro.getNumber().stripTrailingZeros().toPlainString();
String actualStr = pro.getActualAmount().stripTrailingZeros().toPlainString();
String salesStr = pro.getSalesAmount().stripTrailingZeros().toPlainString();
// 商品名称前加2个空格实现缩进效果
String productLine = key4(" " + item.getProductName(), numStr, actualStr, salesStr, 12, 8, 8);
String productLine = key4(" " + pro.getProductName(), numStr, actualStr, salesStr, 12, 8, 8);
builder.append(getFormatLabel(productLine, signLabelInfo.s)).append(signLabelInfo.br);
}
}
@@ -726,9 +713,15 @@ public interface PrinterImpl {
// 充值明细
builder.append(getFormatLabel("----------------------------------------")).append(signLabelInfo.br);
builder.append(getFormatLabel(leftRightAlign(" 充值金额:", record.getRechargeAmount().stripTrailingZeros().toPlainString(), 32), signLabelInfo.s)).append(signLabelInfo.br);
builder.append(getFormatLabel(leftRightAlign(" 赠送金额:", record.getGiftAmount().stripTrailingZeros().toPlainString(), 32), signLabelInfo.s)).append(signLabelInfo.br);
builder.append(getFormatLabel(leftRightAlign(" 赠送积分:", record.getGiftPoints().stripTrailingZeros().toPlainString(), 32), signLabelInfo.s)).append(signLabelInfo.br);
builder.append(getFormatLabel(leftRightAlign(" 赠送优惠券:", record.getGiftCoupon() + "", 32), signLabelInfo.s)).append(signLabelInfo.br);
if (record.getGiftAmount() != null && record.getGiftAmount().compareTo(BigDecimal.ZERO) > 0) {
builder.append(getFormatLabel(leftRightAlign(" 赠送金额:", record.getGiftAmount().stripTrailingZeros().toPlainString(), 32), signLabelInfo.s)).append(signLabelInfo.br);
}
if (record.getGiftPoints() != null && record.getGiftPoints().compareTo(BigDecimal.ZERO) > 0) {
builder.append(getFormatLabel(leftRightAlign(" 赠送积分:", record.getGiftPoints().stripTrailingZeros().toPlainString(), 32), signLabelInfo.s)).append(signLabelInfo.br);
}
if (record.getGiftCoupon() != null && record.getGiftCoupon() > 0) {
builder.append(getFormatLabel(leftRightAlign(" 赠送优惠券:", record.getGiftCoupon() + "", 32), signLabelInfo.s)).append(signLabelInfo.br);
}
builder.append(getFormatLabel(leftRightAlign(" 充值后余额:", record.getBalance().stripTrailingZeros().toPlainString(), 32), signLabelInfo.s)).append(signLabelInfo.br);
builder.append(getFormatLabel("----------------------------------------")).append(signLabelInfo.br);
// 支付信息

View File

@@ -1180,7 +1180,7 @@ public class OrderInfoCustomServiceImpl implements OrderInfoCustomService {
}
shopRechargeService.recharge(payment.getShopId(), payment.getSourceId(), payment.getRelatedId(),
BigDecimal.valueOf(notifyRespDTO.getAmount()).divide(BigDecimal.valueOf(100), 2, RoundingMode.DOWN),
payment.getId(), payment.getSourceType(), bizEnum, orderInfo == null);
payment.getId(), payment.getSourceType(), payment.getPayTime(), bizEnum, orderInfo == null, null);
}
} else if (PayTypeConstants.SourceType.MEMBER_PAY.equals(payment.getSourceType())) {
//购买会员

View File

@@ -1,15 +1,21 @@
package com.czg.service.order.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import com.czg.config.RabbitPublisher;
import com.czg.exception.CzgException;
import com.czg.order.entity.ShopProdStatistic;
import com.czg.order.param.SaleSummaryCountParam;
import com.czg.order.service.ShopProdStatisticService;
import com.czg.order.vo.SaleSummaryCountVo;
import com.czg.print.ProductReportPrintDTO;
import com.czg.product.service.ShopProdCategoryService;
import com.czg.service.order.mapper.ShopProdStatisticMapper;
import com.czg.utils.CzgStrUtils;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
@@ -28,6 +34,11 @@ import java.util.stream.Stream;
@Service
public class ShopProdStatisticServiceImpl extends ServiceImpl<ShopProdStatisticMapper, ShopProdStatistic> implements ShopProdStatisticService {
@Resource
private RabbitPublisher rabbitPublisher;
@DubboReference
private ShopProdCategoryService shopProdCategoryService;
@Override
public List<ShopProdStatistic> getArchiveTradeDataBy10(Long shopId, Integer day) {
LocalDate currentDate = LocalDate.now();
@@ -73,6 +84,86 @@ public class ShopProdStatisticServiceImpl extends ServiceImpl<ShopProdStatisticM
return mergeSummaryCountVo(todaySummary, dateRangeSummary);
}
@Override
public void summaryPrint(SaleSummaryCountParam param) {
// 1. 获取统计数据
SaleSummaryCountVo saleSummaryCountVo = summaryCount(param);
List<ShopProdStatistic> prodStatisticList = getArchiveTradeData(param);
LocalDate currentDate = LocalDate.now();
Map<Long, String> categoryMap = shopProdCategoryService.getCategoryIdNameMap(param.getShopId());
ProductReportPrintDTO printDTO = new ProductReportPrintDTO();
String statisticsTime = "";
if ("today".equals(param.getRangeType())) {
statisticsTime = LocalDateTimeUtil.format(currentDate, "yyyy/MM/dd");
}
if ("yesterday".equals(param.getRangeType())) {
statisticsTime = LocalDateTimeUtil.format(currentDate.minusDays(1), "yyyy/MM/dd");
}
if (param.getBeginDate().isAfter(currentDate)) {
throw new CzgException("开始时间不能晚于当前时间");
}
if (param.getBeginDate().equals(param.getEndDate())) {
statisticsTime = LocalDateTimeUtil.format(param.getBeginDate(), "yyyy/MM/dd");
}
if (param.getEndDate().isBefore(currentDate)) {
statisticsTime = LocalDateTimeUtil.format(param.getBeginDate(), "yyyy/MM/dd") + " ~ " + LocalDateTimeUtil.format(param.getEndDate(), "yyyy/MM/dd");
}
printDTO.setStatisticsTime(statisticsTime);
printDTO.setOperator(param.getOperator());
printDTO.setTotalProductCount(saleSummaryCountVo.getSaleCount());
printDTO.setTotalActualAmount(saleSummaryCountVo.getTotalAmount());
// 4. 先按分类ID分组商品
Map<Long, List<ShopProdStatistic>> groupByCategory = prodStatisticList.stream()
.collect(Collectors.groupingBy(ShopProdStatistic::getCategoryId));
// 5. 组装成新结构 List<CategoryItem>
List<ProductReportPrintDTO.CategoryItem> categoryItems = new ArrayList<>();
for (Map.Entry<Long, List<ShopProdStatistic>> entry : groupByCategory.entrySet()) {
Long categoryId = entry.getKey();
List<ShopProdStatistic> productList = entry.getValue();
// 分类名称
String categoryName = categoryMap.getOrDefault(categoryId, "未分类");
// 商品列表
List<ProductReportPrintDTO.ProductItem> productItems = new ArrayList<>();
BigDecimal categoryTotalNumber = BigDecimal.ZERO;
BigDecimal categoryTotalActual = BigDecimal.ZERO;
BigDecimal categoryTotalSales = BigDecimal.ZERO;
for (ShopProdStatistic s : productList) {
ProductReportPrintDTO.ProductItem item = new ProductReportPrintDTO.ProductItem();
item.setProductName(s.getProductName());
item.setNumber(s.getValidSaleCount());
item.setActualAmount(s.getValidSaleAmount());
item.setSalesAmount(s.getSaleAmount());
productItems.add(item);
// 分类汇总累加
categoryTotalNumber = categoryTotalNumber.add(s.getValidSaleCount());
categoryTotalActual = categoryTotalActual.add(s.getValidSaleAmount());
categoryTotalSales = categoryTotalSales.add(s.getSaleAmount());
}
// 构建分类项
ProductReportPrintDTO.CategoryItem categoryItem = new ProductReportPrintDTO.CategoryItem();
categoryItem.setCategoryName(categoryName);
categoryItem.setNumber(categoryTotalNumber); // 分类总数量
categoryItem.setActualAmount(categoryTotalActual); // 分类总实收
categoryItem.setSalesAmount(categoryTotalSales); // 分类总销售额
categoryItem.setProductItems(productItems); // 分类下商品
categoryItems.add(categoryItem);
}
printDTO.setItems(categoryItems);
rabbitPublisher.sendOtherPrintMsg(param.getShopId(), printDTO, "PRODUCT_REPORT");
}
@Override
public List<ShopProdStatistic> getArchiveTradeData(SaleSummaryCountParam param) {
LocalDate currentDate = LocalDate.now();

View File

@@ -41,6 +41,7 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
@@ -110,16 +111,9 @@ public class ShopUserServiceImpl implements ShopUserPayService {
return CzgResult.failure("支付密码错误");
}
}
// if (shopUser.getIsVip().equals(0)) {
// //更新会员
// ShopUser updateInfo = new ShopUser();
// updateInfo.setIsVip(1);
// updateInfo.setJoinTime(LocalDateTime.now());
// updateInfo.setId(payParam.getShopUserId());
// shopUserService.updateById(updateInfo);
// }
shopRechargeService.recharge(shopUser.getMainShopId(), shopUser.getId(), payParam.getRechargeDetailId(),
payParam.getAmount(), null, "cash", ShopUserFlowBizEnum.CASH_IN, true);
payParam.getAmount(), null, "cash", LocalDateTime.now(),
ShopUserFlowBizEnum.CASH_IN, true, payParam.getOperator());
return CzgResult.success();
}

View File

@@ -0,0 +1,18 @@
package com.czg.service.order.service.impl;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.czg.order.entity.SysPrintData;
import com.czg.order.service.SysPrintDataService;
import com.czg.service.order.mapper.SysPrintDataMapper;
import org.springframework.stereotype.Service;
/**
* 数据打印表 服务层实现。
*
* @author ww
* @since 2026-04-16
*/
@Service
public class SysPrintDataServiceImpl extends ServiceImpl<SysPrintDataMapper, SysPrintData> implements SysPrintDataService{
}

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.czg.service.order.mapper.SysPrintDataMapper">
</mapper>