Bläddra i källkod

Merge remote-tracking branch 'origin/master'

24282 1 år sedan
förälder
incheckning
b27f6c0756
16 ändrade filer med 698 tillägg och 42 borttagningar
  1. 18 8
      sd-business/src/main/java/com/sd/business/controller/statement/StatementOfAccountMergeController.java
  2. 24 0
      sd-business/src/main/java/com/sd/business/entity/excel/enums/ExcelTypeEnum.java
  3. 71 0
      sd-business/src/main/java/com/sd/business/entity/sku/bo/SkuSpecBo.java
  4. 33 0
      sd-business/src/main/java/com/sd/business/entity/statement/dto/SalesRevenueCostSelectDto.java
  5. 190 0
      sd-business/src/main/java/com/sd/business/entity/statement/vo/DocumentByRevenueCostVo.java
  6. 5 0
      sd-business/src/main/java/com/sd/business/mapper/sku/SkuSpecMapper.java
  7. 9 0
      sd-business/src/main/java/com/sd/business/service/order/impl/OrderServiceImpl.java
  8. 12 0
      sd-business/src/main/java/com/sd/business/service/production/impl/StockPreparationServiceImpl.java
  9. 6 0
      sd-business/src/main/java/com/sd/business/service/sku/SkuSpecService.java
  10. 20 0
      sd-business/src/main/java/com/sd/business/service/sku/impl/SkuSpecServiceImpl.java
  11. 14 8
      sd-business/src/main/java/com/sd/business/service/statement/StatementOfAccountMergeService.java
  12. 191 8
      sd-business/src/main/java/com/sd/business/service/statement/impl/StatementOfAccountMergeServiceImpl.java
  13. 1 1
      sd-business/src/main/java/com/sd/business/upload/ObsUploadService.java
  14. 19 0
      sd-business/src/main/resources/mapper/sku/SkuSpecMapper.xml
  15. 13 4
      sd-wln/src/main/java/com/sd/wln/context/OrderContext.java
  16. 72 13
      sd-wln/src/main/java/com/sd/wln/service/impl/WlnOrderServiceImpl.java

+ 18 - 8
sd-business/src/main/java/com/sd/business/controller/statement/StatementOfAccountMergeController.java

@@ -2,14 +2,8 @@ package com.sd.business.controller.statement;
 
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ruoyi.common.annotation.NonInterception;
-import com.sd.business.entity.statement.dto.ExportDocumentDto;
-import com.sd.business.entity.statement.dto.GetDocumentDto;
-import com.sd.business.entity.statement.dto.SalesOutWarehouseDetailsDto;
-import com.sd.business.entity.statement.dto.StatementOfAccountMergePageDto;
-import com.sd.business.entity.statement.vo.DocumentByBomVo;
-import com.sd.business.entity.statement.vo.DocumentByOrderVo;
-import com.sd.business.entity.statement.vo.DocumentBySkuVo;
-import com.sd.business.entity.statement.vo.StatementOfAccountMergePageVo;
+import com.sd.business.entity.statement.dto.*;
+import com.sd.business.entity.statement.vo.*;
 import com.sd.business.service.statement.StatementOfAccountMergeService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.validation.annotation.Validated;
@@ -107,4 +101,20 @@ public class StatementOfAccountMergeController {
         statementOfAccountMergeService.exportSalesOutWarehouseDetails(dto);
     }
 
+    /**
+     * 销售出货明细
+     */
+    @PostMapping("/salesRevenueCostPage")
+    public Page<DocumentByRevenueCostVo> salesRevenueCostPage(@RequestBody SalesRevenueCostSelectDto dto) {
+        return statementOfAccountMergeService.salesRevenueCostPage(dto);
+    }
+
+    /**
+     * 销售出货明细
+     */
+    @PostMapping("/exportSalesRevenueCostData")
+    public void exportSalesRevenueCostData(@RequestBody SalesRevenueCostSelectDto dto) {
+        statementOfAccountMergeService.exportSalesRevenueCostData(dto);
+    }
+
 }

+ 24 - 0
sd-business/src/main/java/com/sd/business/entity/excel/enums/ExcelTypeEnum.java

@@ -1,8 +1,12 @@
 package com.sd.business.entity.excel.enums;
 
+import com.ruoyi.common.exception.ServiceException;
 import lombok.AllArgsConstructor;
 import lombok.Getter;
 
