news 2026/9/17 5:40:57

InvenTree TME 条码插件实战指南:自动识别 TME 产品条码的集成方案

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
InvenTree TME 条码插件实战指南:自动识别 TME 产品条码的集成方案

InvenTree TME 条码插件实战指南:自动识别 TME 产品条码的集成方案

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

InvenTree 是一个开源库存管理系统,其内置插件机制允许通过扫描供应商条码自动识别入库物料。本文聚焦其中的TME Barcode Plugin(TME 条码插件),讲解它如何解析 TME 官网(tme.eu)产品包装上的 QR Code 与 DataMatrix 条码、将条码字段映射为 InvenTree 内部数据、并据此匹配供应商零件与采购订单。读完本文,你将掌握该插件的激活配置流程、底层条码解析与匹配原理、以及可验证的测试用例,能够在自己的 InvenTree 实例中复现这套"扫码收货"工作流。

插件功能定位

TME Barcode Plugin 为 TME 产品提供条码支持。当从 TME 收到物料时,扫描产品包装上的条码即可在 InvenTree 中自动识别该产品,无需手动录入零件编号、订单号等信息。

该插件属于 InvenTree 的内置供应商条码插件家族(与 DigiKey、Mouser、LCSC 同类),其设计遵循一个关键约束——Barcode Plugins 索引文档 明确指出:

这些插件只处理条码内的数据本身,不与其供应商网站或 API 进行任何集成。条码数据用于根据插件设置匹配 InvenTree 中已存在的产品。

也就是说,扫描识别是纯离线、纯本地数据匹配的:条码里有什么字段,插件就解析什么字段,再拿着这些字段去数据库里查找对应的SupplierPart(供应商零件)。

从源码看,插件的类定义位于 tme.py,完整声明如下:

class TMEPlugin(SupplierBarcodeMixin, SettingsMixin, InvenTreePlugin): NAME = 'TMEBarcodePlugin' SLUG = 'tmeplugin' TITLE = _('Supplier Integration - TME') DESCRIPTION = _('Provides support for scanning TME barcodes') VERSION = '1.0.1' AUTHOR = _('InvenTree contributors')

它同时继承了三个基类:InvenTreePlugin(插件基础)、SettingsMixin(提供可配置设置项)以及SupplierBarcodeMixin(提供供应商条码解析与匹配的默认实现)。

底层架构:SupplierBarcodeMixin 解析管线

官方文档说明该插件实现了 BarcodeMixin mixin 以提供自定义条码支持。在源码中,SupplierBarcodeMixin定义于 mixins.py,它继承自BarcodeMixin,职责是"为供应商条码的扫描函数提供默认实现",自定义供应商条码插件只需实现extract_barcode_fields一个方法。

SupplierBarcodeMixin定义了一套标准字段名常量,作为各供应商条码字段与 InvenTree 内部数据的统一中间语言:

常量内部字段名含义
CUSTOMER_ORDER_NUMBERcustomer_order_number客户订单号
SUPPLIER_ORDER_NUMBERsupplier_order_number供应商订单号
PACKING_LIST_NUMBERpacking_list_number装箱单号
SHIP_DATEship_date发货日期
CUSTOMER_PART_NUMBERcustomer_part_number客户零件号
SUPPLIER_PART_NUMBERsupplier_part_number供应商零件号(SKU)
PURCHASE_ORDER_LINEpurchase_order_line采购订单行
QUANTITYquantity数量
DATE_CODEdate_code日期代码
LOT_CODElot_code批次代码
COUNTRY_OF_ORIGINcountry_of_origin原产国
MANUFACTURERmanufacturer制造商
MANUFACTURER_PART_NUMBERmanufacturer_part_number制造商零件号(MPN)

整个条码处理管线分为两层:

  1. 解析层extract_barcode_fields(barcode_data)将原始条码字符串解析成上述标准字段字典;
  2. 匹配层get_supplier_part()get_manufacturer_part()等方法基于解析出的字段,结合插件配置的供应商,到数据库中查询唯一的匹配记录。

