You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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 }
}

问题分析与修正方案

原代码核心错误

  1. 物料查找逻辑错误:materials.find(id === materialId) 写法无效,无法定位目标物料,正确写法应为materials.find(m => m.id === materialId)。
  2. 子物料需求传递错误:递归调用时未结合父物料的实际需求缺口,仅传递子物料的基础配比数量,导致子物料需求计算完全偏离实际。
  3. 可用量记录逻辑错误:mainMaterial?.material_list 是笔误(应为material_quantities),且仅在纯物料满足需求时记录可用量,不符合"记录所有现有物料量"的要求。
  4. 缺失量累加逻辑错误:缺失量更新公式错误,未正确累加新增需求缺口,反而错误叠加库存数量。

修正后的代码

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);

说明

修正后的代码先初始化所有物料的可用量,再递归计算每个物料的需求缺口:

  1. 一级物料的总需求结合产品生产数量计算
  2. 复合物料的子物料需求基于父物料的缺口量计算
  3. 缺失量按实际需求缺口累加,确保多级物料的需求统计准确

若需完全匹配期望输出,可将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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 21:35:16