yzc 1 anno fa
parent
commit
b9fb0d9972

+ 74 - 0
hx-item/src/main/java/com/fjhx/item/entity/product/bo/ProductAnalysisBo.java

@@ -0,0 +1,74 @@
+package com.fjhx.item.entity.product.bo;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/**
+ * 产品分析实体
+ */
+@Getter
+@Setter
+public class ProductAnalysisBo {
+    /**
+     * 产品id
+     */
+    private Long productId;
+    /**
+     * 产品名称
+     */
+    private String productName;
+    /**
+     * 成单数
+     */
+    private BigDecimal orderCount;
+
+    //合同统计
+    /**
+     * 销量
+     */
+    private BigDecimal saleQuantity;
+    /**
+     * 销售额
+     */
+    private BigDecimal saleAmount;
+    /**
+     * 销售平均单价
+     */
+    private BigDecimal saleAveragePrice;
+    /**
+     * 销售最低单价
+     */
+    private BigDecimal saleMinPrice;
+    /**
+     * 销售最高单价
+     */
+    private BigDecimal saleMaxPrice;
+    //采购统计
+    /**
+     * 采购量
+     */
+    private BigDecimal purchasesQuantity;
+    /**
+     * 采购金额
+     */
+    private BigDecimal purchasesAmount;
+    /**
+     * 采购平均单价
+     */
+    private BigDecimal purchasesAveragePrice;
+    /**
+     * 采购最低单价
+     */
+    private BigDecimal purchasesMinPrice;
+    /**
+     * 采购最高单价
+     */
+    private BigDecimal purchasesMaxPrice;
+
+    /**
+     * 总利润
+     */
+    private BigDecimal grossProfit;
+}

+ 9 - 1
hx-item/src/main/java/com/fjhx/item/mapper/product/ProductInfoMapper.java

@@ -3,6 +3,7 @@ package com.fjhx.item.mapper.product;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.fjhx.item.entity.product.bo.ProductAnalysisBo;
 import com.fjhx.item.entity.product.po.ProductInfo;
 import com.fjhx.item.entity.product.vo.ProductInfoVo;
 import com.ruoyi.common.utils.wrapper.IWrapper;
@@ -55,6 +56,7 @@ public interface ProductInfoMapper extends BaseMapper<ProductInfo> {
      * @param query
      */
     Page<ProductInfoVo> productRanking(@Param("page") Page<Object> page,@Param("ew") QueryWrapper<Object> query);
+
     /**
      * 客户产品库
      */
@@ -62,7 +64,13 @@ public interface ProductInfoMapper extends BaseMapper<ProductInfo> {
 
     /**
      * 产品统计
+     *
      * @return
      */
-    Map<String,Object> statisticsProduct();
+    Map<String, Object> statisticsProduct();
+
+    /**
+     * 产品分析
+     */
+    Page<ProductAnalysisBo> getProductAnalysisPage(@Param("page") Page<Object> page, @Param("ew") IWrapper<ProductInfo> wrapper);
 }

+ 10 - 2
hx-item/src/main/java/com/fjhx/item/service/product/ProductInfoService.java

@@ -1,11 +1,13 @@
 package com.fjhx.item.service.product;
 
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.fjhx.item.entity.product.bo.ProductAnalysisBo;
 import com.fjhx.item.entity.product.dto.ProductInfoDto;
 import com.fjhx.item.entity.product.dto.ProductInfoSelectDto;
 import com.fjhx.item.entity.product.po.ProductInfo;
 import com.fjhx.item.entity.product.vo.ProductInfoVo;
 import com.ruoyi.common.core.service.BaseService;
+import com.ruoyi.common.utils.wrapper.IWrapper;
 import org.springframework.web.multipart.MultipartFile;
 
 import java.util.List;
@@ -145,12 +147,18 @@ public interface ProductInfoService extends BaseService<ProductInfo> {
 
     /**
      * 产品统计
+     *
      * @return
      */
-    Map<String,Object> statisticsProduct();
+    Map<String, Object> statisticsProduct();
 
     /**
      * 产品库统计(根据产品库类型进行分类统计)
      */
-    Map<String,Object> productInfoStatistics(ProductInfoSelectDto dto);
+    Map<String, Object> productInfoStatistics(ProductInfoSelectDto dto);
+
+    /**
+     * 产品分析-数据看板
+     */
+    Page<ProductAnalysisBo> getProductAnalysisPage(Page<Object> page, IWrapper<ProductInfo> wrapper);
 }

+ 6 - 0
hx-item/src/main/java/com/fjhx/item/service/product/impl/ProductInfoServiceImpl.java

@@ -18,6 +18,7 @@ import com.fjhx.common.utils.Assert;
 import com.fjhx.customer.entity.customer.po.Customer;
 import com.fjhx.customer.service.customer.CustomerService;
 import com.fjhx.file.utils.ObsFileUtil;
+import com.fjhx.item.entity.product.bo.ProductAnalysisBo;
 import com.fjhx.item.entity.product.dto.ProductInfoDto;
 import com.fjhx.item.entity.product.dto.ProductInfoSelectDto;
 import com.fjhx.item.entity.product.po.ProductClassify;
@@ -856,4 +857,9 @@ public class ProductInfoServiceImpl extends ServiceImpl<ProductInfoMapper, Produ
         return list;
     }
 