TME 插件只在解析层做了高度定制(因为它面对的条码格式特殊),匹配层则完全复用 mixin 的通用实现。

激活与供应商关联配置

第一步:激活插件

TME 插件是一个可选(optional)插件,默认未启用,必须先在 InvenTree 管理后台(admin center)中启用。官方文档中的激活说明如下:

This plugin is anoptionalplugin, and must be enabled in the InvenTree admin center.

在测试代码 test_supplier_barcodes.py 中,也体现了这一前提——所有扫描测试的第一步都是通过插件注册表将插件状态置为启用:

registry.set_plugin_state('tmeplugin', True)

其中'tmeplugin'正是TMEPlugin.SLUG。只有启用后,条码扫描接口才会把条码数据路由给该插件处理。

第二步:在插件设置中指定供应商

激活后,用户必须在插件设置里指定该插件关联的供应商(supplier):从设置页的下拉列表中选择对应的供应商条目。

在源码层面,这个设置项由SettingsMixinSETTINGS字典声明:

DEFAULT_SUPPLIER_NAME = 'TME' SETTINGS = { 'SUPPLIER_ID': { 'name': _('Supplier'), 'description': _("The Supplier which acts as 'TME'"), 'model': 'company.company', 'model_filters': {'is_supplier': True}, } }

关于SUPPLIER_ID这个设置项,需要注意三点:

  • model: 'company.company':设置值关联到公司(Company)模型;
  • model_filters: {'is_supplier': True}:下拉列表只展示被标记为"供应商"(is_supplier=True)的公司,避免误选普通客户或制造商;
  • 匹配隔离:插件只会在这个供应商的范围内查找SupplierPart,从而确保不同供应商的同名 SKU 互不干扰。

自动猜测供应商的兜底逻辑

SupplierBarcodeMixin.get_supplier()还实现了自动猜测逻辑(mixins.py):如果SUPPLIER_ID未设置,它会用DEFAULT_SUPPLIER_NAME = 'TME'做名称模糊匹配(name__icontains),且要求is_supplier=True;只有当匹配到的供应商恰好只有一个时,才会自动写入SUPPLIER_ID并返回该供应商,否则返回None。这个兜底逻辑降低了一开始就手动指定供应商的配置负担。

支持的 TME 条码格式与字段映射

TME 插件最核心的技术价值在于extract_barcode_fields(),它同时支持三种条码形态,并按优先级依次判定(tme.py):

def extract_barcode_fields(self, barcode_data: str) -> dict[str, str]: barcode_fields = {} if self.TME_IS_QRCODE_REGEX.fullmatch(barcode_data): # 1) TME 自定义 QR Code 格式 for item in barcode_data.split(' '): if ':' in item: key, value = item.split(':') if key in self.TME_QRCODE_FIELDS: barcode_fields[self.TME_QRCODE_FIELDS[key]] = value elif self.TME_IS_OLD_BARCODE2D_REGEX.fullmatch(barcode_data): # 2) TME 旧版 2D 条码格式 for item in barcode_data.split(' '): for k, v in self.ecia_field_map().items(): if item.startswith(k): barcode_fields[v] = item[len(k):] else: # 3) 标准 ECIA / ISO-IEC 15434 2D 条码 barcode_fields = self.parse_ecia_barcode2d(barcode_data) # 订单号特殊处理 if SupplierBarcodeMixin.SUPPLIER_ORDER_NUMBER in barcode_fields: order_number = barcode_fields[SupplierBarcodeMixin.SUPPLIER_ORDER_NUMBER] order_number = order_number.split('/')[0] barcode_fields[SupplierBarcodeMixin.SUPPLIER_ORDER_NUMBER] = order_number return barcode_fields

格式一:TME 自定义 QR Code

TME 新版产品标签使用自定义 QR Code,典型内容如下(来自测试用例TME_QRCODE):

QTY:1 PN:WBP-302 PO:19361337/1 CPO:PO-2023-06-08-001337 MFR:WISHERENTERPRI SE MPN:WBP-302 RoHS https://www.tme.eu/details/WBP-302

