news 2026/9/16 12:30:09

InvenTree 生产工单需求数量计算:基础数量、损耗率、准备数量与圆整规则的完整解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
InvenTree 生产工单需求数量计算:基础数量、损耗率、准备数量与圆整规则的完整解析

InvenTree 生产工单需求数量计算:基础数量、损耗率、准备数量与圆整规则的完整解析

【免费下载链接】InvenTreeOpen Source Inventory Management System项目地址: https://gitcode.com/GitHub_Trending/in/InvenTree

在 InvenTree 中创建生产工单(Build Order)时,系统会根据装配件的 BOM(物料清单)自动计算每种组件的“需求数量”(Required Quantity),并据此生成生产明细行(BuildLine)。本篇技术文章以官方文档 Required Build Quantity 为核心,完整讲解需求数量的四级计算公式(基础数量 → 损耗率 → 准备数量 → 圆整倍数),并结合BomItem模型源码、生产工单的信号触发链与单元测试用例,说明这一计算在 InvenTree 中的实际实现方式、触发时机与边界行为。

读完本文,你将掌握:

  • 需求数量计算的完整公式链路,以及每个 BOM 字段的含义、默认值与取值约束;
  • 官方示例(100 件装配、最终需求 325)的逐步推导;
  • 源码层面BomItem.get_required_quantity()的实现细节,以及生产工单创建/变更时如何自动触发重算;
  • 单元测试对该公式的验证方式,便于你在定制或排查数据问题时快速定位。

一、需求数量计算的总体流程

当一张新的生产工单被创建时,InvenTree 会针对该工单所生产装配件的每一条 BOM 行项目,计算生产该批次所需组件的总数量。文档给出的计算按以下四个阶段顺序进行,其中后三个阶段均为可选字段,缺省值为“无影响”(0 或空):

  1. 基础数量(Base Quantity):BOM 行项目的Quantity字段,表示生产一件装配体所需的该组件数量;乘以生产工单的装配数量,得到基础需求。
  2. 损耗率(Attrition):以百分比形式计入生产过程中预期的损耗,在基础需求上按百分比加码。
  3. 准备数量(Setup Quantity):计入生产过程中的固定损耗(如试产、换线消耗),以绝对数量加到需求上。
  4. 圆整倍数(Rounding Multiple):将最终需求量向上圆整到指定倍数的整数倍,满足整包装、标准包装等采购/生产要求。

这一流程在源码中的入口是 BomItem.get_required_quantity 方法,它在单条 BOM 行项目上按文档描述的顺序完成全部四步计算(详见后文源码解析)。

二、四个计算公式详解

2.1 基础数量(Base Quantity)

基础数量由 BOM 行项目的Quantity字段定义,即“生产一件装配体所需的组件件数”。将其乘以正在生产的装配体数量,即得到该组件的总需求量:

Required Quantity = Base Quantity * Number of Assemblies

2.2 损耗率(Attrition)

BOM 行项目的Attrition字段用于计入生产过程中预期的损耗,以Base Quantity的百分比表示(例如 2%)。当指定了非零损耗百分比时,它作用在已算出的Required Quantity之上:

Required Quantity = Required Quantity * (1 + Attrition Percentage)

损耗率是可选字段,未指定时默认为 0%。

2.3 准备数量(Setup Quantity)

Setup Quantity字段用于计入生产过程中的固定损耗——它是为保证整批生产顺利完成而额外需要的组件数量,直接加到已算出的需求数量上:

Required Quantity = Required Quantity + Setup Quantity

准备数量是可选字段,未指定时默认为 0。

注意它与损耗率的语义差异:损耗率是随批量线性放大的比例项,而准备数量是不随批量变化的固定项(例如产线换型试机消耗的部件,生产 1 件和生产 100 件都需要同样的准备量)。

2.4 圆整倍数(Rounding Multiple)

Rounding Multiple字段将计算出的需求数量向上圆整到指定倍数的最近整数倍,用于保证数量为整数或满足特定包装规格:

Required Quantity = ceil(Required Quantity / Rounding Multiple) * Rounding Multiple

圆整倍数是可选字段,未指定时不对计算结果做任何圆整。

2.5 字段定义与取值约束(源码级补充)

文档只说明了字段的语义,而在 InvenTree 的模型定义中(BomItem 字段定义,位于src/backend/InvenTree/part/models.py),这些字段的精确类型与校验规则如下,对配置 BOM 时输入合法值有直接参考价值:

字段模型定义默认值校验规则说明
quantityDecimalField(max_digits=15, decimal_places=5)1.0MinValueValidator(0)基础数量;可带小数(5 位精度)
attritionDecimalField(max_digits=6, decimal_places=3)0MinValueValidator(0)MaxValueValidator(100)损耗百分比,取值范围 0–100
setup_quantityDecimalField(max_digits=15, decimal_places=5)0MinValueValidator(0)固定准备/试产数量
rounding_multipleDecimalField(max_digits=15, decimal_places=5),可空NoneMinValueValidator(0)为空时表示不圆整

