销售统计增加分类区分

This commit is contained in:
gong
2025-12-08 16:56:32 +08:00
parent b02eaa851a
commit e53d275ba0
8 changed files with 118 additions and 73 deletions

View File

@@ -42,8 +42,7 @@ public class SaleSummaryController {
if (param.getShopId() == null) {
param.setShopId(shopId);
}
SaleSummaryCountVo data = prodStatisticService.summaryCount(
param.getShopId(), param.getProductName(), param.getRangeType(), param.getBeginDate(), param.getEndDate());
SaleSummaryCountVo data = prodStatisticService.summaryCount(param);
return CzgResult.success(data);
}
@@ -58,8 +57,7 @@ public class SaleSummaryController {
if (param.getShopId() == null) {
param.setShopId(shopId);
}
List<ShopProdStatistic> list = prodStatisticService.getArchiveTradeData(
param.getShopId(),param.getProductName(), param.getRangeType(), param.getBeginDate(), param.getEndDate());
List<ShopProdStatistic> list = prodStatisticService.getArchiveTradeData(param);
return CzgResult.success(list);
}
@@ -70,8 +68,7 @@ public class SaleSummaryController {
if (param.getShopId() == null) {
param.setShopId(shopId);
}
return prodStatisticService.getArchiveTradeData(
param.getShopId(),param.getProductName(), param.getRangeType(), param.getBeginDate(), param.getEndDate());
return prodStatisticService.getArchiveTradeData(param);
}
}

View File

