24282 il y a 1 an
Parent
commit
cc94e3a6ac

+ 35 - 0
sd-business/src/main/java/com/sd/business/controller/order/OrderInfoController.java

@@ -4,9 +4,12 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ruoyi.common.core.domain.BaseSelectDto;
 import com.sd.business.entity.order.dto.OrderInfoDto;
 import com.sd.business.entity.order.dto.OrderInfoSelectDto;
+import com.sd.business.entity.order.dto.SkuSpecPackageBomDto;
 import com.sd.business.entity.order.dto.SkuSpecPriceDto;
 import com.sd.business.entity.order.enums.OrderExceptionTypeEnum;
 import com.sd.business.entity.order.vo.OrderInfoVo;
+import com.sd.business.entity.order.vo.OrderPackageBomVo;
+import com.sd.business.entity.order.vo.OutBomVo;
 import com.sd.business.entity.order.vo.SkuSpecPriceVo;
 import com.sd.business.service.order.OrderInfoService;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -147,4 +150,36 @@ public class OrderInfoController {
         orderInfoService.cancelSuspendOrder(dto.getId());
     }
 
+    /**
+     * 订单删除退料清单
+     */
+    @PostMapping("/returnBomList")
+    public List<OutBomVo> returnBomList(@RequestBody BaseSelectDto dto) {
+        return orderInfoService.returnBomList(dto.getId());
+    }
+
+    /**
+     * 修改订单产品包装
+     */
+    @PostMapping("/editOrderPackageBom")
+    public void editOrderPackageBom(@RequestBody OrderInfoDto dto) {
+        orderInfoService.editOrderPackageBom(dto);
+    }
+
+    /**
+     * 获取产品包装bom列表
+     */
+    @PostMapping("/getSkuSpecPackageBomList")
+    public List<OrderPackageBomVo> getSkuSpecPackageBomList(@Validated @RequestBody SkuSpecPackageBomDto dto) {
+        return orderInfoService.getSkuSpecPackageBomList(dto);
+    }
+
+    /**
+     * 订单导出
+     */
+    @PostMapping("/orderExportExcel")
+    public void orderExportExcel(@RequestBody BaseSelectDto dto) {
+        orderInfoService.orderExportExcel(dto.getId());
+    }
+
 }

+ 27 - 0
sd-business/src/main/java/com/sd/business/entity/order/dto/SkuSpecPackageBomDto.java

@@ -0,0 +1,27 @@
+package com.sd.business.entity.order.dto;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.validation.Valid;
+import javax.validation.constraints.NotEmpty;
+import java.util.List;
+
+/**
+ * 订单sku包装bom列表查询入参实体
+ *
+ * @author
+ * @since 2023-11-06
+ */
+@Getter
+@Setter
+public class SkuSpecPackageBomDto {
+
+    /**
+     * 订单sku信息
+     */
+    @Valid
+    @NotEmpty(message = "规格不能为空")
+    private List<SkuSpecPriceDto> skuSpecList;
+
+}

+ 70 - 0
sd-business/src/main/java/com/sd/business/entity/order/vo/OrderSkuExportVo.java

@@ -0,0 +1,70 @@
+package com.sd.business.entity.order.vo;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.alibaba.excel.annotation.write.style.ColumnWidth;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/**
+ * 订单sku 导出返回值实体
+ *
+ * @author
+ * @since 2023-11-14
+ */
+@Getter
+@Setter
+@ExcelIgnoreUnannotated
+public class OrderSkuExportVo {
+
+    /**
+     * E10订单号
+     */
+    @ColumnWidth(15)
+    @ExcelProperty(value = "E10订单号", index = 0)
+    private String wlnCode;
+
+    /**
+     * sku品号
+     */
+    @ColumnWidth(15)
+    @ExcelProperty(value = "SKU", index = 1)
+    private String skuSpecCode;
+
+    /**
+     * bom品号
+     */
+    @ColumnWidth(15)
+    @ExcelProperty(value = "bom品号", index = 2)
+    private String bomSpecCode;
+
+
+    /**
+     * E10成品品号
+     */
+    @ColumnWidth(15)
+    @ExcelProperty(value = "E10成品品号", index = 3)
+    private String erpCode;
+
+    /**
+     * E10成品特征码
+     */
+    @ColumnWidth(15)
+    @ExcelProperty(value = "特征码", index = 4)
+    private String featureCode;
+
+    /**
+     * 数量
+     */
+    @ExcelProperty(value = "业务数量", index = 5)
+    private BigDecimal quantity;
+
+    /**
+     * sku总金额
+     */
+    @ExcelProperty(value = "金额", index = 6)
+    private BigDecimal totalAmount;
+
+}

