This commit is contained in:
2025-11-22 14:02:20 +08:00
parent 98a04f8fbe
commit 381ae80eeb
59 changed files with 1930 additions and 1817 deletions

View File

@@ -1,33 +1,269 @@
package com.czg.service.order.mapper;
import com.czg.order.entity.ShopOrderStatistic;
import com.czg.order.param.DataSummaryTradeParam;
import com.czg.order.vo.TotalVo;
import com.mybatisflex.core.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import com.czg.order.entity.ShopOrderStatistic;
import org.apache.ibatis.annotations.Select;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.List;
import java.util.Map;
/**
* 映射层。
* 店铺订单统计报表 映射层。
*
* @author zs
* @since 2025-03-07
* @author ww
* @since 2025-11-20
*/
@Mapper
public interface ShopOrderStatisticMapper extends BaseMapper<ShopOrderStatistic> {
ShopOrderStatistic getTradeData(DataSummaryTradeParam param);
long getNewMemberCount(DataSummaryTradeParam param);
List<Map<String, Object>> getPayTypeAmountCount(DataSummaryTradeParam param);
@Select("SELECT"+
" SUM(pay_amount) AS payAmount,"+
" SUM(online_pay_amount) AS onlinePayAmount,"+
" SUM(member_pay_amount) AS memberPayAmount,"+
" SUM(member_pay_count) AS memberPayCount,"+
" SUM(refund_amount) AS refundAmount,"+
" SUM(online_refund_amount) AS onlineRefundAmount,"+
" SUM(recharge_amount) AS rechargeAmount,"+
" SUM(online_recharge_amount) AS onlineRechargeAmount,"+
" SUM(give_amount) AS giveAmount,"+
" SUM(recharge_refund_amount) AS rechargeRefundAmount,"+
" SUM(online_recharge_refund_amount) AS onlineRechargeRefundAmount,"+
" SUM(cash_recharge_refund_amount) AS cashRechargeRefundAmount,"+
" SUM(cash_recharge_amount) AS cashRechargeAmount,"+
" SUM(member_refund_amount) AS memberRefundAmount,"+
" SUM(cash_refund_amount) AS cashRefundAmount,"+
" SUM(new_member_count) AS newMemberCount,"+
" SUM(customer_count) AS customerCount,"+
" SUM(order_count) AS orderCount,"+
" SUM(table_count) AS tableCount,"+
" SUM(avg_pay_amount) AS avgPayAmount,"+
" SUM(turnover_rate) AS turnoverRate,"+
" SUM(profit_amount) AS profitAmount,"+
" SUM(product_cost_amount) AS productCostAmount,"+
" SUM(profit_rate) AS profitRate,"+
" SUM(net_profit_amount) AS netProfitAmount,"+
" SUM(net_profit_rate) AS netProfitRate,"+
" SUM(discount_amount) AS discountAmount,"+
" SUM(discount_count) AS discountCount,"+
" SUM(new_customer_discount_amount) AS newCustomerDiscountAmount,"+
" SUM(full_discount_amount) AS fullDiscountAmount,"+
" SUM(coupon_discount_amount) AS couponDiscountAmount,"+
" SUM(point_discount_amount) AS pointDiscountAmount,"+
" SUM(back_discount_amount) AS backDiscountAmount,"+
" SUM(member_discount_amount) AS memberDiscountAmount,"+
" SUM(order_price_discount_amount) AS orderPriceDiscountAmount,"+
" SUM(cash_pay_amount) AS cashPayAmount,"+
" SUM(wechat_pay_amount) AS wechatPayAmount,"+
" SUM(alipay_pay_amount) AS alipayPayAmount,"+
" SUM(back_scan_pay_amount) AS backScanPayAmount,"+
" SUM(main_scan_pay_amount) AS mainScanPayAmount,"+
" SUM(credit_pay_amount) AS creditPayAmount "+
"FROM"+
" tb_shop_order_statistic " +
"WHERE " +
" shop_id = #{shopId} " +
" AND statistic_date BETWEEN #{start} AND #{end} ")
ShopOrderStatistic countStatistic(Long shopId, LocalDate start, LocalDate end);
//---------------------------------------------金额统计---------------------------------------------------
/**
* 订单金额统计 当日实时数据
*/
@Select("SELECT" +
" SUM(origin_amount) as orderAmount, " +
" SUM(order_amount) as actualAmount, " +
" SUM(origin_amount - order_amount) as discountAmount, " +
" trade_day as tradeDay" +
" FROM" +
" tb_order_info " +
" WHERE" +
" shop_id = #{shopId} " +
"and trade_day = #{tradeDay} " +
"and paid_time is not null " +
"GROUP BY trade_day desc")
TotalVo getOnlineDataAmount(Long shopId, LocalDate tradeDay);
List<Map<String, Object>> getVipRechargeAmountCount(DataSummaryTradeParam param);
/**
* 订单金额统计 按日期范围查询
*/
@Select("SELECT" +
" SUM(origin_amount) as orderAmount, " +
" SUM(order_amount) as actualAmount, " +
" SUM(origin_amount - order_amount) as discountAmount, " +
" statistic_date as tradeDay" +
" FROM" +
" tb_shop_order_statistic " +
" WHERE" +
" shop_id = #{shopId} " +
"and statistic_date >= #{start} " +
"and statistic_date <= #{end} " +
"GROUP BY tradeDay asc")
List<TotalVo> getStatDateRange(Long shopId, LocalDate start, LocalDate end);
BigDecimal getCustomerUnitPrice(DataSummaryTradeParam param);
/**
* 订单支付方式统计 当日实时数据
*/
@Select("SELECT" +
" SUM(CASE WHEN pay_type = 'main_scan' THEN pay_amount ELSE 0 END) AS mainScanPay," +
" SUM(CASE WHEN pay_type = 'back_scan' THEN pay_amount ELSE 0 END) AS backScanPay," +
" SUM(CASE WHEN pay_type = 'wechat_mini' THEN pay_amount ELSE 0 END) AS wechatPay," +
" SUM(CASE WHEN pay_type = 'alipay_mini' THEN pay_amount ELSE 0 END) AS alipayPay," +
" SUM(CASE WHEN pay_type = 'vip_pay' THEN pay_amount ELSE 0 END) AS memberPay," +
" SUM(CASE WHEN pay_type = 'cash_pay' THEN pay_amount ELSE 0 END) AS cashPay," +
" SUM(CASE WHEN pay_type = 'credit_pay' THEN pay_amount ELSE 0 END) AS creditPay" +
" FROM" +
" tb_order_info " +
" WHERE" +
" shop_id = #{shopId} " +
"and trade_day = #{tradeDay} " +
"and paid_time is not null ")
Map<String, Integer> getOnlinePayTypeDate(Long shopId, LocalDate tradeDay);
BigDecimal getTableTurnoverRate(DataSummaryTradeParam param);
/**
* 订单支付方式统计 按日期范围查询
*/
@Select("SELECT" +
" SUM(member_pay_count) as memberPay, " +
" SUM(cash_pay_count) as cashPay, " +
" SUM(wechat_pay_count) as wechatPay, " +
" SUM(alipay_pay_count) as alipayPay, " +
" SUM(main_scan_pay_count) as mainScanPay, " +
" SUM(back_scan_pay_count) as backScanPay, " +
" SUM(credit_pay_count) as creditPay " +
" FROM tb_shop_order_statistic " +
" WHERE shop_id = #{shopId} " +
" AND statistic_date >= #{start} " +
" AND statistic_date <= #{end} ")
Map<String, Integer> getPayTypeDateRangeRaw(Long shopId, LocalDate start, LocalDate end);
//*********************以下为日常统计********************************************************************************
/**
* 统计某日支付数据 当日实时数据/昨日数据落地
* order 订单支付
* refund 订单退款
* free 霸王餐
* memberIn 会员充值
* memberRefund 会员充值的退款
*/
@Select("SELECT " +
" SUM(CASE WHEN pay_type = 'order' THEN amount ELSE 0 END) AS onlinePayAmount," +
" SUM(CASE WHEN pay_type = 'refund' THEN amount ELSE 0 END) AS onlineRefundAmount," +
" SUM(CASE WHEN pay_type = 'free' THEN amount ELSE 0 END) AS backDiscountAmount," +
" SUM(CASE WHEN pay_type = 'memberIn' THEN amount ELSE 0 END) AS onlineRechargeAmount, " +
" SUM(CASE WHEN pay_type = 'memberRefund' THEN amount ELSE 0 END) AS onlineRechargeRefundAmount " +
"FROM" +
" tb_order_payment " +
"WHERE " +
" pay_status = 'success' " +
" AND shop_id = #{shopId}" +
" AND pay_type NOT IN ('memberPay', 'distribution', 'distributionRecharge')" +
" AND pay_date = #{tradeDay} ;")
ShopOrderStatistic getOnlineStatSingleDate(Long shopId, LocalDate tradeDay);
/**
* 统计某日订单数据 当日实时数据/昨日数据落地
*/
@Select("SELECT" +
" SUM(tb_order_info.origin_amount) AS originAmount," +
" SUM(CASE WHEN pay_type = 'main_scan' THEN pay_amount ELSE 0 END) AS mainScanPayAmount," +
" SUM(CASE WHEN pay_type = 'back_scan' THEN pay_amount ELSE 0 END) AS backScanPayAmount," +
" SUM(CASE WHEN pay_type = 'wechat_mini' THEN pay_amount ELSE 0 END) AS wechatPayAmount," +
" SUM(CASE WHEN pay_type = 'alipay_mini' THEN pay_amount ELSE 0 END) AS alipayPayAmount," +
" SUM(CASE WHEN pay_type = 'vip_pay' THEN pay_amount ELSE 0 END) AS memberPayAmount," +
" SUM(CASE WHEN pay_type = 'cash_pay' THEN pay_amount ELSE 0 END) AS cashPayAmount," +
" SUM(CASE WHEN pay_type = 'credit_pay' THEN pay_amount ELSE 0 END) AS creditPayAmount," +
" SUM(CASE WHEN pay_type = 'free_pay' THEN order_amount ELSE 0 END) AS backDiscountAmount," +
" " +
" SUM(CASE WHEN pay_type = 'vip_pay' THEN refund_amount ELSE 0 END) AS memberRefundAmount," +
" " +
" SUM(CASE WHEN pay_type = 'vip_pay' THEN 1 ELSE 0 END) as memberPayCount," +
" SUM(CASE WHEN pay_type = 'cash_pay' THEN 1 ELSE 0 END) as cashPayCount," +
" SUM(CASE WHEN pay_type = 'wechat_mini' THEN 1 ELSE 0 END) as wechatPayCount," +
" SUM(CASE WHEN pay_type = 'alipay_mini' THEN 1 ELSE 0 END) as alipayPayCount," +
" SUM(CASE WHEN pay_type = 'back_scan' THEN 1 ELSE 0 END) as backScanPayCount," +
" SUM(CASE WHEN pay_type = 'main_scan' THEN 1 ELSE 0 END) as mainScanPayCount," +
" SUM(CASE WHEN pay_type = 'credit_pay' THEN 1 ELSE 0 END) as creditPayCount," +
" " +
" SUM(refund_amount) as refundAmount," +
" " +
" SUM(new_customer_discount_amount) as newCustomerDiscountAmount," +
" SUM(discount_act_amount) as fullDiscountAmount," +
" SUM(product_coupon_discount_amount) + SUM(other_coupon_discount_amount) as couponDiscountAmount," +
" SUM(points_discount_amount) as pointDiscountAmount," +
" SUM(vip_discount_amount) as memberDiscountAmount," +
" SUM(discount_amount) as orderPriceDiscountAmount ," +
" count(1) as orderCount," +
" sum(CASE WHEN seat_num IS NULL OR seat_num <= 0 THEN 1 ELSE seat_num END) as customerCount " +
"FROM" +
" tb_order_info " +
"WHERE" +
" shop_id = #{shopId} " +
"and trade_day = #{tradeDay} " +
"and paid_time is not null")
ShopOrderStatistic getOrderStatSingleDate(Long shopId, LocalDate tradeDay);
/**
* 统计某日用户用户余额数据 当日实时数据/昨日数据落地
*/
@Select("SELECT " +
" SUM(CASE WHEN biz_code = 'cashIn' THEN amount ELSE 0 END) AS cashRechargeAmount, " +
" SUM(CASE WHEN biz_code = 'awardIn' THEN amount ELSE 0 END) AS giveAmount, " +
" SUM(CASE WHEN biz_code = 'cashRefund' THEN amount ELSE 0 END) AS cashRechargeRefundAmount " +
"FROM " +
" tb_shop_user_flow " +
"WHERE " +
" shop_id = #{shopId} " +
" AND trade_day = #{tradeDay} ;")
ShopOrderStatistic getShopUserFlowStatSingleDate(Long shopId, LocalDate tradeDay);
/**
* 优惠笔数 discountCount
*/
@Select("SELECT count(*) " +
"FROM tb_order_info WHERE shop_id = #{shopId} and trade_day = #{tradeDay} and paid_time is not null and discount_all_amount > 0")
Long countDiscountOrder(Long shopId, LocalDate tradeDay);
/**
* 优惠总金额 discountAmount
*/
@Select("SELECT sum(discount_all_amount) " +
"FROM tb_order_info WHERE shop_id = #{shopId} and trade_day = #{tradeDay} and paid_time is not null and discount_all_amount > 0")
BigDecimal countDiscountAmount(Long shopId, LocalDate tradeDay);
/**
* 统计店铺桌台数 tableCount
*/
@Select("SELECT count(*) FROM tb_order_info WHERE shop_id = #{shopId} and status != 'unbound'")
Long countShopTable(Long shopId);
/**
* 新增会员数 newMemberCount
*/
@Select("SELECT count(*) FROM tb_shop_user WHERE main_shop_id = #{mainShopId} and is_vip = 1 " +
"AND join_time BETWEEN CONCAT(#{tradeDay}, ' 00:00:00') AND CONCAT(#{tradeDay}, ' 23:59:59')")
Long countNewMember(Long mainShopId, LocalDate tradeDay);
/**
* 商品成本 productCostAmount
*/
@Select("SELECT " +
" SUM(CASE WHEN sku.cost_price IS NULL OR sku.cost_price <= 0 THEN 0 ELSE sku.cost_price END) AS productCostAmount " +
"FROM " +
" tb_order_info `order` " +
" INNER JOIN tb_order_detail detail ON `order`.id = detail.order_id " +
" AND is_temporary = 0 " +
" LEFT JOIN tb_prod_sku sku ON detail.sku_id = sku.id " +
"WHERE " +
" `order`.shop_id = #{shopId} " +
" and trade_day = #{tradeDay} " +
" and paid_time is not null")
BigDecimal countProductCostAmount(Long shopId, LocalDate tradeDay);
List<Long> getShopIdList();
}