+    @Override
+    public Page<ProductAnalysisBo> getProductAnalysisPage(Page<Object> page, IWrapper<ProductInfo> wrapper) {
+        return baseMapper.getProductAnalysisPage(page, wrapper);
+    }
+
 }

+ 7 - 1
hx-item/src/main/resources/mapper/product/ProductInfoMapper.xml

@@ -123,7 +123,7 @@
     <select id="statisticsProduct" resultType="java.util.Map">
         SELECT
             `type` AS `type`,
-            count( 1 ) AS count
+            count(1) AS count
         FROM
             product_info
         WHERE `type` IS NOT NULL
@@ -133,4 +133,10 @@
         GROUP BY
             `type`
     </select>
+    <select id="getProductAnalysisPage" resultType="com.fjhx.item.entity.product.bo.ProductAnalysisBo">
+        select pi.id   AS productId,
+               pi.name AS productName
+        from product_info pi
+            ${ew.customSqlSegment}
+    </select>
 </mapper>

+ 9 - 0
hx-sale/src/main/java/com/fjhx/sale/controller/contract/ContractController.java

@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.fjhx.account.entity.account.vo.AccountRunningWaterVo;
+import com.fjhx.item.entity.product.bo.ProductAnalysisBo;
 import com.fjhx.item.entity.product.dto.ProductInfoSelectDto;
 import com.fjhx.sale.entity.contract.dto.ContractDto;
 import com.fjhx.sale.entity.contract.dto.ContractSelectDto;
@@ -311,4 +312,12 @@ public class ContractController {
         contractService.settle(dto);
     }
 
+    /**
+     * 产品分析
+     */
+    @PostMapping("/productAnalysis")
+    public Page<ProductAnalysisBo> productAnalysis(@RequestBody ContractSelectDto dto) {
+        return contractService.productAnalysis(dto);
+    }
+
 }

+ 13 - 1
hx-sale/src/main/java/com/fjhx/sale/mapper/contract/ContractMapper.java

@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.fjhx.account.entity.account.vo.AccountRunningWaterVo;
 import com.fjhx.customer.entity.customer.dto.CustomerDto;
+import com.fjhx.item.entity.product.bo.ProductAnalysisBo;
 import com.fjhx.sale.entity.contract.dto.ContractDto;
 import com.fjhx.sale.entity.contract.po.Contract;
 import com.fjhx.sale.entity.contract.vo.ContractBudgetVo;
@@ -122,10 +123,21 @@ public interface ContractMapper extends BaseMapper<Contract> {
 
     /**
      * 外销跟单分页
+     *
      * @param page
      * @param wrapper
      * @return
      */
-    Page<ContractVo> getExportCopyList(@Param("page") Page<Object> page, @Param("ew") IWrapper<Contract> wrapper,@Param("documentaryType") Integer documentaryType );
+    Page<ContractVo> getExportCopyList(@Param("page") Page<Object> page, @Param("ew") IWrapper<Contract> wrapper, @Param("documentaryType") Integer documentaryType);
+
+    /**
+     * 获取合同产品分析
+     */
+    List<ProductAnalysisBo> getContractProductInfo(@Param("ew") IWrapper<Object> wrapper);
+
+    /**
+     * 获取采购产品分析
+     */
+    List<ProductAnalysisBo> getPurchaseProductInfo(@Param("ew") IWrapper<Object> wrapper);
 
 }

+ 6 - 0
hx-sale/src/main/java/com/fjhx/sale/service/contract/ContractService.java

@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.fjhx.account.entity.account.vo.AccountRunningWaterVo;
 import com.fjhx.customer.entity.customer.dto.CustomerDto;
+import com.fjhx.item.entity.product.bo.ProductAnalysisBo;
 import com.fjhx.item.entity.product.dto.ProductInfoSelectDto;
 import com.fjhx.sale.entity.contract.dto.ContractDto;
 import com.fjhx.sale.entity.contract.dto.ContractSelectDto;
@@ -222,4 +223,9 @@ public interface ContractService extends BaseService<Contract> {
      * 合同结清
      */
     void settle(ContractDto dto);
+
+    /**
+     * 产品分析
+     */
+    Page<ProductAnalysisBo> productAnalysis(ContractSelectDto dto);
 }

