From 57a6a9cae46ed14d2e609cf3c58aa832b1012bbe Mon Sep 17 00:00:00 2001 From: Tyler Matteson Date: Wed, 25 Feb 2026 20:39:53 -0500 Subject: [PATCH] feat: add barcode generation settings, update docs --- .pre-commit-config.yaml | 10 ++- beam/beam/barcodes.py | 9 +++ .../doctype/beam_settings/beam_settings.js | 72 ++++++++++++++++- .../doctype/beam_settings/beam_settings.json | 27 ++++++- .../doctype/beam_settings/beam_settings.py | 17 ++++ .../beam_settings/test_beam_settings.py | 9 --- beam/docs/assets/beam_settings.png | Bin 63198 -> 32664 bytes beam/docs/form.md | 4 +- beam/docs/handling_unit.md | 4 +- beam/docs/hooks.md | 6 +- beam/docs/hu_traceability_report.md | 2 +- beam/docs/index.md | 43 +++++++--- beam/docs/listview.md | 4 +- beam/docs/matrix.md | 2 +- beam/docs/print_server.md | 2 +- beam/docs/testing.md | 2 +- beam/docs/zebra_printing.md | 8 +- beam/patches/.gitkeep | 0 beam/tests/test_barcode_auto_generate.py | 74 ++++++++++++++++++ 19 files changed, 251 insertions(+), 44 deletions(-) delete mode 100644 beam/beam/doctype/beam_settings/test_beam_settings.py create mode 100644 beam/patches/.gitkeep create mode 100644 beam/tests/test_barcode_auto_generate.py diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f2151178..68f83376 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -27,6 +27,14 @@ repos: additional_dependencies: - tomli + - repo: local + hooks: + - id: no-titled-beam + name: "Use 'BEAM' not 'Beam'" + language: pygrep + entry: '\bBeam\b' + files: '\.md$' + - repo: https://github.com/asottile/pyupgrade rev: v3.19.1 hooks: @@ -45,7 +53,7 @@ repos: additional_dependencies: ['flake8-bugbear'] - repo: https://github.com/agritheory/test_utils - rev: v1.19.0 + rev: v1.20.0 hooks: - id: update_pre_commit_config - id: validate_frappe_project diff --git a/beam/beam/barcodes.py b/beam/beam/barcodes.py index e37ef30e..fc64b68f 100644 --- a/beam/beam/barcodes.py +++ b/beam/beam/barcodes.py @@ -28,6 +28,15 @@ def create_beam_barcode(doc, method=None): ): # TODO: refactor this to be configurable to "Products" or "sold" items that do not require handling units return + company = get_default_company() + if frappe.db.exists("BEAM Settings", {"company": company}): + settings = frappe.get_cached_doc("BEAM Settings", {"company": company}) + try: + allowed = frappe.parse_json(settings.auto_barcode_doctypes or '["Item", "Warehouse"]') + except Exception: + allowed = ["Item", "Warehouse"] + if doc.doctype not in allowed: + return if any([b for b in doc.barcodes if b.barcode_type == "Code128"]): return # move all other rows back diff --git a/beam/beam/doctype/beam_settings/beam_settings.js b/beam/beam/doctype/beam_settings/beam_settings.js index c653f4d6..281c3bf2 100644 --- a/beam/beam/doctype/beam_settings/beam_settings.js +++ b/beam/beam/doctype/beam_settings/beam_settings.js @@ -1,8 +1,72 @@ // Copyright (c) 2024, AgriTheory and contributors // For license information, please see license.txt -// frappe.ui.form.on("BEAM Settings", { -// refresh(frm) { +frappe.dom.set_style(` + .barcode-auto-generate-editor input[type="checkbox"]:not(:checked) + .label-area { + text-decoration: line-through; + color: var(--text-muted); + } +`) -// }, -// }); +frappe.ui.form.on('BEAM Settings', { + refresh(frm) { + const wrapper = $(frm.fields_dict.barcode_exclusions_html.wrapper) + wrapper.empty() + wrapper.addClass('barcode-auto-generate-editor').css({ + border: '1px solid var(--border-color)', + borderRadius: 'var(--border-radius)', + padding: 'var(--padding-md)', + }) + frm.barcode_exclusions_editor = new BEAMBarcodeAutoGenerateEditor(wrapper, frm) + }, +}) + +class BEAMBarcodeAutoGenerateEditor { + constructor(wrapper, frm) { + this.wrapper = wrapper + this.frm = frm + this.setup() + } + + get allowed() { + try { + return JSON.parse(this.frm.doc.auto_barcode_doctypes || '["Item", "Warehouse"]') + } catch { + return ['Item', 'Warehouse'] + } + } + + setup() { + this.multicheck = frappe.ui.form.make_control({ + parent: this.wrapper, + df: { + fieldname: 'auto_barcode_doctypes', + fieldtype: 'MultiCheck', + select_all: true, + columns: '15rem', + get_data: () => { + return frappe + .xcall('beam.beam.doctype.beam_settings.beam_settings.get_doctypes_with_item_barcodes') + .then(doctypes => { + const allowed = this.allowed + return doctypes.map(dt => ({ + label: __(dt), + value: dt, + checked: allowed.includes(dt), + })) + }) + }, + on_change: () => { + this.sync_json() + this.frm.dirty() + }, + }, + render_input: true, + }) + } + + sync_json() { + const checked = this.multicheck.get_checked_options() + frappe.model.set_value(this.frm.doctype, this.frm.docname, 'auto_barcode_doctypes', JSON.stringify(checked)) + } +} diff --git a/beam/beam/doctype/beam_settings/beam_settings.json b/beam/beam/doctype/beam_settings/beam_settings.json index b59c1ef0..f084e658 100644 --- a/beam/beam/doctype/beam_settings/beam_settings.json +++ b/beam/beam/doctype/beam_settings/beam_settings.json @@ -12,7 +12,11 @@ "column_break_vhpb", "qr_scale", "qr_border", - "qr_error_correct" + "qr_error_correct", + "barcode_generation_section", + "barcode_exclusions_html", + "column_break_barcode", + "auto_barcode_doctypes" ], "fields": [ { @@ -65,6 +69,27 @@ "label": "Company", "options": "Company", "unique": 1 + }, + { + "fieldname": "barcode_generation_section", + "fieldtype": "Section Break", + "label": "Barcode Generation" + }, + { + "fieldname": "barcode_exclusions_html", + "fieldtype": "HTML", + "label": "Disable Auto-Generation For" + }, + { + "fieldname": "column_break_barcode", + "fieldtype": "Column Break" + }, + { + "default": "[\"Item\", \"Warehouse\"]", + "fieldname": "auto_barcode_doctypes", + "fieldtype": "JSON", + "hidden": 1, + "label": "Auto Barcode Doctypes" } ], "links": [], diff --git a/beam/beam/doctype/beam_settings/beam_settings.py b/beam/beam/doctype/beam_settings/beam_settings.py index 23de90d8..15094670 100644 --- a/beam/beam/doctype/beam_settings/beam_settings.py +++ b/beam/beam/doctype/beam_settings/beam_settings.py @@ -15,3 +15,20 @@ def create_beam_settings(company: str) -> str: beams.company = company beams.save() return beams + + +@frappe.whitelist() +def get_doctypes_with_item_barcodes() -> list[str]: + """Return all doctypes that have a Table field with options 'Item Barcode'.""" + existing_doctypes = set(frappe.get_all("DocType", pluck="name")) + standard = frappe.get_all( + "DocField", + filters={"fieldtype": "Table", "options": "Item Barcode"}, + pluck="parent", + ) + custom = frappe.get_all( + "Custom Field", + filters={"fieldtype": "Table", "options": "Item Barcode"}, + pluck="dt", + ) + return sorted(existing_doctypes.intersection(standard + custom)) diff --git a/beam/beam/doctype/beam_settings/test_beam_settings.py b/beam/beam/doctype/beam_settings/test_beam_settings.py deleted file mode 100644 index 61700c28..00000000 --- a/beam/beam/doctype/beam_settings/test_beam_settings.py +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2024, AgriTheory and Contributors -# See license.txt - -# import frappe -from frappe.tests.utils import FrappeTestCase - - -class TestBEAMSettings(FrappeTestCase): - pass diff --git a/beam/docs/assets/beam_settings.png b/beam/docs/assets/beam_settings.png index 1ea936a3e86dda6fdb0c7ae5676ba9aa27de4963..f0716ed93a82daf2857c5bddcc6ec4b2d85ce460 100644 GIT binary patch literal 32664 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