View File

@@ -1,33 +1,33 @@
package com.czg.service.order.mapper;
import com.czg.order.entity.ShopProdStatistic;
import com.czg.order.param.DataSummaryProductSaleParam;
import com.czg.order.param.SaleSummaryCountParam;
import com.czg.order.vo.DataSummaryProductSaleRankingVo;
import com.czg.order.vo.SaleSummaryCountVo;
import com.czg.order.vo.SaleSummaryInfoVo;
import com.mybatisflex.core.BaseMapper;
import com.czg.order.entity.ShopProdStatistic;
import java.time.LocalDate;
import java.util.List;
/**
* 映射层。
* 商品统计表 映射层。
*
* @author zs
* @since 2025-03-07
* @author ww
* @since 2025-11-21
*/
public interface ShopProdStatisticMapper extends BaseMapper<ShopProdStatistic> {
List<DataSummaryProductSaleRankingVo> findProdRandingSummaryPage(DataSummaryProductSaleParam param);
/**
* 根据店铺id和日期 统计商品
*/
List<ShopProdStatistic> selectProStatByDay(Long shopId, LocalDate day, String productName);
List<DataSummaryProductSaleRankingVo> findProdRandingSummaryPage2(DataSummaryProductSaleParam param);
List<ShopProdStatistic> getProdStatSingleDate(Long shopId, LocalDate day, String productName);
SaleSummaryCountVo getSaleSummaryCount(SaleSummaryCountParam param);
List<ShopProdStatistic> getProdStatDateRange(Long shopId, LocalDate start, LocalDate end, String productName);
SaleSummaryCountVo getSaleSummaryCount2(SaleSummaryCountParam param);
List<SaleSummaryInfoVo> findSaleSummaryList(SaleSummaryCountParam param);
List<SaleSummaryInfoVo> findSaleSummaryList2(SaleSummaryCountParam param);
//-----------------总统计 总金额统计-----------------
SaleSummaryCountVo summaryCountByDay(Long shopId, LocalDate day, String productName);
SaleSummaryCountVo summaryCountSingleDate(Long shopId, LocalDate day, String productName);
SaleSummaryCountVo summaryCountDateRange(Long shopId, LocalDate start, LocalDate end, String productName);
}

View File

@@ -3,27 +3,88 @@ package com.czg.service.order.mapper;
import com.czg.order.entity.ShopTableOrderStatistic;
import com.czg.order.param.TableSummaryParam;
import com.czg.order.vo.TableSummaryExportVo;
import com.czg.order.vo.TableSummaryInfoVo;
import com.mybatisflex.core.BaseMapper;
import org.apache.ibatis.annotations.Select;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.List;
/**
* 台桌订单统计表 映射层。
*
* @author zs
* @since 2025-03-07
* @author ww
* @since 2025-11-21
*/
public interface ShopTableOrderStatisticMapper extends BaseMapper<ShopTableOrderStatistic> {
List<ShopTableOrderStatistic> selectSummary(Long shopId, String startTime, String endTime);
boolean incrInfo(long shopId, long tableId, long count, BigDecimal amount, String dateStr);
List<TableSummaryInfoVo> findSummaryList(TableSummaryParam param);
/**
* 获取指定天的在线数据台桌
*
* @param shopId 店铺ID
* @param tradeDay 时间 yyyy-MM-dd
*/
@Select("SELECT " +
" `table`.id AS tableId, " +
" `table`.table_code AS tableCode, " +
" `table`.`name` AS tableName, " +
" `area`.`name` AS areaName, " +
" count( `order`.id ) AS orderCount, " +
" SUM( CASE WHEN `order`.pay_type = 'free_pay' THEN `order`.order_amount ELSE `order`.pay_amount END ) AS orderAmount, " +
" SUM( CASE WHEN `order`.refund_amount > 0 THEN 1 ELSE 0 END ) AS refundCount, " +
" SUM( `order`.refund_amount ) AS refundAmount " +
"FROM " +
" tb_order_info `order` " +
" INNER JOIN tb_shop_table `table` ON `order`.shop_id = `table`.shop_id " +
" AND `order`.table_code = `table`.table_code " +
" LEFT JOIN tb_shop_table_area `area` ON `table`.area_id = `area`.id " +
" AND `table`.shop_id = `area`.shop_id " +
"WHERE " +
" `order`.shop_id = #{shopId} " +
" AND `order`.trade_day = #{tradeDay} " +
" AND `order`.paid_time IS NOT NULL " +
" AND `order`.pay_mode != 'no-table'")
List<ShopTableOrderStatistic> getOnlineData(Long shopId, LocalDate tradeDay);
/**
* 获取指定天的台桌订单统计数据
*
* @param shopId 店铺ID
* @param tradeDay 时间 yyyy-MM-dd
*/
@Select("SELECT " +
" * " +
"FROM " +
" `tb_shop_table_order_statistic` " +
"WHERE " +
" shop_id = #{shopId} " +
" AND create_day = #{tradeDay}")
List<ShopTableOrderStatistic> getStatSingleDate(Long shopId, LocalDate tradeDay);
/**
* 获取指定时间范围内的台桌订单统计数据
*
* @param shopId 店铺ID
* @param startDate 开始时间 yyyy-MM-dd
* @param endDate 结束时间 yyyy-MM-dd
*/
@Select("SELECT" +
" id,table_id,table_code,table_name,area_name," +
" sum(order_count) as orderCount," +
" sum(order_amount) as orderAmount," +
" sum(refund_count) as refundCount," +
" sum(refund_amount) as refundAmount" +
" FROM" +
" tb_shop_table_order_statistic " +
"WHERE" +
" shop_id = #{shopId} " +
" AND create_day >=#{startDate} " +
" AND create_day <=#{endDate} " +
" GROUP BY table_id")
List<ShopTableOrderStatistic> getStatDateRange(Long shopId, LocalDate startDate, LocalDate endDate);
List<TableSummaryInfoVo> findSummaryList2(TableSummaryParam param);
List<TableSummaryExportVo> findSummaryExportList(TableSummaryParam param);
}

View File