+ 62 - 0
sd-business/src/main/java/com/sd/business/entity/order/vo/OutBomVo.java

@@ -0,0 +1,62 @@
+package com.sd.business.entity.order.vo;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+@Getter
+@Setter
+public class OutBomVo {
+
+    /**
+     * bom规格id
+     */
+    private Long bomSpecId;
+
+    /**
+     * bom品号
+     */
+    private String bomSpecCode;
+
+    /**
+     * bom品名
+     */
+    private String bomSpecName;
+
+    /**
+     * 仓库id
+     */
+    private Long warehouseId;
+
+    /**
+     * 仓库名称
+     */
+    private String warehouseName;
+
+    /**
+     * 库存数量
+     */
+    private BigDecimal inventoryQuantity;
+
+    /**
+     * 出库数量
+     */
+    private BigDecimal outQuantity;
+
+    /**
+     * 分类id
+     */
+    private Long classifyId;
+
+    /**
+     * 分类名称
+     */
+    private String classifyName;
+
+    /**
+     * 分类父id
+     */
+    private Long classifyParentId;
+
+}

+ 25 - 0
sd-business/src/main/java/com/sd/business/service/order/OrderInfoService.java

@@ -4,11 +4,16 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ruoyi.common.core.service.BaseService;
 import com.sd.business.entity.order.dto.OrderInfoDto;
 import com.sd.business.entity.order.dto.OrderInfoSelectDto;
+import com.sd.business.entity.order.dto.SkuSpecPackageBomDto;
 import com.sd.business.entity.order.dto.SkuSpecPriceDto;
 import com.sd.business.entity.order.po.OrderInfo;
 import com.sd.business.entity.order.vo.OrderInfoVo;
+import com.sd.business.entity.order.vo.OrderPackageBomVo;
+import com.sd.business.entity.order.vo.OutBomVo;
 import com.sd.business.entity.order.vo.SkuSpecPriceVo;
 
+import java.util.List;
+
 
 /**
  * <p>
@@ -90,4 +95,24 @@ public interface OrderInfoService extends BaseService<OrderInfo> {
      */
     void cancelSuspendOrder(Long id);
 
+    /**
+     * 订单删除退料清单
+     */
+    List<OutBomVo> returnBomList(Long id);
+
+    /**
+     * 修改订单产品包装
+     */
+    void editOrderPackageBom(OrderInfoDto dto);
+
+    /**
+     * 获取产品包装bom列表
+     */
+    List<OrderPackageBomVo> getSkuSpecPackageBomList(SkuSpecPackageBomDto dto);
+
+    /**
+     * 订单导出
+     */
+    void orderExportExcel(Long id);
+
 }

+ 313 - 7
sd-business/src/main/java/com/sd/business/service/order/impl/OrderInfoServiceImpl.java

@@ -19,15 +19,18 @@ import com.ruoyi.system.service.ISysUserService;
 import com.sd.business.entity.bom.bo.BomSpecBo;
 import com.sd.business.entity.bom.po.Bom;
 import com.sd.business.entity.bom.po.BomSpec;
+import com.sd.business.entity.department.constant.DepartmentConstant;
 import com.sd.business.entity.department.po.Department;
 import com.sd.business.entity.in.dto.InOutStorageDto;
 import com.sd.business.entity.in.emums.InDetailTypeEnum;
 import com.sd.business.entity.in.emums.InOutTypeEnum;
