diff --git a/src/main/java/com/czg/mergedata/common/utils/CodeGen.java b/src/main/java/com/czg/mergedata/common/utils/CodeGen.java index 5668584..60c8bda 100644 --- a/src/main/java/com/czg/mergedata/common/utils/CodeGen.java +++ b/src/main/java/com/czg/mergedata/common/utils/CodeGen.java @@ -81,7 +81,7 @@ public class CodeGen { //设置表前缀和只生成哪些表,setGenerateTable 未配置时,生成所有表 globalConfig.getStrategyConfig() .setTablePrefix("tb_") - .setGenerateTable("tb_prod_cons_relation"); + .setGenerateTable("tb_shop_order_statistic", "tb_shop_prod_statistic", "tb_shop_table_order_statistic"); EntityConfig entityConfig = globalConfig.getEntityConfig(); if (IS_OLD_VERSION) { diff --git a/src/main/java/com/czg/mergedata/controller/StatisticController.java b/src/main/java/com/czg/mergedata/controller/StatisticController.java new file mode 100644 index 0000000..3ce4be9 --- /dev/null +++ b/src/main/java/com/czg/mergedata/controller/StatisticController.java @@ -0,0 +1,22 @@ +package com.czg.mergedata.controller; + +import com.czg.mergedata.cur.service.CurShopOrderStatisticService; +import jakarta.annotation.Resource; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author GYJoker + */ +@RestController +@RequestMapping("/statistic") +public class StatisticController { + + @Resource + private CurShopOrderStatisticService curShopOrderStatisticService; + + @RequestMapping("/order") + public Object curShopOrder() { + return curShopOrderStatisticService.statisticOrderData(); + } +} diff --git a/src/main/java/com/czg/mergedata/cur/entity/CurShopOrderStatistic.java b/src/main/java/com/czg/mergedata/cur/entity/CurShopOrderStatistic.java new file mode 100644 index 0000000..ea20170 --- /dev/null +++ b/src/main/java/com/czg/mergedata/cur/entity/CurShopOrderStatistic.java @@ -0,0 +1,161 @@ +package com.czg.mergedata.cur.entity; + +import com.alibaba.fastjson2.annotation.JSONField; +import com.mybatisflex.annotation.Column; +import com.mybatisflex.annotation.Id; +import com.mybatisflex.annotation.KeyType; +import com.mybatisflex.annotation.Table; +import java.io.Serializable; +import java.math.BigDecimal; +import java.sql.Date; +import java.time.LocalDate; +import java.time.LocalDateTime; + +import java.io.Serial; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 订单统计表 实体类。 + * + * @author mac + * @since 2025-03-19 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Table("tb_shop_order_statistic") +public class CurShopOrderStatistic implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + @Id(keyType = KeyType.Auto) + private Integer id; + + /** + * 销售额 + */ + private BigDecimal saleAmount = BigDecimal.ZERO; + + /** + * 销售数量 + */ + private Long saleCount = 0L; + + /** + * 优惠金额 + */ + private BigDecimal discountAmount = BigDecimal.ZERO; + + /** + * 优惠笔数 + */ + private Long discountCount = 0L; + + /** + * 退款金额 + */ + private BigDecimal refundAmount = BigDecimal.ZERO; + + /** + * 退款笔数 + */ + private Long refundCount = 0L; + + /** + * 微信支付笔数 + */ + private Long wechatPayCount = 0L; + + /** + * 微信支付金额 + */ + private BigDecimal wechatPayAmount = BigDecimal.ZERO; + + /** + * 支付宝支付笔数 + */ + private Long aliPayCount = 0L; + + /** + * 支付宝支付金额 + */ + private BigDecimal aliPayAmount = BigDecimal.ZERO; + + /** + * 挂账支付笔数 + */ + private Long creditPayCount = 0L; + + /** + * 挂账支付金额 + */ + private BigDecimal creditPayAmount = BigDecimal.ZERO; + + /** + * 会员支付笔数 + */ + private Long memberPayCount = 0L; + + /** + * 会员支付金额 + */ + private BigDecimal memberPayAmount = BigDecimal.ZERO; + + /** + * 主扫支付笔数 + */ + private Long scanPayCount = 0L; + + /** + * 主扫支付金额 + */ + private BigDecimal scanPayAmount = BigDecimal.ZERO; + + /** + * 现金支付笔数 + */ + private Long cashPayCount = 0L; + /** + * 现金支付金额 + */ + private BigDecimal cashPayAmount = BigDecimal.ZERO; + /** + * 充值金额 + */ + private BigDecimal rechargeAmount = BigDecimal.ZERO; + /** + * 客单价 + */ + private BigDecimal customerUnitPrice = BigDecimal.ZERO; + /** + * 翻台率 + */ + private BigDecimal tableTurnoverRate = BigDecimal.ZERO; + /** + * 新增会员数 + */ + @Column(ignore = true) + private Long newMemberCount = 0L; + /** + * 店铺id + */ + @JSONField(serialize = false) + private Long shopId; + /** + * 创建时间 + */ + @JSONField(serialize = false, format = "yyyy-MM-dd") + private Date createDay; + /** + * 最近一次统计时间 + */ + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime updateTime; + +} diff --git a/src/main/java/com/czg/mergedata/cur/entity/CurShopProdStatistic.java b/src/main/java/com/czg/mergedata/cur/entity/CurShopProdStatistic.java new file mode 100644 index 0000000..1d141d2 --- /dev/null +++ b/src/main/java/com/czg/mergedata/cur/entity/CurShopProdStatistic.java @@ -0,0 +1,71 @@ +package com.czg.mergedata.cur.entity; + +import com.mybatisflex.annotation.Id; +import com.mybatisflex.annotation.KeyType; +import com.mybatisflex.annotation.Table; +import java.io.Serializable; +import java.math.BigDecimal; +import java.sql.Date; + +import java.io.Serial; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 商品统计表 实体类。 + * + * @author mac + * @since 2025-03-19 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Table("tb_shop_prod_statistic") +public class CurShopProdStatistic implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + @Id(keyType = KeyType.Auto) + private Long id; + + /** + * 商品id + */ + private Long prodId; + + /** + * 销售数量 + */ + private BigDecimal saleCount; + + /** + * 销售金额 + */ + private BigDecimal saleAmount; + + /** + * 退单量 + */ + private BigDecimal refundCount; + + /** + * 退单金额 + */ + private BigDecimal refundAmount; + + /** + * 店铺id + */ + private Long shopId; + + /** + * 创建时间 + */ + private Date createDay; + +} diff --git a/src/main/java/com/czg/mergedata/cur/entity/CurShopTableOrderStatistic.java b/src/main/java/com/czg/mergedata/cur/entity/CurShopTableOrderStatistic.java new file mode 100644 index 0000000..677e214 --- /dev/null +++ b/src/main/java/com/czg/mergedata/cur/entity/CurShopTableOrderStatistic.java @@ -0,0 +1,66 @@ +package com.czg.mergedata.cur.entity; + +import com.mybatisflex.annotation.Id; +import com.mybatisflex.annotation.KeyType; +import com.mybatisflex.annotation.Table; +import java.io.Serializable; +import java.math.BigDecimal; +import java.sql.Date; + +import java.io.Serial; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 台桌订单统计表 实体类。 + * + * @author mac + * @since 2025-03-19 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Table("tb_shop_table_order_statistic") +public class CurShopTableOrderStatistic implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + @Id(keyType = KeyType.Auto) + private Long id; + + private Long tableId; + + /** + * 订单数量 + */ + private Long orderCount; + + /** + * 订单金额 + */ + private BigDecimal orderAmount; + + /** + * 店铺id + */ + private Long shopId; + + /** + * 创建日期 年月日 + */ + private Date createDay; + /** + * 退款数量 + */ + private long refundCount; + /** + * 退款金额 + */ + private BigDecimal refundAmount; + +} diff --git a/src/main/java/com/czg/mergedata/cur/mapper/CurShopOrderStatisticMapper.java b/src/main/java/com/czg/mergedata/cur/mapper/CurShopOrderStatisticMapper.java new file mode 100644 index 0000000..ad7babc --- /dev/null +++ b/src/main/java/com/czg/mergedata/cur/mapper/CurShopOrderStatisticMapper.java @@ -0,0 +1,16 @@ +package com.czg.mergedata.cur.mapper; + +import com.mybatisflex.core.BaseMapper; +import com.czg.mergedata.cur.entity.CurShopOrderStatistic; +import org.apache.ibatis.annotations.Select; + +/** + * 订单统计表 映射层。 + * + * @author mac + * @since 2025-03-19 + */ +public interface CurShopOrderStatisticMapper extends BaseMapper { + @Select("truncate tb_shop_order_statistic") + void truncateTable(); +} diff --git a/src/main/java/com/czg/mergedata/cur/mapper/CurShopProdStatisticMapper.java b/src/main/java/com/czg/mergedata/cur/mapper/CurShopProdStatisticMapper.java new file mode 100644 index 0000000..377a405 --- /dev/null +++ b/src/main/java/com/czg/mergedata/cur/mapper/CurShopProdStatisticMapper.java @@ -0,0 +1,16 @@ +package com.czg.mergedata.cur.mapper; + +import com.mybatisflex.core.BaseMapper; +import com.czg.mergedata.cur.entity.CurShopProdStatistic; +import org.apache.ibatis.annotations.Select; + +/** + * 商品统计表 映射层。 + * + * @author mac + * @since 2025-03-19 + */ +public interface CurShopProdStatisticMapper extends BaseMapper { + @Select("truncate tb_shop_prod_statistic") + void truncateTable(); +} diff --git a/src/main/java/com/czg/mergedata/cur/mapper/CurShopTableOrderStatisticMapper.java b/src/main/java/com/czg/mergedata/cur/mapper/CurShopTableOrderStatisticMapper.java new file mode 100644 index 0000000..959a312 --- /dev/null +++ b/src/main/java/com/czg/mergedata/cur/mapper/CurShopTableOrderStatisticMapper.java @@ -0,0 +1,16 @@ +package com.czg.mergedata.cur.mapper; + +import com.mybatisflex.core.BaseMapper; +import com.czg.mergedata.cur.entity.CurShopTableOrderStatistic; +import org.apache.ibatis.annotations.Select; + +/** + * 台桌订单统计表 映射层。 + * + * @author mac + * @since 2025-03-19 + */ +public interface CurShopTableOrderStatisticMapper extends BaseMapper { + @Select("truncate tb_shop_table_order_statistic") + void truncateTable(); +} diff --git a/src/main/java/com/czg/mergedata/cur/service/CurShopOrderStatisticService.java b/src/main/java/com/czg/mergedata/cur/service/CurShopOrderStatisticService.java new file mode 100644 index 0000000..a066ccb --- /dev/null +++ b/src/main/java/com/czg/mergedata/cur/service/CurShopOrderStatisticService.java @@ -0,0 +1,15 @@ +package com.czg.mergedata.cur.service; + +import com.czg.mergedata.common.resp.CzgResult; +import com.mybatisflex.core.service.IService; +import com.czg.mergedata.cur.entity.CurShopOrderStatistic; + +/** + * 订单统计表 服务层。 + * + * @author mac + * @since 2025-03-19 + */ +public interface CurShopOrderStatisticService extends IService { + CzgResult statisticOrderData(); +} diff --git a/src/main/java/com/czg/mergedata/cur/service/CurShopProdStatisticService.java b/src/main/java/com/czg/mergedata/cur/service/CurShopProdStatisticService.java new file mode 100644 index 0000000..9d6c996 --- /dev/null +++ b/src/main/java/com/czg/mergedata/cur/service/CurShopProdStatisticService.java @@ -0,0 +1,14 @@ +package com.czg.mergedata.cur.service; + +import com.mybatisflex.core.service.IService; +import com.czg.mergedata.cur.entity.CurShopProdStatistic; + +/** + * 商品统计表 服务层。 + * + * @author mac + * @since 2025-03-19 + */ +public interface CurShopProdStatisticService extends IService { + +} diff --git a/src/main/java/com/czg/mergedata/cur/service/CurShopTableOrderStatisticService.java b/src/main/java/com/czg/mergedata/cur/service/CurShopTableOrderStatisticService.java new file mode 100644 index 0000000..0e82370 --- /dev/null +++ b/src/main/java/com/czg/mergedata/cur/service/CurShopTableOrderStatisticService.java @@ -0,0 +1,14 @@ +package com.czg.mergedata.cur.service; + +import com.mybatisflex.core.service.IService; +import com.czg.mergedata.cur.entity.CurShopTableOrderStatistic; + +/** + * 台桌订单统计表 服务层。 + * + * @author mac + * @since 2025-03-19 + */ +public interface CurShopTableOrderStatisticService extends IService { + +} diff --git a/src/main/java/com/czg/mergedata/cur/service/impl/CurShopOrderStatisticServiceImpl.java b/src/main/java/com/czg/mergedata/cur/service/impl/CurShopOrderStatisticServiceImpl.java new file mode 100644 index 0000000..28fb269 --- /dev/null +++ b/src/main/java/com/czg/mergedata/cur/service/impl/CurShopOrderStatisticServiceImpl.java @@ -0,0 +1,351 @@ +package com.czg.mergedata.cur.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.collection.ListUtil; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.date.LocalDateTimeUtil; +import com.czg.mergedata.common.resp.CzgResult; +import com.czg.mergedata.cur.entity.*; +import com.czg.mergedata.cur.mapper.CurShopOrderStatisticMapper; +import com.czg.mergedata.cur.mapper.CurShopProdStatisticMapper; +import com.czg.mergedata.cur.mapper.CurShopTableOrderStatisticMapper; +import com.czg.mergedata.cur.service.*; +import com.mybatisflex.core.query.QueryWrapper; +import com.mybatisflex.spring.service.impl.ServiceImpl; +import jakarta.annotation.Resource; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.sql.Date; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; + +/** + * 订单统计表 服务层实现。 + * + * @author mac + * @since 2025-03-19 + */ +@Service +@Slf4j +public class CurShopOrderStatisticServiceImpl extends ServiceImpl implements CurShopOrderStatisticService { + @Resource + private CurShopProdStatisticMapper curShopProdStatisticMapper; + + @Resource + private CurShopProdStatisticService curShopProdStatisticService; + + @Resource + private CurShopTableOrderStatisticMapper curShopTableOrderStatisticMapper; + + @Resource + private CurShopTableOrderStatisticService curShopTableOrderStatisticService; + + @Resource + private CurOrderInfoService orderInfoService; + + @Resource + private CurShopTableService shopTableService; + @Resource + private CurShopUserFlowService shopUserFlowService; + @Resource + private CurOrderDetailService orderDetailService; + + @Data + private static class ProdStatisticTask{ + private BigDecimal successCount = BigDecimal.ZERO; + private BigDecimal successAmount = BigDecimal.ZERO; + private BigDecimal refundCount = BigDecimal.ZERO; + private BigDecimal refundAmount = BigDecimal.ZERO; + } + + @Data + private static class TableStatisticTask{ + private long successCount = 0; + private BigDecimal successAmount = BigDecimal.ZERO; + private long refundCount = 0; + private BigDecimal refundAmount = BigDecimal.ZERO; + } + + @Override + public CzgResult statisticOrderData() { + getMapper().truncateTable(); + curShopProdStatisticMapper.truncateTable(); + curShopTableOrderStatisticMapper.truncateTable(); + + startStsData(); + + return CzgResult.success("订单统计数据清理成功"); + } + + private void startStsData() { + AtomicInteger refundIndex = new AtomicInteger(0); + LocalDateTime localDateTime = LocalDateTime.now(); + CurOrderInfo firstOrderInfo = orderInfoService.getOne(QueryWrapper.create().orderBy("create_time asc")); + + LocalDateTime time = firstOrderInfo.getCreateTime(); + + LocalDateTime endTime = LocalDateTime.now().minusDays(1); + LocalDateTime endOfDay = LocalDateTimeUtil.endOfDay(endTime); + List stsDays = new ArrayList<>(); + while (time.isBefore(endOfDay)) { + stsDays.add(time); + time = time.plusDays(1); + } + + System.out.println("stsDays size: " + stsDays.size()); + + List> lists = ListUtil.splitAvg(stsDays, 7); + + List> futures = new ArrayList<>(); + +// lists.stream() +// .flatMap(List::stream) +// .forEach(stsDay -> { +// CompletableFuture future = CompletableFuture.runAsync(() -> { +// stsOrderData(stsDay); +// stsProdData(stsDay); +// stsTableData(stsDay); +// }).whenComplete((m, k) -> { +// LocalDateTime end = LocalDateTime.now(); +// log.info("当前任务完成 当前耗时:{}秒", LocalDateTimeUtil.between(localDateTime, end, ChronoUnit.SECONDS)); +// refundIndex.incrementAndGet(); +// log.info("当前进度:{}", refundIndex.get()); +// }); +// futures.add(future); +// }); + + for (List list : lists) { + CompletableFuture future = CompletableFuture.runAsync(() -> { + for (LocalDateTime stsDay : list) { + stsOrderData(stsDay); + stsProdData(stsDay); + stsTableData(stsDay); + } + }).whenComplete((m, k) -> { + LocalDateTime end = LocalDateTime.now(); + log.info("当前任务完成 当前耗时:{}秒", LocalDateTimeUtil.between(localDateTime, end, ChronoUnit.SECONDS)); + refundIndex.incrementAndGet(); + log.info("当前进度:{}", refundIndex.get()); + }); + futures.add(future); + } + + CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).whenComplete((m, k) -> { + LocalDateTime end = LocalDateTime.now(); + log.info("所有任务已经完成 当前耗时:{}秒", LocalDateTimeUtil.between(localDateTime, end, ChronoUnit.SECONDS)); + }); + } + + private void stsOrderData(LocalDateTime date) { + // 获取前一天的开始时间(00:00:00) + LocalDateTime startOfDay = LocalDateTimeUtil.beginOfDay(date); + // 获取前一天的结束时间(23:59:59) + LocalDateTime endOfDay = LocalDateTimeUtil.endOfDay(date); + List orderInfos = orderInfoService.list(new QueryWrapper() + .ge(CurOrderInfo::getCreateTime, startOfDay) + .le(CurOrderInfo::getCreateTime, endOfDay) + .ne(CurOrderInfo::getStatus, "unpaid").ne(CurOrderInfo::getStatus, "cancelled")); + + // 统计充值记录 + Map flowMap = shopUserFlowService.list(new QueryWrapper() + .ge(CurShopUserFlow::getCreateTime, startOfDay) + .le(CurShopUserFlow::getCreateTime, endOfDay) + .in(CurShopUserFlow::getBizCode, CollUtil.newArrayList("cashIn", "wechatIn", "alipayIn", "awardIn"))).stream() + .collect(Collectors.groupingBy( + CurShopUserFlow::getShopId, + Collectors.reducing( + BigDecimal.ZERO, + CurShopUserFlow::getAmount, + BigDecimal::add + ) + )); + + HashMap countInfo = new HashMap<>(); + for (CurOrderInfo item : orderInfos) { + CurShopOrderStatistic statisticTask = countInfo.get(item.getShopId()); + if (statisticTask == null) { + countInfo.put(item.getShopId(), statisticTask = new CurShopOrderStatistic()); + } + + BigDecimal bigDecimal = flowMap.get(item.getShopId()); + if (bigDecimal != null) { + statisticTask.setRechargeAmount(bigDecimal); + } + + if ("refunding".equals(item.getStatus()) || "refund".equals(item.getStatus()) || "part-refund".equals(item.getStatus())) { + statisticTask.setRefundAmount(statisticTask.getRefundAmount().add(item.getRefundAmount())); + statisticTask.setRefundCount(statisticTask.getRefundCount() + 1); + if (item.getRefundAmount().compareTo(item.getPayAmount()) < 0) { + statisticTask.setSaleAmount(statisticTask.getSaleAmount().add(item.getPayAmount().subtract(item.getRefundAmount()))); + } + } else { + statisticTask.setSaleCount(statisticTask.getSaleCount() + 1); + statisticTask.setSaleAmount(statisticTask.getSaleAmount().add(item.getPayAmount())); + } + + + + switch (item.getPayType()) { + case "wechat-mini": + statisticTask.setWechatPayAmount(statisticTask.getWechatPayAmount().add(item.getPayAmount())); + statisticTask.setWechatPayCount(statisticTask.getWechatPayCount() + 1); + break; + case "main-scan", "back-scan": + statisticTask.setScanPayAmount(statisticTask.getScanPayAmount().add(item.getPayAmount())); + statisticTask.setScanPayCount(statisticTask.getScanPayCount() + 1); + break; + case "alipay-mini": + statisticTask.setAliPayAmount(statisticTask.getAliPayAmount().add(item.getPayAmount())); + statisticTask.setAliPayCount(statisticTask.getAliPayCount() + 1); + break; + case "vip-pay": + statisticTask.setMemberPayAmount(statisticTask.getMemberPayAmount().add(item.getPayAmount())); + statisticTask.setMemberPayCount(statisticTask.getMemberPayCount() + 1); + break; + case "credit-pay": + statisticTask.setCreditPayAmount(statisticTask.getCreditPayAmount().add(item.getPayAmount())); + statisticTask.setCreditPayCount(statisticTask.getCreditPayCount() + 1); + break; + case "cash-pay": + statisticTask.setCashPayAmount(statisticTask.getCashPayAmount().add(item.getPayAmount())); + statisticTask.setCashPayCount(statisticTask.getCashPayCount() + 1); + } + } + + countInfo.forEach((shopId, info) -> { + Date format = DateUtil.parseDate(LocalDateTimeUtil.format(date, "yyyy-MM-dd")).toSqlDate(); + CurShopOrderStatistic statistic = getOne(new QueryWrapper().eq(CurShopOrderStatistic::getShopId, shopId).eq(CurShopOrderStatistic::getCreateDay, format)); + if (statistic == null) { + statistic = new CurShopOrderStatistic(); + statistic.setShopId(shopId); + statistic.setCreateDay(format); + } + BigDecimal totalAmount = statistic.getSaleAmount().add(statistic.getRefundAmount()); + BigDecimal totalCount = BigDecimal.valueOf(statistic.getSaleCount() + statistic.getRefundCount()); +// 充值金额 +// statistic.setRechargeAmount(BigDecimal.ZERO); + //客单价 + if (totalAmount.compareTo(BigDecimal.ZERO) != 0) { + statistic.setCustomerUnitPrice(totalAmount.divide(totalCount, 2, RoundingMode.DOWN)); + } + + // 查询台桌数量 + long count = shopTableService.count(new QueryWrapper().eq(CurShopTable::getShopId, shopId)); + + //翻台率 + if (count > 0) { + statistic.setTableTurnoverRate(totalCount.subtract(BigDecimal.valueOf(count)).divide(BigDecimal.valueOf(count), 2, RoundingMode.DOWN).multiply(BigDecimal.valueOf(100))); + } + statistic.setUpdateTime(LocalDateTime.now()); + BeanUtil.copyProperties(info, statistic); + statistic.setShopId(shopId); + statistic.setCreateDay(format); + saveOrUpdate(statistic); + }); + } + + private void stsProdData(LocalDateTime date) { + // 获取前一天的开始时间(00:00:00) + LocalDateTime startOfDay = LocalDateTimeUtil.beginOfDay(date); + // 获取前一天的结束时间(23:59:59) + LocalDateTime endOfDay = LocalDateTimeUtil.endOfDay(date); + List orderDetails = orderDetailService.list(new QueryWrapper() + .ge(CurOrderDetail::getCreateTime, startOfDay) + .le(CurOrderDetail::getCreateTime, endOfDay) + .ne(CurOrderDetail::getStatus, "wait-pay")); + + + HashMap> countInfo = new HashMap<>(); + for (CurOrderDetail item : orderDetails) { + Map map = countInfo.computeIfAbsent(item.getShopId(), k -> new HashMap<>()); + ProdStatisticTask statisticTask = map.get(item.getProductId()); + if (statisticTask == null) { + map.put(item.getProductId(), statisticTask = new ProdStatisticTask()); + } + if ("refunding".equals(item.getStatus()) || "refund".equals(item.getStatus()) || "part-refund".equals(item.getStatus())) { + statisticTask.setRefundAmount(statisticTask.getRefundAmount().add(item.getReturnAmount())); + statisticTask.setRefundCount(statisticTask.getRefundCount().add(item.getRefundNum())); + if (item.getReturnNum().compareTo(item.getNum()) < 0) { + statisticTask.setSuccessAmount(statisticTask.getSuccessAmount().add(item.getPayAmount().subtract(item.getReturnAmount()))); + statisticTask.setSuccessCount(statisticTask.getSuccessCount().add(item.getNum().subtract(item.getReturnAmount()))); + } + }else { + statisticTask.setSuccessCount(statisticTask.getSuccessCount().add(item.getNum())); + statisticTask.setSuccessAmount(statisticTask.getSuccessAmount().add(item.getPayAmount())); + } + } + + countInfo.forEach((shopId, map) -> map.forEach((productId, statisticTask) -> { + Date format = DateUtil.parseDate(LocalDateTimeUtil.format(date, "yyyy-MM-dd")).toSqlDate(); + CurShopProdStatistic statistic = curShopProdStatisticService.getOne(new QueryWrapper().eq(CurShopProdStatistic::getShopId, shopId).eq(CurShopProdStatistic::getCreateDay, format)); + if (statistic == null) { + statistic = new CurShopProdStatistic(); + statistic.setShopId(shopId); + statistic.setCreateDay(format); + } + statistic.setProdId(productId); + statistic.setSaleCount(statisticTask.getSuccessCount()); + statistic.setSaleAmount(statisticTask.getSuccessAmount()); + statistic.setRefundCount(statisticTask.getRefundCount()); + statistic.setRefundAmount(statisticTask.getRefundAmount()); + curShopProdStatisticService.saveOrUpdate(statistic); + })); + } + + private void stsTableData(LocalDateTime date) { + // 获取前一天的开始时间(00:00:00) + LocalDateTime startOfDay = LocalDateTimeUtil.beginOfDay(date); + // 获取前一天的结束时间(23:59:59) + LocalDateTime endOfDay = LocalDateTimeUtil.endOfDay(date); + List orderInfos = orderInfoService.list(new QueryWrapper() + .ge(CurOrderInfo::getCreateTime, startOfDay) + .le(CurOrderInfo::getCreateTime, endOfDay) + .ne(CurOrderInfo::getStatus, "unpaid").ne(CurOrderInfo::getStatus, "cancelled")); + + HashMap countInfo = new HashMap<>(); + for (CurOrderInfo item : orderInfos) { + TableStatisticTask statisticTask = countInfo.get(item.getShopId()); + if (statisticTask == null) { + countInfo.put(item.getShopId(), statisticTask = new TableStatisticTask()); + } + if ("refunding".equals(item.getStatus()) || "refund".equals(item.getStatus()) || "part-refund".equals(item.getStatus())) { + statisticTask.setRefundAmount(statisticTask.getRefundAmount().add(item.getRefundAmount())); + statisticTask.setRefundCount(statisticTask.getRefundCount() + 1); + if (item.getRefundAmount().compareTo(item.getPayAmount()) < 0) { + statisticTask.setSuccessAmount(statisticTask.getSuccessAmount().add(item.getPayAmount().subtract(item.getRefundAmount()))); + } + }else { + statisticTask.setSuccessCount(statisticTask.getSuccessCount() + 1); + statisticTask.setSuccessAmount(statisticTask.getSuccessAmount().add(item.getPayAmount())); + } + } + + countInfo.forEach((shopId, statisticTask) -> { + Date format = Date.valueOf(LocalDateTimeUtil.format(date, "yyyy-MM-dd")); + CurShopTableOrderStatistic statistic = curShopTableOrderStatisticService.getOne(new QueryWrapper().eq(CurShopTableOrderStatistic::getShopId, shopId).eq(CurShopTableOrderStatistic::getCreateDay, format)); + if (statistic == null) { + statistic = new CurShopTableOrderStatistic(); + statistic.setShopId(shopId); + statistic.setTableId(0L); + statistic.setCreateDay(format); + } + statistic.setOrderCount(statisticTask.getSuccessCount()); + statistic.setOrderAmount(statisticTask.getSuccessAmount()); + statistic.setRefundCount(statisticTask.getRefundCount()); + statistic.setRefundAmount(statisticTask.getRefundAmount()); + curShopTableOrderStatisticService.saveOrUpdate(statistic); + }); + } +} diff --git a/src/main/java/com/czg/mergedata/cur/service/impl/CurShopProdStatisticServiceImpl.java b/src/main/java/com/czg/mergedata/cur/service/impl/CurShopProdStatisticServiceImpl.java new file mode 100644 index 0000000..a94b3a8 --- /dev/null +++ b/src/main/java/com/czg/mergedata/cur/service/impl/CurShopProdStatisticServiceImpl.java @@ -0,0 +1,18 @@ +package com.czg.mergedata.cur.service.impl; + +import com.mybatisflex.spring.service.impl.ServiceImpl; +import com.czg.mergedata.cur.entity.CurShopProdStatistic; +import com.czg.mergedata.cur.mapper.CurShopProdStatisticMapper; +import com.czg.mergedata.cur.service.CurShopProdStatisticService; +import org.springframework.stereotype.Service; + +/** + * 商品统计表 服务层实现。 + * + * @author mac + * @since 2025-03-19 + */ +@Service +public class CurShopProdStatisticServiceImpl extends ServiceImpl implements CurShopProdStatisticService{ + +} diff --git a/src/main/java/com/czg/mergedata/cur/service/impl/CurShopTableOrderStatisticServiceImpl.java b/src/main/java/com/czg/mergedata/cur/service/impl/CurShopTableOrderStatisticServiceImpl.java new file mode 100644 index 0000000..79ad9c0 --- /dev/null +++ b/src/main/java/com/czg/mergedata/cur/service/impl/CurShopTableOrderStatisticServiceImpl.java @@ -0,0 +1,18 @@ +package com.czg.mergedata.cur.service.impl; + +import com.mybatisflex.spring.service.impl.ServiceImpl; +import com.czg.mergedata.cur.entity.CurShopTableOrderStatistic; +import com.czg.mergedata.cur.mapper.CurShopTableOrderStatisticMapper; +import com.czg.mergedata.cur.service.CurShopTableOrderStatisticService; +import org.springframework.stereotype.Service; + +/** + * 台桌订单统计表 服务层实现。 + * + * @author mac + * @since 2025-03-19 + */ +@Service +public class CurShopTableOrderStatisticServiceImpl extends ServiceImpl implements CurShopTableOrderStatisticService{ + +} diff --git a/src/main/resources/mapper/cur/ShopOrderStatisticMapper.xml b/src/main/resources/mapper/cur/ShopOrderStatisticMapper.xml new file mode 100644 index 0000000..0c477e5 --- /dev/null +++ b/src/main/resources/mapper/cur/ShopOrderStatisticMapper.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/src/main/resources/mapper/cur/ShopProdStatisticMapper.xml b/src/main/resources/mapper/cur/ShopProdStatisticMapper.xml new file mode 100644 index 0000000..a26b3cd --- /dev/null +++ b/src/main/resources/mapper/cur/ShopProdStatisticMapper.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/src/main/resources/mapper/cur/ShopTableOrderStatisticMapper.xml b/src/main/resources/mapper/cur/ShopTableOrderStatisticMapper.xml new file mode 100644 index 0000000..cb5ea25 --- /dev/null +++ b/src/main/resources/mapper/cur/ShopTableOrderStatisticMapper.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/收银机数据迁移关系.md b/收银机数据迁移关系.md index ca7a074..99dae93 100644 --- a/收银机数据迁移关系.md +++ b/收银机数据迁移关系.md @@ -212,4 +212,13 @@ - tb_prod_cons_relation 表 +### 30. 统计订单数据 +> /merge/statistic/order +#### 执行表 +- tb_shop_order_statistic 表 +- tb_shop_prod_statistic 表 +- tb_shop_table_order_statistic 表 + + +