+import java.util.HashMap;
+import java.util.Map;
+
 @Getter
 @AllArgsConstructor
 public enum ExcelTypeEnum {
@@ -11,9 +15,29 @@ public enum ExcelTypeEnum {
     STATISTICS_DOCUMENT_BY_ORDER(2, "订单对账报表"),
     PURCHASE_WAREHOUSING(3, "采购入库明细"),
     SALES_OUT_WAREHOUSE_DETAILS(4, "销货出库明细"),
+    DOCUMENT_BY_SALES_REVENUE_COST(5, "销售收入成本表"),
     ;
 
     private final Integer type;
     private final String explain;
 
+    private static final Map<Integer, ExcelTypeEnum> map = new HashMap<>();
+
+    static {
+        for (ExcelTypeEnum excelTypeEnum : values()) {
+            map.put(excelTypeEnum.getType(), excelTypeEnum);
+        }
+    }
+
+    /**
+     * 通过key获取名称
+     */
+    public static ExcelTypeEnum get(Integer key) {
+        ExcelTypeEnum excelTypeEnum = map.get(key);
+        if (excelTypeEnum == null) {
+            throw new ServiceException("未知导出状态:" + key);
+        }
+        return excelTypeEnum;
+    }
+
 }

+ 71 - 0
sd-business/src/main/java/com/sd/business/entity/sku/bo/SkuSpecBo.java

@@ -0,0 +1,71 @@
+package com.sd.business.entity.sku.bo;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+@Getter
+@Setter
+public class SkuSpecBo {
+
+    /**
+     * sku规格 id
+     */
+    private Long skuSpecId;
+
+    /**
+     * sku规格品号
+     */
+    private String skuSpecCode;
+
+    /**
+     * 条码
+     */
+    private String barCode;
+
+    /**
+     * sku规格品名
+     */
+    private String skuSpecName;
+
+    /**
+     * 加工面板 字典:charge_item
+     */
+    private String machinedPanel;
+
+    /**
+     * 长 cm
+     */
+    private BigDecimal length;
+
+    /**
+     * 宽 cm
+     */
+    private BigDecimal width;
+
+    /**
+     * 高 cm
+     */
+    private BigDecimal height;
+
+    /**
+     * 净重 g
+     */
+    private BigDecimal netWeight;
+
+    /**
+     * bom id
+     */
+    private Long bomSpecId;
+
+    /**
+     * 类目id
+     */
+    private Long skuClassifyId;
+
+    /**
+     * 分类名称
+     */
+    private String skuClassifyName;
+}

+ 33 - 0
sd-business/src/main/java/com/sd/business/entity/statement/dto/SalesRevenueCostSelectDto.java

@@ -0,0 +1,33 @@
+package com.sd.business.entity.statement.dto;
+
+import com.ruoyi.common.core.domain.BaseSelectDto;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 销售收入成本查询入参实体
+ */
+@Getter
+@Setter
+public class SalesRevenueCostSelectDto extends BaseSelectDto {
+
+    /**
+     * 订单号
+     */
+    private String code;
+
+    /**
+     * 事业部id
+     */
+    private Long departmentId;
+
+    /**
+     * sku编码
+     */
+    private String skuSpecCode;
+
+    /**
+     * sku名称
+     */
+    private String skuSpecName;
+}

+ 190 - 0
sd-business/src/main/java/com/sd/business/entity/statement/vo/DocumentByRevenueCostVo.java

@@ -0,0 +1,190 @@
+package com.sd.business.entity.statement.vo;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.alibaba.excel.annotation.write.style.HeadRowHeight;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+@Getter
+@Setter
+@Builder
+@ExcelIgnoreUnannotated
+@HeadRowHeight(30)
+public class DocumentByRevenueCostVo {
+
+    /**
+     * 订单id
+     */
+    private Long orderId;
+
+    /**
+     * 事业部id
+     */
+    private Long departmentId;
+
+    /**
+     * 对账单id
+     */
+    private Long statementOfAccountId;
+
+    /**
+     * 序号
+     */
+    @ExcelProperty({"销售收入成本表", "序号"})
+    private Integer serialNumber;
+
+    /**
+     * 发货时间
+     */
+    @ExcelProperty({"销售收入成本表", "销售日期"})
+    private Date salesDate;
+
+    /**
+     * 客户编号
+     */
+    @ExcelProperty({"销售收入成本表", "客户编号"})
+    private String customerCode;
+
+    /**
+     * 客户名称
+     */
+    @ExcelProperty({"销售收入成本表", "客户名称"})
+    private String customerName;
+
+    /**
+     * 事业部名称
+     */
+    @ExcelProperty({"销售收入成本表", "事业部"})
+    private String departmentName;
+
+    /**
+     * 销售订单号
+     */
+    @ExcelProperty({"销售收入成本表", "销售订单号"})
+    private String code;
+
+    /**
+     * 万里牛单号
+     */
+    @ExcelProperty({"销售收入成本表", "万里牛单号"})
+    private String wlnCode;
+
+    /**
+     * 出库单号
+     */
+    @ExcelProperty({"销售收入成本表", "出库单号"})
+    private String outStorageCode;
+
+    /**
+     * sku规格品号
+     */
+    @ExcelProperty({"销售收入成本表", "成品品号"})
+    private String skuSpecCode;
+
+    /**
+     * sku规格品名
+     */
+    @ExcelProperty({"销售收入成本表", "成品名称"})
+    private String skuSpecName;
+
+    /**
+     * 规格
+     */
+    @ExcelProperty({"销售收入成本表", "规格"})
+    private String spec;
+
+    /**
+     * 成品类别
+     */
+    @ExcelProperty({"销售收入成本表", "成品类别"})
+    private String classifyName;
+
+    /**
+     * 计量单位
+     */
+    @ExcelProperty({"销售收入成本表", "计量单位"})
+    private String measuringUnit;
+
+    /**
+     * 销售数量
+     */
+    @ExcelProperty({"销售收入成本表", "销售数量"})
+    private BigDecimal quantity;
+
+    /**
+     * 销售单价
+     */
+    @ExcelProperty({"销售收入成本表", "销售单价"})
+    private BigDecimal salesUnitPrice;
+
+    /**
+     * 销售金额
+     */
+    @ExcelProperty({"销售收入成本表", "销售金额"})
+    private BigDecimal salesAmount;
+
+    /**
+     * 产品金额
+     */
+    @ExcelProperty({"销售收入成本表", "其中:产品金额"})
+    private BigDecimal productAmount;
+
+    /**
+     * 代发金额
+     */
+    @ExcelProperty({"销售收入成本表", "其中:代发金额"})
+    private BigDecimal issuingAmount;
+
+    /**
+     * 其他金额(包装人工费)
+     */
+    @ExcelProperty({"销售收入成本表", "其中:其他金额"})
+    private BigDecimal otherAmount;
+
+    /**
+     * 材料成本
+     */
+    @ExcelProperty({"销售收入成本表", "材料成本"})
+    private BigDecimal materialCost;
+
+    /**
+     * 辅料成本
+     */
+    @ExcelProperty({"销售收入成本表", "辅料成本"})
+    private BigDecimal auxiliaryMaterialCost;
+
+    /**
+     * 产品包材成本
+     */
+    @ExcelProperty({"销售收入成本表", "产品包材成本"})
+    private BigDecimal productPackagingMaterialCost;
+
+    /**
+     * 物流包材成本
+     */
+    @ExcelProperty({"销售收入成本表", "物流包材成本"})
+    private BigDecimal logisticsPackagingMaterialCost;
+
+    /**
+     * 成本小计
+     */
+    @ExcelProperty({"销售收入成本表", "成本小计"})
+    private BigDecimal costSubtotal;
+
+    /**
+     * 毛利
+     */
+    @ExcelProperty({"销售收入成本表", "毛利"})
+    private BigDecimal grossProfit;
+
+    /**
+     * 毛利率
+     */
+    @ExcelProperty({"销售收入成本表", "毛利率"})
+    private String grossProfitRate;
+}

+ 5 - 0
sd-business/src/main/java/com/sd/business/mapper/sku/SkuSpecMapper.java

@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ruoyi.common.utils.wrapper.IWrapper;
 import com.sd.business.entity.bom.bo.BomSpecBo;
+import com.sd.business.entity.sku.bo.SkuSpecBo;
 import com.sd.business.entity.sku.po.SkuSpec;
 import com.sd.business.entity.sku.vo.SkuSpecVo;
 import org.apache.ibatis.annotations.Param;
@@ -32,4 +33,8 @@ public interface SkuSpecMapper extends BaseMapper<SkuSpec> {
      */
     List<BomSpecBo> getBomSpecBoList(@Param("ew") QueryWrapper<Object> in);
 
+    /**
+     * 根据sku规格id获取sku详情信息
+     */
+    List<SkuSpecBo> getSkuSpecBoList(@Param("ew") QueryWrapper<Object> in);
 }

+ 9 - 0
sd-business/src/main/java/com/sd/business/service/order/impl/OrderServiceImpl.java

@@ -325,6 +325,9 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, OrderInfo> implem
             orderSkuProductionCost.setAuxiliaryMaterialCost(BigDecimal.ZERO);
             // 产品包材成本
             List<OrderSkuBom> bomList = orderSkuBomMap.get(item.getId());
+            if (bomList == null) {
+                bomList = new ArrayList<>();
+            }
             BigDecimal productPackagingMaterialCost = bomList.stream()
                     .map(orderSkuBom -> orderSkuBom.getQuantity()
                             .multiply(orderSkuBom.getUnitPrice())
@@ -428,6 +431,9 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, OrderInfo> implem
             orderSkuProductionCost.setAuxiliaryMaterialCost(BigDecimal.ZERO);
             // 产品包材成本
             List<OrderSkuBom> bomList = orderSkuBomMap.get(item.getId());
+            if (bomList == null) {
+                bomList = new ArrayList<>();
+            }
             BigDecimal productPackagingMaterialCost = bomList.stream()
                     .map(orderSkuBom -> orderSkuBom.getQuantity()
                             .multiply(orderSkuBom.getUnitPrice())
@@ -544,6 +550,9 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, OrderInfo> implem
             orderSkuProductionCost.setAuxiliaryMaterialCost(BigDecimal.ZERO);
             // 产品包材成本
             List<OrderSkuBom> bomList = orderSkuBomMap.get(item.getId());
+            if (bomList == null) {
+                bomList = new ArrayList<>();
+            }
             BigDecimal productPackagingMaterialCost = bomList.stream()
                     .map(orderSkuBom -> orderSkuBom.getQuantity()
                             .multiply(orderSkuBom.getUnitPrice())

+ 12 - 0
sd-business/src/main/java/com/sd/business/service/production/impl/StockPreparationServiceImpl.java

@@ -38,6 +38,7 @@ import com.sd.business.service.bom.BomClassifyService;
 import com.sd.business.service.bom.BomService;
 import com.sd.business.service.bom.BomSpecService;
 import com.sd.business.service.in.InOutStorageService;
+import com.sd.business.service.inventory.InventoryFinishedService;
 import com.sd.business.service.inventory.InventoryService;
 import com.sd.business.service.order.OrderService;
 import com.sd.business.service.order.OrderSkuBomService;
@@ -105,6 +106,9 @@ public class StockPreparationServiceImpl implements StockPreparationService {
     @Autowired
     private StatementOfAccountService statementOfAccountService;
 
+    @Autowired
+    private InventoryFinishedService inventoryFinishedService;
+
     @Override
     public List<UncompletedVo> uncompletedList(StockPreparationDto dto) {
 
@@ -246,6 +250,14 @@ public class StockPreparationServiceImpl implements StockPreparationService {
                 statement.setOrderIdList(orderIds);
                 statementOfAccountService.add(statement);
             }
+
+            List<Long> orderIds = statementOrderList.stream().map(BaseIdPo::getId).collect(Collectors.toList());
+
+            // 生产入库
+            inventoryFinishedService.productionWarehousing(orderIds);
+
+            // 库存销售出库
+            inventoryFinishedService.saleOutOfWarehouse(orderIds);
         }
 
     }

+ 6 - 0
sd-business/src/main/java/com/sd/business/service/sku/SkuSpecService.java

@@ -3,6 +3,7 @@ package com.sd.business.service.sku;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ruoyi.common.core.service.BaseService;
 import com.sd.business.entity.bom.bo.BomSpecBo;
+import com.sd.business.entity.sku.bo.SkuSpecBo;
 import com.sd.business.entity.sku.dto.SkuSpecDto;
 import com.sd.business.entity.sku.dto.SkuSpecSelectDto;
 import com.sd.business.entity.sku.po.SkuSpec;
@@ -62,4 +63,9 @@ public interface SkuSpecService extends BaseService<SkuSpec> {
      * 获取sku的库存数量
      */
     BigDecimal getSkuInventoryQuantity(Long id);
+
+    /**
+     * 根据sku规格id获取sku详情
+     */
+    Map<Long, SkuSpecBo> getSkuSpecBoByIdList(Collection<Long> skuSpecIdList);
 }

+ 20 - 0
sd-business/src/main/java/com/sd/business/service/sku/impl/SkuSpecServiceImpl.java

@@ -9,6 +9,7 @@ import com.ruoyi.common.exception.ServiceException;
 import com.ruoyi.common.utils.wrapper.IWrapper;
 import com.sd.business.entity.bom.bo.BomSpecBo;
 import com.sd.business.entity.inventory.po.Inventory;
+import com.sd.business.entity.sku.bo.SkuSpecBo;
 import com.sd.business.entity.sku.dto.SkuSpecDto;
 import com.sd.business.entity.sku.dto.SkuSpecSelectDto;
 import com.sd.business.entity.sku.po.SkuSpec;
@@ -125,4 +126,23 @@ public class SkuSpecServiceImpl extends ServiceImpl<SkuSpecMapper, SkuSpec> impl
         return inventory == null ? BigDecimal.ZERO : inventory.getQuantity();
     }
 
+    @Override
+    public Map<Long, SkuSpecBo> getSkuSpecBoByIdList(Collection<Long> skuSpecIdList) {
+
+        if (ObjectUtil.isEmpty(skuSpecIdList)) {
+            return Collections.emptyMap();
+        }
+
+        skuSpecIdList = skuSpecIdList.stream().filter(ObjectUtil::isNotNull).distinct().collect(Collectors.toList());
+
+        if (ObjectUtil.isEmpty(skuSpecIdList)) {
+            return Collections.emptyMap();
+        }
+
+        List<SkuSpecBo> list = baseMapper.getSkuSpecBoList(Wrappers.query().in("ss.id", skuSpecIdList));
+
+        return list.stream().collect(Collectors.toMap(SkuSpecBo::getSkuSpecId, Function.identity()));
+
+    }
+
 }

+ 14 - 8
sd-business/src/main/java/com/sd/business/service/statement/StatementOfAccountMergeService.java

@@ -1,14 +1,8 @@
 package com.sd.business.service.statement;
 
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.sd.business.entity.statement.dto.ExportDocumentDto;
-import com.sd.business.entity.statement.dto.GetDocumentDto;
-import com.sd.business.entity.statement.dto.SalesOutWarehouseDetailsDto;
-import com.sd.business.entity.statement.dto.StatementOfAccountMergePageDto;
-import com.sd.business.entity.statement.vo.DocumentByBomVo;
-import com.sd.business.entity.statement.vo.DocumentByOrderVo;
-import com.sd.business.entity.statement.vo.DocumentBySkuVo;
-import com.sd.business.entity.statement.vo.StatementOfAccountMergePageVo;
+import com.sd.business.entity.statement.dto.*;
+import com.sd.business.entity.statement.vo.*;
 
 import java.util.List;
 
@@ -60,4 +54,16 @@ public interface StatementOfAccountMergeService {
      */
     void exportSalesOutWarehouseDetails(SalesOutWarehouseDetailsDto dto);
 
+    /**
+     * 查询销售收入成本分页
+     * @param dto
+     * @return
+     */
+    Page<DocumentByRevenueCostVo> salesRevenueCostPage(SalesRevenueCostSelectDto dto);
+
+    /**
+     * 导出销售收入成本数据
+     * @param dto
+     */
+    void exportSalesRevenueCostData(SalesRevenueCostSelectDto dto);
 }

+ 191 - 8
sd-business/src/main/java/com/sd/business/service/statement/impl/StatementOfAccountMergeServiceImpl.java

@@ -13,26 +13,26 @@ import com.ruoyi.common.core.domain.BasePo;
 import com.ruoyi.common.exception.ServiceException;
 import com.ruoyi.common.utils.PageUtils;
 import com.sd.business.entity.excel.enums.ExcelTypeEnum;
+import com.sd.business.entity.inventory.po.InventoryFinishedOrderDetail;
 import com.sd.business.entity.order.po.OrderInfo;
 import com.sd.business.entity.order.po.OrderSku;
+import com.sd.business.entity.order.po.OrderSkuProductionCost;
+import com.sd.business.entity.sku.bo.SkuSpecBo;
 import com.sd.business.entity.sku.po.SkuSpec;
-import com.sd.business.entity.statement.dto.ExportDocumentDto;
-import com.sd.business.entity.statement.dto.GetDocumentDto;
-import com.sd.business.entity.statement.dto.SalesOutWarehouseDetailsDto;
-import com.sd.business.entity.statement.dto.StatementOfAccountMergePageDto;
+import com.sd.business.entity.statement.dto.*;
 import com.sd.business.entity.statement.po.StatementOfAccount;
-import com.sd.business.entity.statement.vo.DocumentByBomVo;
-import com.sd.business.entity.statement.vo.DocumentByOrderVo;
-import com.sd.business.entity.statement.vo.DocumentBySkuVo;
-import com.sd.business.entity.statement.vo.StatementOfAccountMergePageVo;
+import com.sd.business.entity.statement.vo.*;
 import com.sd.business.service.department.DepartmentService;
 import com.sd.business.service.excel.ExcelGenerateLogService;
+import com.sd.business.service.inventory.InventoryFinishedOrderDetailService;
 import com.sd.business.service.order.OrderService;
+import com.sd.business.service.order.OrderSkuProductionCostService;
 import com.sd.business.service.order.OrderSkuService;
 import com.sd.business.service.sku.SkuSpecService;
 import com.sd.business.service.statement.StatementOfAccountExportService;
 import com.sd.business.service.statement.StatementOfAccountMergeService;
 import com.sd.business.service.statement.StatementOfAccountService;
+import com.sd.business.strategy.impl.DefaultExportStrategy;
 import com.sd.business.strategy.impl.DocumentByOrderExcelExportStrategy;
 import com.sd.business.strategy.impl.SalesOutWarehouseDetailsExportStrategy;
 import com.sd.framework.util.Assert;
@@ -40,6 +40,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import java.math.BigDecimal;
+import java.math.RoundingMode;
 import java.util.*;
 import java.util.function.Function;
 import java.util.stream.Collectors;
@@ -76,6 +77,12 @@ public class StatementOfAccountMergeServiceImpl implements StatementOfAccountMer
     @Autowired
     private SkuSpecService skuSpecService;
 
+    @Autowired
+    private OrderSkuProductionCostService orderSkuProductionCostService;
+
+    @Autowired
+    private InventoryFinishedOrderDetailService inventoryFinishedOrderDetailService;
+
     @Override
     public Page<StatementOfAccountMergePageVo> getPage(StatementOfAccountMergePageDto dto) {
 
@@ -316,6 +323,182 @@ public class StatementOfAccountMergeServiceImpl implements StatementOfAccountMer
                 DateUtil.formatDate(new Date()) + " 销售出货明细");
     }
 
+    @Override
+    public Page<DocumentByRevenueCostVo> salesRevenueCostPage(SalesRevenueCostSelectDto dto) {
+        // 对账单条件查询
+        List<StatementOfAccount> statementOfAccountList = null;
+        List<Long> statementOfAccountIdList = null;
+
+        if (!ObjectUtil.isAllEmpty(dto.getBeginTime(), dto.getEndTime())) {
+            statementOfAccountList = statementOfAccountService.list(q -> q
+                    .ge(ObjectUtil.isNotNull(dto.getBeginTime()), BasePo::getCreateTime, dto.getBeginTime())
+                    .le(ObjectUtil.isNotNull(dto.getEndTime()), BasePo::getCreateTime, dto.getEndTime()));
+
+            if (statementOfAccountList.isEmpty()) {
+                return new Page<>();
+            }
+            statementOfAccountIdList = statementOfAccountList.stream().map(BaseIdPo::getId).collect(Collectors.toList());
+        }
+
+        // sku条件查询
+        List<Long> orderIdList = null;
+        if (!StrUtil.isAllBlank(dto.getSkuSpecCode(), dto.getSkuSpecName())) {
+            List<SkuSpec> skuSpecList = skuSpecService.list(q -> q
+                    .like(StrUtil.isNotBlank(dto.getSkuSpecCode()), SkuSpec::getCode, dto.getSkuSpecCode())
+                    .like(StrUtil.isNotBlank(dto.getSkuSpecName()), SkuSpec::getName, dto.getSkuSpecName()));
+
+            if (skuSpecList.isEmpty()) {
+                return new Page<>();
+            }
+            List<Long> skuSpecIdList = skuSpecList.stream().map(BaseIdPo::getId).collect(Collectors.toList());
+
+            List<OrderSku> orderSkuList = orderSkuService.list(q -> q.in(OrderSku::getSkuSpecId, skuSpecIdList));
+            if (orderSkuList.isEmpty()) {
+                return new Page<>();
+            }
+
+            orderIdList = orderSkuList.stream().map(OrderSku::getOrderId).collect(Collectors.toList());
+        }
+
+        Page<OrderInfo> page = dto.getPage();
+
+        // 查询订单分页
+        orderService.page(page, Wrappers.lambdaQuery(OrderInfo.class)
+                .in(ObjectUtil.isNotEmpty(orderIdList), BaseIdPo::getId, orderIdList)
+                .in(ObjectUtil.isNotEmpty(statementOfAccountIdList), OrderInfo::getStatementOfAccountId, statementOfAccountIdList)
+                .isNotNull(ObjectUtil.isEmpty(statementOfAccountIdList), OrderInfo::getStatementOfAccountId)
+                .eq(ObjectUtil.isNotNull(dto.getDepartmentId()), OrderInfo::getDepartmentId, dto.getDepartmentId())
+                .and(StrUtil.isNotBlank(dto.getCode()), q -> q
+                        .like(OrderInfo::getCode, dto.getCode()).or().like(OrderInfo::getWlnCode, dto.getCode()))
+                .orderByDesc(OrderInfo::getStatementOfAccountId)
+        );
+
+        List<OrderInfo> records = page.getRecords();
+
+        if (records.isEmpty()) {
+            return new Page<>();
+        }
+        Map<Long, OrderInfo> orderInfoMap = records.stream().collect(Collectors.toMap(BaseIdPo::getId, item -> item, (v1, v2) -> v2));
+        List<Long> orderIds = records.stream().map(BaseIdPo::getId).collect(Collectors.toList());
+        List<OrderSku> orderSkuList = orderSkuService.list(q -> q.in(OrderSku::getOrderId, orderIds));
+        // 获取sku详情数据
+        List<Long> skuSpecIds = orderSkuList.stream().map(OrderSku::getSkuSpecId).collect(Collectors.toList());
+        Map<Long, SkuSpecBo> skuSpecBoMap = skuSpecService.getSkuSpecBoByIdList(skuSpecIds);
+        // 获取订单成品出库数据
+        Map<Long, InventoryFinishedOrderDetail> inventoryMap = inventoryFinishedOrderDetailService.mapKEntity(
+                InventoryFinishedOrderDetail::getOrderSkuId,
+                q -> q.eq(InventoryFinishedOrderDetail::getOperationType, 2)
+                        .in(InventoryFinishedOrderDetail::getOrderInfoId, orderIds)
+                        .in(InventoryFinishedOrderDetail::getOrderSkuId, skuSpecIds));
+        // 获取订单sku生产成本数据
+        Map<Long, OrderSkuProductionCost> productionCostMap = orderSkuProductionCostService.mapKEntity(OrderSkuProductionCost::getOrderSkuId,
+                q -> q.in(OrderSkuProductionCost::getOrderId, orderIds));
+        Integer[] serialNumber = {1};
+        List<DocumentByRevenueCostVo> documentByRevenueCostVos = orderSkuList.stream()
+                .map(item -> {
+                    OrderInfo orderInfo = orderInfoMap.get(item.getOrderId());
+                    SkuSpecBo skuSpecBo = skuSpecBoMap.get(item.getSkuSpecId());
+                    InventoryFinishedOrderDetail inventoryDetail = inventoryMap.get(item.getSkuSpecId());
+                    // 规格
+                    String length = skuSpecBo.getLength() == null ? "0" : skuSpecBo.getLength().stripTrailingZeros().toPlainString();
+                    String width = skuSpecBo.getWidth() == null ? "0" : skuSpecBo.getWidth().stripTrailingZeros().toPlainString();
+                    String height = skuSpecBo.getHeight() == null ? "0" : skuSpecBo.getHeight().stripTrailingZeros().toPlainString();
+
+                    OrderSkuProductionCost productionCost = productionCostMap.get(item.getId());
+
+                    return DocumentByRevenueCostVo.builder()
+                            .orderId(item.getOrderId())
+                            .departmentId(orderInfo.getDepartmentId())
+                            .statementOfAccountId(orderInfo.getStatementOfAccountId())
+                            .salesDate(orderInfo.getShippingTime())
+                            .serialNumber(serialNumber[0]++)
+                            .code(orderInfo.getCode())
+                            .wlnCode(orderInfo.getWlnCode())
+                            .outStorageCode(inventoryDetail == null ? "" : inventoryDetail.getCode())
+                            .skuSpecCode(skuSpecBo.getSkuSpecCode())
+                            .skuSpecName(skuSpecBo.getSkuSpecName())
+                            .spec(length + " * " + width + " * " + height)
+                            .classifyName(skuSpecBo.getSkuClassifyName())
+                            .measuringUnit("pcs")
+                            .quantity(item.getQuantity())
+                            .salesUnitPrice(item.getUnitPrice()
+                                    .add(item.getCustomProcessingFee())
+                                    .add(item.getLssueFee())
+                                    .add(item.getDeliveryMaterialsFee())
+                                    .add(item.getPackingLabor())
+                                    .add(item.getPackagingMaterialCost())
+                                    .add(item.getManagementFee()))
+                            .issuingAmount(item.getLssueFee().multiply(item.getQuantity()))
+                            .otherAmount(item.getDeliveryMaterialsFee().multiply(item.getQuantity()))
+                            .materialCost(productionCost.getMaterialCost())
+                            .auxiliaryMaterialCost(productionCost.getAuxiliaryMaterialCost())
+                            .productPackagingMaterialCost(productionCost.getProductPackagingMaterialCost())
+                            .logisticsPackagingMaterialCost(productionCost.getLogisticsPackagingMaterialCost())
+                            .costSubtotal(productionCost.getTotalAmount())
+                            .build();
+                })
+                .peek(item -> item.setSalesAmount(item.getQuantity().multiply(item.getSalesUnitPrice())))
+                .peek(item -> {
+                    // 产品金额
+                    item.setProductAmount(item.getSalesAmount()
+                            .subtract(item.getIssuingAmount()).subtract(item.getOtherAmount()));
+                    // 毛利
+                    BigDecimal grossProfit = item.getSalesAmount().subtract(item.getCostSubtotal());
+                    // 毛利率
+                    String grossProfitRate;
+                    if (ObjectUtil.equals(item.getSalesAmount(), BigDecimal.ZERO)) {
+                        grossProfitRate = "0%";
+                    } else {
+                        grossProfitRate = grossProfit
+                                .divide(item.getSalesAmount(), 4, RoundingMode.HALF_UP)
+                                .multiply(new BigDecimal(100))
+                                .stripTrailingZeros().toPlainString() + "%";
+                    }
+                    item.setGrossProfit(grossProfit);
+                    item.setGrossProfitRate(grossProfitRate);
+                })
+                .collect(Collectors.toList());
+
+        // 赋值事业部名称
+        departmentService.attributeAssign(documentByRevenueCostVos, DocumentByRevenueCostVo::getDepartmentId, (item, department) -> {
+            item.setCustomerName(department.getName().startsWith("胜德实业") ? "胜德实业" : department.getName());
+            item.setDepartmentName(department.getName());
+        });
+
+        // 赋值对账时间
+        if (statementOfAccountList == null) {
+            statementOfAccountList = statementOfAccountService.listByIds(
+                    records.stream().map(OrderInfo::getStatementOfAccountId).collect(Collectors.toList()));
+        }
+        Map<Long, StatementOfAccount> map = statementOfAccountList.stream().collect(Collectors.toMap(BaseIdPo::getId, Function.identity()));
+
+        documentByRevenueCostVos.forEach(item -> {
+            Long statementOfAccountId = item.getStatementOfAccountId();
+            StatementOfAccount statementOfAccount = map.get(statementOfAccountId);
+            item.setSalesDate(statementOfAccount.getCreateTime());
+        });
+
+        Page<DocumentByRevenueCostVo> result = new Page<>();
+        result.setTotal(page.getTotal());
+        result.setRecords(documentByRevenueCostVos);
+        result.setPages(page.getPages());
+        result.setSize(page.getSize());
+        return result;
+    }
+
+    @Override
+    public void exportSalesRevenueCostData(SalesRevenueCostSelectDto dto) {
+        dto.setPageNum(1);
+        dto.setPageSize(999999999);
+        Page<DocumentByRevenueCostVo> page = this.salesRevenueCostPage(dto);
+        List<DocumentByRevenueCostVo> list = page.getRecords();
+        DefaultExportStrategy<DocumentByRevenueCostVo> defaultExportStrategy = new DefaultExportStrategy<>(
+                () -> list, DocumentByRevenueCostVo.class, "销售收入成本数据");
+
+        excelGenerateLogService.generateExcel(ExcelTypeEnum.DOCUMENT_BY_SALES_REVENUE_COST, defaultExportStrategy,
+                DateUtil.formatDate(new Date()) + " 销售收入成本表");
+    }
+
     private List<Long> getIdList(GetDocumentDto dto) {
 
         String idGroupConcat = dto.getIdGroupConcat();

+ 1 - 1
sd-business/src/main/java/com/sd/business/upload/ObsUploadService.java

@@ -63,7 +63,7 @@ public class ObsUploadService {
             // 获取oss链接客户端
             obsClient = getObsClient();
             // 上传
-            getObsClient().putObject(bucketName, objectKey, bis);
+            obsClient.putObject(bucketName, objectKey, bis);
         } catch (Exception e) {
             throw new ServiceException("上传失败");
         } finally {

+ 19 - 0
sd-business/src/main/resources/mapper/sku/SkuSpecMapper.xml

@@ -42,4 +42,23 @@
             ${ew.customSqlSegment}
     </select>
 
+    <select id="getSkuSpecBoList" resultType="com.sd.business.entity.sku.bo.SkuSpecBo">
+        SELECT ss.id                                     skuSpecId,
+               ss.code                                   skuSpecCode,
+               ss.name                                   skuSpecName,
+               ss.bar_code,
+               ss.machined_panel,
+               ss.length,
+               ss.width,
+               ss.height,
+               ss.net_weight,
+               ss.bom_spec_id,
+               s.sku_classify_id,
+               sc.name                                   skuClassifyName
+        FROM sku_spec ss
+                 LEFT JOIN sku s ON ss.sku_id = s.id
+                 LEFT JOIN sku_classify sc on s.sku_classify_id = sc.id
+            ${ew.customSqlSegment}
+    </select>
+
 </mapper>

+ 13 - 4
sd-wln/src/main/java/com/sd/wln/context/OrderContext.java

@@ -9,10 +9,7 @@ import com.ruoyi.common.core.domain.BaseIdPo;
 import com.ruoyi.framework.mybatis.holder.LogicHolder;
 import com.sd.business.entity.bom.bo.BomSpecBo;
 import com.sd.business.entity.department.po.Department;
-import com.sd.business.entity.order.po.OrderInfo;
-import com.sd.business.entity.order.po.OrderPackageBom;
-import com.sd.business.entity.order.po.OrderSku;
-import com.sd.business.entity.order.po.OrderSkuBom;
+import com.sd.business.entity.order.po.*;
 import com.sd.business.entity.price.po.PriceBillingStandard;
 import com.sd.business.entity.price.po.PriceBillingStandardDetail;
 import com.sd.business.entity.sku.po.Sku;
@@ -58,6 +55,12 @@ public class OrderContext {
     private final List<OrderInfo> updateOrderList = new ArrayList<>();
 
     /**
+     * 需要保存对账单的订单列表
+     */
+    @Getter
+    private final List<OrderInfo> saveStatementOrderList = new ArrayList<>();
+
+    /**
      * 保存订单明细列表
      */
     @Getter
@@ -70,6 +73,12 @@ public class OrderContext {
     private final List<OrderSkuBom> saveOrderSkuBomList = new ArrayList<>();
 
     /**
+     * 保存订单产品生产成本
+     */
+    @Getter
+    private final List<OrderSkuProductionCost> saveOrderSkuProductionCostList = new ArrayList<>();
+
+    /**
      * 保存订单包装
      */
     @Getter

+ 72 - 13
sd-wln/src/main/java/com/sd/wln/service/impl/WlnOrderServiceImpl.java

@@ -16,19 +16,14 @@ import com.sd.business.entity.department.po.Department;
 import com.sd.business.entity.order.enums.OrderClassifyEnum;
 import com.sd.business.entity.order.enums.OrderExceptionTypeEnum;
 import com.sd.business.entity.order.enums.OrderStatusEnum;
-import com.sd.business.entity.order.po.OrderInfo;
-import com.sd.business.entity.order.po.OrderPackageBom;
-import com.sd.business.entity.order.po.OrderSku;
-import com.sd.business.entity.order.po.OrderSkuBom;
+import com.sd.business.entity.order.po.*;
 import com.sd.business.entity.price.po.PriceBillingStandardDetail;
 import com.sd.business.entity.sku.po.SkuSpec;
 import com.sd.business.entity.sku.po.SkuSpecLink;
 import com.sd.business.entity.statement.dto.StatementOfAccountDto;
+import com.sd.business.service.inventory.InventoryFinishedService;
 import com.sd.business.service.inventory.InventoryService;
-import com.sd.business.service.order.OrderPackageBomService;
-import com.sd.business.service.order.OrderService;
-import com.sd.business.service.order.OrderSkuBomService;
-import com.sd.business.service.order.OrderSkuService;
+import com.sd.business.service.order.*;
 import com.sd.business.service.sku.SkuSpecService;
 import com.sd.business.service.statement.StatementOfAccountService;
 import com.sd.wln.context.OrderContext;
@@ -80,6 +75,12 @@ public class WlnOrderServiceImpl implements WlnOrderService {
     @Autowired
     private StatementOfAccountService statementOfAccountService;
 
+    @Autowired
+    private OrderSkuProductionCostService orderSkuProductionCostService;
+
+    @Autowired
+    private InventoryFinishedService inventoryFinishedService;
+
     @Override
     public void syncOrder() {
 
@@ -246,6 +247,7 @@ public class WlnOrderServiceImpl implements WlnOrderService {
         Department department = context.getDepartment();
         Map<Long, List<OrderSku>> existOrderSkuMap = context.getExistOrderSkuMap();
         List<OrderInfo> updateOrderList = context.getUpdateOrderList();
+        List<OrderInfo> saveStatementOrderList = context.getSaveStatementOrderList();
 
         orderInfo.setWlnStorageCode(wlnOrder.getString("storage_code"));
         orderInfo.setWlnUid(wlnOrder.getString("uid"));
@@ -277,11 +279,8 @@ public class WlnOrderServiceImpl implements WlnOrderService {
                         orderInfo.setStatus(OrderStatusEnum.COMPLETION_PRODUCTION.getKey());
                     }
                     orderInfo.setClassify(OrderClassifyEnum.NO_REASON_ORDER.getKey());
-                    // 生成对账单
-                    StatementOfAccountDto statement = new StatementOfAccountDto();
-                    statement.setDepartmentId(orderInfo.getDepartmentId());
-                    statement.setOrderIdList(Collections.singletonList(orderInfo.getId()));
-                    statementOfAccountService.add(statement);
+                    // 保存对账单列表
+                    saveStatementOrderList.add(orderInfo);
                 }
             }
         }
@@ -356,6 +355,38 @@ public class WlnOrderServiceImpl implements WlnOrderService {
     }
 
     /**
+     * 创建订单产品成本
+     */
+    private OrderSkuProductionCost createOrderSkuProductionCostList(OrderSku orderSku, List<OrderSkuBom> orderSkuBomList) {
+        OrderSkuProductionCost orderSkuProductionCost = new OrderSkuProductionCost();
+        orderSkuProductionCost.setOrderId(orderSku.getOrderId());
+        orderSkuProductionCost.setOrderSkuId(orderSku.getId());
+        // 材料成本
+        orderSkuProductionCost.setMaterialCost(orderSku.getUnitPrice().multiply(orderSku.getQuantity()));
+        // 辅料成本暂时没有默认为零
+        orderSkuProductionCost.setAuxiliaryMaterialCost(BigDecimal.ZERO);
+        // 产品包材成本
+        if (orderSkuBomList == null) {
+            orderSkuBomList = new ArrayList<>();
+        }
+        BigDecimal productPackagingMaterialCost = orderSkuBomList.stream()
+                .map(orderSkuBom -> orderSkuBom.getQuantity()
+                        .multiply(orderSkuBom.getUnitPrice())
+                        .multiply(orderSku.getQuantity()))
+                .reduce(BigDecimal.ZERO, BigDecimal::add);
+        orderSkuProductionCost.setProductPackagingMaterialCost(productPackagingMaterialCost);
+        // 物流包材成本
+        orderSkuProductionCost.setLogisticsPackagingMaterialCost(orderSku.getDeliveryMaterialsFee()
+                .multiply(orderSku.getQuantity()));
+        orderSkuProductionCost.setTotalAmount(
+                orderSkuProductionCost.getMaterialCost()
+                        .add(orderSkuProductionCost.getAuxiliaryMaterialCost())
+                        .add(orderSkuProductionCost.getProductPackagingMaterialCost())
+                        .add(orderSkuProductionCost.getLogisticsPackagingMaterialCost()));
+
+        return orderSkuProductionCost;
+    }
+    /**
      * 创建订单包装
      */
     private List<OrderPackageBom> createOrderPackageBomList(OrderContext context, List<OrderSku> orderSkuList) {
@@ -404,6 +435,7 @@ public class WlnOrderServiceImpl implements WlnOrderService {
         Map<String, SkuSpec> skuSpecMap = context.getSkuSpecMap();
 
         List<OrderSku> orderSkuList = new ArrayList<>();
+        List<OrderSkuProductionCost> orderSkuProductionCostList = new ArrayList<>();
         List<OrderSkuBom> orderSkuBomList = new ArrayList<>();
 
         // 创建订单sku
@@ -423,11 +455,16 @@ public class WlnOrderServiceImpl implements WlnOrderService {
             // 获取订单sku包材
             List<OrderSkuBom> tempOrderSkuBomList = createOrderSkuBoom(context, orderSku);
 
+            // 获取订单sku成本
+            OrderSkuProductionCost productionCostList = createOrderSkuProductionCostList(orderSku, tempOrderSkuBomList);
+
             // 添加订单金额
             addOrderInfoPrice(orderInfo, orderSku);
 
             orderSkuList.add(orderSku);
             orderSkuBomList.addAll(tempOrderSkuBomList);
+
+            orderSkuProductionCostList.add(productionCostList);
         }
 
         List<OrderPackageBom> orderPackageBomList = createOrderPackageBomList(context, orderSkuList);
@@ -435,6 +472,7 @@ public class WlnOrderServiceImpl implements WlnOrderService {
         context.getSaveOrderList().add(orderInfo);
         context.getSaveOrderSkuList().addAll(orderSkuList);
         context.getSaveOrderSkuBomList().addAll(orderSkuBomList);
+        context.getSaveOrderSkuProductionCostList().addAll(orderSkuProductionCostList);
         context.getOrderPackageBomList().addAll(orderPackageBomList);
     }
 
@@ -589,8 +627,10 @@ public class WlnOrderServiceImpl implements WlnOrderService {
 
         List<OrderInfo> saveOrderList = context.getSaveOrderList();
         List<OrderInfo> updateOrderList = context.getUpdateOrderList();
+        List<OrderInfo> saveStatementOrderList = context.getSaveStatementOrderList();
         List<OrderSku> saveOrderSkuList = context.getSaveOrderSkuList();
         List<OrderSkuBom> saveOrderSkuBomList = context.getSaveOrderSkuBomList();
+        List<OrderSkuProductionCost> saveOrderSkuProductionCostList = context.getSaveOrderSkuProductionCostList();
         List<OrderPackageBom> orderPackageBomList = context.getOrderPackageBomList();
 
         if (!saveOrderList.isEmpty()) {
@@ -599,12 +639,31 @@ public class WlnOrderServiceImpl implements WlnOrderService {
         if (!updateOrderList.isEmpty()) {
             orderService.updateBatchById(updateOrderList);
         }
+        if (!saveStatementOrderList.isEmpty()) {
+            saveStatementOrderList.forEach(item -> {
+                // 生成对账单
+                StatementOfAccountDto statement = new StatementOfAccountDto();
+                statement.setDepartmentId(item.getDepartmentId());
+                statement.setOrderIdList(Collections.singletonList(item.getId()));
+                statementOfAccountService.add(statement);
+
+                // 生产入库
+                inventoryFinishedService.productionWarehousing(Collections.singletonList(item.getId()));
+
+                // 库存销售出库
+                inventoryFinishedService.saleOutOfWarehouse(Collections.singletonList(item.getId()));
+
+            });
+        }
         if (!saveOrderSkuList.isEmpty()) {
             orderSkuService.saveBatch(saveOrderSkuList);
         }
         if (!saveOrderSkuBomList.isEmpty()) {
             orderSkuBomService.saveBatch(saveOrderSkuBomList);
         }
+        if (!saveOrderSkuProductionCostList.isEmpty()) {
+            orderSkuProductionCostService.saveBatch(saveOrderSkuProductionCostList);
+        }
         if (!orderPackageBomList.isEmpty()) {
             orderPackageBomService.saveBatch(orderPackageBomList);
         }