+import com.sd.business.entity.in.emums.OutDetailTypeEnum;
 import com.sd.business.entity.in.po.InOutStorageBom;
 import com.sd.business.entity.order.dto.OrderInfoDto;
 import com.sd.business.entity.order.dto.OrderInfoSelectDto;
 import com.sd.business.entity.order.dto.OrderPackageBomDto;
 import com.sd.business.entity.order.dto.OrderSkuDto;
+import com.sd.business.entity.order.dto.SkuSpecPackageBomDto;
 import com.sd.business.entity.order.dto.SkuSpecPriceDto;
 import com.sd.business.entity.order.enums.OrderClassifyEnum;
 import com.sd.business.entity.order.enums.OrderExceptionTypeEnum;
@@ -40,12 +43,15 @@ import com.sd.business.entity.order.po.OrderSkuProductionCost;
 import com.sd.business.entity.order.vo.OrderInfoVo;
 import com.sd.business.entity.order.vo.OrderPackageBomVo;
 import com.sd.business.entity.order.vo.OrderSkuBomVo;
+import com.sd.business.entity.order.vo.OrderSkuExportVo;
 import com.sd.business.entity.order.vo.OrderSkuVo;
+import com.sd.business.entity.order.vo.OutBomVo;
 import com.sd.business.entity.order.vo.SkuSpecPriceVo;
 import com.sd.business.entity.price.po.PriceBillingStandard;
 import com.sd.business.entity.price.po.PriceBillingStandardDetail;
 import com.sd.business.entity.production.po.ProductionWorkOrder;
 import com.sd.business.entity.sku.po.SkuSpec;
+import com.sd.business.entity.sku.po.SkuSpecLink;
 import com.sd.business.entity.warehouse.constant.WarehouseConstant;
 import com.sd.business.mapper.order.OrderInfoMapper;
 import com.sd.business.service.bom.BomService;
@@ -62,9 +68,11 @@ import com.sd.business.service.order.OrderSkuService;
 import com.sd.business.service.price.PriceBillingStandardDetailService;
 import com.sd.business.service.price.PriceBillingStandardService;
 import com.sd.business.service.production.ProductionWorkOrderService;
+import com.sd.business.service.sku.SkuSpecLinkService;
 import com.sd.business.service.sku.SkuSpecService;
 import com.sd.business.util.CodeEnum;
 import com.sd.framework.util.Assert;
+import com.sd.framework.util.excel.util.ExcelUtil;
 import com.sd.framework.util.sql.Sql;
 import com.sd.framework.util.sql.Where;
 import com.sd.mq.config.ArtworkConfig;
@@ -73,17 +81,23 @@ import com.sd.mq.util.RabbitMqUtil;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import javax.servlet.http.HttpServletResponse;
 import java.math.BigDecimal;