N4nNc6n#9rZdrFUTpAiSQ0^w->VLC(_s{ovFHWw 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 UM89esxB&ik?=s(+W8`q=KYMsM-v9sr literal 63198 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 diff --git a/beam/docs/form.md b/beam/docs/form.md index 3c49d2ad..bb19afd0 100644 --- a/beam/docs/form.md +++ b/beam/docs/form.md @@ -4,7 +4,7 @@ For license information, please see license.txt--> # Form

@@ -19,7 +19,7 @@ For example, when an Item is scanned while viewing a Delivery Note record, it wi |-----------------|-----------------------|--------|--------| |Item|Delivery Note|add_or_increment|item_code| -Beam uses a [decision matrix](./matrix.md) to decide what action to take based on what kind of doctype has been scanned. +BEAM uses a [decision matrix](./matrix.md) to decide what action to take based on what kind of doctype has been scanned. Custom actions and client side functions can be added by using [hooks](./hooks.md). diff --git a/beam/docs/handling_unit.md b/beam/docs/handling_unit.md index ab498d12..8b062505 100644 --- a/beam/docs/handling_unit.md +++ b/beam/docs/handling_unit.md @@ -4,13 +4,13 @@ For license information, please see license.txt--> # Handling Unit A Handling Unit is an abstraction for tracking quantities of items that are moved or stored together. It does not replace Batch or Serial numbers, the manufacture of an Item, or the functionality of the Product Bundle, but can supplement these as a way of conveniently grabbing information that would otherwise require a lot of keystrokes to enter. -By assigning a unique ID to the Handling Unit, it is possible to capture via scanner the item, net quantity, unit of measure and timestamp of the previous transaction, and then act upon that information in context, according to the [decision matrix](./matrix.md). Beam adds a new doctype, Handling Unit, to implement this functionality in ERPNext. +By assigning a unique ID to the Handling Unit, it is possible to capture via scanner the item, net quantity, unit of measure and timestamp of the previous transaction, and then act upon that information in context, according to the [decision matrix](./matrix.md). BEAM adds a new doctype, Handling Unit, to implement this functionality in ERPNext. ![Screen shot of the Handling Unit doctype listview. The list shows several new Handling Units that were created for items received via a Purchase Receipt.](./assets/handling_unit_list.png) diff --git a/beam/docs/hooks.md b/beam/docs/hooks.md index 537253b1..f3f4adb4 100644 --- a/beam/docs/hooks.md +++ b/beam/docs/hooks.md @@ -1,14 +1,14 @@ -# Extending Beam With Custom Hooks +# Extending BEAM With Custom Hooks -Beam can be extended by adding configurations to your application's `hooks.py`. +BEAM can be extended by adding configurations to your application's `hooks.py`. To make scanning available on a custom doctype, add a table field for "Item Barcode" directly in the doctype or via customize form. Then add a key that is a peer with "Item" in the example below. diff --git a/beam/docs/hu_traceability_report.md b/beam/docs/hu_traceability_report.md index 9a55467d..4e47c0f0 100644 --- a/beam/docs/hu_traceability_report.md +++ b/beam/docs/hu_traceability_report.md @@ -4,7 +4,7 @@ For license information, please see license.txt--> # Handling Unit Traceability Report diff --git a/beam/docs/index.md b/beam/docs/index.md index 5577d66a..6e5ff86c 100644 --- a/beam/docs/index.md +++ b/beam/docs/index.md @@ -1,18 +1,17 @@ -# Beam +# BEAM - -Beam is a general purpose 2D barcode scanning application for ERPNext. +BEAM is a general purpose barcode scanning application for ERPNext. ## What does this application do? -Beam allows a user to scan a 2D barcode from either a listview or a form view, then helps enter data that would otherwise require numerous keystrokes. Unlike ERPNext's built-in barcode scanning, Beam expects the user to have a hardware barcode scanner connected to their device. +BEAM allows a user to scan a 2D or QR barcode from either a listview or a form view, then helps enter data that would otherwise require numerous keystrokes. Unlike ERPNext's built-in barcode scanning, BEAM expects the user to have a hardware barcode scanner connected to their device. For example, if the user scans a barcode associated with an Item in the Item listview, it will take them to that item's record. @@ -28,22 +27,42 @@ If the user scans an Item in a Delivery Note, it will populate everything it kno Read more about [how scanning in form views works](./form.md). -## Beam Settings +## BEAM Settings -Beam's version 15 introduced a new Beam Settings document to allow users to opt in or out of features in the app. Settings are unique on a per-company basis and are automatically generated (with default options) during certain related transactions if a Beam Settings document doesn't already exist for the company. Related transactions include submission of a Purchase Receipt, Purchase Invoice, or Stock Entry. +Version 15 introduced a new BEAM Settings document to allow users to opt in or out of features in the app. Settings are unique on a per-company basis and are automatically generated (with default options) during certain related transactions if a BEAM Settings document doesn't already exist for the company. Related transactions include submission of a Purchase Receipt, Purchase Invoice, or Stock Entry. -![Screen shot of the Beam Settings document with a field for company and a check box to enable handling units.](./assets/beam_settings.png) +![Screen shot of the BEAM Settings document showing all configuration options including barcode font size, QR code settings, and the Barcode Generation section.](./assets/beam_setings.png) Settings options include: -- **Company:** the company in ERPNext to apply the given settings to. One Beam Settings document may exist for each company in the system +- **Company:** the company in ERPNext to apply the given settings to. One BEAM Settings document may exist for each company in the system - **Enable Handling Units:** (default checked) enables the generation of Handling Units (see What is a Handling Unit section for more information) +- **Enable Scanning of Serial Numbers:** (default unchecked) when enabled, BEAM will resolve scanned barcodes against Serial Number records in addition to Item barcodes +- **Barcode Font Size:** (default 12) controls the font size of the human-readable text rendered beneath Code128 barcode images in print formats + +### QR Code Settings + +- **QR Scale:** (default 8) the module size in pixels used when generating QR code images — larger values produce a bigger image +- **QR Border:** (default 4) the quiet zone border size in modules surrounding the QR code +- **QR Error Correct:** (default M) the error correction level encoded into QR codes; options are L (7%), M (15%), Q (25%), and H (30%) — higher levels allow the code to remain scannable even if partially damaged, at the cost of a denser image + +### Barcode Generation + +The Barcode Generation section controls which document types receive an automatically generated Code128 barcode when saved. Any document type that has a Barcodes table (using the Item Barcode child doctype) is listed here. Checked items have auto-generation **enabled**; unchecked items are shown with a strikethrough and will not have barcodes generated on save. +By default, **Item** and **Warehouse** are enabled. If a Code128 barcode already exists on a document, a new one will never be generated regardless of this setting. If you customize another doctype by adding a Item Barcode table, automatic generation can be configured here but still requires a `doc_event` hook to trigger, which can be configured in your app's `hooks.py` or in a Server Script. +```python +"Asset": { + "validate": [ + "beam.beam.barcodes.create_beam_barcode", + ] +}, +``` ## What is a Handling Unit? A Handling Unit is the combination of a container, any packaging material, and the items within or on it. This could be a pallet of raw materials used in a manufacturing process, a crate containing several other Handling Units, or a delivery vehicle transporting the crates and pallets. -Handling Units have unique, scannable identification numbers that are used in any stock transaction involving the items contained within the unit. The ID allows the user to reference everything about the stock transaction, saved from previous transactions. It also enables you to track the Handling Unit throughout its life cycle. The Beam application includes a [Handling Unit Traceability report](./hu_traceability_report.md) to summarize the transactions, related documents, quantities, and warehouses that involved a given Handling Unit. +Handling Units have unique, scannable identification numbers that are used in any stock transaction involving the items contained within the unit. The ID allows the user to reference everything about the stock transaction, saved from previous transactions. It also enables you to track the Handling Unit throughout its life cycle. The BEAM application includes a [Handling Unit Traceability report](./hu_traceability_report.md) to summarize the transactions, related documents, quantities, and warehouses that involved a given Handling Unit. A Handling Unit is generated when materials are received or created in the manufacturing process. @@ -51,7 +70,7 @@ Read more [about Handling Units here](./handling_unit.md). ## Installation and Customization -Beam comes packed with features, but can be extended with custom hooks both on the server side and in the client as needed. See the following pages for detailed instructions on installing and customizing the application: +BEAM comes packed with features, but can be extended with custom hooks both on the server side and in the client as needed. See the following pages for detailed instructions on installing and customizing the application: - [Installation](https://github.com/agritheory/beam) - [Customization](./hooks.md) @@ -64,7 +83,7 @@ Warehouses may also have unique barcodes associated with them. The user can navi ## Print Server Integration -Beam offers the ability to print to raw input printers like Zebra printers directly from the browser. Also included are several debugging and example print formats. For more details about configuring this, see the [print server section](./print_server.md). +BEAM offers the ability to print to raw input printers like Zebra printers directly from the browser. Also included are several debugging and example print formats. For more details about configuring this, see the [print server section](./print_server.md). ### Zebra Printing diff --git a/beam/docs/listview.md b/beam/docs/listview.md index 7cbb0f1b..8b913928 100644 --- a/beam/docs/listview.md +++ b/beam/docs/listview.md @@ -4,7 +4,7 @@ For license information, please see license.txt--> # Listview @@ -27,7 +27,7 @@ Another example: If an Item is scanned while viewing the Purchase Receipt list, |Item|Purchase Receipt|filter|item_code| -Beam uses a [decision matrix](./matrix.md) to decide what action to take based on what kind of doctype has been scanned. +BEAM uses a [decision matrix](./matrix.md) to decide what action to take based on what kind of doctype has been scanned. Custom actions and client side functions can be added by using [hooks](./hooks.md) diff --git a/beam/docs/matrix.md b/beam/docs/matrix.md index d29daf52..d8558a12 100644 --- a/beam/docs/matrix.md +++ b/beam/docs/matrix.md @@ -4,7 +4,7 @@ For license information, please see license.txt--> # Listview Actions | Scanned Doctype | Listview | Action | Target | diff --git a/beam/docs/print_server.md b/beam/docs/print_server.md index c603be88..0a71a168 100644 --- a/beam/docs/print_server.md +++ b/beam/docs/print_server.md @@ -4,7 +4,7 @@ For license information, please see license.txt--> # Print Server diff --git a/beam/docs/testing.md b/beam/docs/testing.md index 7d9aff4f..e26c2d05 100644 --- a/beam/docs/testing.md +++ b/beam/docs/testing.md @@ -4,7 +4,7 @@ For license information, please see license.txt--> # Testing diff --git a/beam/docs/zebra_printing.md b/beam/docs/zebra_printing.md index 69559ec8..b8543ae0 100644 --- a/beam/docs/zebra_printing.md +++ b/beam/docs/zebra_printing.md @@ -4,7 +4,7 @@ For license information, please see license.txt--> # Zebra Printing @@ -14,16 +14,16 @@ To create a Zebra print format, you need the following documents: ### ZPL Code Generation -Currently, only three types of printable ZPL data can be generated with utilities within Beam: +Currently, only three types of printable ZPL data can be generated with utilities within BEAM: - `Text` - `Barcode` - `Label` -Beam uses the [py-zebra-zpl](https://github.com/mtking2/py-zebra-zpl) library to generate the above types, as it provides a basic interface to create ZPL code using Python objects. Please refer to the library's documentation for more information on how to use it. +BEAM uses the [py-zebra-zpl](https://github.com/mtking2/py-zebra-zpl) library to generate the above types, as it provides a basic interface to create ZPL code using Python objects. Please refer to the library's documentation for more information on how to use it. **Note:** Additional ZPL elements (like graphic fields) and commands (text mirroring, character encoding, etc.) can be developed separately and added as text directly to the ZPL Print Format. For more information, visit the [official documentation page](https://supportcommunity.zebra.com/s/article/ZPL-Command-Information-and-DetailsV2?language=en_US) or the [Labelary ZPL Programming Guide](https://labelary.com/zpl.html). -In addition, Beam exposes the following Jinja functions to be used within a Print Format: +In addition, BEAM exposes the following Jinja functions to be used within a Print Format: --- diff --git a/beam/patches/.gitkeep b/beam/patches/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/beam/tests/test_barcode_auto_generate.py b/beam/tests/test_barcode_auto_generate.py new file mode 100644 index 00000000..1115a780 --- /dev/null +++ b/beam/tests/test_barcode_auto_generate.py @@ -0,0 +1,74 @@ +# Copyright (c) 2025, AgriTheory and contributors +# For license information, please see license.txt + +import frappe +import pytest + +from beam.beam.barcodes import create_beam_barcode +from beam.beam.doctype.beam_settings.beam_settings import get_doctypes_with_item_barcodes + + +def test_get_doctypes_with_item_barcodes(): + doctypes = get_doctypes_with_item_barcodes() + assert isinstance(doctypes, list) + assert "Item" in doctypes + assert "Warehouse" in doctypes + # all returned values must be real doctypes + for dt in doctypes: + assert frappe.db.exists("DocType", dt), f"Stale DocField reference: '{dt}' does not exist" + + +def _make_item(item_code): + if frappe.db.exists("Item", item_code): + item = frappe.get_doc("Item", item_code) + item.barcodes = [] + return item + item = frappe.new_doc("Item") + item.item_code = item_code + item.item_name = item_code + item.item_group = "All Item Groups" + item.stock_uom = "Nos" + item.is_stock_item = 1 + return item + + +@pytest.fixture() +def beam_settings(): + company = frappe.defaults.get_defaults().get("company") + settings = frappe.get_doc("BEAM Settings", {"company": company}) + original = settings.auto_barcode_doctypes + yield settings + settings.auto_barcode_doctypes = original + settings.save() + + +def test_barcode_generated_when_doctype_allowed(beam_settings): + beam_settings.auto_barcode_doctypes = '["Item", "Warehouse"]' + beam_settings.save() + + item = _make_item("_Test Barcode Allow Item") + create_beam_barcode(item) + + assert any(b.barcode_type == "Code128" for b in item.barcodes) + + +def test_barcode_not_generated_when_doctype_not_allowed(beam_settings): + beam_settings.auto_barcode_doctypes = '["Warehouse"]' + beam_settings.save() + + item = _make_item("_Test Barcode Disallow Item") + create_beam_barcode(item) + + assert not any(b.barcode_type == "Code128" for b in item.barcodes) + + +def test_barcode_not_duplicated_when_code128_exists(beam_settings): + beam_settings.auto_barcode_doctypes = '["Item", "Warehouse"]' + beam_settings.save() + + item = _make_item("_Test Barcode Dedup Item") + item.append("barcodes", {"barcode": "12345678901234567890", "barcode_type": "Code128"}) + create_beam_barcode(item) + + code128_barcodes = [b for b in item.barcodes if b.barcode_type == "Code128"] + assert len(code128_barcodes) == 1