|
@@ -73,78 +73,104 @@ public class MrpOperationServiceImpl implements MrpOperationService {
|
|
|
@Override
|
|
@Override
|
|
|
@Transactional(rollbackFor = Exception.class)
|
|
@Transactional(rollbackFor = Exception.class)
|
|
|
public void mrpOperation(List<OrderInformation> orderInformationList, PlanOperationProgress planOperationProgress) {
|
|
public void mrpOperation(List<OrderInformation> orderInformationList, PlanOperationProgress planOperationProgress) {
|
|
|
|
|
+ // 总体说明:
|
|
|
|
|
+ // 1、方法概述
|
|
|
|
|
+ // 1)、本方法为事务方法,针对传入的订单列表逐个执行 MRP 排程;
|
|
|
|
|
+ // 2)、主流程(高层次):预处理 -> 订单循环(库存优先 -> BOM 展开 -> 逐层需求计算 -> 建议/采购计划生成) -> 批量保存
|
|
|
if (CollectionUtils.isEmpty(orderInformationList)) {
|
|
if (CollectionUtils.isEmpty(orderInformationList)) {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
+ // 2、预处理(对所有订单进行统一处理)
|
|
|
|
|
+ // 1)、清除计划延迟标签(LabelStatus.PLAN_LATE);
|
|
|
|
|
+ // 2)、将订单调度状态置为 ARRANGING(表示正在排程);
|
|
|
orderInformationList.forEach(orderInformation -> {
|
|
orderInformationList.forEach(orderInformation -> {
|
|
|
- //排程清除计划延迟标签,所选中的终止排程订单没有影响
|
|
|
|
|
|
|
+ // 排程清除计划延迟标签
|
|
|
orderInformation.removeLabelsValue(LabelStatus.PLAN_LATE);
|
|
orderInformation.removeLabelsValue(LabelStatus.PLAN_LATE);
|
|
|
|
|
+ // 设置调度状态为正在排程
|
|
|
orderInformation.setSchedulingStatus(SchedulingStatusEnum.ARRANGING);
|
|
orderInformation.setSchedulingStatus(SchedulingStatusEnum.ARRANGING);
|
|
|
});
|
|
});
|
|
|
orderInformationService.updateBatchById(orderInformationList);
|
|
orderInformationService.updateBatchById(orderInformationList);
|
|
|
int size = orderInformationList.size();
|
|
int size = orderInformationList.size();
|
|
|
|
|
+ // 3、按订单循环处理(每个订单在事务中顺序处理)
|
|
|
for (int i = 0; i < size; i++) {
|
|
for (int i = 0; i < size; i++) {
|
|
|
|
|
+ // 3、订单处理的子步骤(序号示例)
|
|
|
|
|
+ // 1)、初始化每订单的中间集合:建议计划(suggestedPlans)、采购计划(purchasePlanes);
|
|
|
|
|
+ // 2)、更新计划进度(进度写入 Redis,用于前端展示);
|
|
|
|
|
+ // 3)、计算计划数量(考虑完工率的反算);
|
|
|
|
|
+ // 4)、顶层库存优先校验:若库存充足则直接消耗并关闭订单;
|
|
|
|
|
+ // 5)、若库存不足则展开 BOM,逐级计算并生成建议计划/采购计划;
|
|
|
List<SuggestedPlan> suggestedPlans = new ArrayList<>();
|
|
List<SuggestedPlan> suggestedPlans = new ArrayList<>();
|
|
|
List<PurchasePlan> purchasePlanes = new ArrayList<>();
|
|
List<PurchasePlan> purchasePlanes = new ArrayList<>();
|
|
|
- //更新计划进度
|
|
|
|
|
|
|
+ // 更新计划进度(将进度写入 Redis,供前端或监控读取)
|
|
|
updatePlanOperationProgress(planOperationProgress, i + 1, size);
|
|
updatePlanOperationProgress(planOperationProgress, i + 1, size);
|
|
|
OrderInformation orderInformation = orderInformationList.get(i);
|
|
OrderInformation orderInformation = orderInformationList.get(i);
|
|
|
- //计划数量
|
|
|
|
|
|
|
+ // 3)、计算计划数量:以订单数量为基准,若顶层物料存在完工率则进行反算
|
|
|
BigDecimal planQuantity = orderInformation.getOrderQuantity() == null ? BigDecimal.ZERO :
|
|
BigDecimal planQuantity = orderInformation.getOrderQuantity() == null ? BigDecimal.ZERO :
|
|
|
orderInformation.getOrderQuantity();
|
|
orderInformation.getOrderQuantity();
|
|
|
Material orderMaterial = materialService.getOne(new LambdaQueryWrapper<Material>().eq(Material::getMaterialCode, orderInformation.getItemCode()));
|
|
Material orderMaterial = materialService.getOne(new LambdaQueryWrapper<Material>().eq(Material::getMaterialCode, orderInformation.getItemCode()));
|
|
|
- //实际库存&安全库存
|
|
|
|
|
|
|
+ // 3)、获取顶层物料的实际库存与安全库存
|
|
|
BigDecimal actualInventory = orderMaterial.getActualInventory();
|
|
BigDecimal actualInventory = orderMaterial.getActualInventory();
|
|
|
BigDecimal safetyInventory = orderMaterial.getSafetyInventory();
|
|
BigDecimal safetyInventory = orderMaterial.getSafetyInventory();
|
|
|
if (orderMaterial.getFinishedProductRate() != null && orderMaterial.getFinishedProductRate().compareTo(BigDecimal.ZERO) > 0) {
|
|
if (orderMaterial.getFinishedProductRate() != null && orderMaterial.getFinishedProductRate().compareTo(BigDecimal.ZERO) > 0) {
|
|
|
|
|
+ // 若顶层物料存在完工率,需要将订单交付量转换为投入量(按完工率反算,向上取整)
|
|
|
planQuantity = planQuantity.multiply(new BigDecimal(100)).divide(orderMaterial.getFinishedProductRate(), 0, RoundingMode.UP);
|
|
planQuantity = planQuantity.multiply(new BigDecimal(100)).divide(orderMaterial.getFinishedProductRate(), 0, RoundingMode.UP);
|
|
|
}
|
|
}
|
|
|
- //库存逻辑校验
|
|
|
|
|
|
|
+ // 4、顶层库存优先:若 actual - safety >= planQuantity 则直接占用库存并关闭订单(不展开 BOM)
|
|
|
if (inventoryCheck(actualInventory, safetyInventory, planQuantity)) {
|
|
if (inventoryCheck(actualInventory, safetyInventory, planQuantity)) {
|
|
|
actualInventory = calculateActualInventory(actualInventory, planQuantity);
|
|
actualInventory = calculateActualInventory(actualInventory, planQuantity);
|
|
|
- //更新库存
|
|
|
|
|
|
|
+ // 更新物料库存并持久化
|
|
|
updateMaterial(actualInventory, orderMaterial);
|
|
updateMaterial(actualInventory, orderMaterial);
|
|
|
|
|
+ // 标记订单为已关闭(无需生成下层计划)
|
|
|
orderInformation.setSchedulingStatus(SchedulingStatusEnum.CLOSE);
|
|
orderInformation.setSchedulingStatus(SchedulingStatusEnum.CLOSE);
|
|
|
orderInformation.setPlannedQuantity(planQuantity);
|
|
orderInformation.setPlannedQuantity(planQuantity);
|
|
|
orderInformationService.updateById(orderInformation);
|
|
orderInformationService.updateById(orderInformation);
|
|
|
continue;
|
|
continue;
|
|
|
}
|
|
}
|
|
|
|
|
+ // 5、库存不足时初始化建议计划与采购计划的生成
|
|
|
Map<String, SuggestedPlan> suggestedPlanMap = new HashMap<>();
|
|
Map<String, SuggestedPlan> suggestedPlanMap = new HashMap<>();
|
|
|
- //增加建议计划
|
|
|
|
|
|
|
+ // 1)、添加顶层建议计划(作为父级,用于向下传递需求量)
|
|
|
addSuggestPlan(suggestedPlanMap, suggestedPlans, orderInformation, orderMaterial,
|
|
addSuggestPlan(suggestedPlanMap, suggestedPlans, orderInformation, orderMaterial,
|
|
|
orderInformation.getOrderQuantity() == null ? BigDecimal.ZERO : orderInformation.getOrderQuantity(),
|
|
orderInformation.getOrderQuantity() == null ? BigDecimal.ZERO : orderInformation.getOrderQuantity(),
|
|
|
planQuantity, 0, BigDecimal.ZERO, orderMaterial.getMaterialCode());
|
|
planQuantity, 0, BigDecimal.ZERO, orderMaterial.getMaterialCode());
|
|
|
orderInformation.setPlannedQuantity(planQuantity);
|
|
orderInformation.setPlannedQuantity(planQuantity);
|
|
|
orderInformationService.updateById(orderInformation);
|
|
orderInformationService.updateById(orderInformation);
|
|
|
- //bom层级展开
|
|
|
|
|
|
|
+ // 2、BOM 层级展开与校验:
|
|
|
|
|
+ // 1)、获取子件清单并按层级排序;
|
|
|
|
|
+ // 2)、展开前必须校验工艺/设备/日历/辅助资料等配置信息,校验失败会抛出异常中断排程
|
|
|
List<MaterialBom> materials = materialMapper.getMaterialByMaterialCode(orderMaterial.getId());
|
|
List<MaterialBom> materials = materialMapper.getMaterialByMaterialCode(orderMaterial.getId());
|
|
|
- //校验工序设备日历信息
|
|
|
|
|
checkProcessEquipmentCalendar(orderInformation, orderMaterial, materials);
|
|
checkProcessEquipmentCalendar(orderInformation, orderMaterial, materials);
|
|
|
materials = materials.stream().sorted(Comparator.comparing(MaterialBom::getLevel)).collect(Collectors.toList());
|
|
materials = materials.stream().sorted(Comparator.comparing(MaterialBom::getLevel)).collect(Collectors.toList());
|
|
|
Map<Long, MaterialBom> materialBomMap = materials.stream().collect(Collectors.toMap(MaterialBom::getBomItemId, Function.identity()));
|
|
Map<Long, MaterialBom> materialBomMap = materials.stream().collect(Collectors.toMap(MaterialBom::getBomItemId, Function.identity()));
|
|
|
BigDecimal subDemandQuantity;
|
|
BigDecimal subDemandQuantity;
|
|
|
BigDecimal subPlanQuantity;
|
|
BigDecimal subPlanQuantity;
|
|
|
- //子级bom运算
|
|
|
|
|
|
|
+ // 6、逐层处理 BOM:对每个子项计算需求、校验库存并决定是自制/外购的处理分支
|
|
|
for (MaterialBom materialBom : materials) {
|
|
for (MaterialBom materialBom : materials) {
|
|
|
|
|
+ // 1)、确定父物料编码(用于从 suggestedPlanMap 中读取父级计划量)
|
|
|
String materialParentCode = getMaterialParentCode(materialBom, orderMaterial, materialBomMap);
|
|
String materialParentCode = getMaterialParentCode(materialBom, orderMaterial, materialBomMap);
|
|
|
|
|
+ // 2)、计算子级计划数量 = 父级计划量 * 单位用量,向上取整;对外购件再做单位换算(保留小数情况)
|
|
|
subPlanQuantity = getSubPlanQuantity(planQuantity, orderInformation.getOrderNumber() + materialParentCode, suggestedPlanMap).multiply(materialBom.getUnitUsage()).setScale(0, RoundingMode.UP);
|
|
subPlanQuantity = getSubPlanQuantity(planQuantity, orderInformation.getOrderNumber() + materialParentCode, suggestedPlanMap).multiply(materialBom.getUnitUsage()).setScale(0, RoundingMode.UP);
|
|
|
if (ProductionType.OUTSIDE_PURCHASE.equals(materialBom.getProductionType())) {
|
|
if (ProductionType.OUTSIDE_PURCHASE.equals(materialBom.getProductionType())) {
|
|
|
|
|
+ // 若为外购件,按产品/采购单位比率换算为采购单位数量(保留2位小数)
|
|
|
String[] productPurchaseUnit = materialBom.getProductPurchaseUnitRatio().split(":");
|
|
String[] productPurchaseUnit = materialBom.getProductPurchaseUnitRatio().split(":");
|
|
|
subPlanQuantity = subPlanQuantity.multiply(new BigDecimal(productPurchaseUnit[1])).divide(new BigDecimal(productPurchaseUnit[0]), 2, RoundingMode.UP);
|
|
subPlanQuantity = subPlanQuantity.multiply(new BigDecimal(productPurchaseUnit[1])).divide(new BigDecimal(productPurchaseUnit[0]), 2, RoundingMode.UP);
|
|
|
}
|
|
}
|
|
|
subDemandQuantity = subPlanQuantity;
|
|
subDemandQuantity = subPlanQuantity;
|
|
|
- //根据成品率计算计划数量
|
|
|
|
|
|
|
+ // 3)、若子件存在完工率,按完工率进行反算(自制件向上取整,外购保留2位小数)
|
|
|
if (materialBom.getFinishedProductRate() != null && materialBom.getFinishedProductRate().compareTo(BigDecimal.ZERO) > 0) {
|
|
if (materialBom.getFinishedProductRate() != null && materialBom.getFinishedProductRate().compareTo(BigDecimal.ZERO) > 0) {
|
|
|
if (ProductionType.OUTSIDE_PURCHASE.equals(materialBom.getProductionType())) {
|
|
if (ProductionType.OUTSIDE_PURCHASE.equals(materialBom.getProductionType())) {
|
|
|
subPlanQuantity = subPlanQuantity.multiply(new BigDecimal(100)).divide(materialBom.getFinishedProductRate(), 2, RoundingMode.UP);
|
|
subPlanQuantity = subPlanQuantity.multiply(new BigDecimal(100)).divide(materialBom.getFinishedProductRate(), 2, RoundingMode.UP);
|
|
|
- }else {
|
|
|
|
|
|
|
+ } else {
|
|
|
subPlanQuantity = subPlanQuantity.multiply(new BigDecimal(100)).divide(materialBom.getFinishedProductRate(), 0, RoundingMode.UP);
|
|
subPlanQuantity = subPlanQuantity.multiply(new BigDecimal(100)).divide(materialBom.getFinishedProductRate(), 0, RoundingMode.UP);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
BigDecimal subActualInventory = materialBom.getActualInventory();
|
|
BigDecimal subActualInventory = materialBom.getActualInventory();
|
|
|
BigDecimal subSafetyInventory = materialBom.getSafetyInventory();
|
|
BigDecimal subSafetyInventory = materialBom.getSafetyInventory();
|
|
|
|
|
+ // 4)、读取父级建议计划以判断是否需要展开或采购
|
|
|
SuggestedPlan suggestedPlan = suggestedPlanMap.get(orderInformation.getOrderNumber() + materialParentCode);
|
|
SuggestedPlan suggestedPlan = suggestedPlanMap.get(orderInformation.getOrderNumber() + materialParentCode);
|
|
|
- //自制件
|
|
|
|
|
|
|
+ // 5)、自制件(SELF_MADE)处理:
|
|
|
|
|
+ // 1)、若库存充足:占用库存并生成 CLOSE 建议计划;
|
|
|
|
|
+ // 2)、若库存不足且父级存在建议计划:生成 NOTARRANGED 建议计划;
|
|
|
|
|
+ // 3)、若父级不存在建议计划:不展开
|
|
|
if (ProductionType.SELF_MADE.equals(materialBom.getProductionType())) {
|
|
if (ProductionType.SELF_MADE.equals(materialBom.getProductionType())) {
|
|
|
if (inventoryCheck(subActualInventory, subSafetyInventory, subPlanQuantity)) {
|
|
if (inventoryCheck(subActualInventory, subSafetyInventory, subPlanQuantity)) {
|
|
|
subActualInventory = calculateActualInventory(subActualInventory, subPlanQuantity);
|
|
subActualInventory = calculateActualInventory(subActualInventory, subPlanQuantity);
|
|
@@ -157,6 +183,11 @@ public class MrpOperationServiceImpl implements MrpOperationService {
|
|
|
}
|
|
}
|
|
|
continue;
|
|
continue;
|
|
|
}
|
|
}
|
|
|
|
|
+ // 6)、外购件(OUTSIDE_PURCHASE)处理:
|
|
|
|
|
+ // 1)、若父级无建议计划或父级已 CLOSE:生成 CLOSE 建议计划并跳过;
|
|
|
|
|
+ // 2)、若库存充足:占用库存并更新;
|
|
|
|
|
+ // 3)、若库存部分满足:占用现有库存并生成采购计划补足;
|
|
|
|
|
+ // 4)、若库存为 0:全部生成采购计划
|
|
|
if (suggestedPlan == null || suggestedPlan.getSchedulingStatus().equals(SchedulingStatusEnum.CLOSE)) {
|
|
if (suggestedPlan == null || suggestedPlan.getSchedulingStatus().equals(SchedulingStatusEnum.CLOSE)) {
|
|
|
addSuggestPlan(suggestedPlanMap, suggestedPlans, orderInformation, materialBom, subDemandQuantity, subPlanQuantity, materialBom.getLevel(), BigDecimal.ZERO, materialParentCode, SchedulingStatusEnum.CLOSE);
|
|
addSuggestPlan(suggestedPlanMap, suggestedPlans, orderInformation, materialBom, subDemandQuantity, subPlanQuantity, materialBom.getLevel(), BigDecimal.ZERO, materialParentCode, SchedulingStatusEnum.CLOSE);
|
|
|
continue;
|
|
continue;
|
|
@@ -169,30 +200,28 @@ public class MrpOperationServiceImpl implements MrpOperationService {
|
|
|
BigDecimal possessionInventory = subPlanQuantity;
|
|
BigDecimal possessionInventory = subPlanQuantity;
|
|
|
BigDecimal shortageQuantity = BigDecimal.ZERO;
|
|
BigDecimal shortageQuantity = BigDecimal.ZERO;
|
|
|
if (subActualInventory.compareTo(subPlanQuantity) >= 0) {
|
|
if (subActualInventory.compareTo(subPlanQuantity) >= 0) {
|
|
|
|
|
+ // 有一部分库存可用于占用
|
|
|
subActualInventory = calculateActualInventory(subActualInventory, subPlanQuantity);
|
|
subActualInventory = calculateActualInventory(subActualInventory, subPlanQuantity);
|
|
|
updateMaterialBom(materialBom, subActualInventory);
|
|
updateMaterialBom(materialBom, subActualInventory);
|
|
|
addSuggestPlan(suggestedPlanMap, suggestedPlans, orderInformation, materialBom, subDemandQuantity, subPlanQuantity, materialBom.getLevel(), possessionInventory, materialParentCode);
|
|
addSuggestPlan(suggestedPlanMap, suggestedPlans, orderInformation, materialBom, subDemandQuantity, subPlanQuantity, materialBom.getLevel(), possessionInventory, materialParentCode);
|
|
|
continue;
|
|
continue;
|
|
|
}
|
|
}
|
|
|
|
|
+ // 计算不足量并生成采购计划
|
|
|
shortageQuantity = subPlanQuantity.subtract(subActualInventory);
|
|
shortageQuantity = subPlanQuantity.subtract(subActualInventory);
|
|
|
possessionInventory = subActualInventory;
|
|
possessionInventory = subActualInventory;
|
|
|
subActualInventory = BigDecimal.ZERO;
|
|
subActualInventory = BigDecimal.ZERO;
|
|
|
- //更新子级物料信息
|
|
|
|
|
updateMaterialBom(materialBom, subActualInventory);
|
|
updateMaterialBom(materialBom, subActualInventory);
|
|
|
addSuggestPlan(suggestedPlanMap, suggestedPlans, orderInformation, materialBom, subDemandQuantity, subPlanQuantity, materialBom.getLevel(), possessionInventory, materialParentCode);
|
|
addSuggestPlan(suggestedPlanMap, suggestedPlans, orderInformation, materialBom, subDemandQuantity, subPlanQuantity, materialBom.getLevel(), possessionInventory, materialParentCode);
|
|
|
addPurchasePlan(purchasePlanes, orderInformation, materialBom, shortageQuantity);
|
|
addPurchasePlan(purchasePlanes, orderInformation, materialBom, shortageQuantity);
|
|
|
}
|
|
}
|
|
|
- //保存建议计划、齐套分析、采购计划初始值
|
|
|
|
|
|
|
+ // 7、批量保存:将本订单产生的建议计划与采购计划批量入库
|
|
|
saveMrpPlans(suggestedPlans, purchasePlanes);
|
|
saveMrpPlans(suggestedPlans, purchasePlanes);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* 校验工序设备日历信息
|
|
* 校验工序设备日历信息
|
|
|
- *
|
|
|
|
|
- * @param orderInformation 订单信息
|
|
|
|
|
- * @param orderMaterial 订单物料
|
|
|
|
|
- * @param materials 物料
|
|
|
|
|
|
|
+ * 注释:该方法在 BOM 展开前被调用,若校验失败会抛出异常,阻断整个排程流程
|
|
|
*/
|
|
*/
|
|
|
private void checkProcessEquipmentCalendar(OrderInformation orderInformation, Material orderMaterial, List<MaterialBom> materials) {
|
|
private void checkProcessEquipmentCalendar(OrderInformation orderInformation, Material orderMaterial, List<MaterialBom> materials) {
|
|
|
Map<String, String> materialsMap = materials.stream().collect(Collectors.toMap(MaterialBom::getMaterialCode, MaterialBom::getMaterialName));
|
|
Map<String, String> materialsMap = materials.stream().collect(Collectors.toMap(MaterialBom::getMaterialCode, MaterialBom::getMaterialName));
|
|
@@ -392,11 +421,7 @@ public class MrpOperationServiceImpl implements MrpOperationService {
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* 获取子级计划数量
|
|
* 获取子级计划数量
|
|
|
- *
|
|
|
|
|
- * @param planQuantity 计划数量
|
|
|
|
|
- * @param materialParentCode 父级
|
|
|
|
|
- * @param suggestedPlanMap 计划数量
|
|
|
|
|
- * @return 计划数量
|
|
|
|
|
|
|
+ * 注释:如果父级编码为空返回顶层 planQuantity;否则尝试从 suggestedPlanMap 中读取父级 plannedQuantity
|
|
|
*/
|
|
*/
|
|
|
private BigDecimal getSubPlanQuantity(BigDecimal planQuantity, String materialParentCode, Map<String, SuggestedPlan> suggestedPlanMap) {
|
|
private BigDecimal getSubPlanQuantity(BigDecimal planQuantity, String materialParentCode, Map<String, SuggestedPlan> suggestedPlanMap) {
|
|
|
if ("".equals(materialParentCode)) {
|
|
if ("".equals(materialParentCode)) {
|
|
@@ -411,9 +436,7 @@ public class MrpOperationServiceImpl implements MrpOperationService {
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* 批量保存MRP计划初始值
|
|
* 批量保存MRP计划初始值
|
|
|
- *
|
|
|
|
|
- * @param suggestedPlans 建议计划
|
|
|
|
|
- * @param purchasePlanes 采购计划
|
|
|
|
|
|
|
+ * 注释:分别批量保存建议计划与采购计划,避免多次数据库交互
|
|
|
*/
|
|
*/
|
|
|
private void saveMrpPlans(List<SuggestedPlan> suggestedPlans, List<PurchasePlan> purchasePlanes) {
|
|
private void saveMrpPlans(List<SuggestedPlan> suggestedPlans, List<PurchasePlan> purchasePlanes) {
|
|
|
if (CollectionUtil.isNotEmpty(suggestedPlans)) {
|
|
if (CollectionUtil.isNotEmpty(suggestedPlans)) {
|
|
@@ -426,10 +449,7 @@ public class MrpOperationServiceImpl implements MrpOperationService {
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* 更新计划排程进度
|
|
* 更新计划排程进度
|
|
|
- *
|
|
|
|
|
- * @param planOperationProgress 计划排程进度model
|
|
|
|
|
- * @param i 订单下标
|
|
|
|
|
- * @param size 订单数
|
|
|
|
|
|
|
+ * 注释:将订单处理进度的前 20% 写入 Redis,表示这是排程中的第一阶段进度
|
|
|
*/
|
|
*/
|
|
|
private void updatePlanOperationProgress(PlanOperationProgress planOperationProgress, int i, int size) {
|
|
private void updatePlanOperationProgress(PlanOperationProgress planOperationProgress, int i, int size) {
|
|
|
if (planOperationProgress == null) {
|
|
if (planOperationProgress == null) {
|
|
@@ -443,11 +463,7 @@ public class MrpOperationServiceImpl implements MrpOperationService {
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* 增加采购计划
|
|
* 增加采购计划
|
|
|
- *
|
|
|
|
|
- * @param purchasePlans 采购计划信息list
|
|
|
|
|
- * @param orderInformation 订单信息
|
|
|
|
|
- * @param materialBom 物料bom
|
|
|
|
|
- * @param shortageQuantity 缺料数量
|
|
|
|
|
|
|
+ * 注释:构造 PurchasePlan;若外购件则按采购单位设置 unit,并保持数量按采购单位换算(注释处显示可扩展)
|
|
|
*/
|
|
*/
|
|
|
private void addPurchasePlan(List<PurchasePlan> purchasePlans, OrderInformation orderInformation, MaterialBom materialBom, BigDecimal shortageQuantity) {
|
|
private void addPurchasePlan(List<PurchasePlan> purchasePlans, OrderInformation orderInformation, MaterialBom materialBom, BigDecimal shortageQuantity) {
|
|
|
PurchasePlan plan = PurchasePlan.builder()
|
|
PurchasePlan plan = PurchasePlan.builder()
|
|
@@ -471,10 +487,8 @@ public class MrpOperationServiceImpl implements MrpOperationService {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * 更新物料信息
|
|
|
|
|
- *
|
|
|
|
|
- * @param materialBom 物料bom
|
|
|
|
|
- * @param actualInventory 实际库存
|
|
|
|
|
|
|
+ * 更新物料信息(MaterialBom -> Material)
|
|
|
|
|
+ * 注释:把 bom 的最新库存同步回物料表
|
|
|
*/
|
|
*/
|
|
|
private void updateMaterialBom(MaterialBom materialBom, BigDecimal actualInventory) {
|
|
private void updateMaterialBom(MaterialBom materialBom, BigDecimal actualInventory) {
|
|
|
Material material = new Material();
|
|
Material material = new Material();
|
|
@@ -484,9 +498,6 @@ public class MrpOperationServiceImpl implements MrpOperationService {
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* 更新物料信息
|
|
* 更新物料信息
|
|
|
- *
|
|
|
|
|
- * @param actualInventory 实际库存
|
|
|
|
|
- * @param material 物料信息
|
|
|
|
|
*/
|
|
*/
|
|
|
private void updateMaterial(BigDecimal actualInventory, Material material) {
|
|
private void updateMaterial(BigDecimal actualInventory, Material material) {
|
|
|
material.setActualInventory(actualInventory);
|
|
material.setActualInventory(actualInventory);
|
|
@@ -494,11 +505,7 @@ public class MrpOperationServiceImpl implements MrpOperationService {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * 计算实际库存
|
|
|
|
|
- *
|
|
|
|
|
- * @param actualInventory 实际库存
|
|
|
|
|
- * @param planQuantity 计划数量
|
|
|
|
|
- * @return 实际库存
|
|
|
|
|
|
|
+ * 计算实际库存(扣减计划量)
|
|
|
*/
|
|
*/
|
|
|
private BigDecimal calculateActualInventory(BigDecimal actualInventory, BigDecimal planQuantity) {
|
|
private BigDecimal calculateActualInventory(BigDecimal actualInventory, BigDecimal planQuantity) {
|
|
|
actualInventory = actualInventory.subtract(planQuantity);
|
|
actualInventory = actualInventory.subtract(planQuantity);
|
|
@@ -507,46 +514,22 @@ public class MrpOperationServiceImpl implements MrpOperationService {
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* 实际库存、安全库存、计划数量校验逻辑
|
|
* 实际库存、安全库存、计划数量校验逻辑
|
|
|
- *
|
|
|
|
|
- * @param actualInventory 实际库存
|
|
|
|
|
- * @param safetyInventory 安全库存
|
|
|
|
|
- * @param planQuantity 计划适量
|
|
|
|
|
- * @return true or false
|
|
|
|
|
|
|
+ * 注释:当 actual - safety >= plan 返回 true,表示库存可直接支持计划
|
|
|
*/
|
|
*/
|
|
|
private boolean inventoryCheck(BigDecimal actualInventory, BigDecimal safetyInventory, BigDecimal planQuantity) {
|
|
private boolean inventoryCheck(BigDecimal actualInventory, BigDecimal safetyInventory, BigDecimal planQuantity) {
|
|
|
return actualInventory.subtract(safetyInventory).compareTo(planQuantity) >= 0;
|
|
return actualInventory.subtract(safetyInventory).compareTo(planQuantity) >= 0;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * 增加建议计划
|
|
|
|
|
- *
|
|
|
|
|
- * @param suggestedPlanMap 建议计划map
|
|
|
|
|
- * @param suggestedPlans 建议计划list
|
|
|
|
|
- * @param orderInformation 订单信息
|
|
|
|
|
- * @param material 物料信息
|
|
|
|
|
- * @param demandQuantity 需求数量
|
|
|
|
|
- * @param planQuantity 计划数量
|
|
|
|
|
- * @param level bom层级
|
|
|
|
|
- * @param possessionInventory 物料占用量
|
|
|
|
|
- * @param materialParentCode 父级物料编码
|
|
|
|
|
|
|
+ * 增加建议计划(默认 NOTARRANGED)
|
|
|
*/
|
|
*/
|
|
|
private void addSuggestPlan(Map<String, SuggestedPlan> suggestedPlanMap, List<SuggestedPlan> suggestedPlans, OrderInformation orderInformation, Material material, BigDecimal demandQuantity, BigDecimal planQuantity, int level, BigDecimal possessionInventory, String materialParentCode) {
|
|
private void addSuggestPlan(Map<String, SuggestedPlan> suggestedPlanMap, List<SuggestedPlan> suggestedPlans, OrderInformation orderInformation, Material material, BigDecimal demandQuantity, BigDecimal planQuantity, int level, BigDecimal possessionInventory, String materialParentCode) {
|
|
|
addSuggestPlan(suggestedPlanMap, suggestedPlans, orderInformation, material, demandQuantity, planQuantity, level, possessionInventory, materialParentCode, SchedulingStatusEnum.NOTARRANGED);
|
|
addSuggestPlan(suggestedPlanMap, suggestedPlans, orderInformation, material, demandQuantity, planQuantity, level, possessionInventory, materialParentCode, SchedulingStatusEnum.NOTARRANGED);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * 增加建议计划
|
|
|
|
|
- *
|
|
|
|
|
- * @param suggestedPlanMap 建议计划map
|
|
|
|
|
- * @param suggestedPlans 建议计划list
|
|
|
|
|
- * @param orderInformation 订单信息
|
|
|
|
|
- * @param material 物料信息
|
|
|
|
|
- * @param demandQuantity 需求数量
|
|
|
|
|
- * @param planQuantity 计划数量
|
|
|
|
|
- * @param level bom层级
|
|
|
|
|
- * @param possessionInventory 物料占用量
|
|
|
|
|
- * @param materialParentCode 父级物料编码
|
|
|
|
|
- * @SchedulingStatusEnum 计划状态
|
|
|
|
|
|
|
+ * 增加建议计划(带状态重载)
|
|
|
|
|
+ * 注释:构造 SuggestedPlan,并放入 map(key = orderNumber + materialCode)用于父子传递
|
|
|
*/
|
|
*/
|
|
|
private void addSuggestPlan(Map<String, SuggestedPlan> suggestedPlanMap, List<SuggestedPlan> suggestedPlans, OrderInformation orderInformation, Material material, BigDecimal demandQuantity, BigDecimal planQuantity, int level, BigDecimal possessionInventory, String materialParentCode, SchedulingStatusEnum schedulingStatusEnum) {
|
|
private void addSuggestPlan(Map<String, SuggestedPlan> suggestedPlanMap, List<SuggestedPlan> suggestedPlans, OrderInformation orderInformation, Material material, BigDecimal demandQuantity, BigDecimal planQuantity, int level, BigDecimal possessionInventory, String materialParentCode, SchedulingStatusEnum schedulingStatusEnum) {
|
|
|
SuggestedPlan suggestedPlan = SuggestedPlan.builder().
|
|
SuggestedPlan suggestedPlan = SuggestedPlan.builder().
|
|
@@ -567,17 +550,14 @@ public class MrpOperationServiceImpl implements MrpOperationService {
|
|
|
possessionInventory(possessionInventory).
|
|
possessionInventory(possessionInventory).
|
|
|
creator(ISecurity.userMust().getUsername()).
|
|
creator(ISecurity.userMust().getUsername()).
|
|
|
build();
|
|
build();
|
|
|
|
|
+ // 使用 orderNumber + materialCode 作为 key,方便父级传递计划量给子级
|
|
|
suggestedPlanMap.put(orderInformation.getOrderNumber() + material.getMaterialCode(), suggestedPlan);
|
|
suggestedPlanMap.put(orderInformation.getOrderNumber() + material.getMaterialCode(), suggestedPlan);
|
|
|
suggestedPlans.add(suggestedPlan);
|
|
suggestedPlans.add(suggestedPlan);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* 获取父级物料编码
|
|
* 获取父级物料编码
|
|
|
- *
|
|
|
|
|
- * @param materialBom 物料bom
|
|
|
|
|
- * @param orderMaterial 父级物料
|
|
|
|
|
- * @param materialBomMap 物料bomMap
|
|
|
|
|
- * @return 父级物料编码
|
|
|
|
|
|
|
+ * 注释:用于将子项关联到父项的 materialCode(顶层父使用订单物料的 code)
|
|
|
*/
|
|
*/
|
|
|
private String getMaterialParentCode(MaterialBom materialBom, Material orderMaterial, Map<Long, MaterialBom> materialBomMap) {
|
|
private String getMaterialParentCode(MaterialBom materialBom, Material orderMaterial, Map<Long, MaterialBom> materialBomMap) {
|
|
|
Long parentId = materialBom.getParentId();
|
|
Long parentId = materialBom.getParentId();
|