+import java.math.RoundingMode;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
 import java.util.function.Function;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 
 /**
@@ -145,6 +159,12 @@ public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo
     @Autowired
     private PriceBillingStandardDetailService priceBillingStandardDetailService;
 
+    @Autowired
+    private SkuSpecLinkService skuSpecLinkService;
+
+    @Autowired
+    private HttpServletResponse response;
+
     @Override
     public Page<OrderInfoVo> getPage(OrderInfoSelectDto dto) {
 
@@ -880,36 +900,230 @@ public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo
 
     @Override
     public void saveOrderDeliveryCode(OrderInfoDto dto) {
-        OrderInfo orderInfo = this.getById(dto.getId());
+        OrderInfo orderInfo = getById(dto.getId());
         if (orderInfo == null) {
             throw new ServiceException("未找到订单");
         }
         if (StrUtil.isBlank(dto.getDeliveryCode())) {
             throw new ServiceException("送货单号不能为空");
         }
-        OrderInfo one = this.getOne(q -> q.eq(OrderInfo::getDeliveryCode, dto.getDeliveryCode()));
+        OrderInfo one = getOne(q -> q.eq(OrderInfo::getDeliveryCode, dto.getDeliveryCode()));
         if (one != null) {
             throw new ServiceException("送货单号重复,请重新生成!");
         }
-        this.update(q -> q.set(OrderInfo::getDeliveryCode, dto.getDeliveryCode()).eq(BaseIdPo::getId, dto.getId()));
+        update(q -> q.set(OrderInfo::getDeliveryCode, dto.getDeliveryCode()).eq(BaseIdPo::getId, dto.getId()));
     }
 
     @Override
     public void suspendOrder(Long id) {
-        OrderInfo orderInfo = this.getById(id);
+        OrderInfo orderInfo = getById(id);
         if (orderInfo == null) {
             throw new ServiceException("未找到订单");
         }
-        this.update(q -> q.set(OrderInfo::getStatus, OrderStatusEnum.SUSPEND.getKey()).eq(BaseIdPo::getId, id));
+        update(q -> q.set(OrderInfo::getStatus, OrderStatusEnum.SUSPEND.getKey()).eq(BaseIdPo::getId, id));
     }
 
     @Override
     public void cancelSuspendOrder(Long id) {
-        OrderInfo orderInfo = this.getById(id);
+        OrderInfo orderInfo = getById(id);
         if (orderInfo == null) {
             throw new ServiceException("未找到订单");
         }
-        this.update(q -> q.set(OrderInfo::getStatus, OrderStatusEnum.STOCK_PREPARATION.getKey()).eq(BaseIdPo::getId, id));
+        update(q -> q.set(OrderInfo::getStatus, OrderStatusEnum.STOCK_PREPARATION.getKey()).eq(BaseIdPo::getId, id));
+    }
+
+    @Override
+    public List<OutBomVo> returnBomList(Long id) {
+        OrderInfo orderInfo = getById(id);
+        Assert.notNull(orderInfo, "未找到订单");
+
+        List<OrderSku> orderSkuList = orderSkuService.list(q -> q.eq(OrderSku::getOrderId, id));
+        List<OrderSkuBom> orderSkuBomList = orderSkuBomService.list(q -> q.eq(OrderSkuBom::getOrderId, id));
+        Map<Long, OrderSku> orderSkuMap = orderSkuList.stream().collect(Collectors.toMap(BaseIdPo::getId, Function.identity()));
+        if (Objects.equals(orderInfo.getClassify(), OrderClassifyEnum.OUTSOURCE_ORDER.getKey())) {
+            orderSkuList = Collections.emptyList();
+        }
+
+        Map<Long, OutBomVo> map = Stream.concat(
+                        // 主材
+                        orderSkuList.stream().map(item -> {
+                            OutBomVo outBomVo = new OutBomVo();
+                            outBomVo.setBomSpecId(item.getBomSpecId());
+                            outBomVo.setOutQuantity(item.getQuantity());
+                            return outBomVo;
+                        }),
+
+                        // 包材
+                        orderSkuBomList.stream().map(item -> {
+                            OrderSku orderSku = orderSkuMap.get(item.getOrderSkuId());
+                            OutBomVo outBomVo = new OutBomVo();
+                            outBomVo.setBomSpecId(item.getBomSpecId());
+                            outBomVo.setOutQuantity(item.getQuantity().multiply(orderSku.getQuantity()));
+                            return outBomVo;
+                        })
+                )
+                .collect(Collectors.toMap(
+                        OutBomVo::getBomSpecId,
+                        Function.identity(),
+                        (v1, v2) -> {
+                            v1.setOutQuantity(v1.getOutQuantity().add(v2.getOutQuantity()));
+                            return v1;
+                        })
+                );
+
+        // 合并sku主材和包材
+        List<OutBomVo> outBomVoList = new ArrayList<>(map.values());
+
+        // 区分半成品仓和包材仓库
+        Map<Long, BomSpecBo> bomSpecBoMap = bomSpecService.getBomSpecBo(map.keySet());
+
+        for (OutBomVo outBomVo : outBomVoList) {
+            Long bomSpecId = outBomVo.getBomSpecId();
+            BomSpecBo bomSpecBo = bomSpecBoMap.get(bomSpecId);
+            outBomVo.setBomSpecCode(bomSpecBo.getBomSpecCode());
+            outBomVo.setBomSpecName(bomSpecBo.getBomSpecName());
+            outBomVo.setClassifyId(bomSpecBo.getClassifyId());
+            outBomVo.setClassifyName(bomSpecBo.getClassifyName());
+            outBomVo.setClassifyParentId(bomSpecBo.getClassifyParentId());
+
+            // 主材
+            if (Objects.equals(bomSpecBo.getClassifyParentId(), 1L)) {
+                outBomVo.setWarehouseId(WarehouseConstant.SEMI_FINISHED_PRODUCT);
+                outBomVo.setWarehouseName("半成品仓");
+            }
+            // 包材
+            else {
+                outBomVo.setWarehouseId(WarehouseConstant.PACKAGING_MATERIAL);
+                outBomVo.setWarehouseName("包材仓");
+            }
+        }
+        return outBomVoList.stream()
+                .sorted(Comparator.comparing(OutBomVo::getWarehouseId, Comparator.reverseOrder()).thenComparing(OutBomVo::getBomSpecCode))
+                .collect(Collectors.toList());
+    }
+
+    @Override
+    public void editOrderPackageBom(OrderInfoDto dto) {
+        OrderInfo orderInfo = getById(dto.getId());
+        Assert.notNull(orderInfo, "未找到订单");
+
+        // 生产中和生产完成的订单快递包材归还入库
+        if (ObjectUtil.equals(orderInfo.getStatus(), OrderStatusEnum.IN_PRODUCTION.getKey())
+                || ObjectUtil.equals(orderInfo.getStatus(), OrderStatusEnum.COMPLETION_PRODUCTION.getKey())) {
+            dto.setCode(orderInfo.getCode());
+            dto.setWlnCode(orderInfo.getWlnCode());
+            orderPackageBomInOutStorage(dto);
+        }
+
+        List<OrderPackageBomDto> tempOrderPackageBomList = dto.getOrderPackageBomList();
+        BigDecimal totalAmount = orderInfo.getTotalAmount();
+        BigDecimal oldDeliveryMaterialsFee = orderInfo.getDeliveryMaterialsFee();
+        BigDecimal newDeliveryMaterialsFee = BigDecimal.ZERO;
+        if (ObjectUtil.isEmpty(tempOrderPackageBomList)) {
+            orderPackageBomService.remove(q -> q.eq(OrderPackageBom::getOrderId, orderInfo.getId()));
+        } else {
+            List<OrderPackageBom> orderPackageBomList = tempOrderPackageBomList.stream()
+                    .peek(item -> item.setOrderId(dto.getId()))
+                    .map(item -> (OrderPackageBom) item)
+                    .collect(Collectors.toList());
+            orderPackageBomService.editLinked(orderPackageBomList, OrderPackageBom::getOrderId, orderInfo.getId());
+            newDeliveryMaterialsFee = orderPackageBomList.stream()
+                    .map(item -> item.getInternalSellingPrice().multiply(item.getQuantity()))
+                    .reduce(BigDecimal.ZERO, BigDecimal::add);
+        }
+        orderInfo.setDeliveryMaterialsFee(newDeliveryMaterialsFee);
+        List<OrderSku> orderSkuList = orderSkuService.list(q -> q.eq(OrderSku::getOrderId, orderInfo.getId()));
+        BigDecimal quantity = orderSkuList.stream().map(OrderSku::getQuantity).reduce(BigDecimal.ZERO, BigDecimal::add);
+        orderSkuList.forEach(item ->
+                item.setDeliveryMaterialsFee(orderInfo.getDeliveryMaterialsFee()
+                        .divide(quantity, 4, RoundingMode.HALF_UP))
+        );
+        orderInfo.setTotalAmount(totalAmount.subtract(oldDeliveryMaterialsFee).add(newDeliveryMaterialsFee));
+        updateById(orderInfo);
+        orderSkuService.updateBatchById(orderSkuList);
+        ObsFileUtil.editFile(dto.getOuterBoxSelfAdhesiveStickerFile(), dto.getId(), 1);
+    }
+
+    @Override
+    public List<OrderPackageBomVo> getSkuSpecPackageBomList(SkuSpecPackageBomDto dto) {
+        List<SkuSpecPriceDto> skuSpecList = dto.getSkuSpecList();
+        List<Long> skuSpecIds = skuSpecList.stream().map(SkuSpecPriceDto::getSkuSpecId).collect(Collectors.toList());
+        Map<Long, List<SkuSpecLink>> skuSpecMap = skuSpecLinkService.mapKGroup(
+                SkuSpecLink::getSkuSpecId,
+                q -> q.in(SkuSpecLink::getSkuSpecId, skuSpecIds).eq(SkuSpecLink::getType, 2));
+        if (ObjectUtil.isEmpty(skuSpecMap)) {
+            return Collections.emptyList();
+        }
+        List<Long> bomSpecIds = skuSpecMap.values().stream()
+                .flatMap(item -> item.stream().map(SkuSpecLink::getBomSpecId))
+                .collect(Collectors.toList());
+        Map<Long, BomSpec> bomSpecPriceMap = bomSpecService.mapKEntity(BaseIdPo::getId, q -> q.in(BaseIdPo::getId, bomSpecIds));
+
+        List<OrderPackageBomVo> list = new ArrayList<>();
+        for (SkuSpecPriceDto skuSpecPriceDto : skuSpecList) {
+            List<SkuSpecLink> skuSpecLinkList = skuSpecMap.getOrDefault(skuSpecPriceDto.getSkuSpecId(), Collections.emptyList());
+            List<OrderPackageBomVo> packageBomVoList = skuSpecLinkList.stream().map(item -> {
+                BomSpec bomSpec = bomSpecPriceMap.get(item.getBomSpecId());
+                OrderPackageBomVo orderPackageBomVo = new OrderPackageBomVo();
+                orderPackageBomVo.setBomSpecName(bomSpec.getName());
+                orderPackageBomVo.setBomSpecCode(bomSpec.getCode());
+                orderPackageBomVo.setCostPrice(bomSpec.getCostPrice());
+                orderPackageBomVo.setInternalSellingPrice(bomSpec.getInternalSellingPrice());
+                orderPackageBomVo.setBomSpecId(item.getBomSpecId());
+                orderPackageBomVo.setQuantity(item.getQuantity().multiply(skuSpecPriceDto.getQuantity()));
+                return orderPackageBomVo;
+            }).collect(Collectors.toList());
+            list.addAll(packageBomVoList);
+        }
+        // 合并相同bom
+        Map<Long, OrderPackageBomVo> bomVoMap = list.stream().collect(Collectors.toMap(
+                OrderPackageBom::getBomSpecId,
+                Function.identity(),
+                (v1, v2) -> {
+                    v1.setQuantity(v1.getQuantity().add(v2.getQuantity()));
+                    return v1;
+                }));
+        return new ArrayList<>(bomVoMap.values());
+    }
+
+    @Override
+    public void orderExportExcel(Long id) {
+        OrderInfo orderInfo = this.getById(id);
+        List<OrderSku> list = orderSkuService.list(q -> q.eq(OrderSku::getOrderId, id));
+        List<Long> bomSpecIds = list.stream().map(OrderSku::getBomSpecId).collect(Collectors.toList());
+        List<Long> skuSpecIds = list.stream().map(OrderSku::getSkuSpecId).collect(Collectors.toList());
+        Map<Long, BomSpecBo> bomSpecBoMap = bomSpecService.getBomSpecBo(bomSpecIds);
+        Map<Long, SkuSpec> skuSpecMap = skuSpecService.byIdsToMap(skuSpecIds);
+        List<OrderSku> orderPackageSkuList = list.stream()
+                .filter(item -> !Objects.equals(bomSpecBoMap.get(item.getBomSpecId()).getClassifyParentId(), 1L))
+                .collect(Collectors.toList());
+        List<OrderSku> orderSkuList = list.stream()
+                .filter(item -> Objects.equals(bomSpecBoMap.get(item.getBomSpecId()).getClassifyParentId(), 1L))
+                .collect(Collectors.toList());
+        BigDecimal orderPackageSku = orderPackageSkuList.stream()
+                .map(item -> (item.getUnitPrice()
+                        .add(item.getDeliveryMaterialsFee())
+                        .add(item.getPackagingMaterialCost()))
+                        .multiply(item.getQuantity()))
+                .reduce(BigDecimal.ZERO, BigDecimal::add);
+        BigDecimal orderPackagePrice = orderPackageSku.divide(BigDecimal.valueOf(orderSkuList.size()), 2, RoundingMode.HALF_UP);
+        List<OrderSkuExportVo> exportVoList = orderSkuList.stream().map(item -> {
+            BigDecimal subtotal = item.getUnitPrice()
+                    .add(item.getDeliveryMaterialsFee())
+                    .add(item.getPackagingMaterialCost());
+            BomSpecBo bomSpecBo = bomSpecBoMap.get(item.getBomSpecId());
+            SkuSpec skuSpec = skuSpecMap.get(item.getSkuSpecId());
+            OrderSkuExportVo orderSkuExportVo = new OrderSkuExportVo();
+            orderSkuExportVo.setWlnCode(orderInfo.getWlnCode());
+            orderSkuExportVo.setSkuSpecCode(skuSpec.getCode());
+            orderSkuExportVo.setBomSpecCode(bomSpecBo.getBomSpecCode());
+            orderSkuExportVo.setErpCode(item.getErpCode());
+            orderSkuExportVo.setFeatureCode(item.getFeatureCode());
+            orderSkuExportVo.setQuantity(item.getQuantity());
+            orderSkuExportVo.setTotalAmount(subtotal.multiply(item.getQuantity()).add(orderPackagePrice));
+            return orderSkuExportVo;
+        }).collect(Collectors.toList());
+        ExcelUtil.export(response, exportVoList, OrderSkuExportVo.class);
     }
 
     /**
@@ -1024,4 +1238,96 @@ public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo
         }
     }
 
+    /**
+     * 订单修改快递包材出入库操作
+     */
+    private void orderPackageBomInOutStorage(OrderInfoDto dto) {
+        List<OrderPackageBom> oldOrderPackageBomList = orderPackageBomService.list(q -> q.eq(OrderPackageBom::getOrderId, dto.getId()));
+        List<OrderPackageBomDto> newOrderPackageBomList = dto.getOrderPackageBomList();
+
+        // 旧bom
+        Map<Long, BigDecimal> oldBomMap = oldOrderPackageBomList.stream()
+                .collect(Collectors.toMap(
+                        OrderPackageBom::getBomSpecId,
+                        OrderPackageBom::getQuantity,
+                        BigDecimal::add
+                ));
+        Map<Long, BigDecimal> newBomMap = newOrderPackageBomList.stream()
+                .collect(Collectors.toMap(
+                        OrderPackageBom::getBomSpecId,
+                        OrderPackageBom::getQuantity,
+                        BigDecimal::add
+                ));
+        // 查询所有bom进行对比
+        Set<Long> bomIds = new HashSet<>(oldBomMap.keySet());
+        bomIds.addAll(newBomMap.keySet());
+        Map<Long, BigDecimal> outBomMap = new HashMap<>();
+        Map<Long, BigDecimal> inBomMap = new HashMap<>();
+        for (Long bomId : bomIds) {
+            BigDecimal oldReturnQuantity = oldBomMap.get(bomId);
+            BigDecimal newReturnQuantity = newBomMap.get(bomId);
+            // 旧bom没有,出库库存,反之则归还库存
+            if (oldReturnQuantity == null) {
+                outBomMap.put(bomId, newReturnQuantity);
+                continue;
+            } else if (newReturnQuantity == null) {
+                inBomMap.put(bomId, oldReturnQuantity);
+                continue;
+            }
+            // 都有值,判断数量
+            if (oldReturnQuantity.compareTo(newReturnQuantity) == 0) {
+                continue;
+            }
+            // 旧bom大于新bom则归还入库,反之出库库存
+            if (oldReturnQuantity.compareTo(newReturnQuantity) > 0) {
+                inBomMap.put(bomId, oldReturnQuantity.subtract(newReturnQuantity));
+            } else {
+                outBomMap.put(bomId, newReturnQuantity.subtract(oldReturnQuantity));
+            }
+        }
+        if (!outBomMap.isEmpty()) {
+            // 包材从包材仓出库
+            List<InOutStorageBom> outStorageBomList = outBomMap.entrySet().stream()
+                    .map(item -> {
+                        InOutStorageBom inOutStorageBom = new InOutStorageBom();
+                        inOutStorageBom.setBomSpecId(item.getKey());
+                        inOutStorageBom.setQuantity(item.getValue());
+                        return inOutStorageBom;
+                    })
+                    .collect(Collectors.toList());
+            InOutStorageDto inOutStorageDto = new InOutStorageDto();
+            inOutStorageDto.setType(InOutTypeEnum.OUT.getKey());
+            inOutStorageDto.setDetailType(OutDetailTypeEnum.PRODUCTION.getKey());
+            inOutStorageDto.setWarehouseId(WarehouseConstant.PACKAGING_MATERIAL);
+            inOutStorageDto.setDepartmentId(DepartmentConstant.SD_SPORTS);
+            inOutStorageDto.setApplicant(SecurityUtils.getLoginUser().getUser().getNickName());
+            inOutStorageDto.setInOutStorageBomList(outStorageBomList);
+            inOutStorageDto.setLockStorage(StatusConstant.NO);
+            inOutStorageService.add(inOutStorageDto);
+        }
+        if (!inBomMap.isEmpty()) {
+            // 包材归还入库
+            List<InOutStorageBom> inOutStorageBomList = inBomMap.entrySet()
+                    .stream()
+                    .map(item -> {
+                        InOutStorageBom inOutStorageBom = new InOutStorageBom();
+                        inOutStorageBom.setBomSpecId(item.getKey());
+                        inOutStorageBom.setQuantity(item.getValue());
+                        return inOutStorageBom;
+                    })
+                    .collect(Collectors.toList());
+            InOutStorageDto packagingMaterialInOutStorageDto = new InOutStorageDto();
+            packagingMaterialInOutStorageDto.setType(InOutTypeEnum.IN.getKey());
+            packagingMaterialInOutStorageDto.setDetailType(InDetailTypeEnum.RETURN_GOODS.getKey());
+            packagingMaterialInOutStorageDto.setWarehouseId(WarehouseConstant.PACKAGING_MATERIAL);
+            packagingMaterialInOutStorageDto.setDepartmentId(DepartmentConstant.SD_SPORTS);
+            packagingMaterialInOutStorageDto.setApplicant(SecurityUtils.getLoginUser().getUser().getNickName());
+            packagingMaterialInOutStorageDto.setRemark("订单产品快递包装修改:" + dto.getCode()
+                    + (StrUtil.isBlank(dto.getWlnCode()) ? StringPool.EMPTY : "(" + dto.getWlnCode() + ")")
+                    + " 包材归还入库");
+            packagingMaterialInOutStorageDto.setInOutStorageBomList(inOutStorageBomList);
+            inOutStorageService.add(packagingMaterialInOutStorageDto);
+        }
+    }
+
 }