判断依据是正则TME_IS_QRCODE_REGEX([^\s:]+:[^\s:]+\s+)+(\S+(\s|$)+)+)。解析时按空格切分,遇到含:的字段段再做键值拆分,最终通过TME_QRCODE_FIELDS映射为 InvenTree 标准字段:

TME 条码字段映射到的标准字段含义
PNsupplier_part_number供应商零件号(SKU)
CPOcustomer_order_number客户订单号
POsupplier_order_number供应商订单号
MPNmanufacturer_part_number制造商零件号
QTYquantity数量

注意:测试样本中的RoHSMFR、URL 等非映射字段会被安全忽略,不会进入结果字典,也不会导致解析失败。

格式二:TME 旧版 2D 条码

TME 旧款包装使用另一种 2D 条码,典型内容如下(来自测试用例TME_DATAMATRIX_CODE):

PWBP-302 1PMPNWBP-302 Q1 K19361337/1

该格式由正则TME_IS_OLD_BARCODE2D_REGEX(([^\s]+)(\s+|$))+)识别(会匹配几乎所有空格分隔内容,所以它排在 QR Code 判定之后,作为第二优先级)。解析逻辑与 ECIA 格式共用同一张字段映射表(ecia_field_map()):逐项检查每个空格分隔的字段段是否以映射表中的前缀开头,若命中则去掉前缀得到字段值。

对照 ECIA 映射表(完整定义见 mixins.py),上面的样本可拆解为:

  • PWBP-302→ 前缀Psupplier_part_number = WBP-302
  • 1PMPNWBP-302→ 前缀1Pmanufacturer_part_number = MPNWBP-302
  • Q1→ 前缀Qquantity = 1
  • K19361337/1→ 前缀Kcustomer_order_number = 19361337/1

格式三:标准 ECIA / ISO-IEC 15434 2D 条码

若前两种正则都不匹配,插件会回退到行业通用的 ECIA 规范 2D 条码解析(parse_ecia_barcode2d),该规范参考 ECIA 官方文档,同时支持 ISO/IEC 15434 格式。这类条码以固定头[)>\x1e06\x1d开始、以\x1e\x04结尾,字段之间以\x1d分隔。

标准 ECIA 字段前缀映射表(ecia_field_map())如下,这也是 TME 旧版条码解析所复用的同一张表:

条码前缀标准字段
Kcustomer_order_number
1Ksupplier_order_number
11Kpacking_list_number
6Dship_date
9D/10Ddate_code
4K/14Kpurchase_order_line
P/30Psupplier_part_number
1Pmanufacturer_part_number
1Tlot_code
4Lcountry_of_origin
1Vmanufacturer
Qquantity

订单号的归一化处理

无论走哪条解析分支,extract_barcode_fields()最后都会对supplier_order_number(供应商订单号)做一次归一化:取其/之前的部分。例如样本中的PO:19361337/1会被归一化为19361337。这样做的目的是剥离 TME 订单号中形如/1的订单行后缀,使订单号能与 InvenTree 中采购订单的supplier_reference精确对齐。

条码匹配与扫码收货流程

供应商零件匹配(get_supplier_part)

解析出标准字段后,SupplierBarcodeMixin.get_supplier_part()负责完成数据库匹配(mixins.py),其匹配策略为:

  1. 必须至少具备 SKU(supplier_part_number)或 MPN(manufacturer_part_number),否则直接返回None
  2. 若插件配置了供应商,则先按supplier过滤SupplierPart,实现供应商间隔离;
  3. 若有 SKU,则按SKU精确过滤;
  4. 若过滤后仍有多个结果且存在 MPN,则进一步按manufacturer_part__MPN收窄范围;
  5. 要求唯一匹配——只有恰好命中一条SupplierPart时才返回,多匹配或零匹配都返回None

扫码接口与采购收货

