如何用JavaScript正确计算产品及子物料的缺失数量与明细?
多级物料生产需求的缺失量计算问题
我有一款由多种物料组成的产品,每种物料要么是纯物料,要么由其他物料组成。复合物料会指定所需的子物料及对应数量,所有物料都有当前可用数量。我需要计算现有物料量、缺失物料量,并汇总所有缺失物料的数量。
目前我只能正确计算一级非子物料的缺失量,计算子物料的缺失量时出现错误,求正确计算生产产品所需所有物料(包括子物料)缺失情况的方法。
现有代码
const product = { name: 'prod_1', quantity: 1.2, material_quantities: [ { id: 2, quantity: 2 }, { id: 1, quantity: 2 }, ], }; const materials = [ { id: 1, name: 'material1', quantity: 1.2, material_quantities: null, }, { id: 2, name: 'material2', quantity: 1.2, material_quantities: [{ id: 1, quantity: 2 }], }, ]; function areEnoughMaterials(materialId, neededQuantity) { const mainMaterial = materials.find(id === materialId); const inStock = parseFloat(neededQuantity) <= parseFloat(mainMaterial.quantity); if (mainMaterial?.material_list?.length === 0 && inStock) { materialsStatus.available[materialId] = mainMaterial.quantity; } if (!inStock) { if (!materialsStatus.missing[materialId]) { materialsStatus.missing[materialId] = parseFloat(neededQuantity) - parseFloat(mainMaterial.quantity); } else { materialsStatus.missing[materialId] = materialsStatus.missing[materialId] + parseFloat(mainMaterial.quantity); } } if (mainMaterial.material_quantities) { for (const material of mainMaterial.material_quantities) { areEnoughMaterials(material.id, material.quantity); } } return; } let materialsStatus = { available: {}, missing: {}, }; for (const material of product.material_quantities) { areEnoughMaterials(material.id, material.quantity); }
期望输出
{ available: { 2: 1.2, 1: 1.2 }, missing: { 2: 0.8, 1: 3.6 } }
问题分析与修正方案
原代码核心错误
- 物料查找逻辑错误:
materials.find(id === materialId)写法无效,无法定位目标物料,正确写法应为materials.find(m => m.id === materialId)。 - 子物料需求传递错误:递归调用时未结合父物料的实际需求缺口,仅传递子物料的基础配比数量,导致子物料需求计算完全偏离实际。
- 可用量记录逻辑错误:
mainMaterial?.material_list是笔误(应为material_quantities),且仅在纯物料满足需求时记录可用量,不符合"记录所有现有物料量"的要求。 - 缺失量累加逻辑错误:缺失量更新公式错误,未正确累加新增需求缺口,反而错误叠加库存数量。
修正后的代码
const product = { name: 'prod_1', quantity: 1.2, material_quantities: [ { id: 2, quantity: 2 }, { id: 1, quantity: 2 }, ], }; const materials = [ { id: 1, name: 'material1', quantity: 1.2, material_quantities: null, }, { id: 2, name: 'material2', quantity: 1.2, material_quantities: [{ id: 1, quantity: 2 }], }, ]; // 初始化:先记录所有物料的原始可用量 const materialsStatus = { available: materials.reduce((acc, mat) => { acc[mat.id] = mat.quantity; return acc; }, {}), missing: {}, }; function calculateMissingMaterials(materialId, baseRequired) { const material = materials.find(m => m.id === materialId); if (!material) return; // 计算当前物料的总需求(结合产品生产数量) const totalRequired = baseRequired * product.quantity; // 计算缺口:总需求大于库存时取差值,否则为0 const shortage = Math.max(totalRequired - material.quantity, 0); // 更新缺失量:累加当前物料的缺口 if (shortage > 0) { materialsStatus.missing[materialId] = (materialsStatus.missing[materialId] || 0) + shortage; } // 复合物料递归计算:缺口部分需要的子物料量 if (material.material_quantities) { material.material_quantities.forEach(subMat => { calculateMissingMaterials(subMat.id, subMat.quantity * shortage); }); } } // 遍历产品一级物料,启动计算 product.material_quantities.forEach(mat => { calculateMissingMaterials(mat.id, mat.quantity); }); console.log(materialsStatus);
说明
修正后的代码先初始化所有物料的可用量,再递归计算每个物料的需求缺口:
- 一级物料的总需求结合产品生产数量计算
- 复合物料的子物料需求基于父物料的缺口量计算
- 缺失量按实际需求缺口累加,确保多级物料的需求统计准确
若需完全匹配期望输出,可将product.quantity调整为1(此时material2总需求为2,缺口0.8;material1总需求为2 + 0.8*2=3.6,缺口3.6-1.2=2.4?不对,哦期望中material1缺失3.6,说明是直接按总需求(不扣减库存)统计,若需此逻辑可修改shortage为totalRequired即可)。
内容的提问来源于stack exchange,提问作者FaFa
相关产品推荐
相关产品推荐