@@ -76,7 +76,7 @@ public class StatisticTask {
public void statisticAndInsertProd(Long shopId, LocalDate date) {
try {
shopProdStatisticService.statisticAndInsert(shopId, date);
shopProdStatisticService.statisticAndInsert(shopId, date, 0L);
} catch (Exception e) {
log.error("统计商品数据失败店铺id:{},日期:{}", shopId, date, e);
}

View File

@@ -40,6 +40,13 @@ public class ShopProdStatistic implements Serializable {
*/
@ExcelIgnore
private Long prodId;
/**
* 分类 ID
*/
@ExcelIgnore
private Long categoryId;
/**
* 商品名称
*/

View File

@@ -3,6 +3,7 @@ package com.czg.order.param;
import com.czg.validator.group.DefaultGroup;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serial;
import java.io.Serializable;
@@ -14,6 +15,7 @@ import java.time.LocalDate;
* @since 2025-03-07 16:23
*/
@Data
@Accessors(chain = true)
public class SaleSummaryCountParam implements Serializable {
@Serial
@@ -24,6 +26,11 @@ public class SaleSummaryCountParam implements Serializable {
*/
private String productName;
/**
* 分类 Id
*/
private Long categoryId;
/**
* 开始时间 格式yyyy-MM-dd
*/

View File

@@ -1,6 +1,7 @@
package com.czg.order.service;
import com.czg.order.entity.ShopProdStatistic;
import com.czg.order.param.SaleSummaryCountParam;
import com.czg.order.vo.SaleSummaryCountVo;
import com.mybatisflex.core.service.IService;
@@ -20,13 +21,12 @@ public interface ShopProdStatisticService extends IService<ShopProdStatistic> {
*
* @return 商品数据
*/
SaleSummaryCountVo summaryCount(Long shopId, String productName, String rangeType, LocalDate start, LocalDate end);
SaleSummaryCountVo summaryCount(SaleSummaryCountParam param);
/**
* 获取某一段时间的商品交易数据
*
* @param shopId 店铺id
* @param rangeType 时间范围类型
* shopId 店铺id
* rangeType 时间范围类型
* TODAY, // 今天
* YESTERDAY, // 昨天
* LAST_7_DAYS, // 最近7天
@@ -34,11 +34,11 @@ public interface ShopProdStatisticService extends IService<ShopProdStatistic> {
* THIS_WEEK, // 本周
* THIS_MONTH // 本月
* CUSTOM // 自定义时间范围
* @param start 开始时间 格式yyyy-MM-dd 今天/昨天不用传
* @param end 结束时间 格式yyyy-MM-dd 今天/昨天不用传
* start 开始时间 格式yyyy-MM-dd 今天/昨天不用传
* end 结束时间 格式yyyy-MM-dd 今天/昨天不用传
* @return 商品数据
*/
List<ShopProdStatistic> getArchiveTradeData(Long shopId, String productName, String rangeType, LocalDate start, LocalDate end);
List<ShopProdStatistic> getArchiveTradeData(SaleSummaryCountParam param);
List<ShopProdStatistic> getArchiveTradeDataBy10(Long shopId, Integer day);
//------------------------------------------------------------下列为 后台使用------------------------------------------------------------
@@ -46,18 +46,18 @@ public interface ShopProdStatisticService extends IService<ShopProdStatistic> {
/**
* 统计某天数据并插入数据库
*/
void statisticAndInsert(Long shopId, LocalDate day);
void statisticAndInsert(Long shopId, LocalDate day, Long categoryId);
/**
* 实时统计某天数据
*/
List<ShopProdStatistic> getRealTimeDataByDay(Long shopId, LocalDate day, String productName);
List<ShopProdStatistic> getRealTimeDataByDay(Long shopId, LocalDate day, String productName, Long categoryId);
/**
* 获取某一天的数据 历史数据
* 从ShopOrderStatistic 表中查询
*/
List<ShopProdStatistic> getProdStatSingleDate(Long shopId, LocalDate day, String productName);
List<ShopProdStatistic> getProdStatSingleDate(Long shopId, LocalDate day, String productName, Long categoryId);
/**
* 统计 某时间段数据 总和 不包括当日实时数据
@@ -65,5 +65,5 @@ public interface ShopProdStatisticService extends IService<ShopProdStatistic> {
* @param start 开始时间
* @param end 结束时间
*/
List<ShopProdStatistic> getProdStatDateRange(Long shopId, LocalDate start, LocalDate end, String productName);
List<ShopProdStatistic> getProdStatDateRange(Long shopId, LocalDate start, LocalDate end, String productName, Long categoryId);
}

View File

@@ -18,16 +18,16 @@ public interface ShopProdStatisticMapper extends BaseMapper<ShopProdStatistic> {
/**
* 根据店铺id和日期 统计商品
*/
List<ShopProdStatistic> selectProStatByDay(Long shopId, LocalDate day, String productName);
List<ShopProdStatistic> selectProStatByDay(Long shopId, LocalDate day, String productName, Long categoryId);
List<ShopProdStatistic> getProdStatSingleDate(Long shopId, LocalDate day, String productName);
List<ShopProdStatistic> getProdStatSingleDate(Long shopId, LocalDate day, String productName, Long categoryId);
List<ShopProdStatistic> getProdStatDateRange(Long shopId, LocalDate start, LocalDate end, String productName);
List<ShopProdStatistic> getProdStatDateRange(Long shopId, LocalDate start, LocalDate end, String productName, Long categoryId);
//-----------------总统计 总金额统计-----------------
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);
SaleSummaryCountVo summaryCountByDay(Long shopId, LocalDate day, String productName, Long categoryId);
SaleSummaryCountVo summaryCountSingleDate(Long shopId, LocalDate day, String productName, Long categoryId);
SaleSummaryCountVo summaryCountDateRange(Long shopId, LocalDate start, LocalDate end, String productName, Long categoryId);
}

View File

@@ -3,6 +3,7 @@ package com.czg.service.order.service.impl;
import cn.hutool.core.collection.CollUtil;
import com.czg.exception.CzgException;
import com.czg.order.entity.ShopProdStatistic;
import com.czg.order.param.SaleSummaryCountParam;
import com.czg.order.service.ShopProdStatisticService;
import com.czg.order.vo.SaleSummaryCountVo;
import com.czg.service.order.mapper.ShopProdStatisticMapper;
@@ -34,7 +35,9 @@ public class ShopProdStatisticServiceImpl extends ServiceImpl<ShopProdStatisticM
public List<ShopProdStatistic> getArchiveTradeDataBy10(Long shopId, Integer day) {
LocalDate currentDate = LocalDate.now();
LocalDate startDate = currentDate.minusDays(day - 1);
List<ShopProdStatistic> archiveTradeData = getArchiveTradeData(shopId, null, "", startDate, currentDate);
List<ShopProdStatistic> archiveTradeData = getArchiveTradeData(new SaleSummaryCountParam()
.setShopId(shopId).setProductName(null).setRangeType("").setBeginDate(startDate)
.setEndDate(currentDate).setCategoryId(0L));
// 按照 saleCount 降序排序
return archiveTradeData.stream()
.sorted(
@@ -50,51 +53,55 @@ public class ShopProdStatisticServiceImpl extends ServiceImpl<ShopProdStatisticM
@Override
public SaleSummaryCountVo summaryCount(Long shopId, String productName, String rangeType, LocalDate start, LocalDate end) {
public SaleSummaryCountVo summaryCount(SaleSummaryCountParam param) {
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)) {
if ("today".equals(param.getRangeType())) {
return mapper.summaryCountByDay(param.getShopId(), currentDate, param.getProductName(), param.getCategoryId());
}
if ("yesterday".equals(param.getRangeType())) {
return mapper.summaryCountSingleDate(param.getShopId(), currentDate.minusDays(1), param.getProductName(), param.getCategoryId());
}
if (param.getBeginDate().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);
if (param.getBeginDate().equals(param.getEndDate())) {
return mapper.summaryCountSingleDate(param.getShopId(), param.getBeginDate(), param.getProductName(), param.getCategoryId());
}
if (param.getEndDate().isBefore(currentDate)) {
return mapper.summaryCountDateRange(param.getShopId(), param.getBeginDate(), param.getEndDate(), param.getProductName(), param.getCategoryId());
}
SaleSummaryCountVo todaySummary = mapper.summaryCountByDay(param.getShopId(), currentDate, param.getProductName(), param.getCategoryId());
SaleSummaryCountVo dateRangeSummary = mapper.summaryCountDateRange(param.getShopId(), param.getBeginDate(), param.getEndDate(), param.getProductName(), param.getCategoryId());
return mergeSummaryCountVo(todaySummary, dateRangeSummary);
}
}
}
}
@Override
public List<ShopProdStatistic> getArchiveTradeData(Long shopId, String productName, String rangeType, LocalDate start, LocalDate end) {
public List<ShopProdStatistic> getArchiveTradeData(SaleSummaryCountParam param) {
LocalDate currentDate = LocalDate.now();
productName = CzgStrUtils.getStrOrNull(productName);
param.setProductName(CzgStrUtils.getStrOrNull(param.getProductName()));
List<ShopProdStatistic> resultList;
if ("today".equals(rangeType)) {
resultList = getRealTimeDataByDay(shopId, currentDate, productName);
} else if ("yesterday".equals(rangeType)) {
resultList = getProdStatSingleDate(shopId, currentDate.minusDays(1), productName);
if ("today".equals(param.getRangeType())) {
resultList = getRealTimeDataByDay(param.getShopId(), currentDate, param.getProductName(), param.getCategoryId());
} else if ("yesterday".equals(param.getRangeType())) {
resultList = getProdStatSingleDate(param.getShopId(), currentDate.minusDays(1),
param.getProductName(), param.getCategoryId());
} else {
if (start.isAfter(currentDate)) {
if (param.getBeginDate().isAfter(currentDate)) {
throw new CzgException("开始时间不能晚于当前时间");
}
if (start.equals(end)) {
resultList = getProdStatSingleDate(shopId, start, productName);
if (param.getBeginDate().equals(param.getEndDate())) {
resultList = getProdStatSingleDate(param.getShopId(), param.getBeginDate(), param.getProductName(),
param.getCategoryId());
} else {
if (end.isBefore(currentDate)) {
resultList = getProdStatDateRange(shopId, start, end, productName);
if (param.getEndDate().isBefore(currentDate)) {
resultList = getProdStatDateRange(param.getShopId(), param.getBeginDate(), param.getEndDate(),
param.getProductName(), param.getCategoryId());
} else {
List<ShopProdStatistic> realTimeDataByDay = getRealTimeDataByDay(shopId, currentDate, productName);
List<ShopProdStatistic> dateRange = getProdStatDateRange(shopId, start, end, productName);
List<ShopProdStatistic> realTimeDataByDay = getRealTimeDataByDay(param.getShopId(), currentDate,
param.getProductName(), param.getCategoryId());
List<ShopProdStatistic> dateRange = getProdStatDateRange(param.getShopId(), param.getBeginDate(),
param.getEndDate(), param.getProductName(), param.getCategoryId());
resultList = mergeProdStatistic(realTimeDataByDay, dateRange);
}
@@ -105,8 +112,8 @@ public class ShopProdStatisticServiceImpl extends ServiceImpl<ShopProdStatisticM
@Override
public void statisticAndInsert(Long shopId, LocalDate day) {
List<ShopProdStatistic> realTimeData = getRealTimeDataByDay(shopId, day, null);
public void statisticAndInsert(Long shopId, LocalDate day, Long categoryId) {
List<ShopProdStatistic> realTimeData = getRealTimeDataByDay(shopId, day, null, categoryId);
if (CollUtil.isNotEmpty(realTimeData)) {
boolean exists = exists(QueryWrapper.create().eq(ShopProdStatistic::getShopId, shopId).eq(ShopProdStatistic::getCreateDay, day));
if (exists) {
@@ -117,8 +124,8 @@ public class ShopProdStatisticServiceImpl extends ServiceImpl<ShopProdStatisticM
}
@Override
public List<ShopProdStatistic> getRealTimeDataByDay(Long shopId, LocalDate day, String productName) {
List<ShopProdStatistic> shopProdStatistics = mapper.selectProStatByDay(shopId, day, productName);
public List<ShopProdStatistic> getRealTimeDataByDay(Long shopId, LocalDate day, String productName, Long categoryId) {
List<ShopProdStatistic> shopProdStatistics = mapper.selectProStatByDay(shopId, day, productName, categoryId);
// 过滤掉没有有效数据的记录
shopProdStatistics = shopProdStatistics.stream()
.filter(ShopProdStatistic::isValid)
@@ -128,18 +135,22 @@ public class ShopProdStatisticServiceImpl extends ServiceImpl<ShopProdStatisticM
}
@Override
public List<ShopProdStatistic> getProdStatSingleDate(Long shopId, LocalDate day, String productName) {
return mapper.getProdStatSingleDate(shopId, day, productName);
public List<ShopProdStatistic> getProdStatSingleDate(Long shopId, LocalDate day, String productName, Long categoryId) {
return mapper.getProdStatSingleDate(shopId, day, productName, categoryId);
}
@Override
public List<ShopProdStatistic> getProdStatDateRange(Long shopId, LocalDate start, LocalDate end, String productName) {
return mapper.getProdStatDateRange(shopId, start, end, productName);
public List<ShopProdStatistic> getProdStatDateRange(Long shopId, LocalDate start, LocalDate end, String productName, Long categoryId) {
return mapper.getProdStatDateRange(shopId, start, end, productName, categoryId);
}
private SaleSummaryCountVo mergeSummaryCountVo(SaleSummaryCountVo todaySummary, SaleSummaryCountVo dateRangeSummary) {
if (todaySummary == null) todaySummary = new SaleSummaryCountVo();
if (dateRangeSummary == null) dateRangeSummary = new SaleSummaryCountVo();
if (todaySummary == null) {
todaySummary = new SaleSummaryCountVo();
}
if (dateRangeSummary == null) {
dateRangeSummary = new SaleSummaryCountVo();
}
return new SaleSummaryCountVo(
safeAdd(todaySummary.getTotalAmount(), dateRangeSummary.getTotalAmount()),
@@ -158,8 +169,12 @@ public class ShopProdStatisticServiceImpl extends ServiceImpl<ShopProdStatisticM
* @return 合并后的数据
*/
private List<ShopProdStatistic> mergeProdStatistic(List<ShopProdStatistic> realTimeDataByDay, List<ShopProdStatistic> dateRange) {
if (realTimeDataByDay == null) realTimeDataByDay = new ArrayList<>();
if (dateRange == null) dateRange = new ArrayList<>();
if (realTimeDataByDay == null) {
realTimeDataByDay = new ArrayList<>();
}
if (dateRange == null) {
dateRange = new ArrayList<>();
}
return Stream.concat(realTimeDataByDay.stream(), dateRange.stream())
.filter(Objects::nonNull)

View File

@@ -8,6 +8,7 @@
SELECT
#{shopId} as shopId,
#{day} as createDay,
prod.category_id AS categoryId,
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,
@@ -17,7 +18,7 @@
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
INNER JOIN tb_product prod ON detail.product_id = prod.id
WHERE
`order`.shop_id = #{shopId}
AND `order`.trade_day = #{day}
@@ -25,6 +26,9 @@
<if test="productName != null and productName != ''">
AND detail.product_name LIKE CONCAT('%',#{productName},'%')
</if>
<if test="categoryId != null and categoryId > 0">
AND prod.category_id = #{categoryId}
</if>
GROUP BY prodId
</select>
@@ -41,6 +45,9 @@
<if test="productName != null and productName != ''">
AND prod.name LIKE CONCAT('%',#{productName},'%')
</if>
<if test="categoryId != null and categoryId > 0">
AND prod.category_id = #{categoryId}
</if>
ORDER BY
tb_shop_prod_statistic.sale_count DESC, tb_shop_prod_statistic.prod_id
</select>
@@ -63,6 +70,9 @@
<if test="productName != null and productName != ''">
AND prod.name LIKE CONCAT('%',#{productName},'%')
</if>
<if test="categoryId != null and categoryId > 0">
AND prod.category_id = #{categoryId}
</if>
GROUP BY
tb_shop_prod_statistic.prod_id
ORDER BY
@@ -79,7 +89,7 @@
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
INNER JOIN tb_product prod ON detail.product_id = prod.id
WHERE
`order`.shop_id = #{shopId}
AND `order`.trade_day = #{day}
@@ -87,6 +97,9 @@
<if test="productName != null and productName != ''">
AND detail.product_name LIKE CONCAT('%',#{productName},'%')
</if>
<if test="categoryId != null and categoryId > 0">
AND prod.category_id = #{categoryId}
</if>
</select>
<select id="summaryCountSingleDate" resultType="com.czg.order.vo.SaleSummaryCountVo">
SELECT
@@ -103,6 +116,9 @@
<if test="productName != null and productName != ''">
AND prod.name LIKE CONCAT('%',#{productName},'%')
</if>
<if test="categoryId != null and categoryId > 0">
AND prod.category_id = #{categoryId}
</if>
</select>
<select id="summaryCountDateRange" resultType="com.czg.order.vo.SaleSummaryCountVo">
@@ -121,6 +137,9 @@
<if test="productName != null and productName != ''">
AND prod.name LIKE CONCAT('%',#{productName},'%')
</if>
<if test="categoryId != null and categoryId > 0">
AND prod.category_id = #{categoryId}
</if>
</select>