+ 95 - 4
hx-sale/src/main/java/com/fjhx/sale/service/contract/impl/ContractServiceImpl.java

@@ -29,7 +29,6 @@ import com.fjhx.common.entity.documentary.bo.DocumentaryData;
 import com.fjhx.common.enums.FlowStatusEnum1;
 import com.fjhx.common.service.contract.ContractTemplateService;
 import com.fjhx.common.service.corporation.CorporationService;
-import com.fjhx.common.service.currency.CurrencyRateService;
 import com.fjhx.common.service.documentary.GetDocumentaryBusinessTemplate;
 import com.fjhx.common.utils.Assert;
 import com.fjhx.customer.entity.customer.dto.CustomerDto;
@@ -40,6 +39,7 @@ import com.fjhx.file.entity.FileInfoVo;
 import com.fjhx.file.service.FileInfoService;
 import com.fjhx.file.utils.ObsFileUtil;
 import com.fjhx.flow.service.flow.FlowExampleService;
+import com.fjhx.item.entity.product.bo.ProductAnalysisBo;
 import com.fjhx.item.entity.product.dto.ProductInfoSelectDto;
 import com.fjhx.item.entity.product.po.ProductInfo;
 import com.fjhx.item.service.product.ProductInfoService;
@@ -102,6 +102,7 @@ import java.text.SimpleDateFormat;
 import java.util.*;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ThreadPoolExecutor;
+import java.util.function.Function;
 import java.util.stream.Collectors;
 
 
@@ -154,9 +155,6 @@ public class ContractServiceImpl extends ServiceImpl<ContractMapper, Contract>
     private PurchaseDetailService purchaseDetailService;
 
     @Autowired
-    private CurrencyRateService currencyRateService;
-
-    @Autowired
     private ClaimContractService claimContractService;
 
     @Autowired
@@ -2263,4 +2261,97 @@ public class ContractServiceImpl extends ServiceImpl<ContractMapper, Contract>
         );
     }
 