两点值得注意:

  • attrition的上限由MaxValueValidator(100)硬性约束,即损耗率不能超过 100%,这在模型层就拒绝了非法配置;
  • 从源码结构看,BOM 行项目还包含一个文档未提及的piece_count(件数)字段,用于“按长度裁切”类物料(如线缆、管材):quantity表示每件的尺寸/长度,piece_count表示每件装配需要的裁切段数,源码中的总需求量公式因此扩展为quantity * piece_count * build_quantity(见 get_required_quantity 的 docstring 与测试 test_piece_count_multiplier)。这是文档公式之上的一个实现细节,默认piece_count=1时行为与文档完全一致。

三、官方示例计算:100 件装配 → 需求 325

文档给出了一个贯穿四步的完整算例。考虑一条 BOM 行项目:

  • 基础数量(Base Quantity):3
  • 损耗率(Attrition):2%(0.02)
  • 准备数量(Setup Quantity):10
  • 圆整倍数(Rounding Multiple):25

当生产工单要生产 100 件装配体时,需求数量按如下顺序推导:

Required Quantity = Base Quantity * Number of Assemblies = 3 * 100 = 300 Attrition Value = Required Quantity * Attrition Percentage = 300 * 0.02 = 6 Required Quantity = Required Quantity + Attrition Value = 300 + 6 = 306 Required Quantity = Required Quantity + Setup Quantity = 306 + 10 = 316 Required Quantity = ceil(Required Quantity / Rounding Multiple) * Rounding Multiple = ceil(316 / 25) * 25 = 13 * 25 = 325

因此该组件的最终需求生产数量为325。该计算在新生产工单创建时由系统自动执行,无需人工干预。

四、源码实现:BomItem.get_required_quantity()的逐步对应

上述公式在 InvenTree 中的权威实现位于 BomItem.get_required_quantity(src/backend/InvenTree/part/models.py)。将源码逻辑与文档公式逐段对照:

def get_required_quantity(self, build_quantity: float) -> float: # 1) 基础需求(quantity 为单件用量,piece_count 为裁切件数) required = self.quantity * self.piece_count * build_quantity # 2) 损耗率:仅当 attrition > 0 时,乘以 (1 + attrition/100) if self.attrition > 0: attrition = Decimal(self.attrition) / Decimal(100) required *= 1 + attrition # 3) 准备数量:仅当 setup_quantity > 0 时直接累加 if self.setup_quantity > 0: required += Decimal(self.setup_quantity) # 4) 圆整:仅当 rounding_multiple 非空且 > 0 时,向上圆整 if self.rounding_multiple and self.rounding_multiple > 0: round_up = Decimal(self.rounding_multiple) value = Decimal(required) value = math.ceil(value / round_up) * round_up required = float(value) return required

实现上有几个细节值得注意:

  • 顺序与文档严格一致:先乘批量、再乘损耗、再加准备量、最后圆整。由于圆整在最后,前一步的浮点结果也会被向上取整,保证最终值严格落在倍数格点上;
  • 全程使用Decimal运算:三个计算分支都包裹在try/except中,异常时调用log_error('bom_item.get_required_quantity')记录而不抛出,保证单个 BOM 数据异常不会阻断整张工单的行项目生成;
  • 可选分支显式判空rounding_multiple and self.rounding_multiple > 0的写法同时处理了“字段为空(None)”和“字段为 0”两种“不圆整”的语义,与文档中“未指定时不做圆整”的描述一致;
  • 裁切件数的扩展:文档公式的第一步在这里体现为quantity * piece_count * build_quantity,默认piece_count=1时退化为文档公式。

4.1 触发时机:生产工单的信号链

文档提到“新生产工单创建时自动计算”。在源码中,这一自动化的实现是一条 Django 信号链(build/models.py 的 after_save_build):

  • 创建工单created=True):Build实例保存后触发after_save_build信号,调用 Build.create_build_line_items。它遍历装配件的所有非虚拟BOM 行(get_bom_items(include_virtual=False)),对每条调用bom_item.get_required_quantity(self.quantity)得到数量,批量创建BuildLine对象(batch_size=250);
  • 修改工单数量created=False):同一信号回调中调用 Build.update_build_line_items,逐行用新的self.quantity重新计算line.quantitybulk_update,保证 BOM 明细行始终与工单数量同步;
  • BOM 变更时反向同步:part/models.py 中的 update_bom_build_lines 信号接收器 在BomItem创建/更新时,通过后台任务 update_build_order_lines 找到所有引用该 BOM 行的活跃生产工单,逐张重算对应BuildLine.quantity,BOM 行指向虚拟件时则会删除该明细行;
  • 库存告警联动:工单创建后还会执行 check_build_stock 任务,比较需求数量与可用库存,库存不足时向订阅用户推送“生产工单需要额外库存”的通知。

4.2 逆向计算:can_build_quantity()unallocated_quantity

