InvenTree Stocktake Exporter 插件指南:为零件盘点数据定制导出格式
【免费下载链接】InvenTreeOpen Source Inventory Management System项目地址: https://gitcode.com/GitHub_Trending/in/InvenTree
本文聚焦 InvenTree 内置的Stocktake Exporter(盘点导出器)插件,讲解它如何基于DataExportMixin为零件(Part)数据提供一套专门的"库存盘点"导出格式,覆盖激活方式、导出选项、列结构、底层数据处理逻辑与单元测试验证。读完本文,你将掌握该插件的完整配置与使用方式,并能结合源码理解其导出的数值口径(外部库存、变体库存、零库存过滤与盘点价值计算)。
插件定位:面向"盘点"的定制导出
InvenTree 的通用导出流程由 InvenTree API 提供,默认行为是把接口返回的数据原样序列化为表格文件。而 Stocktake Exporter 插件文档 介绍的PartStocktakeExporter则是对该流程的定制:它只针对Part(零件)数据,导出一份"当前库存水平清单",用于盘点(stocktake)场景——例如定期核对各零件在库数量、计算在库金额。
从源码看,该插件类定义于 stocktake_exporter.py:
class PartStocktakeExporter(DataExportMixin, InvenTreePlugin): NAME = 'Part Stocktake Exporter' SLUG = 'inventree-stocktake-exporter' TITLE = _('Part Stocktake Exporter') DESCRIPTION = _('Exporter for part stocktake data') VERSION = '1.1.1' AUTHOR = _('InvenTree contributors')它与通用导出器 InvenTreeExporter 的显著区别在于:后者supports_export对所有模型返回True(支持全部数据集的通用导出),而盘点导出器只在导出目标为零件数据时可用:
def supports_export(self, model_class, user=None, serializer_class=None, view_class=None, *args, **kwargs) -> bool: """Supported if the base model is Part.""" return model_class == Part and serializer_class == PartSerializer也就是说,只有当导出数据集底层模型为Part且序列化器为PartSerializer时,用户才能在导出对话框中选中该插件(详见 DataExportMixin.supports_export)。
激活方式:可选的插件开关
该插件属于 InvenTree 内置的可选(optional)插件,默认不生效,需要在 InvenTree 管理界面 / 插件设置页面中将其启用,才能出现在导出对话框中。相关文档原文见 stocktake_exporter.md 的 Activation 一节,单元测试 test_exporter.py 中也演示了通过插件注册表启用的方式:
from plugin.registry import registry slug = 'inventree-stocktake-exporter' registry.set_plugin_state(slug, True)插件本身的标识为SLUG = 'inventree-stocktake-exporter',可作为 API 导出的export_plugin参数值直接使用。
说明:该插件没有可配置的设置项(Plugin Settings 为空),所有行为均由导出时刻的选项控制。
导出选项:导出对话框中的可调开关
在零件数据的导出对话框中,选中Part Stocktake Exporter插件后,会出现一组额外的导出选项。选项由插件内的PartStocktakeExportOptionsSerializer(DRF Serializer)定义:
| 选项(字段名) | 默认值 | 说明 |
|---|---|---|
export_pricing_data | True | 是否在导出中包含定价数据,开启后额外增加"在库金额"相关列(Minimum/Maximum 单位成本与总成本) |
export_include_external_items | False | 是否包含外部仓库(external warehouse)的库存,开启后增加External Stock列,并将外部数量计入总库存与估值 |
export_include_variant_items | False | 是否包含变体(variant)零件库存,开启后增加Variant Stock列,并将变体数量计入总库存与估值 |
export_exclude_zero_stock_entries | False | 是否在导出数据中排除零库存零件(False时零库存零件仍会输出,数量记为 0) |
前三个选项与文档中的 Export Options 表格 一一对应,而第四个选项export_exclude_zero_stock_entries是源码中额外提供的过滤能力(文档未列出,但源码实现中存在),在 API 导出时可通过export_exclude_zero_stock_entries=True传入。
这些选项通过ExportOptionsSerializer属性挂接在插件类上,机制见 DataExportMixin 文档 的 "Custom Export Options" 一节:插件定义一个自定义序列化器,即可在导出时刻向用户提供控制开关。
导出列结构:Part 字段的精简子集
盘点导出并不导出PartSerializer的全部字段,而是由 update_headers 挑选一组与库存/订单/成本相关的核心列:
| 分组 | 列 |
|---|---|
| 基础信息 | pk、name、IPN、active、component、assembly、description、category |
| 订单占用 | allocated_to_build_orders、allocated_to_sales_orders、required_for_build_orders、required_for_sales_orders |
| 在库与在途 | ordering(在途采购)、building(在制)、scheduled_to_build(计划投产)、stock_item_count(库存项数)、total_in_stock(总在库) |
| 可选范围 | external_stock(仅开启外部库存时)、variant_stock(仅开启变体库存时) |
| 定价(可选) | pricing_min(Minimum Unit Cost)、pricing_max(Maximum Unit Cost)、pricing_min_total(Minimum Total Cost)、pricing_max_total(Maximum Total Cost) |
其中external_stock与variant_stock两列会根据导出选项动态增删:
if not include_external_items: base_headers.remove('external_stock') if not include_variant_items: base_headers.remove('variant_stock')可见,默认(两个选项均为False)导出的是一份不掺入外部仓库与变体库存的"本库盘点口径"清单。
数据口径:total_in_stock 的归一化与估值计算
导出的数量口径在 export_data 中最终确定,逻辑为:
- 先调用
super().export_data(...)(即 DataExportMixin.export_data,按EXPORT_CHUNK_SIZE = 250行分批序列化)拿到原始行数据; - 读取
total_in_stock,若未开启外部库存则减去external_stock,若未开启变体库存则减去variant_stock; - 计算结果若为负数则钳制为 0(并将整行丢弃当且仅当开启了
export_exclude_zero_stock_entries); - 将修正后的数量写回
total_in_stock; - 若开启了定价数据,则以「单位成本 × 数量」计算
pricing_min_total/pricing_max_total,并通过normalize(..., rounding=10)做金额归一化。
也就是说,Total Stock、Minimum/Maximum Total Cost这几列的含义随选项变化:默认口径只统计本仓库(非外部、非变体)的在库数量与在库金额;开启相关选项后,外部仓库与变体零件的数量/金额才会被计入。
文件名与查询集优化
- 文件名:覆盖了默认的
InvenTree_{model}_{date}.{format}命名,固定为InvenTree_Stocktake_{date}.{format}(日期取自current_date()),便于盘点导出文件按日期归档与识别:def generate_filename(self, model_class, export_format: str) -> str: date = current_date().isoformat() return f'InvenTree_Stocktake_{date}.{export_format}' - 查询集优化:通过 prefetch_queryset 对
stock_items做预取(prefetch_related),减少导出大量零件时对库存子项的 N+1 查询。
单元测试验证
仓库内置了针对该插件的接口级测试 test_exporter.py,可帮助验证上述行为:
- 默认参数导出:必需列含
Name、IPN、Total Stock、Minimum Unit Cost、Maximum Total Cost;排除External Stock与Variant Stock; - 同时开启外部与变体库存:必需列额外包含
On Order、External Stock、Variant Stock; - 关闭定价数据:
Minimum Unit Cost、Maximum Total Cost、Variant Stock、External Stock均不出现。
测试通过registry.set_plugin_state(slug, True)启用插件后,以 CSV 格式调用零件列表接口(api-part-list),并把export_plugin=inventree-stocktake-exporter与各选项作为导出参数传入,最后校验导出文件的列集合。
使用小结
Stocktake Exporter 适合需要周期性导出零件库存快照(含数量与估值)的盘点场景。在界面中,只需在零件数据导出对话框选择Part Stocktake Exporter并按需勾选定价、外部库存、变体库存选项;在 API 侧,则可直接通过零件列表接口搭配export_plugin与上述选项参数实现自动化导出。结合源码可知,其核心价值在于把"通用表格导出"收窄为"盘点口径导出":按选项剔除外部/变体库存、钳制零库存、补充成本估值列,并输出固定命名的归档文件。
【免费下载链接】InvenTreeOpen Source Inventory Management System项目地址: https://gitcode.com/GitHub_Trending/in/InvenTree
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考