+    /**
+     * 产品分析
+     */
+    @Override
+    public Page<ProductAnalysisBo> productAnalysis(ContractSelectDto dto) {
+        IWrapper<ProductInfo> wrapper = IWrapper.getWrapper();
+        Page<ProductAnalysisBo> productAnalysisPage = productInfoService.getProductAnalysisPage(dto.getPage(), wrapper);
+        List<ProductAnalysisBo> records = productAnalysisPage.getRecords();
+        if (ObjectUtil.isEmpty(records)) {
+            return productAnalysisPage;
+        }
+        List<Long> productIds = records.stream().map(ProductAnalysisBo::getProductId).collect(Collectors.toList());
+        List<ProductAnalysisBo> contractProductInfo = baseMapper.getContractProductInfo(IWrapper.getWrapper()
+                .in("cp.product_id", productIds)
+                .groupBy("cp.product_id")
+                .ge("c.create_time", dto.getBeginTime())
+                .le("c.create_time", dto.getEndTime())
+        );
+        Map<Long, ProductAnalysisBo> contractProductInfoMap = contractProductInfo.stream()
+                .collect(Collectors.toMap(ProductAnalysisBo::getProductId, Function.identity()));
+
+        List<ProductAnalysisBo> purchaseProductInfo = baseMapper.getPurchaseProductInfo(IWrapper.getWrapper()
+                .in("epp.product_id", productIds)
+                .groupBy("epp.product_id")
+                .ge("ep.create_time", dto.getBeginTime())
+                .le("ep.create_time", dto.getEndTime())
+        );
+        Map<Long, ProductAnalysisBo> purchaseProductInfoMap = purchaseProductInfo.stream()
+                .collect(Collectors.toMap(ProductAnalysisBo::getProductId, Function.identity()));
+
+        for (ProductAnalysisBo record : records) {
+
+            //合同统计
+            BigDecimal orderCount = BigDecimal.ZERO;
+            BigDecimal saleQuantity = BigDecimal.ZERO;
+            BigDecimal saleAmount = BigDecimal.ZERO;
+            BigDecimal saleAveragePrice = BigDecimal.ZERO;
+            BigDecimal saleMinPrice = BigDecimal.ZERO;
+            BigDecimal saleMaxPrice = BigDecimal.ZERO;
+
+            ProductAnalysisBo contractProduct = contractProductInfoMap.get(record.getProductId());
+            if (ObjectUtil.isNotEmpty(contractProduct)) {
+                orderCount = contractProduct.getOrderCount();
+                saleQuantity = contractProduct.getSaleQuantity();
+                saleAmount = contractProduct.getSaleAmount();
+                //计算平均单价
+                if (contractProduct.getSaleQuantity().compareTo(BigDecimal.ZERO) != 0) {
+                    saleAveragePrice = contractProduct.getSaleAmount()
+                            .divide(contractProduct.getSaleQuantity(), 4, RoundingMode.HALF_UP);
+                }
+                saleMinPrice = contractProduct.getSaleMinPrice();
+                saleMaxPrice = contractProduct.getSaleMaxPrice();
+            }
+
+            record.setOrderCount(orderCount.setScale(4, RoundingMode.HALF_UP));
+            record.setSaleQuantity(saleQuantity.setScale(4, RoundingMode.HALF_UP));
+            record.setSaleAmount(saleAmount.setScale(4, RoundingMode.HALF_UP));
+            record.setSaleAveragePrice(saleAveragePrice.setScale(4, RoundingMode.HALF_UP));
+            record.setSaleMinPrice(saleMinPrice.setScale(4, RoundingMode.HALF_UP));
+            record.setSaleMaxPrice(saleMaxPrice.setScale(4, RoundingMode.HALF_UP));
+
+            //采购统计
+            BigDecimal purchasesQuantity = BigDecimal.ZERO;
+            BigDecimal purchasesAmount = BigDecimal.ZERO;
+            BigDecimal purchasesAveragePrice = BigDecimal.ZERO;
+            BigDecimal purchasesMinPrice = BigDecimal.ZERO;
+            BigDecimal purchasesMaxPrice = BigDecimal.ZERO;
+
+            ProductAnalysisBo purchaseProduct = purchaseProductInfoMap.get(record.getProductId());
+            if (ObjectUtil.isNotEmpty(purchaseProduct)) {
+                purchasesQuantity = purchaseProduct.getPurchasesQuantity();
+                purchasesAmount = purchaseProduct.getPurchasesAmount();
+                //计算平均单价
+                if (purchaseProduct.getPurchasesQuantity().compareTo(BigDecimal.ZERO) != 0) {
+                    purchasesAveragePrice = purchaseProduct.getPurchasesAmount()
+                            .divide(purchaseProduct.getPurchasesQuantity(), 4, RoundingMode.HALF_UP);
+                }
+                purchasesMinPrice = purchaseProduct.getPurchasesMinPrice();
+                purchasesMaxPrice = purchaseProduct.getPurchasesMaxPrice();
+            }
+
+            record.setPurchasesQuantity(purchasesQuantity.setScale(4, RoundingMode.HALF_UP));
+            record.setPurchasesAmount(purchasesAmount.setScale(4, RoundingMode.HALF_UP));
+            record.setPurchasesAveragePrice(purchasesAveragePrice.setScale(4, RoundingMode.HALF_UP));
+            record.setPurchasesMinPrice(purchasesMinPrice.setScale(4, RoundingMode.HALF_UP));
+            record.setPurchasesMaxPrice(purchasesMaxPrice.setScale(4, RoundingMode.HALF_UP));
+
+            //计算总利润
+            record.setGrossProfit(record.getSaleAmount().subtract(record.getPurchasesAmount()));
+        }
+        return productAnalysisPage;
+    }
+
 }

+ 21 - 0
hx-sale/src/main/resources/mapper/contract/ContractMapper.xml

@@ -496,4 +496,25 @@
         ) t1
         ${ew.customSqlSegment}
     </select>
+    <select id="getContractProductInfo" resultType="com.fjhx.item.entity.product.bo.ProductAnalysisBo">
+        SELECT cp.product_id,
+               count(DISTINCT (cp.contract_id))                AS orderCount,
+               IFNULL(sum(cp.quantity), 0)                     AS saleQuantity,
+               IFNULL(sum(cp.price * cp.quantity * c.rate), 0) AS saleAmount,
+               IFNULL(min(cp.price * c.rate), 0)               AS saleMinPrice,
+               IFNULL(max(cp.price * c.rate), 0)               AS saleMaxPrice
+        FROM contract_product cp
+                 LEFT JOIN contract c ON cp.contract_id = c.id
+            ${ew.customSqlSegment}
+    </select>
+    <select id="getPurchaseProductInfo" resultType="com.fjhx.item.entity.product.bo.ProductAnalysisBo">
+        SELECT epp.product_id,
+               IFNULL(sum(epp.quantity), 0)                       AS purchasesQuantity,
+               IFNULL(sum(epp.price * epp.quantity * ep.rate), 0) AS purchasesAmount,
+               IFNULL(min(epp.price * ep.rate), 0)                AS purchasesMinPrice,
+               IFNULL(max(epp.price * ep.rate), 0)                AS purchasesMaxPrice
+        FROM ehsd_purchase_product epp
+                 LEFT JOIN ehsd_purchase ep ON epp.purchase_id = ep.id
+            ${ew.customSqlSegment}
+    </select>
 </mapper>