需求数量还反向服务于两个生产决策:

  • BomItem.can_build_quantity:给定可用库存,反推该 BOM 行最多能生产多少件装配——先把准备数量从可用库存中扣除,再按quantity * (1 + attrition/100)折算每件装配的消耗量;
  • BuildLine.unallocated_quantity:从需求数量中扣除已消耗(consumed)与已分配(allocated)数量,得出该行还需要分配的库存量,is_fully_allocated/is_overallocated判断均以此为基础(build/models.py)。

因此“需求数量”不仅是报表数字,而是驱动库存分配、消耗校验与告警通知的核心输入。

五、单元测试:公式的正确性验证

InvenTree 在 part/test_bom_item.py 中为四个阶段分别编写了测试,是验证本文公式理解的可靠依据:

  • 损耗率(test_attrition):quantity=300attrition=5%、生产 10 件 →get_required_quantity(10) == 3150(即 3000 + 5%);
  • 准备数量(test_setup_quantity):quantity=3默认setup_quantity=0get_required_quantity(10) == 30;改为setup_quantity=5后 →8(3+5)与35(30+5),确认准备数量不随批量放大;
  • 圆整倍数(test_round_up):quantity=3rounding_multiple=17时,生产 1/2/5/10/100 件分别得到17/17/17/34/306,精确验证了ceil向上圆整语义;测试还进一步创建生产工单(quantity=21)断言BuildLine自动创建且数量为3*21=63 → 68(63 向上圆整到 17 的倍数),印证了第 4.1 节的信号链;
  • 裁切件数(test_piece_count_multiplier):quantity=200mmpiece_count=10、生产 5 件 → 总长 10000mm,验证源码对文档公式的扩展。

六、小结

InvenTree 的“需求生产数量”是一套四级、可选、顺序确定的计算公式:基础数量 × 批量乘以(1 + 损耗率),再加准备数量,最后按圆整倍数向上取整。文档定义的公式与源码实现 BomItem.get_required_quantity 一一对应,并由 part/test_bom_item.py 中的分组测试完整覆盖。生产工单的创建与数量变更通过 Django 信号自动调用 create_build_line_items / update_build_line_items 完成重算,BOM 编辑则由 update_build_order_lines 后台任务反向同步所有活跃工单——整条链路上需求数量始终是自动维护的派生数据。

配置 BOM 时的实践建议:把与批量成比例的正常损耗放进Attrition,把换线/试产等固定消耗放进Setup Quantity,采购有整包要求时设置Rounding Multiple,并注意Attrition的合法范围是 0–100 的百分比值。如需了解 BOM 行的其他属性(可选件、可消耗件、校验和等),可继续阅读 BOM 文档 与 生产示例文档。

【免费下载链接】InvenTreeOpen Source Inventory Management System项目地址: https://gitcode.com/GitHub_Trending/in/InvenTree

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/16 12:29:09

Vane本地AI问答引擎部署与优化指南

1. 项目概述Vane是一款开源的本地AI问答引擎,它允许用户在完全离线的环境下运行一个智能问答系统。不同于依赖云服务的商业AI产品,Vane将全部数据处理和模型推理都保留在本地设备上,特别适合对数据隐私有严格要求的企业或个人用户。我在过去三…

作者头像 李华
网站建设 2026/9/16 12:28:42

RAG私有知识库落地实战:从文档解析到检索增强生成

简介:本资源是一套完整的基于RAG(检索增强生成)架构的私有知识库问答系统Python源码,面向高校学生、毕业设计与课程设计开发者、科研人员及企业技术实践者,解决非结构化文档高效检索与精准问答的技术落地难题。压缩包共…

作者头像 李华
网站建设 2026/9/16 12:28:18

华为硬件工程师能力图谱:单板开发机试背后的SI/PI/DFT逻辑

1. 这不是“刷题包”,而是华为硬件工程师真实能力切片图谱你搜到的这个标题——“(最新)华为 2026 届校招实习-硬件技术工程师-硬件通用/单板开发—机试题—(共14套)(每套四十题)”,表面看是一份题库汇总&a…

作者头像 李华
网站建设 2026/9/16 12:26:56

FPGA图像链路实战:SD卡SPI读取FAT32文件与VGA显示

简介:面向数字逻辑与图像处理方向的开发者,FPGA读取SD卡图片并经VGA显示输出的完整Verilog工程提供了从SPI读取、SDRAM缓存到VGA驱动的全流程参考。工程基于Cyclone IV E系列EP4CE10F17C8,Quartus 18.0环境,顶层模块top_sd_photo_…

作者头像 李华
网站建设 2026/9/16 12:26:51

LeetCode组合问题:回溯算法与剪枝优化实战

1. 问题背景与核心挑战LeetCode 77题"组合"是算法学习中的经典回溯问题,要求从整数1到n中选出k个数的所有可能组合。这个问题看似简单,却蕴含着DFS(深度优先搜索)和回溯算法的精髓,也是理解剪枝优化的绝佳案…

作者头像 李华