| | |
| | | package cn.iocoder.yudao.module.erp.service.statistics; |
| | | |
| | | import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; |
| | | import cn.iocoder.yudao.module.crm.api.customer.CrmCustomerApi; |
| | | import cn.iocoder.yudao.module.crm.api.customer.dto.CrmCustomerRespDTO; |
| | | import cn.iocoder.yudao.module.erp.controller.admin.statistics.vo.sale.ErpSaleCustomerSummaryRespVO; |
| | | import cn.iocoder.yudao.module.erp.controller.admin.statistics.vo.sale.ErpSaleProductSummaryRespVO; |
| | | import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleCustomerReceiptStatisticsDO; |
| | | import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleCustomerStatisticsDO; |
| | | import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleProductStatisticsDO; |
| | | import cn.iocoder.yudao.module.erp.dal.mysql.statistics.ErpSaleStatisticsMapper; |
| | | import cn.iocoder.yudao.module.mdm.api.item.MdmItemApi; |
| | | import cn.iocoder.yudao.module.mdm.api.item.dto.MdmItemRespDTO; |
| | | import jakarta.annotation.Resource; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDateTime; |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * ERP 销售统计 Service 实现类 |
| | |
| | | @Resource |
| | | private ErpSaleStatisticsMapper saleStatisticsMapper; |
| | | |
| | | @Resource |
| | | private CrmCustomerApi customerApi; |
| | | |
| | | @Resource |
| | | private MdmItemApi mdmItemApi; |
| | | |
| | | @Override |
| | | public BigDecimal getSalePrice(LocalDateTime beginTime, LocalDateTime endTime) { |
| | | return saleStatisticsMapper.getSalePrice(beginTime, endTime); |
| | | } |
| | | |
| | | @Override |
| | | public List<ErpSaleCustomerSummaryRespVO> getCustomerSummary(Long customerId, LocalDateTime beginTime, LocalDateTime endTime) { |
| | | List<ErpSaleCustomerStatisticsDO> saleList = saleStatisticsMapper.selectCustomerStatistics(customerId, beginTime, endTime); |
| | | if (CollectionUtils.isAnyEmpty(saleList)) { |
| | | return new ArrayList<>(); |
| | | } |
| | | // 1. 已收款金额按客户归集(收款单可能早于/晚于订单,不做订单级勾稽,只按客户汇总) |
| | | Map<Long, BigDecimal> receiptMap = CollectionUtils.convertMap( |
| | | saleStatisticsMapper.selectCustomerReceiptStatistics(customerId, beginTime, endTime), |
| | | ErpSaleCustomerReceiptStatisticsDO::getCustomerId, |
| | | ErpSaleCustomerReceiptStatisticsDO::getReceiptAmount); |
| | | // 2. 客户名称 |
| | | Map<Long, CrmCustomerRespDTO> customerMap = customerApi.getCustomerMap( |
| | | CollectionUtils.convertSet(saleList, ErpSaleCustomerStatisticsDO::getCustomerId)); |
| | | // 3. 组装 |
| | | List<ErpSaleCustomerSummaryRespVO> result = new ArrayList<>(saleList.size()); |
| | | for (ErpSaleCustomerStatisticsDO sale : saleList) { |
| | | BigDecimal saleAmount = sale.getSaleAmount() == null ? BigDecimal.ZERO : sale.getSaleAmount(); |
| | | BigDecimal receiptAmount = receiptMap.getOrDefault(sale.getCustomerId(), BigDecimal.ZERO); |
| | | CrmCustomerRespDTO customer = customerMap.get(sale.getCustomerId()); |
| | | ErpSaleCustomerSummaryRespVO vo = new ErpSaleCustomerSummaryRespVO(); |
| | | vo.setCustomerId(sale.getCustomerId()); |
| | | vo.setCustomerName(customer != null ? customer.getName() : "客户(" + sale.getCustomerId() + ")"); |
| | | vo.setOrderCount(sale.getOrderCount()); |
| | | vo.setSaleAmount(saleAmount); |
| | | vo.setReceiptAmount(receiptAmount); |
| | | vo.setUnreceivedAmount(saleAmount.subtract(receiptAmount)); |
| | | vo.setLastOrderTime(sale.getLastOrderTime()); |
| | | result.add(vo); |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | @Override |
| | | public List<ErpSaleProductSummaryRespVO> getProductSummary(Long productId, LocalDateTime beginTime, LocalDateTime endTime) { |
| | | List<ErpSaleProductStatisticsDO> saleList = saleStatisticsMapper.selectProductStatistics(productId, beginTime, endTime); |
| | | if (CollectionUtils.isAnyEmpty(saleList)) { |
| | | return new ArrayList<>(); |
| | | } |
| | | // 1. 产品名称与参考成本价 |
| | | Map<Long, MdmItemRespDTO> itemMap = mdmItemApi.getItemMap( |
| | | CollectionUtils.convertSet(saleList, ErpSaleProductStatisticsDO::getProductId)); |
| | | // 2. 组装,毛利 = 销售金额 - 数量 × 参考成本价 |
| | | List<ErpSaleProductSummaryRespVO> result = new ArrayList<>(saleList.size()); |
| | | for (ErpSaleProductStatisticsDO sale : saleList) { |
| | | MdmItemRespDTO item = itemMap.get(sale.getProductId()); |
| | | BigDecimal saleAmount = sale.getSaleAmount() == null ? BigDecimal.ZERO : sale.getSaleAmount(); |
| | | BigDecimal costPrice = item != null && item.getCostPrice() != null ? item.getCostPrice() : BigDecimal.ZERO; |
| | | BigDecimal totalCount = sale.getTotalCount() == null ? BigDecimal.ZERO : sale.getTotalCount(); |
| | | BigDecimal costAmount = costPrice.multiply(totalCount); |
| | | ErpSaleProductSummaryRespVO vo = new ErpSaleProductSummaryRespVO(); |
| | | vo.setProductId(sale.getProductId()); |
| | | vo.setProductName(item != null ? item.getName() : "产品(" + sale.getProductId() + ")"); |
| | | vo.setOrderCount(sale.getOrderCount()); |
| | | vo.setTotalCount(totalCount); |
| | | vo.setSaleAmount(saleAmount); |
| | | vo.setCostAmount(costAmount); |
| | | vo.setProfitAmount(saleAmount.subtract(costAmount)); |
| | | result.add(vo); |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | } |