|
|
@@ -10,15 +10,10 @@ import com.sckw.core.utils.BeanUtils;
|
|
|
import com.sckw.core.utils.DateUtils;
|
|
|
import com.sckw.core.utils.StringUtils;
|
|
|
import com.sckw.core.web.context.LoginUserHolder;
|
|
|
+import com.sckw.order.api.model.*;
|
|
|
import com.sckw.order.dao.KwoTradeOrderMapper;
|
|
|
import com.sckw.order.model.SalesReportRawData;
|
|
|
import com.sckw.order.model.dto.*;
|
|
|
-import com.sckw.order.api.model.DailySalesStatisticsDto;
|
|
|
-import com.sckw.order.api.model.DailyShipmentStatisticsDto;
|
|
|
-import com.sckw.order.api.model.GoodsAmountStatisticsDto;
|
|
|
-import com.sckw.order.api.model.GoodsVolumeStatisticsDto;
|
|
|
-import com.sckw.order.api.model.SalesReportDataVo;
|
|
|
-import com.sckw.order.api.model.SalesReportQueryDto;
|
|
|
import com.sckw.order.model.vo.req.WbTOrderDataStsParam;
|
|
|
import com.sckw.order.model.vo.req.WbTOrderExcelStsParam;
|
|
|
import com.sckw.order.model.vo.res.TOrderDataStsResVO;
|
|
|
@@ -34,8 +29,6 @@ import com.sckw.product.api.model.KwpGoods;
|
|
|
import com.sckw.system.api.RemoteSystemService;
|
|
|
import lombok.RequiredArgsConstructor;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
-import java.util.*;
|
|
|
-import java.util.stream.Collectors;
|
|
|
import org.apache.dubbo.config.annotation.DubboReference;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
@@ -43,7 +36,10 @@ import java.math.BigDecimal;
|
|
|
import java.math.RoundingMode;
|
|
|
import java.time.LocalDate;
|
|
|
import java.time.LocalDateTime;
|
|
|
+import java.time.format.DateTimeFormatter;
|
|
|
import java.time.temporal.TemporalAdjusters;
|
|
|
+import java.util.*;
|
|
|
+import java.util.stream.Collectors;
|
|
|
|
|
|
/**
|
|
|
* @desc: 贸易订单统计service
|
|
|
@@ -329,47 +325,75 @@ public class KwoTradeOrderStatisticsService {
|
|
|
* @return 销售报表数据列表
|
|
|
*/
|
|
|
public List<SalesReportDataVo> querySalesReportData(SalesReportQueryDto queryDto) {
|
|
|
- if(StringUtils.isBlank(queryDto.getEndTime())){
|
|
|
+ if (StringUtils.isBlank(queryDto.getEndTime())) {
|
|
|
queryDto.setEndTime(DateUtils.getCurrentTime());
|
|
|
}
|
|
|
+ // 将字符串时间转换为 LocalDateTime 用于比较
|
|
|
+ LocalDateTime endDateTime = LocalDateTime.parse(queryDto.getEndTime(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
|
|
|
+ LocalDateTime startDateTime = null;
|
|
|
+ if (StringUtils.isNotBlank(queryDto.getStartTime())) {
|
|
|
+ startDateTime = LocalDateTime.parse(queryDto.getStartTime(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
|
|
|
+ }
|
|
|
+
|
|
|
// 1. 查询基础销售订单数据
|
|
|
List<SalesReportRawData> rawDataList = tradeOrderMapper.querySalesReportRawData(
|
|
|
queryDto.getCurEntId(),
|
|
|
queryDto.getTradeEntId(),
|
|
|
queryDto.getGoodsId()
|
|
|
);
|
|
|
-
|
|
|
- // 2. 收集商品ID,获取商品名称
|
|
|
+
|
|
|
+ // 2. 收集商品ID(过滤 null)
|
|
|
List<Long> goodsIds = rawDataList.stream()
|
|
|
.map(SalesReportRawData::getGoodsId)
|
|
|
.filter(Objects::nonNull)
|
|
|
.distinct()
|
|
|
.collect(Collectors.toList());
|
|
|
-
|
|
|
+
|
|
|
// 3. 调用商品服务获取商品名称
|
|
|
Map<Long, KwpGoods> goodsMap = new HashMap<>();
|
|
|
if (!goodsIds.isEmpty()) {
|
|
|
goodsMap = goodsInfoService.getGoodsByIds(goodsIds);
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
// 4. 按客户和商品分组汇总数据
|
|
|
Map<Long, Map<Long, SalesReportDataVo>> customerGoodsMap = new HashMap<>();
|
|
|
-
|
|
|
+
|
|
|
for (SalesReportRawData rawData : rawDataList) {
|
|
|
- Long customerId = rawData.getCustomerId();
|
|
|
Long goodsId = rawData.getGoodsId();
|
|
|
- BigDecimal amount = rawData.getAmount();
|
|
|
- BigDecimal price = rawData.getPrice();
|
|
|
- String createTime = rawData.getCreateTime();
|
|
|
-
|
|
|
+ // 过滤商品ID为 null 的数据
|
|
|
+ if (goodsId == null) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ Long customerId = rawData.getCustomerId();
|
|
|
+ // 金额/数量判空处理
|
|
|
+ BigDecimal amount = rawData.getAmount() != null ? rawData.getAmount() : BigDecimal.ZERO;
|
|
|
+ BigDecimal price = rawData.getPrice() != null ? rawData.getPrice() : BigDecimal.ZERO;
|
|
|
+ String createTimeStr = rawData.getCreateTime();
|
|
|
+ if (createTimeStr == null) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ LocalDateTime createTime = LocalDateTime.parse(createTimeStr, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
|
|
|
+
|
|
|
// 初始化客户和商品的映射
|
|
|
customerGoodsMap.putIfAbsent(customerId, new HashMap<>());
|
|
|
Map<Long, SalesReportDataVo> goodsMapForCustomer = customerGoodsMap.get(customerId);
|
|
|
-
|
|
|
- // 初始化销售报表数据对象
|
|
|
goodsMapForCustomer.putIfAbsent(goodsId, new SalesReportDataVo());
|
|
|
+
|
|
|
SalesReportDataVo vo = goodsMapForCustomer.get(goodsId);
|
|
|
-
|
|
|
+ // 初始化 BigDecimal 字段(防止 null)
|
|
|
+ if (vo.getCumulativeQuantity() == null) {
|
|
|
+ vo.setCumulativeQuantity(BigDecimal.ZERO);
|
|
|
+ }
|
|
|
+ if (vo.getCumulativeAmount() == null) {
|
|
|
+ vo.setCumulativeAmount(BigDecimal.ZERO);
|
|
|
+ }
|
|
|
+ if (vo.getSalesQuantity() == null) {
|
|
|
+ vo.setSalesQuantity(BigDecimal.ZERO);
|
|
|
+ }
|
|
|
+ if (vo.getSalesAmount() == null) {
|
|
|
+ vo.setSalesAmount(BigDecimal.ZERO);
|
|
|
+ }
|
|
|
+
|
|
|
// 设置基本信息
|
|
|
vo.setCustomerId(customerId);
|
|
|
vo.setCustomerName(rawData.getCustomerName());
|
|
|
@@ -378,40 +402,45 @@ public class KwoTradeOrderStatisticsService {
|
|
|
if (goods != null) {
|
|
|
vo.setGoodsName(goods.getName());
|
|
|
}
|
|
|
-
|
|
|
- // 计算累计数据
|
|
|
- if (createTime.compareTo(queryDto.getEndTime()) <= 0){
|
|
|
+
|
|
|
+ // 累计数据(createTime <= endTime)
|
|
|
+ if (createTime.compareTo(endDateTime) <= 0) {
|
|
|
vo.setCumulativeQuantity(vo.getCumulativeQuantity().add(amount));
|
|
|
vo.setCumulativeAmount(vo.getCumulativeAmount().add(price));
|
|
|
if (vo.getCumulativeQuantity().compareTo(BigDecimal.ZERO) > 0) {
|
|
|
- vo.setCumulativeAveragePrice(vo.getCumulativeAmount().divide(vo.getCumulativeQuantity(), 2, RoundingMode.HALF_UP));
|
|
|
+ vo.setCumulativeAveragePrice(vo.getCumulativeAmount()
|
|
|
+ .divide(vo.getCumulativeQuantity(), 2, RoundingMode.HALF_UP));
|
|
|
}
|
|
|
- // 计算当前时间段数据
|
|
|
- if(queryDto.getStartTime() == null){
|
|
|
+ // 当前时间段数据
|
|
|
+ if (startDateTime == null) {
|
|
|
+ // 无开始时间:所有累计数据也计入销售
|
|
|
vo.setSalesQuantity(vo.getSalesQuantity().add(amount));
|
|
|
vo.setSalesAmount(vo.getSalesAmount().add(price));
|
|
|
if (vo.getSalesQuantity().compareTo(BigDecimal.ZERO) > 0) {
|
|
|
- vo.setAveragePrice(vo.getSalesAmount().divide(vo.getSalesQuantity(), 2, RoundingMode.HALF_UP));
|
|
|
+ vo.setAveragePrice(vo.getSalesAmount()
|
|
|
+ .divide(vo.getSalesQuantity(), 2, RoundingMode.HALF_UP));
|
|
|
}
|
|
|
- }else if(createTime.compareTo(queryDto.getStartTime()) >= 0){
|
|
|
+ } else if (createTime.compareTo(startDateTime) >= 0) {
|
|
|
vo.setSalesQuantity(vo.getSalesQuantity().add(amount));
|
|
|
vo.setSalesAmount(vo.getSalesAmount().add(price));
|
|
|
if (vo.getSalesQuantity().compareTo(BigDecimal.ZERO) > 0) {
|
|
|
- vo.setAveragePrice(vo.getSalesAmount().divide(vo.getSalesQuantity(), 2, RoundingMode.HALF_UP));
|
|
|
+ vo.setAveragePrice(vo.getSalesAmount()
|
|
|
+ .divide(vo.getSalesQuantity(), 2, RoundingMode.HALF_UP));
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
// 5. 转换为列表并返回
|
|
|
List<SalesReportDataVo> result = new ArrayList<>();
|
|
|
for (Map<Long, SalesReportDataVo> goodsMapForCustomer : customerGoodsMap.values()) {
|
|
|
result.addAll(goodsMapForCustomer.values());
|
|
|
}
|
|
|
-
|
|
|
- // 6. 排序
|
|
|
- result.sort(Comparator.comparing(SalesReportDataVo::getCustomerName).thenComparing(SalesReportDataVo::getGoodsName));
|
|
|
-
|
|
|
+
|
|
|
+ // 6. 排序(处理 null 名称)
|
|
|
+ result.sort(Comparator.comparing(SalesReportDataVo::getCustomerName, Comparator.nullsLast(String::compareTo))
|
|
|
+ .thenComparing(SalesReportDataVo::getGoodsName, Comparator.nullsLast(String::compareTo)));
|
|
|
+
|
|
|
return result;
|
|
|
}
|
|
|
|