Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
9 changes: 9 additions & 0 deletions beam/beam/barcodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
72 changes: 68 additions & 4 deletions beam/beam/doctype/beam_settings/beam_settings.js
Original file line number Diff line number Diff line change
@@ -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))
}
}
27 changes: 26 additions & 1 deletion beam/beam/doctype/beam_settings/beam_settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": [
{
Expand Down Expand Up @@ -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": [],
Expand Down
17 changes: 17 additions & 0 deletions beam/beam/doctype/beam_settings/beam_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -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))
9 changes: 0 additions & 9 deletions beam/beam/doctype/beam_settings/test_beam_settings.py

This file was deleted.

Binary file modified beam/docs/assets/beam_settings.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions beam/docs/form.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ For license information, please see license.txt-->
# Form

<div class="byline">
Tyler Matteson 2026-02-21
Tyler Matteson 2026-02-23
</div>


Expand All @@ -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).

4 changes: 2 additions & 2 deletions beam/docs/handling_unit.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ For license information, please see license.txt-->
# Handling Unit

<div class="byline">
Tyler Matteson 2026-02-21
Tyler Matteson 2026-02-23
</div>


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)

Expand Down
6 changes: 3 additions & 3 deletions beam/docs/hooks.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
<!-- Copyright (c) 2025, AgriTheory and contributors
For license information, please see license.txt-->

# Extending Beam With Custom Hooks
# Extending BEAM With Custom Hooks

<div class="byline">
Tyler Matteson 2026-02-21
Tyler Matteson 2026-02-23
</div>


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.

Expand Down
2 changes: 1 addition & 1 deletion beam/docs/hu_traceability_report.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ For license information, please see license.txt-->
# Handling Unit Traceability Report

<div class="byline">
Tyler Matteson 2026-02-21
Tyler Matteson 2026-02-23
</div>


Expand Down
43 changes: 31 additions & 12 deletions beam/docs/index.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
<!-- Copyright (c) 2025, AgriTheory and contributors
For license information, please see license.txt-->

# Beam
# BEAM

<div class="byline">
Tyler Matteson 2026-02-21
Tyler Matteson 2026-02-23
</div>


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.

Expand All @@ -28,30 +27,50 @@ 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.

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)
Expand All @@ -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

Expand Down
4 changes: 2 additions & 2 deletions beam/docs/listview.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ For license information, please see license.txt-->
# Listview

<div class="byline">
Tyler Matteson 2026-02-21
Tyler Matteson 2026-02-23
</div>


Expand All @@ -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)

2 changes: 1 addition & 1 deletion beam/docs/matrix.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ For license information, please see license.txt-->
# Listview Actions

<div class="byline">
Tyler Matteson 2026-02-21
Tyler Matteson 2026-02-23
</div>

| Scanned Doctype | Listview | Action | Target |
Expand Down
2 changes: 1 addition & 1 deletion beam/docs/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ For license information, please see license.txt-->
# Testing

<div class="byline">
Tyler Matteson 2026-02-21
Tyler Matteson 2026-02-23
</div>


Expand Down
8 changes: 4 additions & 4 deletions beam/docs/zebra_printing.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ For license information, please see license.txt-->
# Zebra Printing

<div class="byline">
AgriTheory and Tyler Matteson 2026-02-24
Tyler Matteson 2026-02-24
</div>


Expand All @@ -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:

---

Expand Down
Empty file added beam/patches/.gitkeep
Empty file.
Loading
Loading