@@ -4,7 +4,6 @@ import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.czg.account.dto.HandoverRecordDTO;
import com.czg.account.dto.PrintOrderDetailDTO;
@@ -578,7 +577,7 @@ public abstract class PrinterHandler {
* @return 是否退款
*/
protected static boolean isReturn(OrderInfo orderInfo) {
return ArrayUtil.contains(new String[]{"refunding", "part-refund", "refund"}, orderInfo.getStatus());
return ArrayUtil.contains(new String[]{"refunding", "part_refund", "refund"}, orderInfo.getStatus());
}

View File

@@ -1,220 +0,0 @@
package com.czg.service.order.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ReflectUtil;
import com.czg.order.entity.OrderInfo;
import com.czg.order.entity.ShopOrderStatistic;
import com.czg.order.enums.PayEnums;
import com.czg.order.param.DataSummaryProductSaleParam;
import com.czg.order.param.DataSummaryTradeParam;
import com.czg.order.service.DataSummaryService;
import com.czg.order.vo.DataSummaryDateAmountVo;
import com.czg.order.vo.DataSummaryPayTypeVo;
import com.czg.order.vo.DataSummaryProductSaleRankingVo;
import com.czg.order.vo.TotalVo;
import com.czg.service.order.mapper.OrderInfoMapper;
import com.czg.service.order.mapper.ShopOrderStatisticMapper;
import com.czg.service.order.mapper.ShopProdStatisticMapper;
import com.czg.utils.PageUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 数据统计Service实现类
*
* @author tankaikai
* @since 2025-03-07 15:32
*/
@Service
public class DataSummaryServiceImpl implements DataSummaryService {
@Resource
private ShopOrderStatisticMapper shopOrderStatisticMapper;
@Resource
private OrderInfoMapper orderInfoMapper;
@Resource
private ShopProdStatisticMapper shopProdStatisticMapper;
@Override
public ShopOrderStatistic getArchiveTradeData(DataSummaryTradeParam param) {
ShopOrderStatistic shopOrderStatistic = shopOrderStatisticMapper.getTradeData(param);
if(shopOrderStatistic == null){
shopOrderStatistic = new ShopOrderStatistic();
}
shopOrderStatistic.setCustomerUnitPrice(shopOrderStatistic.getCustomerUnitPrice().setScale(2, java.math.RoundingMode.HALF_UP));
shopOrderStatistic.setTableTurnoverRate(shopOrderStatistic.getTableTurnoverRate().setScale(2, java.math.RoundingMode.HALF_UP));
return shopOrderStatistic;
}
@Override
public ShopOrderStatistic getRealTimeTradeData(DataSummaryTradeParam param) {
List<String> funs = Arrays.asList("getPayTypeAmountCount", "getVipRechargeAmountCount", "getNewMemberCount", "getCustomerUnitPrice", "getTableTurnoverRate");
Map<String, Object> collect = funs.parallelStream().collect(Collectors.toMap(fun -> fun, fun ->
ReflectUtil.invoke(shopOrderStatisticMapper, fun, param)
));
/*Map<String, Object> collect = new ConcurrentHashMap<>();
for (String fun : funs) {
Object invoke = ReflectUtil.invoke(shopOrderStatisticMapper, fun, param);
collect.put(fun, ObjUtil.defaultIfNull(invoke,BigDecimal.ZERO));
}*/
ShopOrderStatistic data = new ShopOrderStatistic();
//List<Map<String, Object>> list = shopOrderStatisticMapper.getPayTypeAmountCount(param);
List<Map<String, Object>> list = (List<Map<String, Object>>) collect.get("getPayTypeAmountCount");
Map<String, BigDecimal> sum = list.stream().collect(Collectors.toMap(item -> Convert.toStr(item.get("payType")), item -> Convert.toBigDecimal(item.get("amount"))));
Map<String, Long> count = list.stream().collect(Collectors.toMap(item -> Convert.toStr(item.get("payType")), item -> Convert.toLong(item.get("count"))));
data.setWechatPayAmount(sum.getOrDefault(PayEnums.WECHAT_MINI.getValue(), BigDecimal.ZERO));
data.setWechatPayCount(count.getOrDefault(PayEnums.WECHAT_MINI.getValue(), 0L));
data.setAliPayAmount(sum.getOrDefault(PayEnums.ALIPAY_MINI.getValue(), BigDecimal.ZERO));
data.setAliPayCount(count.getOrDefault(PayEnums.ALIPAY_MINI.getValue(), 0L));
data.setScanPayAmount(sum.getOrDefault(PayEnums.MAIN_SCAN.getValue(), BigDecimal.ZERO));
data.setScanPayCount(count.getOrDefault(PayEnums.MAIN_SCAN.getValue(), 0L));
data.setCashPayAmount(sum.getOrDefault(PayEnums.CASH_PAY.getValue(), BigDecimal.ZERO));
data.setCashPayCount(count.getOrDefault(PayEnums.CASH_PAY.getValue(), 0L));
data.setCreditPayAmount(sum.getOrDefault(PayEnums.CREDIT_PAY.getValue(), BigDecimal.ZERO));
data.setCreditPayCount(count.getOrDefault(PayEnums.CREDIT_PAY.getValue(), 0L));
data.setBackScanPayAmount(sum.getOrDefault(PayEnums.BACK_SCAN.getValue(), BigDecimal.ZERO));
data.setBackScanPayCount(count.getOrDefault(PayEnums.BACK_SCAN.getValue(), 0L));
data.setH5PayAmount(sum.getOrDefault(PayEnums.H5_PAY.getValue(), BigDecimal.ZERO));
data.setH5PayCount(count.getOrDefault(PayEnums.H5_PAY.getValue(), 0L));
//List<Map<String, Object>> list1 = shopOrderStatisticMapper.getVipRechargeAmountCount(param);
List<Map<String, Object>> list1 = (List<Map<String, Object>>) collect.get("getVipRechargeAmountCount");
Map<String, BigDecimal> sum1 = list1.stream().collect(Collectors.toMap(item -> Convert.toStr(item.get("bizCode")), item -> Convert.toBigDecimal(item.get("amount"))));
Map<String, Long> count1 = list1.stream().collect(Collectors.toMap(item -> Convert.toStr(item.get("bizCode")), item -> Convert.toLong(item.get("count"))));
data.setRechargeAmount(NumberUtil.add(sum1.getOrDefault("cashIn", BigDecimal.ZERO), sum1.getOrDefault("wechatIn", BigDecimal.ZERO), sum1.getOrDefault("alipayIn", BigDecimal.ZERO)));
data.setRechargeRefundAmount(sum1.getOrDefault("rechargeRefund", BigDecimal.ZERO).abs());
data.setMemberPayAmount(sum1.getOrDefault("orderPay", BigDecimal.ZERO).abs());
data.setMemberPayCount(count1.getOrDefault("orderPay", 0L));
data.setSaleAmount(NumberUtil.add(data.getWechatPayAmount(), data.getAliPayAmount(), data.getScanPayAmount(), data.getCashPayAmount(), data.getCreditPayAmount(),data.getBackScanPayAmount(),data.getH5PayAmount()));
data.setSaleCount(NumberUtil.add(data.getWechatPayCount(), data.getAliPayCount(), data.getScanPayCount(), data.getCashPayCount(), data.getCreditPayCount(),data.getBackScanPayCount(),data.getH5PayCount()).longValue());
BigDecimal refundAmount = list.stream().filter(item -> item.get("payType") != null).map(item -> Convert.toBigDecimal(item.get("refund"), BigDecimal.ZERO)).reduce(BigDecimal.ZERO, BigDecimal::add);
data.setRefundAmount(refundAmount);
long refundCount = list.stream().filter(item -> item.get("payType") != null).map(item -> Convert.toLong(item.get("refundCount"), 0L)).reduce(0L, Long::sum);
data.setRefundCount(refundCount);
//long newMemberCount = shopOrderStatisticMapper.getNewMemberCount(param);
long newMemberCount = (long) collect.get("getNewMemberCount");
data.setNewMemberCount(newMemberCount);
//BigDecimal customerUnitPrice = shopOrderStatisticMapper.getCustomerUnitPrice(param);
BigDecimal customerUnitPrice = (BigDecimal) collect.get("getCustomerUnitPrice");
data.setCustomerUnitPrice(NumberUtil.nullToZero(customerUnitPrice).setScale(2, java.math.RoundingMode.HALF_UP));
//BigDecimal tableTurnoverRate = shopOrderStatisticMapper.getTableTurnoverRate(param);
BigDecimal tableTurnoverRate = (BigDecimal) collect.get("getTableTurnoverRate");
data.setTableTurnoverRate(tableTurnoverRate);
BigDecimal discountAmount = list.stream().filter(item -> item.get("payType") != null).map(item -> Convert.toBigDecimal(item.get("discount"), BigDecimal.ZERO)).reduce(BigDecimal.ZERO, BigDecimal::add);
long discountCount = list.stream().filter(item -> item.get("payType") != null).map(item -> Convert.toLong(item.get("discountCount"), 0L)).reduce(0L, Long::sum);
data.setDiscountAmount(discountAmount);
data.setDiscountCount(discountCount);
return data;
}
@Override
public Page<DataSummaryProductSaleRankingVo> getProductSaleRankingPage(DataSummaryProductSaleParam param) {
LocalDate now = LocalDate.now();
Integer day = param.getDay();
LocalDate beginDate = now.plusDays(-day);
List<String> days = new ArrayList<>();
for (int i = 1; i <= day; i++) {
String thisDay = beginDate.plusDays(i).format(DatePattern.NORM_DATE_FORMATTER);
days.add(thisDay);
}
param.setDays(days);
param.setBeginDate(days.getFirst() + " 00:00:00");
param.setEndDate(days.getLast() + " 23:59:59");
PageHelper.startPage(PageUtil.buildPageHelp());
PageInfo<DataSummaryProductSaleRankingVo> pageInfo = new PageInfo<>(shopProdStatisticMapper.findProdRandingSummaryPage(param));
return PageUtil.convert(pageInfo);
}
@Override
public DataSummaryDateAmountVo getSummaryAmountData(Long shopId, Integer day) {
LocalDate now = LocalDate.now();
LocalDate beginDate = now.plusDays(-day);
DataSummaryDateAmountVo data = new DataSummaryDateAmountVo();
List<TotalVo> total = new ArrayList<>();
for (int i = 1; i <= day; i++) {
String thisDay = beginDate.plusDays(i).format(DatePattern.NORM_DATE_FORMATTER);
OrderInfo orderInfo = orderInfoMapper.selectOneByQuery(QueryWrapper.create()
.select("ifnull(sum(order_amount),0) as order_amount,ifnull(sum(pay_amount),0) as pay_amount,ifnull(sum(order_amount-pay_amount),0) as discount_amount")
.eq(OrderInfo::getShopId, shopId)
.eq(OrderInfo::getTradeDay, thisDay)
.isNotNull(OrderInfo::getPaidTime)
);
TotalVo totalVo = new TotalVo();
if (orderInfo != null) {
totalVo.setOrderAmount(orderInfo.getOrderAmount());
totalVo.setActualAmount(orderInfo.getPayAmount());
totalVo.setDiscountAmount(orderInfo.getDiscountAmount());
}
totalVo.setTradeDay(thisDay);
total.add(totalVo);
}
data.setTotal(total);
return data;
}
@Override
public DataSummaryPayTypeVo getSummaryPayTypeData(Long shopId, Integer day) {
LocalDate now = LocalDate.now();
LocalDate beginDate = now.plusDays(-day);
DataSummaryPayTypeVo data = new DataSummaryPayTypeVo();
List<DataSummaryPayTypeVo.CountPayTypeVo> total = new ArrayList<>();
List<String> days = new ArrayList<>();
for (int i = 1; i <= day; i++) {
String thisDay = beginDate.plusDays(i).format(DatePattern.NORM_DATE_FORMATTER);
days.add(thisDay);
}
List<OrderInfo> orderList = orderInfoMapper.selectListByQuery(QueryWrapper.create()
.select("pay_type,count(1) as place_num")
.eq(OrderInfo::getShopId, shopId)
.in(OrderInfo::getTradeDay, days)
.isNotNull(OrderInfo::getPaidTime)
.groupBy(OrderInfo::getPayType)
);
PayEnums[] pays = PayEnums.values();
if (CollUtil.isEmpty(orderList)) {
for (PayEnums pay : pays) {
DataSummaryPayTypeVo.CountPayTypeVo payTypeVo = new DataSummaryPayTypeVo.CountPayTypeVo();
payTypeVo.setPayType(pay.getMsg());
payTypeVo.setCount(0);
total.add(payTypeVo);
}
data.setCountPayType(total);
return data;
}
for (PayEnums pay : pays) {
OrderInfo orderInfo = orderList.stream().filter(order -> pay.getValue().equals(order.getPayType())).findFirst().orElse(null);
DataSummaryPayTypeVo.CountPayTypeVo payTypeVo = new DataSummaryPayTypeVo.CountPayTypeVo();
payTypeVo.setPayType(pay.getMsg());
payTypeVo.setCount(0);
if (orderInfo != null) {
payTypeVo.setPayType(PayEnums.getText(orderInfo.getPayType()));
payTypeVo.setCount(orderInfo.getPlaceNum());
}
total.add(payTypeVo);
}
data.setCountPayType(total);
return data;
}
@Override
public List<Long> getShopIdList() {
return shopOrderStatisticMapper.getShopIdList();
}
}

View File

@@ -435,7 +435,7 @@ public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo
//优惠券部分 目前规则 每个券只能用一张
couponExecute(orderDetails, param, totalAmount, tempAmount, prodCouponAmount,
oneGiftAmount, twoHalfAmount, rateAmount, fullReductionAmount);
orderInfo.setOriginAmount(param.getOriginAmount());
//总商品支付金额 不包含打包费 用来计算后续
BigDecimal newTotalAmount = totalAmount.getPrice();
@@ -465,7 +465,8 @@ public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo
}
//(商品金额+打包费+餐位费)
newTotalAmount = newTotalAmount.add(packAmount.getPrice()).add(orderInfo.getSeatAmount());
//填充原价
orderInfo.setOriginAmount(totalAmount.getPrice().add(packAmount.getPrice()).add(orderInfo.getSeatAmount()));
//新客立减
if (shopUser != null) {
newTotalAmount = newTotalAmount.subtract(param.getNewCustomerDiscountAmount());
@@ -1090,6 +1091,8 @@ public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo
orderInfo1.setIsFreeDine(1);
orderInfo1.setStatus(OrderStatusEnums.DONE.getCode());
orderInfo1.setPayAmount(BigDecimal.ZERO);
orderInfo1.setPaidTime(LocalDateTime.now());
orderInfo1.setPayType(PayEnums.FREE_PAY.getValue());
updateById(orderInfo1);
orderDetailService.updateOrderDetailStatus(orderInfo.getId(), OrderStatusEnums.DONE.getCode());
redisService.del(RedisCst.classKeyExpired.EXPIRED_ORDER + orderInfo.getId());
@@ -1105,6 +1108,7 @@ public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo
updateChain().eq(OrderInfo::getId, orderInfo.getId())
.set(OrderInfo::getPayType, PayEnums.VIP_PAY.getValue())
.set(OrderInfo::getStatus, OrderStatusEnums.DONE.getCode())
.set(OrderInfo::getPaidTime, LocalDateTime.now())
.set(OrderInfo::getPayAmount, orderInfo.getOrderAmount())
.update();
orderDetailService.updateOrderDetailStatus(orderInfo.getId(), OrderStatusEnums.DONE.getCode());
@@ -1441,23 +1445,30 @@ public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo
private void upOrderPayInfo(OrderInfo orderInfo, CheckOrderPay param) {
orderInfo.setPointsNum(param.getPointsNum());
orderInfo.setIsPrint(param.getIsPrint());
orderInfo.setRoundAmount(param.getRoundAmount());
orderInfo.setOrderAmount(param.getOrderAmount());
orderInfo.setPointsDiscountAmount(param.getPointsDiscountAmount());
// ----------------------优惠金额-------------------------
//优惠卷
orderInfo.setCouponInfoList(CollUtil.isEmpty(param.getCouponList()) ? "" : JSONObject.toJSONString(param.getCouponList()));
orderInfo.setProductCouponDiscountAmount(param.getProductCouponDiscountAmount());
orderInfo.setOtherCouponDiscountAmount(param.getOtherCouponDiscountAmount());
//积分
orderInfo.setPointsDiscountAmount(param.getPointsDiscountAmount());
//新客立减
orderInfo.setNewCustomerDiscountAmount(param.getNewCustomerDiscountAmount());
// orderInfo.setFullCouponDiscountAmount(param.getFullCouponDiscountAmount());
orderInfo.setOtherCouponDiscountAmount(param.getOtherCouponDiscountAmount());
//商家最终改价
orderInfo.setDiscountAmount(param.getDiscountAmount());
//优惠券
orderInfo.setCouponInfoList(CollUtil.isEmpty(param.getCouponList()) ? "" : JSONObject.toJSONString(param.getCouponList()));
//满减活动抵扣金额
orderInfo.setDiscountActAmount(param.getDiscountActAmount());
//会员折扣金额
orderInfo.setVipDiscountAmount(param.getVipDiscountAmount());
//抹零
// orderInfo.setRoundAmount(param.getRoundAmount());
//优惠总金额
orderInfo.initDiscountAllAmount();
//折扣信息
orderInfo.setDiscountInfo(buildDiscountInfo(orderInfo));
//0元按照现金支付处理
if (orderInfo.getOrderAmount().compareTo(BigDecimal.ZERO) == 0) {
orderInfo.setStatus(OrderStatusEnums.DONE.getCode());
@@ -1508,6 +1519,9 @@ public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo
if (orderInfo.getProductCouponDiscountAmount().compareTo(BigDecimal.ZERO) > 0) {
jsonObject.put("商品券抵扣", orderInfo.getProductCouponDiscountAmount());
}
if (orderInfo.getOtherCouponDiscountAmount().compareTo(BigDecimal.ZERO) > 0) {
jsonObject.put("其它优惠券折扣", orderInfo.getOtherCouponDiscountAmount());
}
if (orderInfo.getDiscountAmount().compareTo(BigDecimal.ZERO) > 0) {
jsonObject.put("打折优惠", orderInfo.getDiscountAmount());
}
@@ -1517,9 +1531,6 @@ public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo
if (orderInfo.getVipDiscountAmount() != null && orderInfo.getVipDiscountAmount().compareTo(BigDecimal.ZERO) > 0) {
jsonObject.put("会员整单折扣", orderInfo.getVipDiscountAmount());
}
if (orderInfo.getOtherCouponDiscountAmount().compareTo(BigDecimal.ZERO) > 0) {
jsonObject.put("其它优惠券折扣", orderInfo.getOtherCouponDiscountAmount());
}
if (orderInfo.getPointsDiscountAmount().compareTo(BigDecimal.ZERO) > 0) {
jsonObject.put("积分抵扣", orderInfo.getPointsDiscountAmount());
}

View File

@@ -1,48 +0,0 @@
package com.czg.service.order.service.impl;
import com.czg.order.param.SaleSummaryCountParam;
import com.czg.order.service.SaleSummaryService;
import com.czg.order.vo.SaleSummaryCountVo;
import com.czg.order.vo.SaleSummaryInfoVo;
import com.czg.service.order.mapper.ShopProdStatisticMapper;
import com.czg.utils.PageUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.mybatisflex.core.paginate.Page;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 销量统计Service实现类
*
* @author tankaikai
* @since 2025-03-07 15:32
*/
@Service
public class SaleSummaryServiceImpl implements SaleSummaryService {
@Resource
private ShopProdStatisticMapper shopProdStatisticMapper;
@Override
public SaleSummaryCountVo summaryCount(SaleSummaryCountParam param) {
SaleSummaryCountVo saleSummaryCount = shopProdStatisticMapper.getSaleSummaryCount(param);
if (saleSummaryCount == null) {
saleSummaryCount = new SaleSummaryCountVo();
}
return saleSummaryCount;
}
@Override
public Page<SaleSummaryInfoVo> summaryPage(SaleSummaryCountParam param) {
PageHelper.startPage(PageUtil.buildPageHelp());
PageInfo<SaleSummaryInfoVo> pageInfo = new PageInfo<>(shopProdStatisticMapper.findSaleSummaryList(param));
return PageUtil.convert(pageInfo);
}
@Override
public List<SaleSummaryInfoVo> summaryList(SaleSummaryCountParam param) {
return shopProdStatisticMapper.findSaleSummaryList(param);
}
}

View File

@@ -1,88 +1,174 @@
package com.czg.service.order.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.czg.account.entity.ShopInfo;
import com.czg.account.service.ShopInfoService;
import com.czg.exception.CzgException;
import com.czg.order.entity.ShopOrderStatistic;
import com.czg.order.param.DataSummaryTradeParam;
import com.czg.order.service.DataSummaryService;
import com.czg.order.service.ShopOrderStatisticService;
import com.czg.order.vo.CountPayTypeVo;
import com.czg.order.vo.TotalVo;
import com.czg.service.order.mapper.ShopOrderStatisticMapper;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.List;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.util.*;
/**
* 服务层实现。
* 店铺订单统计报表 服务层实现。
*
* @author zs
* @since 2025-03-07
* @author ww
* @since 2025-11-20
*/
@Service
@Slf4j
public class ShopOrderStatisticServiceImpl extends ServiceImpl<ShopOrderStatisticMapper, ShopOrderStatistic> implements ShopOrderStatisticService {
@Resource
private DataSummaryService dataSummaryService;
@DubboReference
private ShopInfoService shopInfoService;
@Override
public void statistic(DateTime dateTime) {
// 获取前一天的开始时间00:00:00
DateTime startOfDay = DateUtil.beginOfDay(dateTime);
// 获取前一天的结束时间23:59:59
DateTime endOfDay = DateUtil.endOfDay(dateTime);
List<Long> shopIdList = dataSummaryService.getShopIdList();
if (CollUtil.isEmpty(shopIdList)) {
return;
public ShopOrderStatistic getArchiveTradeData(Long shopId, String rangeType, LocalDate start, LocalDate end) {
LocalDate currentDate = LocalDate.now();
if ("today".equals(rangeType)) {
return getRealTimeDataByDay(shopId, currentDate);
} else if ("yesterday".equals(rangeType)) {
return getStatSingleDate(shopId, currentDate.minusDays(1));
}
List<List<Long>> split = CollUtil.split(shopIdList, 5);
for (List<Long> splitIdList : split) {
splitIdList.parallelStream().forEach(shopId -> {
Long mainShopId = shopInfoService.getMainIdByShopId(shopId);
DataSummaryTradeParam param = new DataSummaryTradeParam();
param.setShopId(shopId);
param.setMainShopId(mainShopId);
param.setBeginDate(startOfDay.toStringDefaultTimeZone());
param.setEndDate(endOfDay.toStringDefaultTimeZone());
ShopOrderStatistic statistic = dataSummaryService.getRealTimeTradeData(param);
statistic.setShopId(shopId);
statistic.setCreateDay(dateTime.toLocalDateTime().toLocalDate());
statistic.setUpdateTime(LocalDateTime.now());
if (statistic.getNewMemberCount() != 0L) {
System.out.println("newMemberCount:" + statistic.getNewMemberCount());
}
// 如果没有订单和退款,则不更新数据,否则会产出很多数据
if (statistic.getSaleCount() == 0
&& statistic.getRefundCount() == 0
&& statistic.getMemberPayCount() == 0
&& statistic.getNewMemberCount() == 0
) {
log.info("店铺:{}{},没有要存档的订单统计数据", shopId, dateTime.toDateStr());
} else {
ShopOrderStatistic entity =
getMapper()
.selectOneByQuery(query().eq("shop_id", shopId)
.eq("create_day", dateTime.toDateStr()));
if (entity != null) {
statistic.setId(entity.getId());
updateById(statistic);
} else {
save(statistic);
}
}
});
if (start.isAfter(currentDate)) {
throw new CzgException("开始时间不能晚于当前时间");
}
if (start.equals(end)) {
return getStatSingleDate(shopId, start);
}
//包括当前时间
if (end.isBefore(currentDate)) {
return getStatDateRange(shopId, start, end);
} else {
ShopOrderStatistic realTimeDataByDay = getRealTimeDataByDay(shopId, currentDate);
ShopOrderStatistic statDateRange = getStatDateRange(shopId, start, end);
ShopOrderStatistic shopOrderStatistic = ShopOrderStatistic.mergeStatistics(realTimeDataByDay, statDateRange);
shopOrderStatistic.setShopId(shopId);
return shopOrderStatistic;
}
}
@Override
public List<TotalVo> getDateAmount(Long shopId, Integer day) {
LocalDate currentDate = LocalDate.now();
LocalDate startDate = currentDate;
if (day == 7) {
startDate = currentDate.minusDays(6);
} else if (day == 30) {
startDate = currentDate.minusDays(29);
}
TotalVo onlineDataAmount = mapper.getOnlineDataAmount(shopId, currentDate);
List<TotalVo> statDateRange = mapper.getStatDateRange(shopId, startDate, currentDate);
return TotalVo.mergeAndFillData(onlineDataAmount, statDateRange, startDate, currentDate);
}
@Override
public List<CountPayTypeVo> getSummaryPayTypeData(Long shopId, Integer day) {
LocalDate currentDate = LocalDate.now();
LocalDate startDate = currentDate;
if (day == 7) {
startDate = currentDate.minusDays(6);
} else if (day == 30) {
startDate = currentDate.minusDays(29);
}
return CountPayTypeVo.mergePayTypeData(
mapper.getOnlinePayTypeDate(shopId, currentDate),
mapper.getPayTypeDateRangeRaw(shopId, startDate, currentDate));
}
@Override
public void statisticAndInsert(Long shopId, LocalDate day) {
ShopOrderStatistic realTimeData = getRealTimeDataByDay(shopId, day);
if (realTimeData != null && realTimeData.hasValidData(realTimeData)) {
ShopOrderStatistic result = getOne(QueryWrapper.create().eq(ShopOrderStatistic::getShopId, shopId).eq(ShopOrderStatistic::getStatisticDate, day));
if (result != null) {
removeById(result);
}
save(realTimeData);
}
}
@Override
public ShopOrderStatistic getRealTimeDataByDay(Long shopId, LocalDate day) {
ShopOrderStatistic result = new ShopOrderStatistic();
ShopOrderStatistic onlineStat = mapper.getOnlineStatSingleDate(shopId, day);
ShopOrderStatistic orderStat = mapper.getOrderStatSingleDate(shopId, day);
ShopOrderStatistic userFlowStat = mapper.getShopUserFlowStatSingleDate(shopId, day);
Long discountCount = mapper.countDiscountOrder(shopId, day);
BigDecimal discountAmount = mapper.countDiscountAmount(shopId, day);
Long tableCount = mapper.countShopTable(shopId);
Long newMemberCount = mapper.countNewMember(shopId, day);
BigDecimal productCostAmount = mapper.countProductCostAmount(shopId, day);
// 合并结果
BeanUtils.copyProperties(onlineStat, result);
BeanUtils.copyProperties(orderStat, result);
BeanUtils.copyProperties(userFlowStat, result);
result.setShopId(shopId);
result.setStatisticDate(day);
result.setDiscountCount(discountCount);
result.setDiscountAmount(discountAmount);
result.setTableCount(tableCount);
result.setNewMemberCount(newMemberCount);
result.setProductCostAmount(productCostAmount);
//会员充值退款 充值退款金额(线上退款+现金退款)
result.setRechargeRefundAmount(onlineStat.getOnlineRechargeRefundAmount().add(userFlowStat.getCashRechargeRefundAmount()));
//实付金额 (线上付款 现金支付 会员支付 挂账)
result.setPayAmount(onlineStat.getOnlinePayAmount().add(orderStat.getCashPayAmount()).add(orderStat.getMemberPayAmount()).add(orderStat.getCreditPayAmount()));
//毛利润(订单实付金额-商品成本)
result.setProfitAmount(result.getPayAmount().subtract(productCostAmount));
//毛利率(订单实付金额-商品成本)/订单实付金额*100%
if (result.getPayAmount().compareTo(BigDecimal.ZERO) > 0) {
BigDecimal profitRate = result.getProfitAmount().divide(result.getPayAmount(), 4, RoundingMode.HALF_DOWN).multiply(BigDecimal.valueOf(100));
result.setProfitRate(profitRate);
result.setNetProfitAmount(profitRate);
} else {
result.setProfitRate(BigDecimal.ZERO);
result.setNetProfitAmount(BigDecimal.ZERO);
}
//客单价 实付金额(包括线上支付 包含现金支付 包含会员支付 包含挂账)/就餐人数
result.setAvgPayAmount(result.getPayAmount().divide(new BigDecimal(result.getCustomerCount()), 2, RoundingMode.HALF_DOWN));
//翻台率 (订单数-桌台数)/桌台数*100%
if (tableCount > 0) {
BigDecimal turnoverRate = new BigDecimal(result.getOrderCount()).subtract(new BigDecimal(tableCount)).divide(new BigDecimal(tableCount), 4, RoundingMode.HALF_DOWN).multiply(BigDecimal.valueOf(100));
result.setTurnoverRate(turnoverRate);
} else {
result.setTurnoverRate(BigDecimal.ZERO);
}
return result;
}
@Override
public ShopOrderStatistic getStatSingleDate(Long shopId, LocalDate day) {
ShopOrderStatistic result = getOne(QueryWrapper.create().eq(ShopOrderStatistic::getShopId, shopId).eq(ShopOrderStatistic::getStatisticDate, day));
if (result == null) {
result = new ShopOrderStatistic();
result.setShopId(shopId);
result.setStatisticDate(day);
result.init();
}
return result;
}
@Override
public ShopOrderStatistic getStatDateRange(Long shopId, LocalDate start, LocalDate end) {
ShopOrderStatistic result = mapper.countStatistic(shopId, start, end);
if (result == null) {
result = new ShopOrderStatistic();
result.setStatisticDate(start);
result.init();
}
result.setShopId(shopId);
return result;
}
}

View File

@@ -1,87 +1,194 @@
package com.czg.service.order.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import com.czg.exception.CzgException;
import com.czg.order.entity.ShopProdStatistic;
import com.czg.order.param.DataSummaryProductSaleParam;
import com.czg.order.service.DataSummaryService;
import com.czg.order.service.ShopProdStatisticService;
import com.czg.order.vo.DataSummaryProductSaleRankingVo;
import com.czg.order.vo.SaleSummaryCountVo;
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 lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* 服务层实现。
* 商品统计表 服务层实现。
*
* @author zs
* @since 2025-03-07
* @author ww
* @since 2025-11-21
*/
@Service
@Slf4j
public class ShopProdStatisticServiceImpl extends ServiceImpl<ShopProdStatisticMapper, ShopProdStatistic> implements ShopProdStatisticService {
@Resource
private DataSummaryService dataSummaryService;
@Resource
private ShopProdStatisticMapper shopProdStatisticMapper;
@Data
private static class StatisticTask {
private BigDecimal successCount = BigDecimal.ZERO;
private BigDecimal successAmount = BigDecimal.ZERO;
private BigDecimal refundCount = BigDecimal.ZERO;
private BigDecimal refundAmount = BigDecimal.ZERO;
@Override
public List<ShopProdStatistic> getArchiveTradeDataBy20(Long shopId, String rangeType, LocalDate start, LocalDate end) {
List<ShopProdStatistic> archiveTradeData = getArchiveTradeData(shopId, null, rangeType, start, end);
// 按照 saleCount 降序排序
return archiveTradeData.stream()
.sorted(
Comparator.comparing(
ShopProdStatistic::getSaleCount,
Comparator.nullsLast(BigDecimal::compareTo).reversed()
)
)
.limit(20)
.toList();
}
@Override
public SaleSummaryCountVo summaryCount(Long shopId, String productName, String rangeType, LocalDate start, LocalDate end) {
LocalDate currentDate = LocalDate.now();
if ("today".equals(rangeType)) {
return mapper.summaryCountByDay(shopId, currentDate, productName);
} else if ("yesterday".equals(rangeType)) {
return mapper.summaryCountSingleDate(shopId, currentDate.minusDays(1), productName);
} else {
if (start.isAfter(currentDate)) {
throw new CzgException("开始时间不能晚于当前时间");
}
if (start.equals(end)) {
return mapper.summaryCountSingleDate(shopId, start, productName);
} else {
if (end.isBefore(currentDate)) {
return mapper.summaryCountDateRange(shopId, start, end, productName);
} else {
SaleSummaryCountVo todaySummary = mapper.summaryCountByDay(shopId, currentDate, productName);
SaleSummaryCountVo dateRangeSummary = mapper.summaryCountDateRange(shopId, start, end, productName);
return mergeSummaryCountVo(todaySummary, dateRangeSummary);
}
}
}
}
@Override
public void statistic(DateTime dateTime) {
// 获取前一天的开始时间00:00:00
DateTime startOfDay = DateUtil.beginOfDay(dateTime);
// 获取前一天的结束时间23:59:59
DateTime endOfDay = DateUtil.endOfDay(dateTime);
List<Long> shopIdList = dataSummaryService.getShopIdList();
if (CollUtil.isEmpty(shopIdList)) {
return;
}
List<List<Long>> split = CollUtil.split(shopIdList, 5);
for (List<Long> splitIdList : split) {
splitIdList.parallelStream().forEach(shopId -> {
DataSummaryProductSaleParam param = new DataSummaryProductSaleParam();
param.setShopId(shopId);
param.setBeginDate(startOfDay.toStringDefaultTimeZone());
param.setEndDate(endOfDay.toStringDefaultTimeZone());
// 删除之前统计数据
getMapper().deleteByQuery(
QueryWrapper.create()
.eq("shop_id", shopId)
.eq("create_day", dateTime.toDateStr()));
// 重新统计数据
List<DataSummaryProductSaleRankingVo> list = shopProdStatisticMapper.findProdRandingSummaryPage2(param);
for (DataSummaryProductSaleRankingVo dto : list) {
ShopProdStatistic entity = new ShopProdStatistic();
entity.setProdId(dto.getProductId());
entity.setSaleCount(dto.getNumber());
entity.setSaleAmount(dto.getAmount());
entity.setRefundCount(dto.getRefundCount());
entity.setRefundAmount(dto.getRefundAmount());
entity.setShopId(shopId);
entity.setCreateDay(dateTime.toJdkDate());
if (NumberUtil.isLessOrEqual(entity.getSaleCount(), BigDecimal.ZERO) && NumberUtil.isLessOrEqual(entity.getRefundCount(), BigDecimal.ZERO)) {
log.info("店铺:{}{},没有要存档的商品统计数据", shopId, dateTime.toDateStr());
} else {
save(entity);
}
public List<ShopProdStatistic> getArchiveTradeData(Long shopId, String productName, String rangeType, LocalDate start, LocalDate end) {
LocalDate currentDate = LocalDate.now();
productName = CzgStrUtils.getStrOrNull(productName);
List<ShopProdStatistic> resultList;
if ("today".equals(rangeType)) {
resultList = getRealTimeDataByDay(shopId, currentDate, productName);
} else if ("yesterday".equals(rangeType)) {
resultList = getProdStatSingleDate(shopId, currentDate.minusDays(1), productName);
} else {
if (start.isAfter(currentDate)) {
throw new CzgException("开始时间不能晚于当前时间");
}
if (start.equals(end)) {
resultList = getProdStatSingleDate(shopId, start, productName);
} else {
if (end.isBefore(currentDate)) {
resultList = getProdStatDateRange(shopId, start, end, productName);
} else {
List<ShopProdStatistic> realTimeDataByDay = getRealTimeDataByDay(shopId, currentDate, productName);
List<ShopProdStatistic> dateRange = getProdStatDateRange(shopId, start, end, productName);
resultList = mergeProdStatistic(realTimeDataByDay, dateRange);
}
});
}
}
return resultList;
}
@Override
public void statisticAndInsert(Long shopId, LocalDate day) {
List<ShopProdStatistic> realTimeData = getRealTimeDataByDay(shopId, day, null);
if (CollUtil.isNotEmpty(realTimeData)) {
// 过滤掉没有有效数据的记录
realTimeData = realTimeData.stream()
.filter(ShopProdStatistic::isValid)
.toList();
if(CollUtil.isNotEmpty(realTimeData)) {
boolean exists = exists(QueryWrapper.create().eq(ShopProdStatistic::getShopId, shopId).eq(ShopProdStatistic::getCreateDay, day));
if (exists) {
remove(QueryWrapper.create().eq(ShopProdStatistic::getShopId, shopId).eq(ShopProdStatistic::getCreateDay, day));
}
saveBatch(realTimeData);
}
}
}
@Override
public List<ShopProdStatistic> getRealTimeDataByDay(Long shopId, LocalDate day, String productName) {
return mapper.selectProStatByDay(shopId, day, productName);
}
@Override
public List<ShopProdStatistic> getProdStatSingleDate(Long shopId, LocalDate day, String productName) {
return mapper.getProdStatSingleDate(shopId, day, productName);
}
@Override
public List<ShopProdStatistic> getProdStatDateRange(Long shopId, LocalDate start, LocalDate end, String productName) {
return mapper.getProdStatDateRange(shopId, start, end, productName);
}
private SaleSummaryCountVo mergeSummaryCountVo(SaleSummaryCountVo todaySummary, SaleSummaryCountVo dateRangeSummary) {
if (todaySummary == null) todaySummary = new SaleSummaryCountVo();
if (dateRangeSummary == null) dateRangeSummary = new SaleSummaryCountVo();
return new SaleSummaryCountVo(
safeAdd(todaySummary.getTotalAmount(), dateRangeSummary.getTotalAmount()),
safeAdd(todaySummary.getRefundAmount(), dateRangeSummary.getRefundAmount()),
safeAdd(todaySummary.getSaleCount(), dateRangeSummary.getSaleCount()),
safeAdd(todaySummary.getRefundCount(), dateRangeSummary.getRefundCount())
);
}
/**
* 合并实时数据和日期范围数据
*
* @param realTimeDataByDay 实时数据
* @param dateRange 日期范围数据
* @return 合并后的数据
*/
private List<ShopProdStatistic> mergeProdStatistic(List<ShopProdStatistic> realTimeDataByDay, List<ShopProdStatistic> dateRange) {
if (realTimeDataByDay == null) realTimeDataByDay = new ArrayList<>();
if (dateRange == null) dateRange = new ArrayList<>();
return Stream.concat(realTimeDataByDay.stream(), dateRange.stream())
.filter(Objects::nonNull)
.collect(Collectors.toMap(
ShopProdStatistic::getProdId,
Function.identity(),
(stat1, stat2) -> {
// 创建合并后的对象
ShopProdStatistic merged = new ShopProdStatistic();
merged.setId(stat1.getId());
merged.setProdId(stat1.getProdId());
merged.setShopId(stat1.getShopId());
// 安全处理BigDecimal相加处理null值
merged.setSaleCount(safeAdd(stat1.getSaleCount(), stat2.getSaleCount()));
merged.setSaleAmount(safeAdd(stat1.getSaleAmount(), stat2.getSaleAmount()));
merged.setRefundCount(safeAdd(stat1.getRefundCount(), stat2.getRefundCount()));
merged.setRefundAmount(safeAdd(stat1.getRefundAmount(), stat2.getRefundAmount()));
return merged;
}
))
.values()
.stream()
.toList();
}
private BigDecimal safeAdd(BigDecimal num1, BigDecimal num2) {
BigDecimal safeNum1 = num1 != null ? num1 : BigDecimal.ZERO;
BigDecimal safeNum2 = num2 != null ? num2 : BigDecimal.ZERO;
return safeNum1.add(safeNum2);
}
}

View File

@@ -1,118 +1,79 @@
package com.czg.service.order.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.czg.exception.CzgException;
import com.czg.order.entity.ShopTableOrderStatistic;
import com.czg.order.param.TableSummaryParam;
import com.czg.order.service.DataSummaryService;
import com.czg.order.service.ShopTableOrderStatisticService;
import com.czg.order.vo.TableSummaryInfoVo;
import com.czg.service.order.mapper.ShopTableOrderStatisticMapper;
import com.czg.utils.PageUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.mybatisflex.core.paginate.Page;
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.time.LocalDate;
import java.util.List;
/**
* 台桌订单统计表 服务层实现。
*
* @author zs
* @since 2025-03-07
* @author ww
* @since 2025-11-21
*/
@Service
@Slf4j
public class ShopTableOrderStatisticServiceImpl extends ServiceImpl<ShopTableOrderStatisticMapper, ShopTableOrderStatistic> implements ShopTableOrderStatisticService {
@Resource
private DataSummaryService dataSummaryService;
@Resource
private ShopTableOrderStatisticMapper shopTableOrderStatisticMapper;
public class ShopTableOrderStatisticServiceImpl extends ServiceImpl<ShopTableOrderStatisticMapper, ShopTableOrderStatistic> implements ShopTableOrderStatisticService{
@Override
public Page<ShopTableOrderStatistic> summary(Long shopId, String startTime, String endTime) {
Page<Object> page = PageUtil.buildPage();
PageHelper.startPage(Math.toIntExact(page.getPageNumber()), Math.toIntExact(page.getPageSize()));
return PageUtil.convert(new PageInfo<>(mapper.selectSummary(shopId, startTime, endTime)));
}
@Override
public boolean addInfo(long shopId, long tableId, long count, BigDecimal amount) {
ShopTableOrderStatistic statistic = getOne(new QueryWrapper().eq(ShopTableOrderStatistic::getShopId, shopId).eq(ShopTableOrderStatistic::getTableId, tableId)
.eq(ShopTableOrderStatistic::getCreateDay, DateUtil.date().toDateStr()));
if (statistic == null) {
statistic = new ShopTableOrderStatistic();
statistic.setShopId(shopId);
statistic.setTableId(tableId);
statistic.setCreateDay(DateUtil.date().toSqlDate());
statistic.setOrderCount(count);
statistic.setOrderAmount(amount);
save(statistic);
public List<ShopTableOrderStatistic> getArchiveTradeData(Long shopId, String rangeType, LocalDate start, LocalDate end) {
LocalDate currentDate = LocalDate.now();
if ("today".equals(rangeType)) {
return getRealTimeDataByDay(shopId, currentDate);
} else if ("yesterday".equals(rangeType)) {
return getStatSingleDate(shopId, currentDate.minusDays(1));
}
return mapper.incrInfo(shopId, tableId, count, amount, DateUtil.date().toDateStr());
}
@Data
private static class StatisticTask {
private long successCount = 0;
private BigDecimal successAmount = BigDecimal.ZERO;
private long refundCount = 0;
private BigDecimal refundAmount = BigDecimal.ZERO;
}
@Override
public void statistic(DateTime dateTime) {
// 获取前一天的开始时间00:00:00
DateTime startOfDay = DateUtil.beginOfDay(dateTime);
// 获取前一天的结束时间23:59:59
DateTime endOfDay = DateUtil.endOfDay(dateTime);
List<Long> shopIdList = dataSummaryService.getShopIdList();
if (CollUtil.isEmpty(shopIdList)) {
return;
if (start.isAfter(currentDate)) {
throw new CzgException("开始时间不能晚于当前时间");
}
List<List<Long>> split = CollUtil.split(shopIdList, 5);
for (List<Long> splitIdList : split) {
splitIdList.parallelStream().forEach(shopId -> {
TableSummaryParam param = new TableSummaryParam();
param.setShopId(shopId);
param.setBeginDate(startOfDay.toStringDefaultTimeZone());
param.setEndDate(endOfDay.toStringDefaultTimeZone());
// 删除之前统计数据
getMapper()
.deleteByQuery(
new QueryWrapper()
.eq("shop_id", shopId)
.eq("create_day", dateTime.toDateStr()));
// 重新统计数据
List<TableSummaryInfoVo> list = shopTableOrderStatisticMapper.findSummaryList2(param);
for (TableSummaryInfoVo dto : list) {
ShopTableOrderStatistic entity = new ShopTableOrderStatistic();
entity.setTableId(dto.getTableId());
entity.setTableCode(dto.getTableCode());
entity.setTableName(dto.getTableName());
entity.setAreaName(dto.getAreaName());
entity.setOrderCount(dto.getOrderCount());
entity.setOrderAmount(dto.getOrderAmount());
entity.setRefundCount(dto.getRefundCount());
entity.setRefundAmount(dto.getRefundAmount());
entity.setShopId(shopId);
entity.setCreateDay(dateTime.toJdkDate());
if (entity.getOrderCount() == 0L && entity.getRefundCount() == 0L) {
log.info("店铺:{}{},没有要存档的台桌统计数据", shopId, dateTime.toDateStr());
} else {
save(entity);
}
}
});
if (start.equals(end)) {
return getStatSingleDate(shopId, start);
}
//包括当前时间
if (end.isBefore(currentDate)) {
return getStatDateRange(shopId, start, end);
} else {
List<ShopTableOrderStatistic> realTimeDataByDay = getRealTimeDataByDay(shopId, currentDate);
List<ShopTableOrderStatistic> statDateRange = getStatDateRange(shopId, start, end);
return ShopTableOrderStatistic.mergeWithStream(realTimeDataByDay, statDateRange);
}
}
@Override
public void statisticAndInsert(Long shopId, LocalDate day) {
List<ShopTableOrderStatistic> realTimeData = getRealTimeDataByDay(shopId, day);
if (CollUtil.isNotEmpty(realTimeData)) {
// 过滤掉没有有效数据的记录
realTimeData = realTimeData.stream()
.filter(ShopTableOrderStatistic::hasValidData)
.toList();
if (CollUtil.isNotEmpty(realTimeData)) {
remove(QueryWrapper.create().eq(ShopTableOrderStatistic::getShopId, shopId).eq(ShopTableOrderStatistic::getCreateDay, day));
saveBatch(realTimeData);
}
}
}
@Override
public List<ShopTableOrderStatistic> getRealTimeDataByDay(Long shopId, LocalDate day) {
return mapper.getOnlineData(shopId, day);
}
@Override
public List<ShopTableOrderStatistic> getStatSingleDate(Long shopId, LocalDate day) {
return mapper.getStatSingleDate(shopId, day);
}
@Override
public List<ShopTableOrderStatistic> getStatDateRange(Long shopId, LocalDate start, LocalDate end) {
return mapper.getStatDateRange(shopId, start, end);
}
}

View File

@@ -4,7 +4,6 @@ import cn.hutool.core.collection.CollUtil;
import com.czg.order.param.TableSummaryParam;
import com.czg.order.service.TableSummaryService;
import com.czg.order.vo.TableSummaryExportVo;
import com.czg.order.vo.TableSummaryInfoVo;
import com.czg.service.order.mapper.ShopTableOrderStatisticMapper;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
@@ -28,10 +27,7 @@ public class TableSummaryServiceImpl implements TableSummaryService {
@Resource
private ShopTableOrderStatisticMapper shopTableOrderStatisticMapper;
@Override
public List<TableSummaryInfoVo> summaryList(TableSummaryParam param) {
return shopTableOrderStatisticMapper.findSummaryList(param);
}
@Override
public List<TableSummaryExportVo> summaryExportList(TableSummaryParam param) {

View File

@@ -3,125 +3,4 @@
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.czg.service.order.mapper.ShopOrderStatisticMapper">
<select id="getTradeData" resultType="com.czg.order.entity.ShopOrderStatistic">
select
sum(sale_amount) as sale_amount,
sum(sale_count) as sale_count,
sum(discount_amount) as discount_amount,
sum(discount_count) as discount_count,
sum(refund_amount) as refund_amount,
sum(refund_count) as refund_count,
sum(wechat_pay_count) as wechat_pay_count,
sum(wechat_pay_amount) as wechat_pay_amount,
sum(ali_pay_count) as ali_pay_count,
sum(ali_pay_amount) as ali_pay_amount,
sum(credit_pay_count) as credit_pay_count,
sum(credit_pay_amount) as credit_pay_amount,
sum(member_pay_count) as member_pay_count,
sum(member_pay_amount) as member_pay_amount,
sum(scan_pay_count) as scan_pay_count,
sum(scan_pay_amount) as scan_pay_amount,
sum(cash_pay_count) as cash_pay_count,
sum(cash_pay_amount) as cash_pay_amount,
sum(recharge_amount) as recharge_amount,
avg(customer_unit_price) as customer_unit_price,
avg(table_turnover_rate) as table_turnover_rate,
sum(new_member_count) as new_member_count,
max(update_time) as update_time
from tb_shop_order_statistic
where shop_id = #{shopId}
<if test="beginDate != null and beginDate != ''">
and create_day >= str_to_date(#{beginDate}, '%Y-%m-%d')
</if>
<if test="endDate != null and endDate != ''">
<![CDATA[
and create_day <= str_to_date(#{endDate}, '%Y-%m-%d')
]]>
</if>
group by shop_id
</select>
<select id="getNewMemberCount" resultType="java.lang.Long">
select count(1) from tb_shop_user where main_shop_id = #{mainShopId} and is_vip = 1
<if test="beginDate != null and beginDate != ''">
and join_time >= str_to_date(#{beginDate}, '%Y-%m-%d %H:%i:%s')
</if>
<if test="endDate != null and endDate != ''">
<![CDATA[
and join_time <= str_to_date(#{endDate}, '%Y-%m-%d %H:%i:%s')
]]>
</if>
</select>
<select id="getPayTypeAmountCount" resultType="java.util.Map">
SELECT
t1.pay_type as payType,
sum(t1.pay_amount) as amount,
sum(t1.refund_amount) as refund,
count(case when t1.refund_amount>0 then 1 end) as refundCount,
sum(t1.discount_amount) as discount,
count(case when t1.discount_amount>0 then 1 end) as discountCount,
count(*) as count
FROM
tb_order_info t1
WHERE t1.shop_id = #{shopId}
and t1.paid_time is not null
<if test="beginDate != null and beginDate != ''">
and t1.create_time >= str_to_date(#{beginDate}, '%Y-%m-%d %H:%i:%s')
</if>
<if test="endDate != null and endDate != ''">
<![CDATA[
and t1.create_time <= str_to_date(#{endDate}, '%Y-%m-%d %H:%i:%s')
]]>
</if>
group by t1.pay_type
</select>
<select id="getVipRechargeAmountCount" resultType="java.util.Map">
select
t1.biz_code as bizCode,sum(t1.amount) as amount,count(*) as count
from tb_shop_user_flow t1
where t1.shop_id = #{shopId}
<if test="beginDate != null and beginDate != ''">
and t1.create_time >= str_to_date(#{beginDate}, '%Y-%m-%d %H:%i:%s')
</if>
<if test="endDate != null and endDate != ''">
<![CDATA[
and t1.create_time <= str_to_date(#{endDate}, '%Y-%m-%d %H:%i:%s')
]]>
</if>
group by t1.biz_code
</select>
<select id="getCustomerUnitPrice" resultType="java.math.BigDecimal">
SELECT
ifnull((sum(t1.pay_amount)-sum(t1.refund_amount))/count(ifnull(case t1.seat_num when 0 then 1 end,1)),0.00) as customerUnitPrice
FROM
tb_order_info t1
WHERE t1.shop_id = #{shopId}
and t1.paid_time is not null
<if test="beginDate != null and beginDate != ''">
and t1.create_time >= str_to_date(#{beginDate}, '%Y-%m-%d %H:%i:%s')
</if>
<if test="endDate != null and endDate != ''">
<![CDATA[
and t1.create_time <= str_to_date(#{endDate}, '%Y-%m-%d %H:%i:%s')
]]>
</if>
</select>
<select id="getTableTurnoverRate" resultType="java.math.BigDecimal">
SELECT
ifnull((count(*)-count(DISTINCT t1.table_code))/count(DISTINCT t1.table_code)*100,0.00)
FROM
tb_order_info t1
WHERE t1.shop_id = #{shopId}
and t1.paid_time is not null
<if test="beginDate != null and beginDate != ''">
and t1.create_time >= str_to_date(#{beginDate}, '%Y-%m-%d %H:%i:%s')
</if>
<if test="endDate != null and endDate != ''">
<![CDATA[
and t1.create_time <= str_to_date(#{endDate}, '%Y-%m-%d %H:%i:%s')
]]>
</if>
</select>
<select id="getShopIdList" resultType="java.lang.Long">
select id from tb_shop_info order by id
</select>
</mapper>

View File

@@ -4,164 +4,120 @@
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.czg.service.order.mapper.ShopProdStatisticMapper">
<select id="findProdRandingSummaryPage" resultType="com.czg.order.vo.DataSummaryProductSaleRankingVo">
select
t1.prod_id,
t2.name as product_name,
sum(t1.sale_count) as number,
sum(t1.sale_amount) as amount
from tb_shop_prod_statistic t1
left join tb_product t2 on t1.prod_id = t2.id
where t1.shop_id = #{shopId}
and t1.create_day in
<foreach item="day" collection="days" open="(" separator="," close=")">
#{day}
</foreach>
group by t1.prod_id,t2.name
order by sum(t1.sale_count) desc
</select>
<select id="getSaleSummaryCount" resultType="com.czg.order.vo.SaleSummaryCountVo">
select
sum(t1.sale_count) as sale_count,
sum(t1.sale_amount) as total_amount,
sum(t1.refund_count) as refund_count,
sum(t1.refund_amount) as refund_amount
from tb_shop_prod_statistic t1
left join tb_product t2 on t1.prod_id = t2.id
where t1.shop_id = #{shopId}
<if test="productName != null and productName != ''">
and t2.name like concat('%', #{productName}, '%')
</if>
<if test="prodCategoryId != null">
and t2.category_id = #{prodCategoryId}
</if>
<if test="beginDate != null and beginDate != ''">
and t1.create_day >= str_to_date(#{beginDate}, '%Y-%m-%d')
</if>
<if test="endDate != null and endDate != ''">
<![CDATA[
and t1.create_day <= str_to_date(#{endDate}, '%Y-%m-%d')
]]>
</if>
</select>
<select id="findSaleSummaryList" resultType="com.czg.order.vo.SaleSummaryInfoVo">
select
t1.prod_id,
max(t1.id) as id,
t2.NAME AS product_name,
t3.name as category_name,
sum(t1.sale_count) as sale_count,
sum(t1.sale_amount) as sale_amount,
sum(t1.refund_count) as refund_count,
sum(t1.refund_amount) as refund_amount
from tb_shop_prod_statistic t1
left join tb_product t2 on t1.prod_id = t2.id
left join tb_shop_prod_category t3 on t2.category_id = t3.id
where t1.shop_id = #{shopId}
<if test="productName != null and productName != ''">
and t2.name like concat('%', #{productName}, '%')
</if>
<if test="prodCategoryId != null">
and t2.category_id = #{prodCategoryId}
</if>
<if test="beginDate != null and beginDate != ''">
and t1.create_day >= str_to_date(#{beginDate}, '%Y-%m-%d')
</if>
<if test="endDate != null and endDate != ''">
<![CDATA[
and t1.create_day <= str_to_date(#{endDate}, '%Y-%m-%d')
]]>
</if>
group by t1.prod_id
ORDER BY sum( t1.sale_count ) DESC,max(t1.id) DESC
</select>
<select id="getSaleSummaryCount2" resultType="com.czg.order.vo.SaleSummaryCountVo">
<select id="selectProStatByDay" resultType="com.czg.order.entity.ShopProdStatistic">
SELECT
sum(t1.pay_amount) as totalAmount,
sum(t1.refund_amount) as refundAmount,
count(*) as saleCount,
count(case when t1.refund_amount > 0 then 1 end) as refundCount
CASE WHEN detail.is_temporary = 1 THEN -1 ELSE detail.product_id END AS prodId,
CASE WHEN detail.is_temporary = 1 THEN '临时菜' ELSE prod.name END AS productName,
sum(detail.num-detail.return_num) as saleCount,
sum(detail.pay_amount) as saleAmount,
sum(detail.refund_num) refundCount,
sum(detail.return_amount) refundAmount
FROM
tb_order_info t1
left join (
SELECT
x1.order_id,
concat( ',', GROUP_CONCAT( x2.category_id ), ',' ) AS category_id,
GROUP_CONCAT( x1.product_name ) AS product_name
FROM
tb_order_detail x1
LEFT JOIN tb_product x2 ON x1.product_id = x2.id
GROUP BY x1.order_id
) t2 on t1.id = t2.order_id
where t1.shop_id = #{shopId}
and t1.status in ('part-refund','refund','done')
tb_order_info `order`
INNER JOIN tb_order_detail detail ON `order`.id = detail.order_id
LEFT JOIN tb_product prod ON detail.product_id = prod.id
WHERE
`order`.shop_id = #{shopId}
AND `order`.trade_day = #{tradeDay}
AND `order`.paid_time IS NOT NULL
<if test="productName != null and productName != ''">
and t2.product_name like concat('%', #{productName}, '%')
</if>
<if test="prodCategoryId != null">
and t2.category_id like concat('%,', #{prodCategoryId}, ',%')
</if>
<if test="beginDate != null and beginDate != ''">
and t1.create_time >= str_to_date(#{beginDate}, '%Y-%m-%d %H:%i:%s')
</if>
<if test="endDate != null and endDate != ''">
<![CDATA[
and t1.create_time <= str_to_date(#{endDate}, '%Y-%m-%d %H:%i:%s')
]]>
AND detail.name LIKE CONCAT('%',#{productName},'%')
</if>
GROUP BY prodId
</select>
<select id="findSaleSummaryList2" resultType="com.czg.order.vo.SaleSummaryInfoVo">
<select id="getProdStatSingleDate" resultType="com.czg.order.entity.ShopProdStatistic">
SELECT
t1.product_id,
t1.product_name as productName,
t3.name as category_name,
sum( t1.num ) AS saleCount,
sum( t1.pay_amount ) AS saleAmount,
sum( t1.return_num ) AS refundCount,
sum( t1.return_amount ) AS refundAmount
tb_shop_prod_statistic.*,
CASE WHEN tb_shop_prod_statistic.prod_id = -1 THEN '临时菜' ELSE prod.name END AS productName
FROM
tb_order_detail t1
left join tb_product t2 on t1.product_id = t2.id
left join tb_shop_prod_category t3 on t2.category_id = t3.id
where t1.shop_id = #{shopId}
and t1.status in ('part-refund','refund','done')
tb_shop_prod_statistic
LEFT JOIN tb_product prod ON tb_shop_prod_statistic.prod_id = prod.id
WHERE
tb_shop_prod_statistic.shop_id = #{shopId}
AND tb_shop_prod_statistic.create_day = #{day}
<if test="productName != null and productName != ''">
and t1.product_name like concat('%', #{productName}, '%')
AND prod.name LIKE CONCAT('%',#{productName},'%')
</if>
<if test="prodCategoryId != null">
and t2.category_id = #{prodCategoryId}
</if>
<if test="beginDate != null and beginDate != ''">
and t1.create_time >= str_to_date(#{beginDate}, '%Y-%m-%d %H:%i:%s')
</if>
<if test="endDate != null and endDate != ''">
<![CDATA[
and t1.create_time <= str_to_date(#{endDate}, '%Y-%m-%d %H:%i:%s')
]]>
</if>
GROUP BY t1.product_id,t1.product_name
ORDER BY sum( t1.num ) DESC,max(t1.product_id) DESC
ORDER BY
tb_shop_prod_statistic.sale_count DESC, tb_shop_prod_statistic.prod_id
</select>
<select id="findProdRandingSummaryPage2" resultType="com.czg.order.vo.DataSummaryProductSaleRankingVo">
select
t1.product_id,
t1.product_name,
sum(t1.num) as number,
sum(t1.pay_amount) as amount,
sum(t1.return_num) AS refundCount,
sum(t1.return_amount) AS refundAmount
from tb_order_detail t1
where t1.shop_id = #{shopId}
and t1.status in ('part-refund','refund','done')
<if test="beginDate != null and beginDate != ''">
and t1.create_time >= str_to_date(#{beginDate}, '%Y-%m-%d %H:%i:%s')
<select id="getProdStatDateRange" resultType="com.czg.order.entity.ShopProdStatistic">
SELECT
tb_shop_prod_statistic.prod_id as prodId,
CASE WHEN prod_id = -1 THEN '临时菜' ELSE prod.name END AS productName,
tb_shop_prod_statistic.shop_id as shopId,
SUM(tb_shop_prod_statistic.sale_count) AS saleCount,
SUM(tb_shop_prod_statistic.sale_amount) AS saleAmount,
SUM(tb_shop_prod_statistic.refund_count) AS refundCount,
SUM(tb_shop_prod_statistic.refund_amount) AS refundAmount
FROM
tb_shop_prod_statistic
LEFT JOIN tb_product prod ON tb_shop_prod_statistic.prod_id = prod.id
WHERE
tb_shop_prod_statistic.shop_id = #{shopId}
AND tb_shop_prod_statistic.create_day &gt;= #{start}
AND tb_shop_prod_statistic.create_day &lt;= #{end}
<if test="productName != null and productName != ''">
AND prod.name LIKE CONCAT('%',#{productName},'%')
</if>
<if test="endDate != null and endDate != ''">
<![CDATA[
and t1.create_time <= str_to_date(#{endDate}, '%Y-%m-%d %H:%i:%s')
]]>
</if>
GROUP BY t1.product_id,t1.product_name
order by sum(t1.num) desc
GROUP BY
tb_shop_prod_statistic.prod_id
ORDER BY
tb_shop_prod_statistic.sale_count DESC, tb_shop_prod_statistic.prod_id
</select>
<select id="summaryCountByDay" resultType="com.czg.order.vo.SaleSummaryCountVo">
SELECT
sum(detail.num-detail.return_num) as saleCount,
sum(detail.pay_amount) as saleAmount,
sum(detail.refund_num) refundCount,
sum(detail.return_amount) refundAmount
FROM
tb_order_info `order`
INNER JOIN tb_order_detail detail ON `order`.id = detail.order_id
LEFT JOIN tb_product prod ON detail.product_id = prod.id
WHERE
`order`.shop_id = #{shopId}
AND `order`.trade_day = #{day}
AND `order`.paid_time IS NOT NULL
<if test="productName != null and productName != ''">
AND detail.name LIKE CONCAT('%',#{productName},'%')
</if>
</select>
<select id="summaryCountSingleDate" resultType="com.czg.order.vo.SaleSummaryCountVo">
SELECT
sum(tb_shop_prod_statistic.sale_count) AS saleCount,
sum(tb_shop_prod_statistic.sale_amount) AS saleAmount,
sum(tb_shop_prod_statistic.refund_count) AS refundCount,
sum(tb_shop_prod_statistic.refund_amount) AS refundAmount
FROM
tb_shop_prod_statistic
WHERE
tb_shop_prod_statistic.shop_id = #{shopId}
AND tb_shop_prod_statistic.create_day = #{day}
<if test="productName != null and productName != ''">
AND prod.name LIKE CONCAT('%',#{productName},'%')
</if>
</select>
<select id="summaryCountDateRange" resultType="com.czg.order.vo.SaleSummaryCountVo">
SELECT
sum(tb_shop_prod_statistic.sale_count) AS saleCount,
sum(tb_shop_prod_statistic.sale_amount) AS saleAmount,
sum(tb_shop_prod_statistic.refund_count) AS refundCount,
sum(tb_shop_prod_statistic.refund_amount) AS refundAmount
FROM
tb_shop_prod_statistic
WHERE
tb_shop_prod_statistic.shop_id = #{shopId}
AND tb_shop_prod_statistic.create_day &gt;= #{start}
AND tb_shop_prod_statistic.create_day &lt;= #{end}
<if test="productName != null and productName != ''">
AND prod.name LIKE CONCAT('%',#{productName},'%')
</if>
</select>
</mapper>

View File

@@ -3,124 +3,50 @@
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.czg.service.order.mapper.ShopTableOrderStatisticMapper">
<update id="incrInfo">
update tb_shop_table_order_statistic set order_count=order_count + #{count}, order_amount=order_amount + #{count}
where shop_id = #{shopId} and table_id = #{tableId} and create_day=#{date}
</update>
<select id="selectSummary" resultType="com.czg.order.entity.ShopTableOrderStatistic">
<select id="findSummaryExportList" resultType="com.czg.order.vo.TableSummaryExportVo">
SELECT
a.table_id as tableId, b.name as name, sum(a.order_count) as orderCount, sum(a.order_amount) as orderAmount
t.product_name,
date_format(t.create_time, '%Y-%m-%d') as create_date,
if(t.table_name = 'NONE','银收客',t.table_name) as table_name,
concat(if(t.table_name = 'NONE','银收客',t.table_name),'-',date_format(t.create_time, '%Y-%m-%d')) as tableConcatDate,
t.category_name,
t.unit_name,
group_concat(distinct t.sku_name SEPARATOR ';') as sku_name,
sum(t.num) as num,
avg(t.unit_price) as unit_price,
sum(t.num*t.unit_price) as amount,
sum(-t.refund_num) as refund_num,
sum(-t.refund_num*t.unit_price) as refund_amount
FROM
tb_shop_table_order_statistic as a
left join tb_shop_table as b on a.table_id = b.id
WHERE
a.shop_id = #{shopId}
<if test="startTime != null and startTime != ''">
AND a.create_day >= #{startTime}
</if>
<if test="endTime != null and endTime != ''">
and a.create_day &lt;= #{endTime}
</if>
GROUP BY
a.table_id
order by a.id desc
</select>
<select id="findSummaryList" resultType="com.czg.order.vo.TableSummaryInfoVo">
select
t1.table_code,
t1.table_id,
t1.table_name as table_name,
t1.area_name as area_name,
sum(t1.order_count) as order_count,
sum(t1.order_amount) as order_amount,
ifnull(sum(t1.refund_count),0) as refund_count,
ifnull(sum(t1.refund_amount),0) as refund_amount
from tb_shop_table_order_statistic t1
left join tb_shop_table t2 on t1.table_id = t2.id
left join tb_shop_table_area t3 on t2.area_id = t3.id
where t1.shop_id = #{shopId}
<if test="beginDate != null and beginDate != ''">
AND t1.create_day >= str_to_date(#{beginDate}, '%Y-%m-%d')
</if>
<if test="endDate != null and endDate != ''">
and t1.create_day &lt;= str_to_date(#{endDate}, '%Y-%m-%d')
</if>
group by t1.table_code
order by sum(t1.order_count) desc,sum(t1.order_amount) desc
</select>
<select id="findSummaryList2" resultType="com.czg.order.vo.TableSummaryInfoVo">
(
SELECT
t1.table_code,
t2.id as table_id,
ifnull(t2.NAME,t1.table_code) AS table_name,
ifnull(t3.NAME,'未知') AS area_name,
count( t1.id ) AS order_count,
sum( t1.pay_amount ) as order_amount,
ifnull(count( case when t1.refund_amount > 0 then 1 end),0) AS refund_count,
ifnull( sum( t1.refund_amount ), 0 ) AS refund_amount
t1.product_id,
t2.table_code,
IF(t2.table_code is null or t2.table_code = '' or t6.NAME is null, 'NONE', t6.NAME) AS table_name,
t1.create_time,
t4.NAME AS category_name,
t3.name as product_name,
t5.NAME AS unit_name,
t1.sku_name,
t1.num,
t1.unit_price,
t1.refund_num as refund_num
FROM
tb_order_info t1
LEFT JOIN tb_shop_table t2 ON t1.table_code = t2.table_code and t1.shop_id = t2.shop_id
LEFT JOIN tb_shop_table_area t3 ON t2.area_id = t3.id
where t1.shop_id = #{shopId}
and t1.table_code is not null
and t2.table_code is not null
and t2.table_code != ''
and t2.name is not null
and t1.paid_time is not null
tb_order_detail t1
LEFT JOIN tb_order_info t2 ON t1.order_id = t2.id
LEFT JOIN tb_product t3 ON t1.product_id = t3.id
LEFT JOIN tb_shop_prod_category t4 ON t3.category_id = t4.id
LEFT JOIN tb_shop_prod_unit t5 ON t3.unit_id = t5.id
LEFT JOIN tb_shop_table t6 ON t2.table_code = t6.table_code AND t1.shop_id = t6.shop_id and t6.table_code != '' and t6.table_code is not null
WHERE t1.shop_id = #{shopId}
<if test="beginDate != null and beginDate != ''">
AND t1.create_time >= str_to_date(#{beginDate}, '%Y-%m-%d %H:%i:%s')
</if>
<if test="endDate != null and endDate != ''">
and t1.create_time &lt;= str_to_date(#{endDate}, '%Y-%m-%d %H:%i:%s')
</if>
GROUP BY t1.table_code
order by count( t1.id ) desc,sum( t1.pay_amount ) desc
</select>
<select id="findSummaryExportList" resultType="com.czg.order.vo.TableSummaryExportVo">
SELECT
t.product_name,
date_format(t.create_time, '%Y-%m-%d') as create_date,
if(t.table_name = 'NONE','银收客',t.table_name) as table_name,
concat(if(t.table_name = 'NONE','银收客',t.table_name),'-',date_format(t.create_time, '%Y-%m-%d')) as tableConcatDate,
t.category_name,
t.unit_name,
group_concat(distinct t.sku_name SEPARATOR ';') as sku_name,
sum(t.num) as num,
avg(t.unit_price) as unit_price,
sum(t.num*t.unit_price) as amount,
sum(-t.refund_num) as refund_num,
sum(-t.refund_num*t.unit_price) as refund_amount
FROM
(
SELECT
t1.product_id,
t2.table_code,
IF(t2.table_code is null or t2.table_code = '' or t6.NAME is null, 'NONE', t6.NAME) AS table_name,
t1.create_time,
t4.NAME AS category_name,
t3.name as product_name,
t5.NAME AS unit_name,
t1.sku_name,
t1.num,
t1.unit_price,
t1.refund_num as refund_num
FROM
tb_order_detail t1
LEFT JOIN tb_order_info t2 ON t1.order_id = t2.id
LEFT JOIN tb_product t3 ON t1.product_id = t3.id
LEFT JOIN tb_shop_prod_category t4 ON t3.category_id = t4.id
LEFT JOIN tb_shop_prod_unit t5 ON t3.unit_id = t5.id
LEFT JOIN tb_shop_table t6 ON t2.table_code = t6.table_code AND t1.shop_id = t6.shop_id and t6.table_code != '' and t6.table_code is not null
WHERE t1.shop_id = #{shopId}
<if test="beginDate != null and beginDate != ''">
AND t1.create_time >= str_to_date(#{beginDate}, '%Y-%m-%d %H:%i:%s')
</if>
<if test="endDate != null and endDate != ''">
and t1.create_time &lt;= str_to_date(#{endDate}, '%Y-%m-%d %H:%i:%s')
</if>
) t
) t
group by t.product_id,date_format(t.create_time, '%Y-%m-%d'),t.table_name
order by t.table_name,t.table_code,date_format(t.create_time, '%Y-%m-%d'),t.category_name,t.product_id
</select>