SupplierBarcodeMixin将上述能力封装为scan()/scan_receive_item()等默认扫描实现。在 InvenTree 中,前端扫码后请求条码扫描 API(api-barcode-scan),插件注册表会按顺序让已启用的供应商条码插件尝试解析;匹配成功后返回插件名、供应商零件乃至库存项信息。

当条码包含采购订单信息(如 TME 条码中的PO字段)时,还可走api-barcode-po-receive流程直接按采购订单收货入库。测试类SupplierBarcodePOReceiveTests(test_supplier_barcodes.py)覆盖了该流程的关键规则:

  • 采购订单必须已下达(placed),否则拒绝收货并提示 "received against an order marked as...";
  • 同一物料不可重复收货,第二次会返回Item has already been received
  • 库存入库位置按"请求指定位置 → 订单行目标位置 → 零件默认位置"的优先级解析;
  • 条码缺失数量字段时,接口返回action_required并预填剩余待收数量;
  • 用户需具备purchase_order.add角色权限,否则返回 403。

测试验证:插件行为的可靠依据

TME 插件的解析行为有明确的自动化测试保障,位于 test_supplier_barcodes.py:

  • test_tme_qrcode:POSTTME_QRCODE到扫描接口,断言响应中的pluginTMEBarcodePlugin,并匹配到SKU = 'WBP-302'的供应商零件;
  • test_tme_barcode2d:POSTTME_DATAMATRIX_CODE(旧版 2D 条码样本),同样解析成功并匹配WBP-302

测试数据里两种条码格式都能解析出相同的 SKU,这验证了extract_barcode_fields中"QR Code 优先、旧 2D 次之、ECIA 兜底"的多分支设计的正确性。你可以直接复用这两个样本(QTY:1 PN:WBP-302 PO:19361337/1 ...PWBP-302 1PMPNWBP-302 Q1 K19361337/1)在自己的实例上验证插件是否正常工作。

集成前提与限制

  • 前置数据:TME 插件只做条码解析与本地匹配,不会自动创建供应商、供应商零件或采购订单。扫描前必须在 InvenTree 中预先创建好 TME 供应商(供应商文档)、对应的SupplierPart(SKU 需与条码中的PN一致)以及已下达的采购订单。
  • 无网络集成:插件不访问 TME API,条码中的 URL 等字段仅作为文本出现,不会被请求或校验。
  • 启用状态:插件必须先在管理后台启用,并在设置中关联供应商(或满足自动猜测条件),否则扫描不会命中该插件。

小结

TME Barcode Plugin 是 InvenTree"扫码收货"体系中的一块拼图,它用约七十行核心逻辑(tme.py)优雅地兼容了 TME 自定义 QR Code、旧版 2D 条码与行业标准 ECIA 条码三种格式,再借助SupplierBarcodeMixin的通用匹配层完成供应商零件与采购订单的自动关联。理解这套"解析字段 → 标准字段映射 → 数据库唯一匹配"的管线,不仅能帮你正确配置 TME 扫描流程,也能为开发其他供应商条码插件提供直接参考——只需继承SupplierBarcodeMixin并实现自己的extract_barcode_fields即可。

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

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

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

Java集成PaddleOCR表格识别:从图片到HTML与Excel导出

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/17 5:37:56

从内核模块到CAN总线:嵌入式Linux驱动开发主线详解

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/17 5:36:47

PHP开发者职业转型与技术升级指南

1. 现象背后的行业背景分析PHP作为一门已有28年历史的服务器端脚本语言,曾支撑了全球超过70%的网站(根据W3Techs 2022年统计)。在Web 2.0时代,LAMP(LinuxApacheMySQLPHP)技术栈几乎是所有互联网创业公司的标…

作者头像 李华
网站建设 2026/9/17 5:36:23

壁纸电视怎么选:六条硬指标与五款机型避坑指南

壁纸电视这个品类,我从它刚冒头那会儿就在盯着,这几年帮朋友挑过、装过、也踩过雷。它好看是真好看,贴墙上像一幅画,客厅瞬间从"家电卖场"变成"艺术展厅";但坑也是真坑,装完发现墙不平…

作者头像 李华