From 39fa16d4825c789bd04f6fb857ed43e3fdf89c90 Mon Sep 17 00:00:00 2001 From: guochaojie Date: Thu, 22 Aug 2024 18:07:49 +0800 Subject: [PATCH] =?UTF-8?q?MRP=20=E8=BF=90=E7=AE=97=203?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jnpf/service/YysBillMaterialService.java | 2 +- .../java/jnpf/service/YysDayWorkService.java | 2 + .../service/YysInventoryQueryService.java | 3 + .../YysMaterialInformationService.java | 2 + .../YysMaterialProcurementOrderService.java | 2 + .../service/YysSubsetMaterialService.java | 4 + .../impl/YysBillMaterialServiceImpl.java | 7 +- .../service/impl/YysDayWorkServiceImpl.java | 9 + .../impl/YysInventoryQueryServiceImpl.java | 10 + .../YysMaterialInformationServiceImpl.java | 9 + ...ysMaterialProcurementOrderServiceImpl.java | 11 + .../impl/YysSubsetMaterialServiceImpl.java | 14 + .../YysMonthlyProductionController.java | 296 ++++++++++++++++-- .../YysMaterialRequirementItemEntity.java | 3 + .../YysMaterialRequirementPlanEntity.java | 4 +- 15 files changed, 344 insertions(+), 34 deletions(-) diff --git a/jnpf-java-boot/jnpf-example/jnpf-example-biz/src/main/java/jnpf/service/YysBillMaterialService.java b/jnpf-java-boot/jnpf-example/jnpf-example-biz/src/main/java/jnpf/service/YysBillMaterialService.java index 77cb6e3..2d5dec2 100644 --- a/jnpf-java-boot/jnpf-example/jnpf-example-biz/src/main/java/jnpf/service/YysBillMaterialService.java +++ b/jnpf-java-boot/jnpf-example/jnpf-example-biz/src/main/java/jnpf/service/YysBillMaterialService.java @@ -31,7 +31,7 @@ public interface YysBillMaterialService extends IService String checkForm(YysBillMaterialForm form,int i); void saveOrUpdate(YysBillMaterialForm yysBillMaterialForm,String id, boolean isSave) throws Exception; YysBillMaterialEntity getByProductId(String id); - List getListByProductIds(List id); + List getListByProductIds(Collection id); String syncMaterial(); diff --git a/jnpf-java-boot/jnpf-example/jnpf-example-biz/src/main/java/jnpf/service/YysDayWorkService.java b/jnpf-java-boot/jnpf-example/jnpf-example-biz/src/main/java/jnpf/service/YysDayWorkService.java index 4336929..937d96a 100644 --- a/jnpf-java-boot/jnpf-example/jnpf-example-biz/src/main/java/jnpf/service/YysDayWorkService.java +++ b/jnpf-java-boot/jnpf-example/jnpf-example-biz/src/main/java/jnpf/service/YysDayWorkService.java @@ -55,4 +55,6 @@ public interface YysDayWorkService extends IService { String cancelFrozen(String id); void syncDayWork(); + + List getUnProducedWorkOrderList(); } diff --git a/jnpf-java-boot/jnpf-example/jnpf-example-biz/src/main/java/jnpf/service/YysInventoryQueryService.java b/jnpf-java-boot/jnpf-example/jnpf-example-biz/src/main/java/jnpf/service/YysInventoryQueryService.java index c260248..a3f3984 100644 --- a/jnpf-java-boot/jnpf-example/jnpf-example-biz/src/main/java/jnpf/service/YysInventoryQueryService.java +++ b/jnpf-java-boot/jnpf-example/jnpf-example-biz/src/main/java/jnpf/service/YysInventoryQueryService.java @@ -33,4 +33,7 @@ public interface YysInventoryQueryService extends IService getListByMaterialCodes(Collection matCodes); + } diff --git a/jnpf-java-boot/jnpf-example/jnpf-example-biz/src/main/java/jnpf/service/YysMaterialInformationService.java b/jnpf-java-boot/jnpf-example/jnpf-example-biz/src/main/java/jnpf/service/YysMaterialInformationService.java index 281c5c6..dee0c60 100644 --- a/jnpf-java-boot/jnpf-example/jnpf-example-biz/src/main/java/jnpf/service/YysMaterialInformationService.java +++ b/jnpf-java-boot/jnpf-example/jnpf-example-biz/src/main/java/jnpf/service/YysMaterialInformationService.java @@ -43,4 +43,6 @@ public interface YysMaterialInformationService extends IService getListByMatIds(ArrayList matIds); } diff --git a/jnpf-java-boot/jnpf-example/jnpf-example-biz/src/main/java/jnpf/service/YysMaterialProcurementOrderService.java b/jnpf-java-boot/jnpf-example/jnpf-example-biz/src/main/java/jnpf/service/YysMaterialProcurementOrderService.java index b5b852f..4d905ca 100644 --- a/jnpf-java-boot/jnpf-example/jnpf-example-biz/src/main/java/jnpf/service/YysMaterialProcurementOrderService.java +++ b/jnpf-java-boot/jnpf-example/jnpf-example-biz/src/main/java/jnpf/service/YysMaterialProcurementOrderService.java @@ -92,4 +92,6 @@ public interface YysMaterialProcurementOrderService extends IService getNotStockedList(Collection matCodes); } diff --git a/jnpf-java-boot/jnpf-example/jnpf-example-biz/src/main/java/jnpf/service/YysSubsetMaterialService.java b/jnpf-java-boot/jnpf-example/jnpf-example-biz/src/main/java/jnpf/service/YysSubsetMaterialService.java index e11f638..3354dae 100644 --- a/jnpf-java-boot/jnpf-example/jnpf-example-biz/src/main/java/jnpf/service/YysSubsetMaterialService.java +++ b/jnpf-java-boot/jnpf-example/jnpf-example-biz/src/main/java/jnpf/service/YysSubsetMaterialService.java @@ -3,5 +3,9 @@ package jnpf.service; import com.baomidou.mybatisplus.extension.service.IService; import jnpf.entity.YysSubsetMaterialEntity; +import java.util.List; + public interface YysSubsetMaterialService extends IService { + List getListByPieceId(String pieceId); + } diff --git a/jnpf-java-boot/jnpf-example/jnpf-example-biz/src/main/java/jnpf/service/impl/YysBillMaterialServiceImpl.java b/jnpf-java-boot/jnpf-example/jnpf-example-biz/src/main/java/jnpf/service/impl/YysBillMaterialServiceImpl.java index 3ffdd0b..645a572 100644 --- a/jnpf-java-boot/jnpf-example/jnpf-example-biz/src/main/java/jnpf/service/impl/YysBillMaterialServiceImpl.java +++ b/jnpf-java-boot/jnpf-example/jnpf-example-biz/src/main/java/jnpf/service/impl/YysBillMaterialServiceImpl.java @@ -34,10 +34,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; @@ -324,7 +321,7 @@ public class YysBillMaterialServiceImpl extends ServiceImpl getListByProductIds(List id) { + public List getListByProductIds(Collection id) { QueryWrapper wrapper = new QueryWrapper<>(); wrapper.lambda().in(YysBillMaterialEntity::getPieceId, id); return this.list(wrapper); diff --git a/jnpf-java-boot/jnpf-example/jnpf-example-biz/src/main/java/jnpf/service/impl/YysDayWorkServiceImpl.java b/jnpf-java-boot/jnpf-example/jnpf-example-biz/src/main/java/jnpf/service/impl/YysDayWorkServiceImpl.java index e082adc..77beb62 100644 --- a/jnpf-java-boot/jnpf-example/jnpf-example-biz/src/main/java/jnpf/service/impl/YysDayWorkServiceImpl.java +++ b/jnpf-java-boot/jnpf-example/jnpf-example-biz/src/main/java/jnpf/service/impl/YysDayWorkServiceImpl.java @@ -586,6 +586,15 @@ public class YysDayWorkServiceImpl extends ServiceImpl getUnProducedWorkOrderList() { + QueryWrapper wrapper = new QueryWrapper<>(); + String start = cn.hutool.core.date.DateUtil.format(new Date(), "yyyy-MM-01 00:00:00"); + wrapper.lambda().gt(YysDayWorkEntity::getStartTime,start). + eq(YysDayWorkEntity::getProductionStatus, "1");//未开工 + return null; + } + private static boolean isCurrentTimeBetween(String startTimeStr, String ednTimeStr) { DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm"); // 将字符串时间转换为LocalTime对象 diff --git a/jnpf-java-boot/jnpf-example/jnpf-example-biz/src/main/java/jnpf/service/impl/YysInventoryQueryServiceImpl.java b/jnpf-java-boot/jnpf-example/jnpf-example-biz/src/main/java/jnpf/service/impl/YysInventoryQueryServiceImpl.java index 09c90a5..4617870 100644 --- a/jnpf-java-boot/jnpf-example/jnpf-example-biz/src/main/java/jnpf/service/impl/YysInventoryQueryServiceImpl.java +++ b/jnpf-java-boot/jnpf-example/jnpf-example-biz/src/main/java/jnpf/service/impl/YysInventoryQueryServiceImpl.java @@ -35,6 +35,7 @@ import org.springframework.transaction.annotation.Transactional; import java.lang.reflect.Field; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.Map; import java.util.function.Function; @@ -357,4 +358,13 @@ public class YysInventoryQueryServiceImpl extends ServiceImpl getListByMaterialCodes(Collection matCodes) { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.lambda().in(YysInventoryQueryEntity::getMaterialCode, matCodes); + List list = this.list(wrapper); + return list; + } } diff --git a/jnpf-java-boot/jnpf-example/jnpf-example-biz/src/main/java/jnpf/service/impl/YysMaterialInformationServiceImpl.java b/jnpf-java-boot/jnpf-example/jnpf-example-biz/src/main/java/jnpf/service/impl/YysMaterialInformationServiceImpl.java index c2e542f..4d48e22 100644 --- a/jnpf-java-boot/jnpf-example/jnpf-example-biz/src/main/java/jnpf/service/impl/YysMaterialInformationServiceImpl.java +++ b/jnpf-java-boot/jnpf-example/jnpf-example-biz/src/main/java/jnpf/service/impl/YysMaterialInformationServiceImpl.java @@ -385,4 +385,13 @@ public class YysMaterialInformationServiceImpl extends ServiceImpl getListByMatIds(ArrayList matIds) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(YysMaterialInformationEntity::getEnableStatus, "1") + .in(YysMaterialInformationEntity::getMaterialId, matIds) + .isNull(YysMaterialInformationEntity::getDeleteMark); + return this.list(wrapper); + } } diff --git a/jnpf-java-boot/jnpf-example/jnpf-example-biz/src/main/java/jnpf/service/impl/YysMaterialProcurementOrderServiceImpl.java b/jnpf-java-boot/jnpf-example/jnpf-example-biz/src/main/java/jnpf/service/impl/YysMaterialProcurementOrderServiceImpl.java index f83995f..b0effa8 100644 --- a/jnpf-java-boot/jnpf-example/jnpf-example-biz/src/main/java/jnpf/service/impl/YysMaterialProcurementOrderServiceImpl.java +++ b/jnpf-java-boot/jnpf-example/jnpf-example-biz/src/main/java/jnpf/service/impl/YysMaterialProcurementOrderServiceImpl.java @@ -1,5 +1,6 @@ package jnpf.service.impl; +import cn.hutool.core.date.DateTime; import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; @@ -584,4 +585,14 @@ public class YysMaterialProcurementOrderServiceImpl extends ServiceImpl getNotStockedList(Collection matCodes) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + DateTime dateTime = cn.hutool.core.date.DateUtil.lastMonth(); + String lastMonth = cn.hutool.core.date.DateUtil.format(dateTime, "yyyy-MM-01 00:00:00"); + wrapper.in(YysMaterialProcurementOrderEntity::getMaterialId, matCodes);//物料 + wrapper.gt(YysMaterialProcurementOrderEntity::getOrderDate, lastMonth);// 采购期 + return this.list(wrapper); + } } diff --git a/jnpf-java-boot/jnpf-example/jnpf-example-biz/src/main/java/jnpf/service/impl/YysSubsetMaterialServiceImpl.java b/jnpf-java-boot/jnpf-example/jnpf-example-biz/src/main/java/jnpf/service/impl/YysSubsetMaterialServiceImpl.java index ebace9c..209c2dd 100644 --- a/jnpf-java-boot/jnpf-example/jnpf-example-biz/src/main/java/jnpf/service/impl/YysSubsetMaterialServiceImpl.java +++ b/jnpf-java-boot/jnpf-example/jnpf-example-biz/src/main/java/jnpf/service/impl/YysSubsetMaterialServiceImpl.java @@ -1,11 +1,25 @@ package jnpf.service.impl; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import jnpf.entity.YysSubsetMaterialEntity; import jnpf.mapper.YysSubsetMaterialMapper; import jnpf.service.YysSubsetMaterialService; import org.springframework.stereotype.Service; +import java.util.List; + @Service public class YysSubsetMaterialServiceImpl extends ServiceImpl implements YysSubsetMaterialService { + + + @Override + public List getListByPieceId(String pieceId) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(YysSubsetMaterialEntity::getPieceId, pieceId); + wrapper.isNull(YysSubsetMaterialEntity::getDeleteMark);//删除标记为空 + wrapper.eq(YysSubsetMaterialEntity::getStatus, 1);//启用标记为1 + return this.list(wrapper); + } } diff --git a/jnpf-java-boot/jnpf-example/jnpf-example-controller/src/main/java/jnpf/controller/YysMonthlyProductionController.java b/jnpf-java-boot/jnpf-example/jnpf-example-controller/src/main/java/jnpf/controller/YysMonthlyProductionController.java index e10cc28..4b80870 100644 --- a/jnpf-java-boot/jnpf-example/jnpf-example-controller/src/main/java/jnpf/controller/YysMonthlyProductionController.java +++ b/jnpf-java-boot/jnpf-example/jnpf-example-controller/src/main/java/jnpf/controller/YysMonthlyProductionController.java @@ -1,13 +1,12 @@ package jnpf.controller; -import cn.hutool.core.util.ObjectUtil; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import cn.hutool.core.lang.UUID; +import cn.hutool.core.lang.generator.UUIDGenerator; +import cn.hutool.core.util.NumberUtil; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jnpf.base.ActionResult; import jnpf.base.UserInfo; -import jnpf.exception.DataException; -import jnpf.permission.entity.UserEntity; import jnpf.service.*; import jnpf.entity.*; import jnpf.util.*; @@ -16,24 +15,21 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; +import javax.annotation.Resource; import javax.validation.Valid; -import java.text.DateFormat; +import java.math.BigDecimal; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.*; -import jnpf.annotation.JnpfField; import jnpf.base.vo.PageListVO; import jnpf.base.vo.PaginationVO; import jnpf.base.vo.DownloadVO; import jnpf.config.ConfigValueUtil; -import jnpf.base.entity.ProvinceEntity; import java.io.IOException; import java.util.stream.Collectors; -import jnpf.engine.entity.FlowTaskEntity; -import jnpf.exception.WorkFlowException; import org.springframework.web.multipart.MultipartFile; import cn.afterturn.easypoi.excel.ExcelExportUtil; import cn.afterturn.easypoi.excel.ExcelImportUtil; @@ -82,7 +78,21 @@ public class YysMonthlyProductionController { private YysMonthlyProductionService yysMonthlyProductionService; @Autowired - private YysBillMaterialService bomService; + private YysBillMaterialService billMaterialService; + @Resource + private YysSubsetMaterialService subsetMaterialService; + @Resource + private YysMaterialInformationService materialInformationService; + @Resource + private YysDayWorkService dayWorkService; + @Resource + private YysInventoryQueryService inventoryQueryService; + @Resource + private YysMaterialProcurementOrderService materialProcurementOrderService; + @Resource + private YysMaterialRequirementPlanService materialRequirementPlanService; + @Resource + private YysMaterialRequirementItemService materialRequirementItemService; @Autowired @@ -556,52 +566,285 @@ public class YysMonthlyProductionController { } else { return ActionResult.fail("月份不能为空"); } + UserInfo userInfo = userProvider.get(); + // 获取没有生成MRP的月度生产计划 List unMPRList = yysMonthlyProductionService.getUnMPRList(month); if (unMPRList.size() == 0) return ActionResult.fail("没有需要生成MRP的月度生产计划"); - // 获取没有生成MRP的月度生产计划 + // 合并相同物料 + unMPRList = mergeProduction(unMPRList); Set productIds = unMPRList.stream().map(YysMonthlyProductionEntity::getProductId).collect(Collectors.toSet()); - - if(productIds.size()==0){ - return ActionResult.fail("没有需要生成MRP的月度生产计划"); - } - // 根据计划生成的物料 获取BOM清单 - List bomList = bomService.getListByProductIds(new ArrayList<>(productIds)); + List bomList = billMaterialService.getListByProductIds(new ArrayList<>(productIds)); + Map> expand = new LinkedHashMap<>(); // 获取bom 清单详情 + for (YysBillMaterialEntity billMaterial : bomList) { + List details = subsetMaterialService.getListByPieceId(billMaterial.getPieceId()); + if (details.isEmpty()) return ActionResult.fail("BOM清单中存在没有子项的物料"); + // 展开BOM清单 + expandBomList(expand, details); + } - // 获取 物料信息 + Set subsetIds = new HashSet<>(); + // 获取物料信息 + expand.forEach((bomId, details) -> { + Set collect = details.stream().map(YysSubsetMaterialEntity::getSubsetId).collect(Collectors.toSet()); + subsetIds.addAll(collect); + }); - // 获取单位信息 + // 物料信息 + List materialList = materialInformationService.getListByMatIds(new ArrayList<>(subsetIds)); + HashMap matInfo = new HashMap<>(); + materialList.forEach(mat -> matInfo.put(mat.getMaterialId(), mat)); - // 计算一个计划的物料需求量 + // 获取单位信息 + Set unit = materialList.stream().map(YysMaterialInformationEntity::getUnitMeasurement).collect(Collectors.toSet()); - // 循环计划 + YysMaterialRequirementPlanEntity plan = new YysMaterialRequirementPlanEntity();//物料需求计划 + String planNumber = generaterSwapUtil.getBillNumber("plannumber", false); - // 所需物料 合并同类项 + // todo 生成物料需求计划 + List planItems = new ArrayList<>();//物料需求详情 - // 获取已排产未生产的物料 + // 计算一个计划的物料需求量 + for (YysMonthlyProductionEntity production : unMPRList) { + String productId = production.getProductId(); + BigDecimal num = BigDecimal.valueOf(Long.valueOf(production.getPlanNumber()));//计划数量 + List subsetMats = expand.get(productId);// bom清单详情 + for (YysSubsetMaterialEntity subset : subsetMats) { + YysMaterialRequirementItemEntity item = new YysMaterialRequirementItemEntity(); + String planNo = plan.getPlanNumber();//物料需求计划编号 + String matType = matInfo.get(subset.getSubsetId()).getMaterialClassification();//物料分类 + String baseUse = subset.getBaseUse();//用量 + String baseNum = subset.getBaseNum();//倍数 + String subsetId = subset.getSubsetId();//子项ID + String subsetName = subset.getSubsetName();//子项名称 + String model = subset.getSubsetModel();//子项型号 + String unit1 = subset.getUnit();//子项单位 + // 计算需求量 + BigDecimal _baseUse = BigDecimal.valueOf(Long.valueOf(baseUse)); + if (StringUtil.isNotEmpty(baseNum) && NumberUtil.isNumber(baseNum)) { + _baseUse = num.divide(BigDecimal.valueOf(Long.valueOf(baseNum))).setScale(3, BigDecimal.ROUND_HALF_UP); + } + BigDecimal needNum = _baseUse.multiply(BigDecimal.valueOf(Long.valueOf(baseUse))); + item.setMaterialRequirementPlanId(planNo);//物料需求计划No + item.setMaterialCode(subsetId);//物料编码 + item.setMaterialName(subsetName);//物料名称 + item.setMaterialType(matType);//物料类型 + item.setSpecification(model);//物料型号 + item.setUnit(unit1);//物料单位 + item.setRequirementNumber(needNum);//需求量 + planItems.add(item); + } + } + // 所需物料 合并同类项 + planItems = mergeMaterial(planItems); + + /*** 未生产占用 ***/ + + // 获取已排产未生产的工单 + List workList = dayWorkService.getUnProducedWorkOrderList(); + // 合并相同产品的工单 + workList = mergeWork(workList); + // 获取产品BOM + Set prodCodes = workList.stream().map(YysDayWorkEntity::getProductCode).collect(Collectors.toSet()); + List bomList2 = billMaterialService.getListByProductIds(prodCodes); + // bom展开 + Map> workBomExpand = new HashMap<>(); + for (YysBillMaterialEntity bom : bomList2) { + List list = subsetMaterialService.getListByPieceId(bom.getPieceId()); + expandBomList(workBomExpand, list); + } // 计算未生产的物料需求量 + HashMap unWorkOccupation = new HashMap<>(); + for (YysDayWorkEntity work : workList) { + String planNum = work.getPlanNumber(); + BigDecimal num = BigDecimal.valueOf(Long.valueOf(planNum)); + String productCode = work.getProductCode(); + workBomExpand.get(productCode).forEach(item -> { + String pieceId = item.getPieceId();//物料编码 + BigDecimal baseUse = BigDecimal.valueOf(Long.valueOf(item.getBaseUse()));//用量 + BigDecimal baseNum = BigDecimal.valueOf(Long.valueOf(item.getBaseNum()));//倍数 + BigDecimal occupation = num.divide(baseNum).multiply(baseUse).setScale(3, BigDecimal.ROUND_HALF_UP); + unWorkOccupation.put(pieceId, occupation); + }); + } // 与所需物料编码 交集 求同类需求量 + for (YysMaterialRequirementItemEntity item : planItems) { + String materialCode = item.getMaterialCode(); + BigDecimal occupy = unWorkOccupation.get(materialCode); + if (null != occupy) { + item.setUnProductOccupy(occupy);//未生产占用 + } else item.setUnProductOccupy(BigDecimal.ZERO); + } - // 根据同类需求量 获取库存量 + /*** 未生产占用 ***/ - // 计算同类需求量 采购未入库的物料量 + // 根据同类需求量 获取库存量 + Set matCodes = planItems.stream().map(YysMaterialRequirementItemEntity::getMaterialCode).collect(Collectors.toSet()); + List inventoryList = inventoryQueryService.getListByMaterialCodes(matCodes); + + // 查询采购 + List orderList = materialProcurementOrderService.getNotStockedList(matCodes); + List origOrder = new ArrayList<>(); + List deliveryOrder = new ArrayList<>(); + if (orderList.size() > 0) { + origOrder = orderList.stream().filter(item -> { + if (item.getOrderNumber().contains("-")) return false; + return true; + }).collect(Collectors.toList()); + deliveryOrder = orderList.stream().filter(item -> { + if (item.getOrderNumber().contains("-")) return true; + return false; + }).collect(Collectors.toList()); + } + // 采购在途的物料量 + Map inTransit = calculateInTransit(origOrder, deliveryOrder); // 计算 同类需求量 - 库存量 - 采购未入库的物料量 = 需要采购的物料量 + for (YysMaterialRequirementItemEntity item : planItems) { + String code = item.getMaterialCode(); + BigDecimal requireNumber = item.getRequirementNumber();//毛需求量 + BigDecimal occupy = item.getUnProductOccupy();//未生产占用 + BigDecimal stock = BigDecimal.ZERO;//库存量 + BigDecimal safeStock = BigDecimal.ZERO;//安全库存量 + if (null == occupy) occupy = BigDecimal.ZERO; + YysInventoryQueryEntity inventory = + inventoryList.stream().filter(in -> in.getMaterialCode().equals(code)).findFirst().get();//库存 + + if (null != inventory && null != inventory.getInventoryNumber() && NumberUtil.isNumber(inventory.getInventoryNumber())) { + stock = BigDecimal.valueOf(Double.parseDouble(inventory.getInventoryNumber())); + } + YysMaterialInformationEntity materialInfo = materialList.stream().filter(m -> m.getMaterialId().equals(code)).findFirst().get(); + if (null != materialInfo && null != materialInfo.getSafetyStock() && NumberUtil.isNumber(materialInfo.getSafetyStock())) { + safeStock = BigDecimal.valueOf(Double.parseDouble(materialInfo.getSafetyStock())); + } + BigDecimal inTransitNumber = inTransit.getOrDefault(item.getMaterialCode(), BigDecimal.ZERO);//采购在途的物料量 + // 净需求量 =(总库存量 + 在途) - (安全库存 + 未生产占用 + 毛需求量) //核心算法 + BigDecimal netDemand = stock.add(inTransitNumber).subtract(safeStock.add(occupy).add(requireNumber)); + if (netDemand.compareTo(BigDecimal.ZERO) > 0) { + netDemand = BigDecimal.ZERO; + } else { + netDemand = netDemand.abs(); + } + item.setId(UUID.randomUUID().toString()); + item.setInventoryNumber(stock);//库存量 + item.setInventorySafetyNumber(safeStock);//安全库存量 + item.setNotIntoNumber(inTransitNumber);//采购在途的物料量 + item.setUnProductOccupy(occupy);//未生产占用 + item.setLackNumber(netDemand);//净需求量 + item.setCreatorTime(new Date()); + item.setCreatorUserId(userInfo.getUserId()); + } + + plan.setPlanNumber(planNumber);//物料需求计划编号 + plan.setId(UUID.randomUUID().toString());// + plan.setPlanYearMonth(cn.hutool.core.date.DateUtil.format(new Date(), "yyyy-MM")); + plan.setOrderDate(cn.hutool.core.date.DateUtil.format(new Date(), "yyyy-MM")); + plan.setCreatorTime(new Date()); + plan.setCreatorUserId(userInfo.getUserId()); + boolean b = materialRequirementPlanService.saveOrUpdate(plan); // 插入物料需求计划表中 + boolean b2 = materialRequirementItemService.saveBatch(planItems); // 更新计划表中物料需求计划ID // 完结 + return ActionResult.success( "计算完成!",planNumber); + } - return ActionResult.success("成功"); + private List mergeWork(List workList) { + workList = workList.stream().collect(Collectors.toMap(YysDayWorkEntity::getProductCode, a -> a, (o1, o2) -> { + o1.setPlanNumber(String.valueOf(Long.valueOf(o1.getPlanNumber()) + Long.valueOf(o2.getPlanNumber()))); + return o1; + })).values().stream().collect(Collectors.toList()); + return workList; } + // 合并生产计划 + private List mergeProduction(List unMPRList) { + List merged = unMPRList.stream().collect(Collectors.toMap(YysMonthlyProductionEntity::getProductId, a -> a, (o1, o2) -> { + o1.setMeasurementNumber(String.valueOf(Integer.valueOf(o1.getMeasurementNumber()) + Integer.valueOf(o2.getMeasurementNumber()))); + return o1; + })).values().stream().collect(Collectors.toList()); + return merged; + } + + // 展开BOM清单 + private Map> expandBomList(Map> expand, List details) { + details.forEach(subsetMaterial -> { + String pieceId = subsetMaterial.getPieceId(); + if (pieceId.startsWith("4")) {// 4 开头的物料是半成品需要再次展开 + String baseUse = subsetMaterial.getBaseUse();//用量 + String baseNum = subsetMaterial.getBaseNum();//倍数 + if (StringUtil.isNotEmpty(baseNum) && NumberUtil.isNumber(baseNum)) { + baseUse = String.valueOf(Integer.valueOf(baseUse) * Integer.valueOf(baseNum));//用量*倍数 + } + List subsetMaterials = subsetMaterialService.getListByPieceId(pieceId); + details.remove(subsetMaterial);//移除当前物料 + String finalBaseUse = baseUse; + subsetMaterials.forEach(mat -> { + mat.setBaseNum(String.valueOf(Integer.valueOf(mat.getBaseUse()) * Integer.valueOf(finalBaseUse)));//用量*用量 + }); + details.addAll(subsetMaterials);//添加展开后的物料 + expandBomList(expand, subsetMaterials);//递归展开 + } + }); + expand.put(details.get(0).getPieceId(), details); + return expand; + } + + // 合并物料需求 + private List mergeMaterial(List planItems) { + List merge = planItems.stream().collect(Collectors.toMap(YysMaterialRequirementItemEntity::getMaterialCode, a -> a, (o1, o2) -> { + o1.setRequirementNumber(o1.getRequirementNumber().add(o2.getRequirementNumber())); + return o1; + })).values().stream().collect(Collectors.toList()); + return merge; + } + + // 计算在途量 + private Map calculateInTransit(List origOrder, + List deliveryOrder) { + HashMap inTransit = new HashMap<>(); + if (origOrder.isEmpty()) return inTransit; + for (YysMaterialProcurementOrderEntity order : origOrder) { + String code = order.getMaterialCode(); + BigDecimal quantity = order.getOrderQuantity(); + BigDecimal num = inTransit.getOrDefault(code, BigDecimal.ZERO); + String orderNumber = order.getOrderNumber(); + if (deliveryOrder.isEmpty()) { + inTransit.put(code, quantity.add(num)); + continue; + } + List list = filterDeliveryOrder(orderNumber, deliveryOrder); + if (list.size() == 0) { + inTransit.put(code, quantity.add(num)); + continue; + } + for (YysMaterialProcurementOrderEntity delivery : list) { + BigDecimal confirmQuantityReceived = delivery.getConfirmQuantityReceived(); + if (confirmQuantityReceived == null) { + confirmQuantityReceived = BigDecimal.ZERO; + } + BigDecimal onRoad = quantity.subtract(confirmQuantityReceived); + num = num.add(onRoad); + } + inTransit.put(code, num); + } + return inTransit; + } + + // 筛选发货单 + private List filterDeliveryOrder(String orderNum, List deliveryOrder) { + return deliveryOrder.stream().filter(order -> order.getOrderNumber().contains(orderNum)).collect(Collectors.toList()); + } + + @PostMapping("/scheduling") @Operation(summary = "生产排产") public ActionResult ProductionScheduling(@RequestBody YysMonthlyProductionStrategyVO strategyVO) { @@ -617,4 +860,5 @@ public class YysMonthlyProductionController { return ActionResult.success("成功"); } + } diff --git a/jnpf-java-boot/jnpf-example/jnpf-example-entity/src/main/java/jnpf/entity/YysMaterialRequirementItemEntity.java b/jnpf-java-boot/jnpf-example/jnpf-example-entity/src/main/java/jnpf/entity/YysMaterialRequirementItemEntity.java index ade4982..9d29ea6 100644 --- a/jnpf-java-boot/jnpf-example/jnpf-example-entity/src/main/java/jnpf/entity/YysMaterialRequirementItemEntity.java +++ b/jnpf-java-boot/jnpf-example/jnpf-example-entity/src/main/java/jnpf/entity/YysMaterialRequirementItemEntity.java @@ -36,7 +36,10 @@ public class YysMaterialRequirementItemEntity { @TableField(value = "REQUIREMENT_NUMBER" , updateStrategy = FieldStrategy.IGNORED) private BigDecimal requirementNumber; @TableField(value = "INVENTORY_NUMBER" , updateStrategy = FieldStrategy.IGNORED) + private BigDecimal inventoryNumber; + @TableField(value = "UN_PRODUCT_OCCUPY" , updateStrategy = FieldStrategy.IGNORED) + private BigDecimal unProductOccupy; @TableField(value = "INVENTORY_SAFETY_NUMBER" , updateStrategy = FieldStrategy.IGNORED) private BigDecimal inventorySafetyNumber; @TableField(value = "NOT_INTO_NUMBER" , updateStrategy = FieldStrategy.IGNORED) diff --git a/jnpf-java-boot/jnpf-example/jnpf-example-entity/src/main/java/jnpf/entity/YysMaterialRequirementPlanEntity.java b/jnpf-java-boot/jnpf-example/jnpf-example-entity/src/main/java/jnpf/entity/YysMaterialRequirementPlanEntity.java index 06ac8ec..1bb3a9d 100644 --- a/jnpf-java-boot/jnpf-example/jnpf-example-entity/src/main/java/jnpf/entity/YysMaterialRequirementPlanEntity.java +++ b/jnpf-java-boot/jnpf-example/jnpf-example-entity/src/main/java/jnpf/entity/YysMaterialRequirementPlanEntity.java @@ -19,9 +19,9 @@ public class YysMaterialRequirementPlanEntity { @TableField(value = "PLAN_NUMBER" , updateStrategy = FieldStrategy.IGNORED) private String planNumber; @TableField(value = "PLAN_YEAR_MONTH" , updateStrategy = FieldStrategy.IGNORED) - private Date planYearMonth; + private String planYearMonth; @TableField(value = "ORDER_DATE" , updateStrategy = FieldStrategy.IGNORED) - private Date orderDate; + private String orderDate; @TableField(value = "IS_CREATE_PLAN" , updateStrategy = FieldStrategy.IGNORED) private String isCreatePlan; @TableField(value = "REAMRK" , updateStrategy = FieldStrategy.IGNORED)