[{"data":1,"prerenderedAt":581},["ShallowReactive",2],{"idea-page-erpnext-for-diversified-businesses":3,"search":11},{"_path":4,"name":5,"title":6,"subject":7,"author":8,"scheduled_on":9,"published_on":9,"content":10,"body":10},"\u002Fideas\u002Ferpnext-for-diversified-businesses","erpnext-for-diversified-businesses","ERPNext for diversified businesses","In this webinar, Tyler Matteson takes us through his journey with ERPNext and shares his reasons as to why ERPNext is valuable to vertically integrated businesses in the context of a case study. \n","Tyler Matteson","2022-05-27","\u003Ciframe width=\"560\" height=\"315\" src=\"https:\u002F\u002Fwww.youtube.com\u002Fembed\u002FflxhC2I3A-w?si=f_0k3sQZTdHRQ8f_\" title=\"YouTube video player\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen>\u003C\u002Fiframe>\n",[12,17,21,25,29,33,37,41,45,48,52,56,60,64,68,71,75,79,83,87,91,95,98,102,106,109,113,117,121,125,129,133,137,141,145,149,153,157,160,164,168,172,176,180,184,188,191,194,198,202,206,209,212,215,219,222,226,230,234,238,241,245,249,253,256,259,262,265,269,272,276,280,284,288,291,295,299,303,307,311,315,319,323,327,331,335,339,343,347,351,354,358,362,366,370,373,377,381,385,389,393,397,401,405,409,413,416,420,424,428,432,436,440,444,448,452,456,460,464,468,472,476,480,484,488,492,496,500,504,508,512,516,520,524,528,532,536,540,544,548,552,556,560,564,568,572,576,580],{"id":13,"title":14,"content":15,"level":16},"\u002Fdocumentation\u002Fapprovals\u002Fconfiguration\u002F","configuration","\u003C!-- Copyright (c) 2026, AgriTheory and contributors For license information, please see license.txt--> # Configuration \u003Cdiv class=\"byline\"> Rohan Bansal, Cursor, fproldan, Ishwarya, Myuddin Khatri, Heather Kusmierz, and Tyler Matteson 2026-10-04 \u003C\u002Fdiv> Organizations often want certain documents reviewed before they post. Purchase Orders over a certain amount might need a manager's sign-off. Invoices that hit capital equipment accounts might need review from the accounting team. In Approvals, each of these requirements is a Document Approval Rule. ## Creating an Approval Rule Navigate to Document Approval Rule and create a new record. A rule answers two questions: 1. Which documents need approval? Select the DocType, for example Purchase Order or Purchase Invoice. 2. Who should approve them? Choose **Approver Type**: - **Role** — someone with a given role, for example Accounts Manager or Purchase Manager. - **User** — specific people resolved from the document through an **Approvers** expression (see [Approving by a person on the document](#approving-by-a-person-on-the-document)). Check Enabled and save. Every document of that type now requires the configured approval. ## Narrowing Down with Conditions Not every Purchase Order needs a manager's approval. Perhaps only the expensive ones do. A condition makes a rule selective. A condition is a short Python expression that the app evaluates against the document. When the expression is true, the rule applies. When it is false, the rule does not apply. A rule with no condition applies to every document of its DocType. Require approval for orders over $10,000: ```python doc.grand_total > 10000 ``` Require approval when any item posts to specific expense accounts: ```python any(i.expense_account in (\"Capital Equipment - CFC\", \"Office Supplies - CFC\") for i in doc.items) ``` Require approval for a specific supplier: ```python doc.supplier == \"SUPPLIER-001\" ``` Combine checks with `and` and `or`: ```python doc.grand_total > ",1,{"id":18,"title":19,"content":20,"level":16},"\u002Fdocumentation\u002Fapprovals\u002Fextending\u002F","extending","\u003C!-- Copyright (c) 2026, AgriTheory and contributors For license information, please see license.txt--> # Extending Approvals \u003Cdiv class=\"byline\"> Tyler Matteson 2026-10-04 \u003C\u002Fdiv> This page is for developers building a Frappe app alongside Approvals. Each extension point is a hook registered in the other app's `hooks.py`. None of them require changes to Approvals itself. ## Adding Names to Conditions Rule conditions and Reapproval Conditions run in Frappe's safe evaluation environment, with `doc` and `settings` added (see [What a Condition Can Use](\u002Fdocumentation\u002Fapprovals\u002Fconfiguration#what-a-condition-can-use)). To add more names, register a function under `approval_condition_context`. The function takes no arguments and returns a dict of names to add. ```python # my_app\u002Fhooks.py approval_condition_context = [\"my_app.approvals.condition_context\"] # my_app\u002Fapprovals.py def condition_context(): return {\"is_capital_account\": is_capital_account} ``` An administrator can then use the new name in a rule condition: ```python any(is_capital_account(i.expense_account) for i in doc.items) ``` ## Supplying Approvers from Your Own Data When the approver can be expressed from `doc` and `settings`, prefer a **User** Document Approval Rule with an **Approvers** expression (see [Configuration](\u002Fdocumentation\u002Fapprovals\u002Fconfiguration#approving-by-a-person-on-the-document)). No hook is required. Use an approver provider when the logic is too complex for a rule expression, when it lives in another app module, or when you need to share the same resolver across DocTypes programmatically. A provider returns those people and the app keeps them in sync as User Approval rows on the document. Register providers under `approvals_approver_providers`, keyed by DocType. Use `\"*\"` for every DocType. ```python # my_app\u002Fhooks.py approvals_approver_providers = { \"Purchase Order\": [\"my_app.approvals.project_manager_provider\"], } # my_app\u002Fapprovals.py import frappe def project_manager_provider(doc): ",{"id":22,"title":23,"content":24,"level":16},"\u002Fdocumentation\u002Fapprovals\u002F","index","\u003C!-- Copyright (c) 2026, AgriTheory and contributors For license information, please see license.txt--> # Approvals \u003Cdiv class=\"byline\"> Rohan Bansal, Cursor, fproldan, Ishwarya, Myuddin Khatri, Heather Kusmierz, and Tyler Matteson 2026-10-04 \u003C\u002Fdiv> Approvals adds conditional sign-off to business documents in ERPNext. An administrator decides which documents need approval and who should give it. For example, a company might require a manager's approval on every Purchase Invoice over $1,000, or a sales manager's approval whenever a customer's credit limit changes. When a document matches, the app assigns the right people, collects their approvals, and then submits the document or moves it to its approved workflow state. The app works with submittable documents such as Purchase Order and Purchase Invoice, with or without a Workflow. It also works with documents that are never submitted, such as Customer, when paired with a Workflow. ## Design Philosophy Approval rules route documents to roles, not to people. People change positions, leave the organization, and take time off. Roles persist. When the organization changes, the approval rules keep working. People still matter when a specific document needs a specific person. Approvers can bring an extra person into a single document, or hand an assignment to a colleague while they are away, without changing the rules for every other document. ## Documentation ### [Usage](\u002Fdocumentation\u002Fapprovals\u002Fusage) Approvers work from the Pending Approvals drawer in the desk navbar. It lists everything waiting on the current user and shows every required approval on the open document. This page covers reviewing, approving, and rejecting documents. It also covers adding an extra approver to a document, reassigning an approval to a colleague, and removing an approver who is no longer needed. ### [Configuration](\u002Fdocumentation\u002Fapprovals\u002Fconfiguration) Administrators create Document Approval Rules that decide which documents need approval",{"id":26,"title":27,"content":28,"level":16},"\u002Fdocumentation\u002Fapprovals\u002Fusage\u002F","usage","\u003C!-- Copyright (c) 2026, AgriTheory and contributors For license information, please see license.txt--> # Usage \u003Cdiv class=\"byline\"> Rohan Bansal, Cursor, fproldan, Ishwarya, Myuddin Khatri, Heather Kusmierz, and Tyler Matteson 2026-10-22 \u003C\u002Fdiv> Approval work happens in one place: the Pending Approvals drawer. The drawer lists every document waiting on the current user. When a document is open, the drawer also shows every approval that document requires, who each one is assigned to, and what the current user can do about it. ## Finding Approval Work When a user saves a document that matches a Document Approval Rule, the app assigns the approval to someone with the rule's role. That person learns about it in several ways: * A ToDo appears in their ToDo list * A notification appears in the desk notification menu * The Pending Approvals icon in the desk navbar shows a count of open approvals * If the site sends reminder emails, a daily email lists everything waiting Each notification and reminder email links directly to the document with the drawer already open and the matching item highlighted. The extra link parameters are removed from the address bar once the drawer opens, so a bookmark or a page refresh does not reopen it. ## The Pending Approvals Drawer Click the Pending Approvals icon in the navbar to open the drawer, or press Ctrl+Shift+X (⌘+Shift+X on macOS) from anywhere in the desk except a text field. The same shortcut closes it. The drawer pushes the page to the left instead of covering it, so the form and its buttons stay visible beside the drawer. The drawer stays open while a user works in the form or in a dialog. It closes from its close button, the navbar icon, or the shortcut. The drawer has up to two sections. | Section | When it appears | What it shows | | :--------------------------------------------------------- | :----------------------------------------------------------------------------- | :-----------------------------------------------------",{"id":30,"title":31,"content":32,"level":16},"\u002Fdocumentation\u002Fautoreader\u002Farchitecture\u002F","architecture","\u003C!-- Copyright (c) 2026, AgriTheory and contributors For license information, please see license.txt--> # AutoReader Architecture \u003Cdiv class=\"byline\"> Tyler Matteson 2026-07-28 \u003C\u002Fdiv> AutoReader watches incoming email on configured Email Accounts (and SMS on a configured Twilio number), identifies the sending party, matches referenced documents (Purchase Orders, Sales Orders, Blanket Orders, Requests for Quotation), and creates or links downstream documents (Purchase Invoices, Sales Invoices, Supplier Quotations, Expense Claims). Everything it does is recorded on the Communication as comments from a bot identity so users can audit each decision. \u003Cdiv class=\"mermaid-chart-container\"> \u003Cdiv class=\"mermaid-svg-version\">\u003Csvg id=\"mermaid-svg-0\" width=\"100%\" xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" xmlns:xlink=\"http:\u002F\u002Fwww.w3.org\u002F1999\u002Fxlink\" class=\"flowchart\" style=\"max-width: 604.00390625px;\" viewBox=\"0 0 604.00390625 1022.921875\" role=\"graphics-document document\" aria-roledescription=\"flowchart-v2\">\u003Cstyle>#mermaid-svg-0{font-family:inherit;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-0 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-0 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-0 .error-icon{fill:#552222;}#mermaid-svg-0 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-0 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-0 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-0 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-0 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-0 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-0 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-0 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-0 .marker.cross{stroke:#33333",{"id":34,"title":35,"content":36,"level":16},"\u002Fdocumentation\u002Fautoreader\u002Fdeduplication\u002F","deduplication","\u003C!-- Copyright (c) 2026, AgriTheory and contributors For license information, please see license.txt--> # Deduplication \u003Cdiv class=\"byline\"> IshwaryaM1030 and Tyler Matteson 2026-07-15 \u003C\u002Fdiv> AutoReader includes a feature to help find and prevent duplicate documents by checking if the values in user-specified fields meet a matching threshold. The feature uses the [RapidFuzz Python package](https:\u002F\u002Frapidfuzz.github.io\u002FRapidFuzz\u002Findex.html) to determine how closely fields match. It's a fuzzy string matching package that offers various methods to quantify how similar two strings are to each other. Not all ERPNext field types are appropriate to match on, and this feature excludes them. Also, some non-string field types (e.g. numeric or date fields) may need some pre-match processing done for better results. Refer to the Field Type Considerations section below for full details. There are two documents to configure the deduplication feature. Deduplication Settings is where overall behavior and the settings for RapidFuzz are specified, and the Deduplication Document is where to select the fields and other parameters to match in a doctype. Settings are created on a per-company basis whereas Deduplication Documents are set for Company-DocType combinations. Refer to the [Matching Configuration for AutoReader and Deduplication Settings section](\u002Fdocumentation\u002Fautoreader\u002Findex) for details around setting the RapidFuzz options for deduplication. If a Deduplication Document exists for a given doctype and it's enabled, the feature checks the specified fields for a duplicate on save and submit (if applicable) of a new document. ## Deduplication Document ![Screen shot of the options available in the Deduplication Document for the company Chelsea Fruit Co and the Project DocType.](\u002Fdocumentation\u002Fautoreader\u002Fassets\u002Fdeduplication_document.png) A Deduplication Document sets the matching criteria for a company-doctype combination. - **Enabled:** (default checked) if this document's criter",{"id":38,"title":39,"content":40,"level":16},"\u002Fdocumentation\u002Fautoreader\u002Fdefault_workflows\u002F","default_workflows","\u003C!-- Copyright (c) 2026, AgriTheory and contributors For license information, please see license.txt--> # Default Workflows \u003Cdiv class=\"byline\"> IshwaryaM1030 and Tyler Matteson 2026-07-27 \u003C\u002Fdiv> Configure one AutoReader per Email Account (and optionally an SMS number). Each mapping row is a workflow. See the [user guide](\u002Fdocumentation\u002Fautoreader\u002Findex) for matching options, item extraction, and Auto Repeat. ## Supplier invoice from a Purchase Order Map From Purchase Order → Map To Purchase Invoice, Party Supplier. Enable Item Extraction when line items should be copied onto the Purchase Invoice. If the named Purchase Order is already fully invoiced, fallback uses another open Purchase Order for that supplier, then a Blanket Order in the same mapping group. ## Recurring vendor bill (known total) Prefer ERPNext Auto Repeat on Purchase Invoice. AutoReader will not create a second invoice when Submit on Creation is set. See [Integration of AutoReader with Auto Repeat](\u002Fdocumentation\u002Fautoreader\u002Findex). ## Recurring vendor bill (unknown total) Blanket Order → Purchase Invoice, or Auto Repeat with Submit on Creation off so a person can edit the draft. ## Customer invoice from a Sales Order Sales Order → Sales Invoice. The same blocking and fallback rules as Purchase Order → Purchase Invoice apply. Blanket Order → Sales Invoice remains available when no open Sales Order matches. ## RFQ reply Request for Quotation → Supplier Quotation. ## Employee receipt (email) Map From Communication → Map To Expense Claim, Party Employee. OCR pulls date and amount from image attachments. **Default Expense Claim Type** is used when no lines extract; that path assigns the Communication for review. ## Employee receipt (SMS) Set SMS Phone Number on the AutoReader. Point Twilio at `autoreader.overrides.sms.handle_incoming_sms`. Use the same Expense Claim mapping; the employee is resolved from phone. ## Unmatched or unknown sender Open ToDos: relink the Contact, or manually match a source doc",{"id":42,"title":43,"content":44,"level":16},"\u002Fdocumentation\u002Fautoreader\u002Finbox\u002F","inbox","\u003C!-- Copyright (c) 2026, AgriTheory and contributors For license information, please see license.txt--> # Inbox \u003Cdiv class=\"byline\"> Tyler Matteson 2026-08-13 \u003C\u002Fdiv> The desk page **Inbox** is AutoReader's mail UI. Users with the **Inbox User** or **System Manager** role can open it. The Vue app lives in `inbox\u002F` and is mounted from `autoreader\u002Fautoreader\u002Fpage\u002Finbox\u002Finbox.js`. See [Work queue](\u002Fdocumentation\u002Fautoreader\u002Fwork_queue) for the exception flyin, and [Architecture](\u002Fdocumentation\u002Fautoreader\u002Farchitecture) for how incoming mail is processed. ## Layout Three resizable panes: folder\u002Faccount sidebar, message list, and detail (or composer). - **Accounts:** Email Accounts available to the user, plus All Accounts when more than one exists - **Folders:** Inbox (open received mail), Sent, Spam, Trash - **Filters:** All, Unread, Assigned to me, Has attachment. **Unassigned** appears when at least one account is a shared inbox - **Search:** filters the loaded list by subject, sender, and snippet - **View:** card or compact list (stored in `localStorage`) - **Compose \u002F Reply \u002F Forward:** `EmailComposer`; sending refreshes the list Selecting a message marks it read via `autoreader.autoreader.api.mark_communications_seen`, which updates `_seen` even when the Communication has no IMAP uid. ## Shared inboxes On Email Account, check **Is Shared Inbox**. Shared accounts default the list filter to Unassigned. The detail header exposes Assign, Assign to me, and Clear assignment. Grant **Inbox User** (or System Manager) to people who should open the Inbox page. ## AutoReader actions Open ToDos on the Communication become buttons on the detail header. Classification matches the exception flyin: - Relink - Match Document - Review Address - Review - Reprocess Build with `yarn build:inbox` or the full `yarn build`. `yarn dev:inbox` watches. ",{"id":46,"title":23,"content":47,"level":16},"\u002Fdocumentation\u002Fautoreader\u002F","\u003C!-- Copyright (c) 2026, AgriTheory and contributors For license information, please see license.txt--> # AutoReader \u003Cdiv class=\"byline\"> IshwaryaM1030 and Tyler Matteson 2026-07-28 \u003C\u002Fdiv> The AutoReader application is an inbox automation utility for Frappe and ERPNext. It helps reduce the amount of time spent monitoring an inbox by automatically converting emails and SMS receipts into drafts and flagging documents that are not able to be reconcilied. The ability to match documents with an actionable score enables an additional feature to prevent duplicate documents in ERPNext or to see a report summarizing duplicates found for a given document type based on user-established parameters. See [Deduplication](\u002Fdocumentation\u002Fautoreader\u002Fdeduplication) for configuration details, [Inbox](\u002Fdocumentation\u002Fautoreader\u002Finbox) for the desk mail UI, [Default workflows](\u002Fdocumentation\u002Fautoreader\u002Fdefault_workflows) for mapping recipes, or [Architecture](\u002Fdocumentation\u002Fautoreader\u002Farchitecture) for how the email pipeline and deduplication hook fit together in code. ## AutoReader Mapping Configuration The AutoReader document sets the behavior for inbox automation. One AutoReader document may be created for each email address in ERPNext. When that address receives an email (or an SMS at the configured phone number), it triggers the app to \"read\" the contents and any PDF, image, or Office attachments and search for a known party and any references to an existing document. The Enabled checkbox is selected by default, and activates this feature for the given email address. Details explaining the other matching options (Include Draft and Canceled Documents in Matches, Preprocess Email Text, Email Scorer, and Match Score Cutoff) can be found below in the Matching Configuration for AutoReader and Deduplication Settings section. The mapping table in AutoReader tells the feature what type of document reference to search for and what type of document to map it to. Mappings may be made for the fo",{"id":49,"title":50,"content":51,"level":16},"\u002Fdocumentation\u002Fautoreader\u002Fwork_queue\u002F","work_queue","\u003C!-- Copyright (c) 2026, AgriTheory and contributors For license information, please see license.txt--> # Work queue and exceptions \u003Cdiv class=\"byline\"> IshwaryaM1030 and Tyler Matteson 2026-07-27 \u003C\u002Fdiv> Incoming email and SMS are enqueued on the dedicated Redis queue **autoreader** (registered in `install.py`, 1500 second timeout, sized for OCR). `frappe.flags.in_test` and `sync_auto_read_email` \u002F `sync_auto_read_sms` run the job inline instead of enqueueing. Failed or incomplete reads create open ToDos with a fixed instruction string. `exception_actions.classify_instruction` maps those strings to actions: | Instruction | Action | |-------------|--------| | Link the sender to a Contact and Supplier, then reprocess the email. | relink | | No matching source document for this email. | manual_match | | Verify the extracted address on the Communication and fix the linked document. | address_review | | Review invoice processed by AutoReader | review_document | The flyin slot `autoreader-exceptions` (`ExceptionQueue.vue`) lists those ToDos. The badge count comes from `get_exception_count`. The [Inbox](\u002Fdocumentation\u002Fautoreader\u002Finbox) detail pane exposes the same actions for the open email. `work_queue\u002F` is a Stonecrop ToDo table bundled as `work_queue.js` (desk include). The flyin and Inbox are the primary exception UIs. See [Architecture](\u002Fdocumentation\u002Fautoreader\u002Farchitecture) for the APIs behind each action. ",{"id":53,"title":54,"content":55,"level":16},"\u002Fdocumentation\u002Fbeam\u002Fform\u002F","form","\u003C!-- Copyright (c) 2025, AgriTheory and contributors For license information, please see license.txt--> # Form \u003Cdiv class=\"byline\"> Tyler Matteson 2026-02-23 \u003C\u002Fdiv> The result of scanning a barcode in the form depends on several factors: - Is the barcode recognized? - What doctype is it associated with? For example, when an Item is scanned while viewing a Delivery Note record, it will add a row for that item if one doesn't exist, or increment the highest-indexed existing row with that Item's item_code in it. | Scanned Doctype | Form | Action | Target | |-----------------|-----------------------|--------|--------| |Item|Delivery Note|add_or_increment|item_code| BEAM uses a [decision matrix](\u002Fdocumentation\u002Fbeam\u002Fmatrix) 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](\u002Fdocumentation\u002Fbeam\u002Fhooks). ",{"id":57,"title":58,"content":59,"level":16},"\u002Fdocumentation\u002Fbeam\u002Fhandling_unit\u002F","handling_unit","\u003C!-- Copyright (c) 2025, AgriTheory and contributors For license information, please see license.txt--> # Handling Unit \u003Cdiv class=\"byline\"> Tyler Matteson 2026-02-23 \u003C\u002Fdiv> 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](\u002Fdocumentation\u002Fbeam\u002Fmatrix). 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.](\u002Fdocumentation\u002Fbeam\u002Fassets\u002Fhandling_unit_list.png) ## Listviews Generally scanning a Handling Unit in a list view will filter to show all the transactions of the doctype with the appropriate Handling Unit. ## Purchase Receipt For Purchase Receipts, Handling Units are generated and cannot be supplied by the user. | Item | Warehouse | Handling Unit | Quantity | | ---------------- | ------------------ | -------------- | --------------:| | Cocoplum | Storeroom | 123 | 40 Ea | ## Purchase Invoice For Purchase Invoices with \"Update Stock\" checked, Handling Units are generated and cannot be supplied by the user. | Item | Warehouse | Handling Unit | Quantity | | ---------------- | ------------------ | -------------- | --------------:| | Cocoplum | Storeroom | 123 | 40 Ea | When \"Update Stock\" is _not_ checked, they can be scanned to facilitate data entry but there's no effect in the Stock Ledger. ## Delivery Note For Delivery Note, Handling Units are ",{"id":61,"title":62,"content":63,"level":16},"\u002Fdocumentation\u002Fbeam\u002Fhooks\u002F","hooks","\u003C!-- Copyright (c) 2025, AgriTheory and contributors For license information, please see license.txt--> # Extending BEAM With Custom Hooks \u003Cdiv class=\"byline\"> Tyler Matteson 2026-02-23 \u003C\u002Fdiv> 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. To extend scanning functionality within a doctype, add a key that is a peer with \"Delivery Note\" in the example below. ```python # hooks.py beam_listview = { \"Item\": { \"Delivery Note\": [ {\"action\": \"filter\", \"doctype\": \"Delivery Note Item\", \"field\": \"item_code\"}, {\"action\": \"filter\", \"doctype\": \"Packed Item\", \"field\": \"item_code\"} ], } } beam_frm = { \"Item\": { \"Delivery Note\": [ { \"action\": \"add_or_increment\", \"doctype\": \"Delivery Note Item\", \"field\": \"item_code\", \"target\": \"target.item_code\", }, { \"action\": \"add_or_increment\", \"doctype\": \"Delivery Note Item\", \"field\": \"uom\", \"target\": \"target.uom\", }, ] } } ``` To add a custom JavaScript function, add the following hook to your application's `hooks.py`. An example implementation is available in the source code. ```python # hooks.py beam_client = { \"show_message\": \"custom_app.show_message\" } ```",{"id":65,"title":66,"content":67,"level":16},"\u002Fdocumentation\u002Fbeam\u002Fhu_traceability_report\u002F","hu_traceability_report","\u003C!-- Copyright (c) 2025, AgriTheory and contributors For license information, please see license.txt--> # Handling Unit Traceability Report \u003Cdiv class=\"byline\"> Tyler Matteson 2026-02-23 \u003C\u002Fdiv> The Handling Unit Traceability report provides a simple interface to track a Handling Unit over its life cycle through your company's processes. Filters for the Handling Unit ID, Delivery Note name, and Sales Invoice name allow for fine-tuning of the report's results. ![Screen shot of the Handling Unit Traceability report's filter fields, including Handling Unit, Delivery Note, and Sales Invoice](\u002Fdocumentation\u002Fbeam\u002Fassets\u002Fhu_trace_filters.png) The following example shows the report output for a Handling Unit associated with finished Kaduka Key Lime Pies. There are three work orders to create the pie - the one shown at the top of the report is for assembling and baking the pie itself, the other two partially or not shown are for making the pie crust or the pie filling. The report shows the Voucher Type and Number, Item Code, Quantity, Warehouse, and Handling Unit (all grouped by Work Order) for all transactions that impact the Stock Ledger that included the given Handling Unit. ![Screen shot of the Traceability Report output for a Handling Unit for Kaduka Key Lime Pies. There is a box highlighting the rows showing the incoming Stock Entry of pies into the Baked Goods warehouse and the outgoing Delivery Note of pies from the warehouse](\u002Fdocumentation\u002Fbeam\u002Fassets\u002Fhu_trace_report_output.png) ",{"id":69,"title":23,"content":70,"level":16},"\u002Fdocumentation\u002Fbeam\u002F","\u003C!-- Copyright (c) 2025, AgriTheory and contributors For license information, please see license.txt--> # BEAM \u003Cdiv class=\"byline\"> Tyler Matteson 2026-02-23 \u003C\u002Fdiv> BEAM is a general purpose barcode scanning application for ERPNext. ## What does this application do? 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. The following screen shot shows the outcome of simulating a scan from the browser's console using a barcode associated with the Stores warehouse. The browser automatically navigates to that warehouse page. ![Screen shot of the Stores warehouse page with the browser's console showing code for a simulation scan of a barcode associated with the warehouse.](\u002Fdocumentation\u002Fbeam\u002Fassets\u002Flistview_wh_navigation.png) Read more about [how scanning in listviews works](\u002Fdocumentation\u002Fbeam\u002Flistview). If the user scans an Item in a Delivery Note, it will populate everything it knows about that item, just as it would if they were to type in the item code. If they scan that item again, it will increment the last row with that item in it. The following screen shot shows a row for the Cloudberry item added in a new Delivery Note after simulating a scan from the browser's console of that item's Handling Unit barcode. ![Screen shot of a new Delivery Note with a row for Cloudberry automatically added and populated after simulating a scan of its barcode from the browser's console.](\u002Fdocumentation\u002Fbeam\u002Fassets\u002Fform_view_delivery_note.png) Read more about [how scanning in form views works](\u002Fdocumentation\u002Fbeam\u002Fform). ## BEAM Settings Version 15 introduced a new BEAM Settings document to allow users to opt in or out of feature",{"id":72,"title":73,"content":74,"level":16},"\u002Fdocumentation\u002Fbeam\u002Flistview\u002F","listview","\u003C!-- Copyright (c) 2025, AgriTheory and contributors For license information, please see license.txt--> # Listview \u003Cdiv class=\"byline\"> Tyler Matteson 2026-02-23 \u003C\u002Fdiv> The result of scanning a barcode in the listview depends on several factors: - Is the barcode recognized? - What doctype is it associated with? For example, when an Item is scanned while viewing the Item list, the user is routed to the record for that Item: | Scanned Doctype | Listview | Action | Target | |-----------------|-----------------------|--------|--------| |Item|Item|route|Item| Another example: If an Item is scanned while viewing the Purchase Receipt list, a filter is added that shows the Delivery Notes with those items: | Scanned Doctype | Listview | Action | Target | |-----------------|-----------------------|--------|--------| |Item|Purchase Receipt|filter|item_code| BEAM uses a [decision matrix](\u002Fdocumentation\u002Fbeam\u002Fmatrix) 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](\u002Fdocumentation\u002Fbeam\u002Fhooks) ",{"id":76,"title":77,"content":78,"level":16},"\u002Fdocumentation\u002Fbeam\u002Fmatrix\u002F","matrix","\u003C!-- Copyright (c) 2025, AgriTheory and contributors For license information, please see license.txt--> # Listview Actions \u003Cdiv class=\"byline\"> Tyler Matteson 2026-02-23 \u003C\u002Fdiv> | Scanned Doctype | Listview | Action | Target | |-----------------|-----------------------|--------|--------| |Handling Unit|Delivery Note|route|Delivery Note| |Handling Unit|Item|route|Item| |Handling Unit|Packing Slip|route|Packing Slip| |Handling Unit|Purchase Invoice|route|Purchase Invoice| |Handling Unit|Purchase Receipt|route|Purchase Receipt| |Handling Unit|Putaway Rule|filter|item_code| |Handling Unit|Quality Inspection|filter|handling_unit| |Handling Unit|Sales Invoice|route|Sales Invoice| |Handling Unit|Stock Entry|route|Stock Entry| |Handling Unit|Stock Reconciliation|route|Stock Reconciliation| |Item|Delivery Note|filter|item_code| |Item|Item|route|Item| |Item|Item Price|filter|item_code| |Item|Packing Slip|filter|item_code| |Item|Purchase Invoice|filter|item_code| |Item|Purchase Receipt|filter|item_code| |Item|Putaway Rule|filter|item_code| |Item|Quality Inspection|filter|item_code| |Item|Sales Invoice|filter|item_code| |Item|Stock Entry|filter|item_code| |Item|Stock Reconciliation|filter|item_code| |Item|Warranty Claim|filter|item_code| |Warehouse|Delivery Note|filter|warehouse| |Warehouse|Item|filter|default_warehouse| |Warehouse|Packing Slip|filter|warehouse| |Warehouse|Purchase Invoice|filter|warehouse| |Warehouse|Purchase Receipt|filter|warehouse| |Warehouse|Sales Invoice|filter|warehouse| |Warehouse|Stock Entry|filter|warehouse| |Warehouse|Stock Reconciliation|filter|warehouse| |Warehouse|Warehouse|route|Warehouse| --- # Form Actions | Scanned Doctype | Form | Action | Target | |-----------------|-----------------------|--------|--------| |Handling Unit|Delivery Note|add_or_associate|handling_unit| |Handling Unit|Delivery Note|add_or_associate|rate| |Handling Unit|Item Price|set_item_code_and_handling_unit|item_code| |Handling Unit|Packing Slip|add_or_associate|conversion_",{"id":80,"title":81,"content":82,"level":16},"\u002Fdocumentation\u002Fbeam\u002Fprint_server\u002F","print_server","\u003C!-- Copyright (c) 2025, AgriTheory and contributors For license information, please see license.txt--> # Print Server \u003Cdiv class=\"byline\"> Rohan Bansal, Heather Kusmierz, and Tyler Matteson 2026-06-25 \u003C\u002Fdiv> There are several steps to get a print server connected in ERPNext. 1. First, the `pycups` dependency needs to be installed on the system, which in turn depends on the CUPS project's `libcups` library. See the following links for installation instructions: - [OpenPrinting CUPS installation and configuration instructions](https:\u002F\u002Fgithub.com\u002FOpenPrinting\u002Fcups\u002Fblob\u002Fmaster\u002FINSTALL.md) - [PyCUPS dependencies, compiling, and installation information](https:\u002F\u002Fgithub.com\u002FOpenPrinting\u002Fpycups) 2. Add the bench user to the `lpadmin` group when administering a local CUPS server: `sudo usermod -aG lpadmin {username}`. Use **Server IP** `localhost` (not `127.0.0.1`) so BEAM uses the CUPS Unix socket and admin operations work without HTTP authentication errors. 3. Add a network printer using the **Network Printer Settings** wizard (**New** opens a guided setup). The **Stock Manager** at **Ambrosia Pie Company** can register a ZD621 on the Chelsea receiving dock when **Chelsea Fruit Co** deliveries arrive — without opening the CUPS web UI. **Administrator** can repeat the wizard during go-live or link a queue that already exists on CUPS (for example `vRAW`). 4. The wizard walks through print server connection, discovery, queue details, and driver selection. Discovery shows network printers and existing CUPS queues, sorted with unconfigured entries first. Use **Test Connection** on the discovery and details steps to ping the host and verify the device URI before creating the queue. USB printers are not supported. ![Screen shot of the Network Printer Settings document fields, including Name, Printer Name, Server IP, and Port.](\u002Fdocumentation\u002Fbeam\u002Fassets\u002Fnetwork_printer_settings.png) The friendly **Network Printer Settings** name (for example **Chelsea Receiving Labels**) is sepa",{"id":84,"title":85,"content":86,"level":16},"\u002Fdocumentation\u002Fbeam\u002Ftesting\u002F","testing","\u003C!-- Copyright (c) 2025, AgriTheory and contributors For license information, please see license.txt--> # Testing \u003Cdiv class=\"byline\"> Tyler Matteson 2026-02-23 \u003C\u002Fdiv> ## Simulating a Scanner Open the browser console. This assumes a barcode of `'9968934975826708157'` which must be sent as a string. ```js window.scanHandler.scanner.simulate(document, '9968934975826708157') ``` ![Screen shot of a new Sales Invoice document. The browser console shows the scanner simulation code with the demo site's Handling Unit for Cloudberries. Running the code added a new row in the Items table for the fruit.](\u002Fdocumentation\u002Fbeam\u002Fassets\u002Ftesting.png) ## About the Test Suite Coming soon ",{"id":88,"title":89,"content":90,"level":16},"\u002Fdocumentation\u002Fbeam\u002Fzebra_printing\u002F","zebra_printing","\u003C!-- Copyright (c) 2025, AgriTheory and contributors For license information, please see license.txt--> # Zebra Printing \u003Cdiv class=\"byline\"> Tyler Matteson 2026-02-24 \u003C\u002Fdiv> To create a Zebra print format, you need the following documents: - A ZPL Print Format made against Doctype that may contain barcodes (Item, Warehouse, Handling Units, etc.) that uses the available Jinja utility functions to generate ZPL code. - A document Print Format that uses the free Labelary API to convert the above ZPL code and generate a preview of the print output for the linked document. ### ZPL Code Generation 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:\u002F\u002Fgithub.com\u002Fmtking2\u002Fpy-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:\u002F\u002Fsupportcommunity.zebra.com\u002Fs\u002Farticle\u002FZPL-Command-Information-and-DetailsV2?language=en_US) or the [Labelary ZPL Programming Guide](https:\u002F\u002Flabelary.com\u002Fzpl.html). In addition, BEAM exposes the following Jinja functions to be used within a Print Format: --- #### `barcode128` Generate a [Code 128](https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FCode_128) barcode image. It takes the following arguments: - `barcode_text`: The text to be encoded in the barcode. Required. ##### Example ```jinja {{ barcode128(doc.barcodes[0].barcode) }} ``` --- #### `formatted_zpl_barcode` Generate a formatted ZPL barcode. It takes the following arguments: - `barcode_text`: The text to be encoded in the barcode. Required. ##### Example ```jinja {{ formatted_zpl_barcode(doc.barcode",{"id":92,"title":93,"content":94,"level":16},"\u002Fdocumentation\u002Fcheck_run\u002Fachgeneration\u002F","achgeneration","\u003C!-- Copyright (c) 2026, AgriTheory and contributors For license information, please see license.txt--> # ACH Generation \u003Cdiv class=\"byline\"> Tyler Matteson 2026-02-21 \u003C\u002Fdiv> For electronic bank transfers, banking institutions require specifically-formatted plain-text files to encode all necessary information. This includes data about the type of payment, the parties, their bank accounts, and payment amounts. These files conform to Automated Clearing House (ACH) standards, which is an electronic-funds transfer system run by the National Automated Clearing House Association (NACHA). ACH files are intended to represent electronic inter-bank transactions. A Check Run will automatically generate this on demand, but only if the run includes payments using an \"Electronic\" Mode of Payment. See the [configuration page](\u002Fdocumentation\u002Fcheck_run\u002Fconfiguration) for details on how to set the `Mode of Payment` `type` field to mark it as an electronic bank transfer. The system defaults to using the \"ach\" file extension, but you can change this as needed in [Check Run Settings](\u002Fdocumentation\u002Fcheck_run\u002Fsettings). The settings page also includes options to set two other mandatory fields in an ACH file: 1. **ACH Service Class Code** indicates the types of transactions in the batch. Code 200 is for both debit and credit transactions, code 220 is for only credit transactions, and code 225 is for only debit transactions 2. **ACH Standard Class Code** indicates how the transaction was authorized. Currently, the Check Run application only supports Prearranged Payment and Deposit Entries (code PPD) Other fields available to help configure your ACH generation include: - ACH Description, which goes into the Batch header - Company Discretionary Data, also in the Batch header - Immediate Origin, which can override the ABA number that the bank is expecting - Custom Post Processing Hook, which allows you to provide a custom function to further manipulate the ACH file. For example, Royal Bank of",{"id":96,"title":14,"content":97,"level":16},"\u002Fdocumentation\u002Fcheck_run\u002Fconfiguration\u002F","\u003C!-- Copyright (c) 2025, AgriTheory and contributors For license information, please see license.txt--> # Configuration \u003Cdiv class=\"byline\"> Tyler Matteson 2026-02-21 \u003C\u002Fdiv> ## Banks and Bank Accounts The Check Run feature requires at least one `Bank` and `Bank Account` defined for the Company. These can be set up under `Accounting > Bank` and `Accounting > Bank Account`, respectively. For parties receiving payment via an electronic bank transfer, their `Bank` and `Bank Account` must be in the system as well. See the sections below for configuration details for Suppliers and Employees. ## Mode of Payment The Check Run application adds a new `type` field into the `Mode of Payment` doctype. The field helps the application properly process different types of payment methods. For any existing or new `Mode of Payment` document, you can specify one of the following `type` options in the table below. The \"Bank\" and \"Electronic\" options are special, and will change the behavior of a Check Run. Usage suggestions are included with each option. | Type | Suggested Usage | |---|---| | Bank | Payments requiring a physical check | | Cash | Cash payments | | Electronic | ACH electronic fund transfers, direct deposit | | General | Bank drafts, wire transfers, credit cards | | Phone | Phone payments | Only Modes of Payment marked as \"Electronic\" will be included in ACH file generation. This should be reserved for methods like \"ACH\u002FEFT\" or \"Employee Direct Deposit\". ACH files are intended to represent electronic inter-bank transactions. \u003Cmarkdown-tip class=\"warning\" label=\"Warning\"> Only Modes of Payment marked as \"Bank\" will be included in the Check Print and Reprint features. Bank Drafts and Wire Transfers should not be configured as \"Bank\" but \"General\" instead.\u003Cbr>\u003Cbr> Only Modes of Payment marked as \"Electronic\" will be included in an ACH file. Credit Cards should not be configured as \"Electronic\" but should use \"General\" instead. \u003C\u002Fmarkdown-tip> ## Default Mode of Payment The op",{"id":99,"title":100,"content":101,"level":16},"\u002Fdocumentation\u002Fcheck_run\u002Fexampledata\u002F","exampledata","\u003C!-- Copyright (c) 2026, AgriTheory and contributors For license information, please see license.txt--> # Using the Example Data to Experiment with Check Run \u003Cdiv class=\"byline\"> Tyler Matteson 2026-02-21 \u003C\u002Fdiv> The Check Run application comes with a `test_setup.py` script that is completely optional to use. If you execute the script, it populates your ERPNext site with demo business data for a fictitious company called Chelsea Fruit Co. The data enable you to experiment with and test the Check Run application's functionality before installing the app into your ERPNext site. It's recommended to install the demo data into its own site to avoid potential interference with the configuration or data in your organization's ERPNext site. With `bench start` running in the background, run the following command to install the demo data: ```shell bench execute 'check_run.test_setup.before_test' # to reinstall from scratch and setup test data bench reinstall --yes --admin-password admin --mariadb-root-password admin && bench execute 'check_run.tests.setup.before_test' ``` Refer to the [installation guide](\u002Fdocumentation\u002Fcheck_run\u002Finstallationguide) for detailed instructions for how to set up a bench, a new site, and installing ERPNext and the Check Run application. ",{"id":103,"title":104,"content":105,"level":16},"\u002Fdocumentation\u002Fcheck_run\u002Fexampleprint\u002F","exampleprint","\u003C!-- Copyright (c) 2026, AgriTheory and contributors For license information, please see license.txt--> # Example Print Format: Voucher Check \u003Cdiv class=\"byline\"> Tyler Matteson 2026-02-21 \u003C\u002Fdiv> To take advantage of Check Run's check printing functionality, you'll need to set up a print format in ERPNext. Print formats are as unique as the organizations using ERPNext, so a voucher check print format serves as an example template. It can be a starting point from which to customize to suit your needs. The example print format included with this application can be found in the Print Format List under Example Voucher. It is disabled by default. ## Using MICR Encoding Font The Check Run app also includes an example print format for a check template that applies the [MICR Encoding font](https:\u002F\u002Fwww.1001fonts.com\u002Fmicr-encoding-font.html) to the routing number, account number, and check number part of the layout. The format is called Example Voucher MICR and is disabled by default. In order for the preview of any print format that's using the MICR Encoding font to render the font correctly, the font must be installed on the machine serving your site. This will be the server for a production environment or your local machine for a development environment. Below are the steps to make the MICR Encoding font available for Check Run print formats and during the conversion to print to a PDF: - Download and install the [MICR Encoding font](https:\u002F\u002Fwww.1001fonts.com\u002Fmicr-encoding-font.html) onto either your server (production environment) or your local machine (development environment). Refer to your Operating System's guide for how to install fonts, as the instructions vary depending on the OS - Installing the font isn't enough to make it available during the PDF conversion process in the current software that Frappe uses to convert print format HTML into a PDF. For the font to render in the PDF, the [Base64](https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FBase64) value of the font's `.ttf` (Truet",{"id":107,"title":23,"content":108,"level":16},"\u002Fdocumentation\u002Fcheck_run\u002F","\u003C!-- Copyright (c) 2026, AgriTheory and contributors For license information, please see license.txt--> # Check Run Documentation \u003Cdiv class=\"byline\"> Heather Kusmierz and Tyler Matteson 2026-02-23 \u003C\u002Fdiv> The Check Run application extends ERPNext[^1] with several payables-related utilities. These include Check Run (a single-page payment mechanism), check printing, and a bank-friendly report. The Check Run feature collects all outstanding payables for a given company and account head. It defaults to returning payables up to the current date, but this can be adjusted as needed. The user then selects the invoices to pay and the payment method. On submission, the form creates payment entries that post against the specified bank account, and gives the user the option to print checks. ## Installation, Configuration, Settings, and Permissions There is some required prerequisite setup to get the Check Run application up and running on your ERPNext site. See the following pages for details on installation, configuration, settings, and permissions: - [Installation Guide](\u002Fdocumentation\u002Fcheck_run\u002Finstallationguide) - [Configuration: Bank Accounts, Mode of Payment for Employees and Suppliers](\u002Fdocumentation\u002Fcheck_run\u002Fconfiguration) - [Check Run Settings](\u002Fdocumentation\u002Fcheck_run\u002Fsettings) - [Default Permissions and Workflows](\u002Fdocumentation\u002Fcheck_run\u002Fpermissions), including an optional Voidable Payment Entry Workflow available with the Check Run app and how to activate it ## Check Run Quick Start To initiate a Check Run, search for \"Check Run List\" in the AwesomeBar, and click the `Add Check Run` button. This opens a dialogue box where the user must select the company, the bank account from which to make the payments, and the payables account head. \u003Cmarkdown-tip> You can add a shortcut to the Check Run list by customizing the Accounts workspace. Instructions are hosted in the ERPNext documentation here: \u003Ca href=\"https:\u002F\u002Ffrappeframework.com\u002Fdocs\u002Fv14\u002Fuser\u002Fen\u002Fdesk\u002Fworkspace\u002Fcustom",{"id":110,"title":111,"content":112,"level":16},"\u002Fdocumentation\u002Fcheck_run\u002Finstallationguide\u002F","installationguide","\u003C!-- Copyright (c) 2026, AgriTheory and contributors For license information, please see license.txt--> # Check Run Installation Guide \u003Cdiv class=\"byline\"> Tyler Matteson 2026-02-21 \u003C\u002Fdiv> ## Developer Setup First, set up a new bench and substitute a path to the python version to use. Python should be 3.8 latest for V13 and 3.10 latest for V14. These instructions use [pyenv](https:\u002F\u002Fgithub.com\u002Fpyenv\u002Fpyenv) for managing environments. ```shell # Version 13 bench init --frappe-branch version-13 {{ bench name }} --python ~\u002F.pyenv\u002Fversions\u002F3.8.12\u002Fbin\u002Fpython3 # Version 14 bench init --frappe-branch version-14 {{ bench name }} --python ~\u002F.pyenv\u002Fversions\u002F3.10.3\u002Fbin\u002Fpython3 ``` Create a new site in that bench ```shell cd {{ bench name }} bench new-site {{ site name }} --force --db-name {{ site name }} ``` Download the ERPNext app ```shell # Version 13 bench get-app erpnext --branch version-13 # Version 14 bench get-app payments bench get-app erpnext --branch version-14 bench get-app hrms ``` Download the Check Run application ```shell bench get-app check_run git@github.com:agritheory\u002Fcheck_run.git ``` Install the apps to your site ```shell bench --site {{ site name }} install-app erpnext hrms check_run # Optional: Check that all apps installed on your site bench --site {{ site name }} list-apps ``` Set developer mode in `site_config.json` ```shell nano sites\u002F{{ site name }}\u002Fsite_config.json # Add this line: \"developer_mode\": 1, ``` Add the site to your computer's hosts file to be able to access it via: `http:\u002F\u002F{{ site name }}:[8000]`. You'll need to enter your root password to allow your command line application to make edits to this file. ```shell bench --site {{site name}} add-to-hosts ``` Launch your bench (note you should be using Node.js v14 for a Version 13 bench and Node.js v16 for a Version 14 bench) ```shell bench start ``` Optional: install a [demo Company and its data](\u002Fdocumentation\u002Fcheck_run\u002Fexampledata) to test the Check Run module's functionality ```shell benc",{"id":114,"title":115,"content":116,"level":16},"\u002Fdocumentation\u002Fcheck_run\u002Fpayment_entry\u002F","payment_entry","\u003C!-- Copyright (c) 2026, AgriTheory and contributors For license information, please see license.txt--> # Payment Entry \u003Cdiv class=\"byline\"> Tyler Matteson 2026-02-21 \u003C\u002Fdiv> ## Auto-Increment Check Number The Check Run application will automatically fetch and increment check numbers, the latest number is stored in the Bank Account doctype. Both Mode of Payment and Company Bank Account are required fields to fetch the data. As long as the number provided is an integer it will save it to the linked Bank Account record. ## Quick Check This setting on Bank Account automatically fetches the Bank Account into the Payment Entry. This allows for paying a single Purchase Invoice with the normal Create => Payment workflow without selecting any additional information. ![Screen shot showing Bank Account Settings](\u002Fdocumentation\u002Fcheck_run\u002Fassets\u002FBankAccount.png) ## Additional Customizations Check Run takes the opinion that there is no scenario where it it appropriate to cut a check without providing a reference document. Payment References has been customized to be required unless the Payment Entry is of type 'Internal Transfer'. Since the Purchase Invoices displayed in a Check Run are automatically split by their Payment Terms (if the invoice has a defined Payment Schedule), it's important that a Payment Entry for a portion of an invoice made outside of a Check Run properly links a Payment Reference to a Payment Term. Check Run includes a validation that attempts to fill this in, and warns the user to review. For more information, refer to the \"Considerations for Purchase Invoices with Payment Schedules\" section on the [Settings page](\u002Fdocumentation\u002Fcheck_run\u002Fsettings). ",{"id":118,"title":119,"content":120,"level":16},"\u002Fdocumentation\u002Fcheck_run\u002Fpermissions\u002F","permissions","\u003C!-- Copyright (c) 2026, AgriTheory and contributors For license information, please see license.txt--> # Default Permissions and Workflow \u003Cdiv class=\"byline\"> Heather Kusmierz and Tyler Matteson 2026-02-23 \u003C\u002Fdiv> It's strongly recommended that you set system permissions to limit which users can see and execute a Check Run. The only permission the application enforces is that a user must have a permission level in ERPNext to create payment entries in order to perform a Check Run. Additionally, only the first user to access a draft Check Run doctype can edit it. See the [ERPNext documentation page](https:\u002F\u002Fdocs.erpnext.com\u002Fdocs\u002Fv13\u002Fuser\u002Fmanual\u002Fen\u002Fsetting-up\u002Fusers-and-permissions) for more information about user and role permissions. ## First User Only The Check Run doctype only allows a single user to interact with it at a time. The first write-permissioned user on the specific Check Run is allowed to edit, subsequent viewers are not. ## Only One Draft Check Run Allowed Only one draft Check Run is allowed per payable\u002Fbank account combination. This is intended to minimize double paying bills. ## Role Permissions Out of the box, Check Run is permissioned the same as Payment Entry. For most small organizations this may be fine, but larger organizations with document approval policies and a desire to limit persons with access to printed checks will likely want to implement additional policies. Check Run print and ACH generation policies are based on permissions for Payment Entry, not on Check Run itself. ## Voidable Payment Entry Workflow Check Run ships with an optional Voidable Payment Entry Workflow that allows a user an additional option to void a Payment Entry, versus cancelling it. To activate this workflow, navigate to Workflow -> Voidable Payment Entry, and check the \"Is Active\" box. While the \"Void\" and \"Cancel\" Payment Entry workflows have similar accounting effects in ERPNext, they differ in the date used to reverse the Payment Entry's General Ledger entries a",{"id":122,"title":123,"content":124,"level":16},"\u002Fdocumentation\u002Fcheck_run\u002Fpositivepay\u002F","positivepay","\u003C!-- Copyright (c) 2026, AgriTheory and contributors For license information, please see license.txt--> # Positive Pay Report \u003Cdiv class=\"byline\"> Tyler Matteson 2026-02-21 \u003C\u002Fdiv> The Check Run application includes a new Positive Pay report. This report generates a bank-friendly summary of check payments for a given bank account and period. To access the report, type \"Report Positive Pay\" into the AwesomeBar. Enter the bank account, start date, and end date. The report will display a table showing the check date, check number, and party name for all checks against the bank account within the specified time period. ![Screen shot of an example Positive Pay report showing columns for Check Date, Check Number, and Party Name.](\u002Fdocumentation\u002Fcheck_run\u002Fassets\u002FPositivePayReport.png)",{"id":126,"title":127,"content":128,"level":16},"\u002Fdocumentation\u002Fcheck_run\u002Frenderpdfsequence\u002F","renderpdfsequence","\u003C!-- Copyright (c) 2026, AgriTheory and contributors For license information, please see license.txt--> # Render PDF Sequence \u003Cdiv class=\"byline\"> Tyler Matteson 2026-02-21 \u003C\u002Fdiv> After a Check Run has been submitted, it will begin rendering the Checks it needs to print. Even on powerful systems it can take several minutes to render checks. The Check Run creates a new Folder in the File Manager for PDFs. These will be linked to the Check Run but removed when the user confirms they have printed correctly. ![Screen shot showing options to \"Confirm Print\" if the Checks printed properly, or \"Re-Print Checks\" if not.](\u002Fdocumentation\u002Fcheck_run\u002Fassets\u002FPrintConfirmation.png)",{"id":130,"title":131,"content":132,"level":16},"\u002Fdocumentation\u002Fcheck_run\u002Fsales_tax_payable\u002F","sales_tax_payable","\u003C!-- Copyright (c) 2026, AgriTheory and contributors For license information, please see license.txt--> # Sales Tax Payable \u003Cdiv class=\"byline\"> Tyler Matteson 2026-04-03 \u003C\u002Fdiv> In Check Run Settings, configure the bank account \u002F Sales Tax Payable account combination and enable **Include Tax Payable from Sales Invoices**. Tax rows on that payable account then require Party Type and Party on the Sales Taxes and Charges table, and an Outstanding Amount is created on submit to track which rows have been satisfied. Tax rows on other accounts are unaffected. Given the large number of rows that may be included in a given period, enabling the secondary print format feature is recommended. ## Recommended Settings for the Sales Tax Payable Check Run When creating Check Run Settings for the bank account \u002F Sales Tax Payable account combination, set **Allow stand-alone debit notes?** to **Yes**. Sales invoice returns create a negative outstanding amount on the corresponding Sales Taxes and Charges row. With this setting enabled, those credit rows appear in the Check Run so the credit can be remitted or netted against future tax payments to the same authority. With the default value of **No**, only positive outstanding amounts are shown and credits from returns will not surface for reconciliation. ## Returns After Tax Has Been Remitted When a sales invoice is returned after the tax liability has already been paid via a Check Run: - The original invoice's tax row outstanding amount remains `0` (it was already remitted). - The return invoice's tax row carries a **negative** outstanding amount equal to the original tax, representing the credit owed back from the tax authority. This credit row will appear in the next Check Run (with **Allow stand-alone debit notes?** set to **Yes**), where it can be selected to net against other tax remittances or processed as a standalone refund. ## Supported Remittance Path Tax remittance is only supported through the Check Run workflow. Using the",{"id":134,"title":135,"content":136,"level":16},"\u002Fdocumentation\u002Fcheck_run\u002Fsales_tax_remittance_report\u002F","sales_tax_remittance_report","\u003C!-- Copyright (c) 2026, AgriTheory and contributors For license information, please see license.txt--> # Sales Tax Remittance Report \u003Cdiv class=\"byline\"> Tyler Matteson 2026-04-01 \u003C\u002Fdiv> The Sales Tax Remittance Report provides a running view of collected sales tax obligations and their remittance status. It is designed for businesses that track sales tax payable to government authorities via the Sales Taxes and Charges table on their Sales Invoices (see [Sales Tax Payable](\u002Fdocumentation\u002Fcheck_run\u002Fsales_tax_payable)). To access the report, type \"Sales Tax Remittance\" into the AwesomeBar. Required filters are Company and Up To Date. Unlike most date-range reports, no start date is required — sales tax is managed on a rolling basis and older liabilities remain visible until remitted. Optional filters include Tax Authority, Tax Account, Remittance Status (`Outstanding`, `Remitted`, or `All`), and Show Detail. ## Summary View (default) Aggregates tax by authority, account, and calendar month. Each row shows the gross tax collected from customers (`total_collected`), how much of that has been received from customers (`customer_paid_amount`), how much has been remitted to the authority (`total_remitted`), and the net amount still owed (`total_outstanding`). Return invoice credits appear as negative values and reduce `total_outstanding` accordingly. ## Detail View Shows one row per Sales Taxes and Charges entry. In addition to the amounts above, each row links to the originating Sales Invoice, shows whether the customer has paid (`customer_paid`), and — once remitted — shows the remittance amount, the Payment Entry voucher, and the remittance date. ## Returns and Credits When a Sales Invoice return is submitted, the original invoice's tax row outstanding is reduced to `0` and the return invoice carries a negative outstanding representing a credit owed back from the authority. Both rows appear in the report. See [Sales Tax Payable](\u002Fdocumentation\u002Fcheck_run\u002Fsales_tax_payab",{"id":138,"title":139,"content":140,"level":16},"\u002Fdocumentation\u002Fcheck_run\u002Fsettings\u002F","settings","\u003C!-- Copyright (c) 2025, AgriTheory and contributors For license information, please see license.txt--> # Check Run Settings \u003Cdiv class=\"byline\"> Heather Kusmierz, Tyler Matteson, and Francisco Roldán 2026-02-23 \u003C\u002Fdiv> A `Check Run Setting` entry determines the behavior in a Check Run for a specific bank account\u002Fpayable account combination. You will need to confirm separate settings for every bank account-payable account combination that you plan to use in a Check Run. ![Screen shot of the Check Run Settings listview with two entries - one for the Local Bank and Payroll Payable combination and the other for the Local Bank and Accounts Payable combination.](\u002Fdocumentation\u002Fcheck_run\u002Fassets\u002FSettingsList.png) If the system doesn't find settings for the account combination you're using in an initiated Check Run, it will automatically take you to the settings page to confirm the options. Alternatively, you can access the setting list directly by searching for \"Check Run Settings List\" in the AwesomeBar and clicking the `Add Check Run Settings` button. ![Screen shot showing the top portion of default settings for one Bank Account and Payable Account combination. A description of each setting and its default value is listed below.](\u002Fdocumentation\u002Fcheck_run\u002Fassets\u002FSettings_Main.png) * **Approver Role:** * If Check Runs require approvals of another User, their Role should be noted here. \u003Cdiv class=\"mermaid-chart-container\"> \u003Cdiv class=\"mermaid-svg-version\">\u003Csvg id=\"mermaid-svg-0\" width=\"100%\" xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" xmlns:xlink=\"http:\u002F\u002Fwww.w3.org\u002F1999\u002Fxlink\" class=\"flowchart\" style=\"max-width: 507.71795654296875px;\" viewBox=\"38.02734375 0 507.71795654296875 558\" role=\"graphics-document document\" aria-roledescription=\"flowchart-v2\">\u003Cstyle>#mermaid-svg-0{font-family:inherit;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-0 .edge-animation-slow{stroke-dasharray:9,5!important;str",{"id":142,"title":143,"content":144,"level":16},"\u002Fdocumentation\u002Fcheck_run\u002Ftranslations\u002F","translations","\u003C!-- Copyright (c) 2026, AgriTheory and contributors For license information, please see license.txt--> # Translations \u003Cdiv class=\"byline\"> Tyler Matteson 2026-02-21 \u003C\u002Fdiv> The Check Run application currently offers a Canadian regionalization. To utilize this feature, Canadian users should select the \"English (United Kingdom)\" (`en-GB`) language option under their user settings. Contributions for other translations are welcome. ",{"id":146,"title":147,"content":148,"level":16},"\u002Fdocumentation\u002Fcloud_storage\u002Faws-s3\u002F","aws-s3","\u003C!-- Copyright (c) 2025, AgriTheory and contributors For license information, please see license.txt--> # [Amazon Web Services S3 Setup](https:\u002F\u002Faws.amazon.com\u002Fs3\u002F) \u003Cdiv class=\"byline\"> Tyler Matteson and semantic-release 2026-02-21 \u003C\u002Fdiv> ## Regions The following documentation shows the available region names for AWS: - [Amazon Web Services S3 Regions](https:\u002F\u002Fdocs.aws.amazon.com\u002Fgeneral\u002Flatest\u002Fgr\u002Fs3.html) ## Credentials In order to generate access keys for your Amazon Web Services S3 instance, go through the following steps: - Open the [IAM console](https:\u002F\u002Fconsole.aws.amazon.com\u002Fiam\u002Fhome#home). - From the navigation menu, click on **Users**. - Select your IAM user name. - Scroll to the **Access keys** section and click on **Create access key**. - In **Step 1**, select **Third-party service**. Confirm and select **Next**. - In **Step 2**, optionally set a description for the access key. - In **Step 3**, click on **Download .csv file**. Your keys should look something like this: - Access key: AKIAIOSFODNN7EXAMPLE - Secret access key: MihgBbJs5yQrKsKNSj\u002FTEqa3q2ZOtaEXAMPLEKEY - Once you have the access key and secret access key, store them in a secure location. ## Buckets The following documentation shows how to generate buckets in Amazon's S3 service: - [Amazon Web Services S3 - Create a Bucket](https:\u002F\u002Fdocs.aws.amazon.com\u002FAmazonS3\u002Flatest\u002Fuserguide\u002Fcreating-bucket.html) ",{"id":150,"title":151,"content":152,"level":16},"\u002Fdocumentation\u002Fcloud_storage\u002Fbackblaze-b2\u002F","backblaze-b2","\u003C!-- Copyright (c) 2025, AgriTheory and contributors For license information, please see license.txt--> # [Backblaze B2](https:\u002F\u002Fwww.backblaze.com\u002Fb2\u002Fcloud-storage.html) \u003Cdiv class=\"byline\"> Tyler Matteson and semantic-release 2026-02-21 \u003C\u002Fdiv> ## Credentials In order to generate access keys for Backblaze B2 with the following steps: - Navigate to the 'App Keys' section - Endpoint is listed on the 'Buckets' page, but will look something like `s3.us-west-004.backblazeb2.com` - Paste the **bucketName** value into the `bucket` field - Paste the **keyID** value into the `access_key` - Paste the **applicationKey** into `secret` ",{"id":154,"title":155,"content":156,"level":16},"\u002Fdocumentation\u002Fcloud_storage\u002Fcommands\u002F","commands","\u003C!-- Copyright (c) 2026, AgriTheory and contributors For license information, please see license.txt--> # Cloud Storage Migration \u003Cdiv class=\"byline\"> Tyler Matteson and semantic-release 2026-02-21 \u003C\u002Fdiv> This guide covers migrating existing local files to cloud storage and updating file paths to the new path strategy. ## Prerequisites Before running migration commands, ensure: 1. Cloud storage is properly configured in `site_config.json` 2. You have tested the configuration with new file uploads 3. You have a backup of your files (recommended) ## Migrating Local Files to Cloud Storage The `migrate-files-to-cloud-storage` command uploads existing local files to your configured cloud storage provider. ### Basic Usage ```bash bench --site mysite migrate-files-to-cloud-storage ``` ### Options | Option | Type | Description | |--------|------|-------------| | `--dry-run` | flag | Preview migration without uploading files | | `--limit` | integer | Maximum number of files to migrate | | `--doctype` | string | Only migrate files attached to specific DocType | | `--older-than` | integer | Only migrate files older than specified days | | `--batch-size` | integer | Number of files to process per batch (default: 100) | | `--remove-local` | flag | Remove local files after successful upload | ### Examples **Preview migration:** ```bash bench --site mysite migrate-files-to-cloud-storage --dry-run ``` **Migrate specific number of files:** ```bash bench --site mysite migrate-files-to-cloud-storage --limit 100 ``` **Migrate files for specific DocType:** ```bash bench --site mysite migrate-files-to-cloud-storage --doctype \"Employee\" ``` **Migrate only old files:** ```bash bench --site mysite migrate-files-to-cloud-storage --older-than 30 ``` **Migrate with custom batch size:** ```bash bench --site mysite migrate-files-to-cloud-storage --batch-size 50 ``` **Migrate and remove local files:** ```bash bench --site mysite migrate-files-to-cloud-storage --remove-local ``` > **Warning:** Use",{"id":158,"title":14,"content":159,"level":16},"\u002Fdocumentation\u002Fcloud_storage\u002Fconfiguration\u002F","\u003C!-- Copyright (c) 2025, AgriTheory and contributors For license information, please see license.txt--> # Cloud Storage Site Configuration \u003Cdiv class=\"byline\"> Tyler Matteson and semantic-release 2026-02-21 \u003C\u002Fdiv> The following documentation shows how to set up some common cloud storage providers: - [Amazon Web Services S3](\u002Fdocumentation\u002Fcloud_storage\u002Faws-s3) - [Backblaze B2](\u002Fdocumentation\u002Fcloud_storage\u002Fbackblaze-b2) - [DigitalOcean Spaces](\u002Fdocumentation\u002Fcloud_storage\u002Fdigitalocean-spaces) ## App Configuration Set the following keys in your site's configuration file (`\u002Fsites\u002F{site_name}\u002Fsite_config.json`): ```json { ... \"cloud_storage_settings\": { \u002F\u002F the ID of the region where your bucket is located \"region\": \"s3-region-name\", \u002F\u002F the endpoint URL for your S3 instance \"endpoint_url\": \"s3-endpoint-url\", \u002F\u002F S3 access key ID \"access_key\": \"s3-access-key\", \u002F\u002F S3 secret access key \"secret\": \"s3-secret-key\", \u002F\u002F the name of the S3 bucket \"bucket\": \"bucket-name\", \u002F\u002F the name of the folder inside the bucket where the files will be stored \"folder\": \"folder-name\", \u002F\u002F (optional) time before the generated URL for the file expires, in seconds \u002F\u002F default: 120 seconds \"expiration\": 120, \u002F\u002F Optional: use new path strategy instead of legacy \u002F\u002F Default: true (uses legacy folder\u002Fdoctype\u002Fattached_to_name\u002Fdocname paths) \"use_legacy_paths\": 0 } ... } ``` ",{"id":161,"title":162,"content":163,"level":16},"\u002Fdocumentation\u002Fcloud_storage\u002Fdecisions\u002F0000-use-markdown-any-decision-records\u002F","0000-use-markdown-any-decision-records","\u003C!-- Copyright (c) 2025, AgriTheory and contributors For license information, please see license.txt--> # Use Markdown Any Decision Records \u003Cdiv class=\"byline\"> Tyler Matteson and semantic-release 2026-02-21 \u003C\u002Fdiv> ## Context and Problem Statement We want to record any decisions made in this project independent whether decisions concern the architecture (\"architectural decision record\"), the code, or other fields. Which format and structure should these records follow? ## Considered Options * [MADR](https:\u002F\u002Fadr.github.io\u002Fmadr\u002F) 3.0.0 – The Markdown Any Decision Records * [Michael Nygard's template](http:\u002F\u002Fthinkrelevance.com\u002Fblog\u002F2011\u002F11\u002F15\u002Fdocumenting-architecture-decisions) – The first incarnation of the term \"ADR\" * [Sustainable Architectural Decisions](https:\u002F\u002Fwww.infoq.com\u002Farticles\u002Fsustainable-architectural-design-decisions) – The Y-Statements * Other templates listed at \u003Chttps:\u002F\u002Fgithub.com\u002Fjoelparkerhenderson\u002Farchitecture_decision_record> * Formless – No conventions for file format and structure ## Decision Outcome Chosen option: \"MADR 3.0.0\", because * Implicit assumptions should be made explicit. Design documentation is important to enable people understanding the decisions later on. See also [A rational design process: How and why to fake it](https:\u002F\u002Fdoi.org\u002F10.1109\u002FTSE.1986.6312940). * MADR allows for structured capturing of any decision. * The MADR format is lean and fits our development style. * The MADR structure is comprehensible and facilitates usage & maintenance. * The MADR project is vivid. ",{"id":165,"title":166,"content":167,"level":16},"\u002Fdocumentation\u002Fcloud_storage\u002Fdecisions\u002F0001-no-expiry-on-public-files\u002F","0001-no-expiry-on-public-files","\u003C!-- Copyright (c) 2025, AgriTheory and contributors For license information, please see license.txt--> --- # These are optional elements. Feel free to remove any of them. \u003Cdiv class=\"byline\"> Tyler Matteson and semantic-release 2026-02-21 \u003C\u002Fdiv> status: proposed date: 2023-02-03 deciders: tyler@agritheory.com --- # No Expiration on Public Files ## Context and Problem Statement For files that are 'public' and can be served to anyone with the URL, don't provide a time expiry value. Permissions are also bypassed for these files. ## Decision Outcome This will improve user experience with files that are meant to be linked or widely accessible. ### Consequences * Good, because if the file is public, it should be accessible by any user agent at any time. * Bad, because it still requires a call to the 'retrieve' API. It would be better to provide a direct link to the S3 block that is hosting the file, but buckets are either public (CDN-ish) or private. ",{"id":169,"title":170,"content":171,"level":16},"\u002Fdocumentation\u002Fcloud_storage\u002Fdecisions\u002F0002-check-permissions-before-serving-private-file\u002F","0002-check-permissions-before-serving-private-file","\u003C!-- Copyright (c) 2025, AgriTheory and contributors For license information, please see license.txt--> --- # These are optional elements. Feel free to remove any of them. \u003Cdiv class=\"byline\"> Tyler Matteson and semantic-release 2026-02-21 \u003C\u002Fdiv> status: proposed date: 2023-02-03 deciders: tyler@agritheory.com --- # Check Permissions Before Serving Private Files ## Context and Problem Statement For files that are 'private' these are theoretically accessible by any user inside the system, even if this isn't appropriate. Cloud Storage provides two opinions about this: - If the user has permissions for the document the file is attached to, there's no change in behavior - If the user does not have permissions for the document the file is attached to, they should be denied access This should be checked on every request against the file. ## Decision Outcome Appropriate of access to attachments. If there are differing opinions about this, it can be overridden by subclassing `CustomFile` and providing a custom `has_permission` function. ",{"id":173,"title":174,"content":175,"level":16},"\u002Fdocumentation\u002Fcloud_storage\u002Fdecisions\u002FREADME\u002F","README","\u003C!-- Copyright (c) 2025, AgriTheory and contributors For license information, please see license.txt--> # Decisions This directory contains decision records for {project name}. For new ADRs, please use [adr-template.md](\u002Fdocumentation\u002Fcloud_storage\u002Fadr-template) as basis. More information on MADR is available at \u003Chttps:\u002F\u002Fadr.github.io\u002Fmadr\u002F>. General information about architectural decision records is available at \u003Chttps:\u002F\u002Fadr.github.io\u002F>. ",{"id":177,"title":178,"content":179,"level":16},"\u002Fdocumentation\u002Fcloud_storage\u002Fdecisions\u002Fadr-template\u002F","adr-template","\u003C!-- Copyright (c) 2025, AgriTheory and contributors For license information, please see license.txt--> --- # These are optional elements. Feel free to remove any of them. \u003Cdiv class=\"byline\"> Tyler Matteson and semantic-release 2026-02-21 \u003C\u002Fdiv> status: proposed | rejected | accepted | deprecated | … | superseded by [ADR-0005](\u002Fdocumentation\u002Fcloud_storage\u002F0005-example) date: YYYY-MM-DD when the decision was last updated deciders: list everyone involved in the decision consulted: list everyone whose opinions are sought (typically subject-matter experts); and with whom there is a two-way communication informed: list everyone who is kept up-to-date on progress; and with whom there is a one-way communication --- # {short title of solved problem and solution} ## Context and Problem Statement {Describe the context and problem statement, e.g., in free form using two to three sentences or in the form of an illustrative story. You may want to articulate the problem in form of a question and add links to collaboration boards or issue management systems.} \u003C!-- This is an optional element. Feel free to remove. --> ## Decision Drivers * {decision driver 1, e.g., a force, facing concern, …} * {decision driver 2, e.g., a force, facing concern, …} * … \u003C!-- numbers of drivers can vary --> ## Considered Options * {title of option 1} * {title of option 2} * {title of option 3} * … \u003C!-- numbers of options can vary --> ## Decision Outcome Chosen option: \"{title of option 1}\", because {justification. e.g., only option, which meets k.o. criterion decision driver | which resolves force {force} | … | comes out best (see below)}. \u003C!-- This is an optional element. Feel free to remove. --> ### Consequences * Good, because {positive consequence, e.g., improvement of one or more desired qualities, …} * Bad, because {negative consequence, e.g., compromising one or more desired qualities, …} * … \u003C!-- numbers of consequences can vary --> \u003C!-- This is an optional element. Feel free to remove. --> #",{"id":181,"title":182,"content":183,"level":16},"\u002Fdocumentation\u002Fcloud_storage\u002Fdevelopment\u002F","development","\u003C!-- Copyright (c) 2025, AgriTheory and contributors For license information, please see license.txt--> # Cloud Storage Developer Setup \u003Cdiv class=\"byline\"> semantic-release 2026-05-28 \u003C\u002Fdiv> Before you begin, make sure that your Python version is: - Latest 3.10 for Frappe's version 14. 1. First, set up a new bench and substitute a path to the python version to use. These instructions use [pyenv](https:\u002F\u002Fgithub.com\u002Fpyenv\u002Fpyenv) for managing environments. ```shell # Version 14 bench init --frappe-branch version-14 {{ bench name }} --python ~\u002F.pyenv\u002Fversions\u002F3.10.3\u002Fbin\u002Fpython3 ``` 2. Create a new site in that bench ```shell cd {{ bench name }} bench new-site {{ site name }} --force --db-name {{ site name }} ``` 3. Download the Cloud Storage application ```shell bench get-app cloud_storage https:\u002F\u002Fgithub.com\u002Fagritheory\u002Fcloud_storage.git ``` 4. Install the app to your site ```shell bench --site {{site name}} install-app cloud_storage # Optional: Check that the app installed on your site bench --site {{ site name }} list-apps ``` 5. Set developer mode in `site_config.json` ```shell nano sites\u002F{{ site name }}\u002Fsite_config.json # Add this line: \"developer_mode\": 1, ``` 6. Add the site to your computer's hosts file to be able to access it via: `http:\u002F\u002F{{ site name }}:[8000]`. You'll need to enter your root password to allow your command line application to make edits to this file. ```shell bench --site {{site name}} add-to-hosts ``` 7. Make sure to configure your S3 instance to access your files. You can do this by setting the permissions defined in the [configuration guide](\u002Fdocumentation\u002Fcloud_storage\u002Fconfiguration). 8. Install the libmagic C library. The [documentation for the python-magic package](https:\u002F\u002Fpypi.org\u002Fproject\u002Fpython-magic\u002F) (a Cloud Storage dependency) notes that the package is a wrapper around the libmagic C library, which needs to be installed on the system as well. ```shell # Debian\u002FUbuntu sudo apt-get install libmagic1 # Windows pip install python-magic-",{"id":185,"title":186,"content":187,"level":16},"\u002Fdocumentation\u002Fcloud_storage\u002Fdigitalocean-spaces\u002F","digitalocean-spaces","# [DigitalOcean Spaces](https:\u002F\u002Fwww.digitalocean.com\u002Fproducts\u002Fspaces) ## Regions The following documentation shows the available region names for DigitalOcean: - [DigitalOcean Spaces Regions](https:\u002F\u002Fdocs.digitalocean.com\u002Fproducts\u002Fplatform\u002Favailability-matrix\u002F) ## Credentials and Buckets The following documentation shows how to generate access credentials and S3-compatible buckets in DigitalOcean Spaces: - [Create a DigitalOcean Space and API Key](https:\u002F\u002Fwww.digitalocean.com\u002Fcommunity\u002Ftutorials\u002Fhow-to-create-a-digitalocean-space-and-api-key) ",{"id":189,"title":62,"content":190,"level":16},"\u002Fdocumentation\u002Fcloud_storage\u002Fhooks\u002F","\u003C!-- Copyright (c) 2025, AgriTheory and contributors For license information, please see license.txt--> # Cloud Storage Hooks \u003Cdiv class=\"byline\"> Tyler Matteson and semantic-release 2026-02-21 \u003C\u002Fdiv> ## Path Generator Hook The Cloud Storage app provides a hook to customize how file paths are generated in your S3-compatible storage bucket. `cloud_storage_path_generator` By default, Cloud Storage uses the File document's name as the S3 object key. However, you may need to customize this behavior for specific integrations or archival requirements. ### Default Behavior The default path generator uses the File document's `name` field and respects the `folder` configuration from your site's `site_config.json`: ```python # Default path structure: # {folder}\u002F{file.file_name} # Examples (with folder=\"documents\" in site_config.json): # - documents\u002Ffile-1.pdf # - documents\u002Fimage-a.png # Examples (without folder configured): # - file-1.pdf # - image-a.png ``` ### Configuration To use a custom path generator, add the following to your custom app's `hooks.py`: ```python # hooks.py cloud_storage_path_generator = \"my_custom_app.utils.custom_path_generator\" ``` ### Custom Path Generator Function Your custom function must accept two parameters and return a string path: ```python def custom_path_generator(file, folder=None): \"\"\" Generate a custom S3 object key for a File document. Args: file (File): The File document instance folder (str|None): Optional base folder from Cloud Storage Settings Returns: str: The S3 object key\u002Fpath \"\"\" # Your custom logic here return \"your\u002Fcustom\u002Fpath.pdf\" ``` ### Example ```python # my_custom_app\u002Futils.py def custom_get_file_path(file: File, folder: str | None = None) -> str: parent_doctype = file.attached_to_doctype or \"No Doctype\" attached_to_name = \"\" if file.attached_to_name: attached_to_name = file.attached_to_name.replace(\"#\", \"%23\") fragments = [ folder, parent_doctype, attached_to_name, file.file_name.replace(\"#\", \"%23\"), ] valid_fragments: lis",{"id":192,"title":23,"content":193,"level":16},"\u002Fdocumentation\u002Fcloud_storage\u002F","\u003C!-- Copyright (c) 2025, AgriTheory and contributors For license information, please see license.txt--> # Cloud Storage Documentation \u003Cdiv class=\"byline\"> Tyler Matteson and semantic-release 2026-02-21 \u003C\u002Fdiv> Cloud Storage extends the file utilities in a Frappe App to integrate with third-party cloud storage applications. Once configured, users can upload, download, or remove files to a cloud storage application via the Frappe App's interface. Depending on user permissions, they may also generate or reset sharing links to files. Cloud Storage can be configured to work with a variety of cloud storage providers, including Amazon Web Services S3, DigitalOcean Spaces, and Backblaze B2. See the following pages for detailed instructions on Cloud Storage installation and configuration: - [Cloud Storage Developer Environment Installation](\u002Fdocumentation\u002Fcloud_storage\u002Fdevelopment) - [Cloud Storage Production Environment Installation](\u002Fdocumentation\u002Fcloud_storage\u002Fproduction) - [Cloud Storage Configuration](\u002Fdocumentation\u002Fcloud_storage\u002Fconfiguration) - [Hooks](\u002Fdocumentation\u002Fcloud_storage\u002Fhooks) - [Commands](\u002Fdocumentation\u002Fcloud_storage\u002Fcommands) ## Cloud Storage Quick Start Once the Cloud Storage application is installed and configured, search for \"File List\" in the AwesomeBar. To upload a file, click the \"+ Add File\" button, load a file, and click \"Upload\". This action automatically adds the file to the configured third-party cloud storage application. ![Upload file dialogue box showing a new, non-private file called \"Cloud_Storage.md\" being uploaded to the system.](\u002Fdocumentation\u002Fcloud_storage\u002Fassets\u002Ffile_upload.png) The page for the uploaded file includes several features. There's a button to \"Download\" the file from the cloud storage service, which will open a new browser window to the file's contents. There's also a \"Get Sharing Link\" button that allows for a user to create a sharing link to the file for unauthenticated users. This only works if the user has permission t",{"id":195,"title":196,"content":197,"level":16},"\u002Fdocumentation\u002Fcloud_storage\u002Fproduction\u002F","production","\u003C!-- Copyright (c) 2025, AgriTheory and contributors For license information, please see license.txt--> # Cloud Storage Production Setup \u003Cdiv class=\"byline\"> Tyler Matteson and semantic-release 2026-02-21 \u003C\u002Fdiv> Before you begin, make sure that your server's Python version is: - Latest 3.8 for Frappe's version 13 - Latest 3.10 for Frappe's version 14. 1. First, set up a new bench and substitute a path to the python version to use. These instructions use [pyenv](https:\u002F\u002Fgithub.com\u002Fpyenv\u002Fpyenv) for managing environments. ```shell # Version 13 bench init --frappe-branch version-13 {{ bench name }} --python ~\u002F.pyenv\u002Fversions\u002F3.8.12\u002Fbin\u002Fpython3 # Version 14 bench init --frappe-branch version-14 {{ bench name }} --python ~\u002F.pyenv\u002Fversions\u002F3.10.3\u002Fbin\u002Fpython3 ``` 2. Create a new site in that bench ```shell cd {{ bench name }} bench new-site {{ site name }} --force --db-name {{ site name }} ``` 3. Download the Cloud Storage application ```shell bench get-app cloud_storage git@github.com:agritheory\u002Fcloud_storage.git ``` 4. Install the app to your site ```shell bench --site {{site name}} install-app cloud_storage # Optional: Check that the app installed on your site bench --site {{ site name }} list-apps ``` 5. Make sure to configure your S3 instance to access your files. You can do this by setting the permissions defined in the [configuration guide](\u002Fdocumentation\u002Fcloud_storage\u002Fconfiguration). 6. Install the libmagic C library. The [documentation for the python-magic package](https:\u002F\u002Fpypi.org\u002Fproject\u002Fpython-magic\u002F) (a Cloud Storage dependency) notes that the package is a wrapper around the libmagic C library, which needs to be installed on the system as well. ```shell # Debian\u002FUbuntu sudo apt-get install libmagic1 # Windows pip install python-magic-bin # OSX Homebrew brew install libmagic # OSX macports port install file ``` 7. Once everything is set up, launch your bench. ```shell bench start ``` ",{"id":199,"title":200,"content":201,"level":16},"\u002Fdocumentation\u002Fcloud_storage\u002Fversioning\u002F","versioning","\u003C!-- Copyright (c) 2025, AgriTheory and contributors For license information, please see license.txt--> # File Versioning and Association Logic \u003Cdiv class=\"byline\"> Tyler Matteson and semantic-release 2026-02-21 \u003C\u002Fdiv> ## S3\u002FCloud Storage Versioning Versioning must be enabled at the bucket level for S3\u002Fcompatible storage. To enable file versioning, enter the following in bench console: ```ipython In [1]: from cloud_storage.cloud_storage.overrides.file import get_cloud_storage_client In [2]: client = get_cloud_storage_client() In [3]: client.put_bucket_versioning(Bucket=client.bucket, VersioningConfiguration={'Status': 'Enabled'}) ``` ## File Versioning in Frappe\u002FCloud Storage App When a file is uploaded, the backend logic manages file versions and associations as follows: ### `add_file_version` The `add_file_version` method is called whenever a new version of a file is uploaded. It appends a new entry to the file's `versions` child table, recording: - The version identifier (S3 VersionId) - The user who uploaded the version - The timestamp of the upload This allows you to track all previous versions of a file within the File DocType. ### Handling Duplicate File Names If a file is uploaded with a name that already exists in the system (and is not a folder): - Instead of creating a new File document, the system updates the content, content hash, and content type of the existing File document with the new file's data. - All associations (linked documents) are updated so that they now point to the updated File document. - The new version is recorded in the `versions` child table using `add_file_version`. - This ensures that all references and links in the system always point to the latest version of the file, and there are no duplicate File records for the same file name. This logic helps maintain a single source of truth for each file name, with a complete version history and correct associations for all linked documents. ",{"id":203,"title":204,"content":205,"level":16},"\u002Fdocumentation\u002Fcommunications\u002F","Communications"," # Communications Upstream has no `docs\u002F` folder at the expected path, or the repository could not be cloned (AutoReader: deploy key env vars; other private repos: HTTPS token). ",{"id":207,"title":14,"content":208,"level":16},"\u002Fdocumentation\u002Felectronic_payments\u002Fconfiguration\u002F","\u003C!-- Copyright (c) 2025, AgriTheory and contributors For license information, please see license.txt--> # Electronic Payments Configuration and Settings \u003Cdiv class=\"byline\"> AgriTheory and Heather Kusmierz 2026-02-23 \u003C\u002Fdiv> One Electronic Payment Settings document may be created for each Company in ERPNext. This document stores the provider credentials (including API keys) and selected accounts that are used in the chosen accounting workflow. Certain fields are required depending on the provider, which are noted below. The keys should be the **testing\u002Fsandbox** values when testing the functionality of the application, and only updated to live keys when using the application in production. Some provider configurations require an endpoint, which is different for their testing sandbox calls and real production ones. See below for information and default values for each field. ## General Settings ![Screen shot showing the fields in the Electronic Payment Settings document's General tab. Field names and descriptions are below.](\u002Fdocumentation\u002Felectronic_payments\u002Fassets\u002Fep_settings_general.png) - **Company:** (required) the company in ERPNext to apply all settings to - only one Electronic Payment Settings document may exist per company - **Automatically Create a Portal Payment Method when Electronic Payment Profile is Saved:** (default checked) when checked, if a desk user clicks the Electronic Payment button for an Order or Invoice, then enters payment information via the dialog box on behalf of a party and selects to save the payment method, this automatically creates a Portal Payment Method for the party. In ERPNext, Portal Payment Methods are viewable and editable in the Electronic Payments tab of the respective party's page, or by the a user associated with that party (via a Contact) when they log into the portal ## Configuration: Accepting Payments The following fields pertain to accepting electronic payments and are found on the \"Accepting Payments\" tab. Note that ",{"id":210,"title":100,"content":211,"level":16},"\u002Fdocumentation\u002Felectronic_payments\u002Fexampledata\u002F","\u003C!-- Copyright (c) 2025, AgriTheory and contributors For license information, please see license.txt--> # Using the Example Data to Experiment with Electronic Payments \u003Cdiv class=\"byline\"> AgriTheory and Tyler Matteson 2026-02-21 \u003C\u002Fdiv> The Electronic Payments application comes with a `setup.py` script that is completely optional to use. If you execute the script, it populates your ERPNext site with demo business data for a fictitious company called Chelsea Fruit Co. The data enable you to experiment with and test the Electronic Payments application's functionality before installing the app into your ERPNext site. It's recommended to install the demo data into its own site to avoid potential interference with the configuration or data in your organization's ERPNext site. With `bench start` running in the background, run the following command to install the demo data (there are more detailed instructions in the [installation guide](\u002Fdocumentation\u002Felectronic_payments\u002F..\u002FREADME) for how to set up test API keys for different providers and have the test data script automatically generate an Electronic Payments Settings document with them): ```shell bench execute 'electronic_payments.tests.setup.before_test' ``` Refer to the [installation guide](\u002Fdocumentation\u002Felectronic_payments\u002F..\u002FREADME) for detailed instructions for how to set up a bench, a new site, and installing ERPNext and the Electronic Payments application. ",{"id":213,"title":23,"content":214,"level":16},"\u002Fdocumentation\u002Felectronic_payments\u002F","\u003C!-- Copyright (c) 2025, AgriTheory and contributors For license information, please see license.txt--> # Electronic Payments Documentation \u003Cdiv class=\"byline\"> Heather Kusmierz and Tyler Matteson 2026-02-24 \u003C\u002Fdiv> The Electronic Payments application extends ERPNext[^1] with the capability to send and receive electronic payments via several vendors directly in the system. The current supported vendors (also called providers) are [Authorize.net](www.authorize.net) (accepting and sending payments), [Stripe](stripe.com) (accepting payments, with some limitations), [Mercury](mercury.com) (sending payments), and [Wise](wise.com) (sending payments, with some limitations). You can configure the app to use different providers to accept vs send payments. The current providers each have their own terms and conditions they require to use their services, including authorization requirements for certain payment methods. Before installing and using the Electronic Payments app, it is your responsibility to comply with your provider's terms, conditions, and requirements for using their services. There are also some limitations around functionality by provider - these are detailed below in the Provider Limitations section. ## Installation, Configuration, Settings, and Permissions There are a few prerequisite steps to get the Electronic Payments application up and running on your ERPNext site. See the following pages for details on installation, configuration, settings, and permissions: - [Installation Guide](\u002Fdocumentation\u002Felectronic_payments\u002F..\u002FREADME) - [Configuration and Settings](\u002Fdocumentation\u002Felectronic_payments\u002Fconfiguration) - [Default Permissions and Accounting Workflows](\u002Fdocumentation\u002Felectronic_payments\u002Fpermissions) - Refer to the [Network Diagrams page](\u002Fdocumentation\u002Felectronic_payments\u002Fnetwork_diagrams) for detailed illustrations of how user actions in ERPNext tie to provider services through their API - Refer to the [Example Data page](\u002Fdocumentation\u002Felectronic_payme",{"id":216,"title":217,"content":218,"level":16},"\u002Fdocumentation\u002Felectronic_payments\u002Fnetwork_diagrams\u002F","network_diagrams","\u003C!-- Copyright (c) 2026, AgriTheory and contributors For license information, please see license.txt--> # Network Diagrams \u003Cdiv class=\"byline\"> Heather Kusmierz 2026-02-25 \u003C\u002Fdiv> The Electronic Payments app offers multiple ways to accomplish the same tasks in terms of adding, editing, or deleting payment methods, or applying one to pay an outstanding invoice. In general: * **ERPNext User (via desk)** (with the appropriate permissions) * Add, edit, or delete payment methods from the Customer or Supplier record from the \"Electronic Payments\" tab. If there are multiple companies in ERPNext with Electronic Payments Settings configured, a new payment method will attach to all companies with \"Accepting Payments\" enabled (for Customers) or with \"Sending Payments\" enabled (for Suppliers) * Add and optionally apply a payment method or apply a saved payment method on a Sales Invoice or Purchase Invoice via the \"Electronic Payments\" button. The payment method will only attach to the company in the Invoice's \"Company\" field * **Customer (self service via portal)** * Add, edit, or delete payment methods through the portal. If there are multiple companies in ERPNext with Electronic Payments Settings configured, a new payment method will attach to all companies with \"Accepting Payments\" enabled * Pay an outstanding Sales Invoice with a saved payment method * **Supplier (self service via portal)** * Add, edit, or delete payment methods through the portal. If there are multiple companies in ERPNext with Electronic Payments Settings configured, a new payment method will attach to all companies with \"Accepting Payments\" enabled Not all providers allow editing or deleting payment methods via their API - this is noted by provider. Throughout all the following processes, ERPNext only stores the customer ID (if one is created), the payment method ID (the token the provider assigns to identify the payment method), and a payment method reference. This reference is a shorthand display (using",{"id":220,"title":119,"content":221,"level":16},"\u002Fdocumentation\u002Felectronic_payments\u002Fpermissions\u002F","\u003C!-- Copyright (c) 2025, AgriTheory and contributors For license information, please see license.txt--> # Electronic Payments Permissions and Workflows \u003Cdiv class=\"byline\"> AgriTheory and Tyler Matteson 2026-02-21 \u003C\u002Fdiv> ## Permissions The Electronic Payments app integrates with ERPNext's existing documents and workflows. The app doesn't introduce any new roles or permission changes, but leverages the existing setup. - Users with the Role of System Manager may create and edit the Electronic Payments Settings for a company - Users with access to Sales Orders and Sales Invoices, or Purchase Orders and Purchase Invoices will see an \"Electronic Payments\" button on those documents, enabling them to make a payment on behalf of a customer or to a supplier - Users with access to Customers or Suppliers are able to see that party's associated Portal Payment Methods on the Electronic Payments tab - Users with the Role of Customer or Supplier are able to add payment methods via their portal access. Customers may apply those payment methods on outstanding Sales Orders or Sales Invoices ## Workflows As noted in the [Configuration and Settings page](\u002Fdocumentation\u002Felectronic_payments\u002Fconfiguration), there are two distinct methods for posting an electronic payment - using a Journal Entry with a Clearing Account, or using a Payment Entry. The major difference between the two options is when the electronic payment reflects against the deposit account (for accepting payments) or the withdrawal account (when sending payments). With a Journal Entry and clearing account, when the electronic payment successfully clears, the balance amount moves off the Accounts Receivable or Accounts Payable account associated with the party and onto the clearing account. Only after transactions settle would the user make the entries to offset the cash transfers to\u002Ffrom the provider against the clearing account. With a Payment Entry, when the electronic payment successfully clears, the transaction immedia",{"id":223,"title":224,"content":225,"level":16},"\u002Fdocumentation\u002Ffleet\u002Fdelivery-trip-optimization\u002F","delivery-trip-optimization","\u003C!-- Copyright (c) 2025, AgriTheory and contributors For license information, please see license.txt--> # Delivery Trip Optimization When a vehicle has multiple stops, the order matters. Visiting locations in a poorly chosen sequence wastes fuel and time. Fleet can analyze a Delivery Trip's stops and suggest an efficient route. ## How Route Optimization Works Fleet uses the Valhalla routing engine, which calculates travel times using real road networks. Given a list of delivery stops, it solves the Traveling Salesperson Problem to find an order that minimizes total travel. This is not a simple \"nearest neighbor\" approach. Valhalla considers actual driving distances, turn restrictions, and road types to produce routes that work in practice. ## Optimizing a Delivery Trip Route optimization is available through the `optimize_path` function. Pass a Delivery Trip document or name, and it returns the stops in optimized order. ```python from fleet.fleet.overrides.delivery_trip import optimize_path optimized_stops = optimize_path(\"DT-00001\") ``` The function returns a list of delivery stops sorted by the recommended visit order. A developer can use this to update the Delivery Trip's stop sequence or display the optimized route to a dispatcher. ## What the Optimizer Considers The current implementation optimizes for a single vehicle visiting all stops in one trip. It assumes: - The vehicle starts at the first delivery stop - All stops must be visited - The vehicle does not need to return to a depot This fits simple delivery scenarios. For more complex routing with time windows, multiple vehicles, or capacity constraints, additional development would be needed. ## Geocoding Addresses Route optimization requires coordinates for each stop. If delivery stops have latitude and longitude populated, those coordinates are used directly. For addresses without coordinates, Fleet includes a geocoding function that looks up locations using OpenStreetMap's Nominatim service: ```python fr",{"id":227,"title":228,"content":229,"level":16},"\u002Fdocumentation\u002Ffleet\u002Fdriver-assignment\u002F","driver-assignment","\u003C!-- Copyright (c) 2025, AgriTheory and contributors For license information, please see license.txt--> # Driver Assignment Knowing who was driving a vehicle matters for compliance, accountability, and payroll. Fleet tracks driver assignments and records which driver was operating each vehicle at any given time. ## Assigning Drivers to Vehicles Open a Vehicle and find the **Drivers** field. This multi-select field links to Driver documents. Add the drivers who are authorized to operate this vehicle. When Fleet creates a Vehicle Log, it records the driver. If the GPS device reports a driver ID (some devices have RFID readers or keypads for driver identification), Fleet uses that. Otherwise, it falls back to the most recently recorded driver for that vehicle, then to the last driver in the Drivers list. This creates an audit trail. A user reviewing Vehicle Logs can see not just where a vehicle went, but who was behind the wheel. ## Syncing Drivers to Traccar Some GPS setups identify drivers through RFID cards or PIN entry. For this to work, Traccar needs to know about your drivers. When a user saves a Driver document, Fleet creates a corresponding driver record in Traccar. The Driver's name becomes the unique identifier that Traccar uses to match driver events from GPS devices. The **Traccar User ID** field on the Driver populates automatically after the sync completes. ## Connecting Driver Time to Locations Fleet's geofencing feature records when vehicles enter and exit specific locations. Combined with driver tracking, this data can support timesheet workflows. For example, a company might create geofences around customer job sites. When a driver enters a site, that event appears in the Vehicle Log. Using Frappe's Notification system, a workflow could create Timesheet entries based on these arrivals and departures. To support this, Location documents have a **Default Activity Type** field. This links to an Activity Type that describes the work typically performed at",{"id":231,"title":232,"content":233,"level":16},"\u002Fdocumentation\u002Ffleet\u002Fgeofencing\u002F","geofencing","\u003C!-- Copyright (c) 2025, AgriTheory and contributors For license information, please see license.txt--> # Geofencing Geofences are virtual boundaries around physical locations. When a vehicle crosses a configured geofence boundary, Fleet records the event. This enables use cases like tracking arrivals at customer sites, monitoring compliance with territorial restrictions, and triggering workflows based on location. ## Why Use Geofences Consider a delivery company that wants to know when drivers arrive at customer locations. Without geofencing, someone would need to watch the map constantly or review Vehicle Logs manually. With geofencing, Fleet automatically records when a vehicle enters or exits each customer site. A dispatcher can see at a glance which deliveries have arrived. Automated notifications can alert customers that their delivery is on-site. Reports can show how long vehicles spent at each location. ## Limitations Traccar does not support circle shapes for geofences. Draw a polygon that approximates a circle if you need a circular boundary. Only polygons, rectangles, and polylines work as geofence shapes. Points and other geometry types are not supported. ## Creating a Geofence Geofences are created from Location documents in ERPNext. 1. Open or create a Location document 2. In the Location field, draw a shape on the map that covers the area you want to monitor. This can be a polygon for irregular boundaries, a rectangle for simple areas, or a polyline for route corridors 3. Check **Sync Traccar Geofence** 4. Save the document Fleet creates the geofence in Traccar. The **Traccar Geofence ID** field populates automatically, confirming the sync succeeded. ## Linking Vehicles to Geofences By default, a geofence monitors all vehicles. To limit monitoring to specific vehicles, use the **Geofenced Vehicle** field on the Location. Add the vehicles that should trigger events for this geofence. Vehicles must have a valid Traccar ID before they can be linked. If y",{"id":235,"title":236,"content":237,"level":16},"\u002Fdocumentation\u002Ffleet\u002Fgps-tracking\u002F","gps-tracking","\u003C!-- Copyright (c) 2025, AgriTheory and contributors For license information, please see license.txt--> # GPS Tracking Fleet provides a central view of where all vehicles are and where they have been. This helps dispatchers coordinate deliveries, managers verify field operations, and maintenance staff locate vehicles that need service. ## Viewing Your Fleet on a Map The Fleet workspace shows an interactive map with markers for each tracked vehicle. The map adjusts its view to fit all vehicles, so a user sees the entire fleet at once. Each marker links to the Vehicle document and displays the most recent driver. Clicking a marker opens details about that vehicle. Below the map, a battery voltage table lists all active vehicles sorted by battery level, lowest first. This highlights vehicles that may need attention before their batteries fail. For companies with active deliveries, an ETA table shows Delivery Trips that are scheduled or in transit, with driver, vehicle, customer, and estimated arrival information. ## Understanding Position History Every time Fleet syncs a vehicle, it creates a Vehicle Log document. These logs accumulate into a complete movement history. To review where a vehicle has been, open the Vehicle Log list and filter by the vehicle's license plate. Each log shows the date, time, coordinates, driver, and any telemetry data the device reported. This history supports several use cases: - Verifying a driver visited a customer site on a specific date - Investigating incidents by reviewing the vehicle's location at a given time - Analyzing route patterns to identify inefficiencies - Auditing compliance with territorial restrictions ## How Syncing Works Fleet runs a scheduled task every minute. This task checks each tracked vehicle and decides whether to sync based on its configuration. Vehicles without a custom poll frequency sync immediately during each run. Vehicles with a custom poll frequency (set as a cron expression) only sync when their schedul",{"id":239,"title":23,"content":240,"level":16},"\u002Fdocumentation\u002Ffleet\u002F","\u003C!-- Copyright (c) 2025, AgriTheory and contributors For license information, please see license.txt--> # Fleet \u003Cdiv class=\"byline\"> Tyler Matteson 2025-12-30 \u003C\u002Fdiv> Fleet brings real-time vehicle tracking into ERPNext. Instead of switching between a GPS tracking system and your ERP, fleet managers can monitor vehicles, track deliveries, and schedule maintenance from a single interface. Fleet connects ERPNext to [Traccar](https:\u002F\u002Fwww.traccar.org\u002F), an open-source GPS tracking platform. Vehicles equipped with GPS devices report their positions to Traccar, and Fleet syncs this data into ERPNext automatically. This creates a record of where vehicles have been, who was driving, and what condition the vehicle was in at each point. 1. [Vehicle Management](\u002Fdocumentation\u002Ffleet\u002Fvehicle-management) — Set up your vehicles for tracking and connect them to Traccar 2. [Driver Assignment](\u002Fdocumentation\u002Ffleet\u002Fdriver-assignment) — Track which drivers operate which vehicles and when 3. [GPS Tracking](\u002Fdocumentation\u002Ffleet\u002Fgps-tracking) — View your fleet on a map and monitor vehicle locations 4. [Telemetry](\u002Fdocumentation\u002Ffleet\u002Ftelemetry) — Monitor vehicle health through battery levels, engine data, and diagnostics 5. [Geofencing](\u002Fdocumentation\u002Ffleet\u002Fgeofencing) — Get notified when vehicles arrive at or leave specific locations 6. [Delivery Trip Optimization](\u002Fdocumentation\u002Ffleet\u002Fdelivery-trip-optimization) — Find the most efficient route for multiple delivery stops ## Requirements Fleet requires Frappe Framework, ERPNext, and HRMS. A Traccar server instance (self-hosted or cloud) provides the GPS tracking backend. ",{"id":242,"title":243,"content":244,"level":16},"\u002Fdocumentation\u002Ffleet\u002Ftelemetry\u002F","telemetry","\u003C!-- Copyright (c) 2025, AgriTheory and contributors For license information, please see license.txt--> # Telemetry Modern GPS devices report more than just location. They can capture battery voltage, engine RPM, speed, temperature, fuel levels, and diagnostic codes. Fleet stores this data in Vehicle Logs, making it available for monitoring and analysis. ## What Fleet Captures Each Vehicle Log can include: - **Coordinates**: Longitude and latitude from the GPS fix - **Speed**: The vehicle's speed at the time of the reading - **Battery Level**: External battery voltage, useful for detecting charging issues - **Engine Hours**: Total runtime, helpful for scheduling maintenance by operating hours rather than mileage - **RPM**: Engine revolutions per minute - **Engine Temperature**: Helps identify overheating before it causes damage - **Fuel Quantity**: Fuel level if the device supports fuel sensors - **Odometer**: Calculated from the device's total distance reading - **Diagnostic Codes**: OBD-II trouble codes that indicate mechanical issues Not every device reports all of these. The data available depends on the GPS hardware and how it connects to the vehicle. ## Monitoring Battery Health The Fleet workspace includes a battery voltage report that lists all active vehicles sorted by battery level, lowest first. This makes it easy to spot vehicles with failing batteries before they leave drivers stranded. For automated alerts, configure the Traccar Integration settings: 1. Set **External Battery Low Threshold** to a voltage level that indicates a problem 2. Link a Notification document in **Battery Level Notification** When a vehicle's battery drops below the threshold, the notification triggers. ## Scheduling Syncs for Critical Vehicles By default, Fleet syncs every vehicle once per minute. For vehicles on time-sensitive routes or carrying valuable cargo, more frequent updates might be necessary. For vehicles parked overnight, less frequent syncs reduce unnecessary load.",{"id":246,"title":247,"content":248,"level":16},"\u002Fdocumentation\u002Ffleet\u002Fvehicle-management\u002F","vehicle-management","\u003C!-- Copyright (c) 2025, AgriTheory and contributors For license information, please see license.txt--> # Vehicle Management Before Fleet can track a vehicle, the vehicle needs a GPS device and a connection between ERPNext and Traccar. This guide walks through setting up that connection. ## Connecting to Traccar Fleet needs to know where your Traccar server is and how to authenticate. A system manager configures this once in Traccar Integration. Navigate to Traccar Integration and enter: - **Traccar Server URL**: The full address of your Traccar instance, for example `https:\u002F\u002Ftraccar.example.com` - **Username** and **Password**: Credentials for a Traccar account with permission to manage devices - **Enable Traccar**: Check this box to activate the integration If your GPS devices report distances in meters but you track odometer readings in miles, set the Traccar Distance UoM and ERPNext Distance UoM fields. Then select the appropriate UOM Conversion Factor to convert between them. ## Setting Up a Vehicle for Tracking Each vehicle needs a unique identifier that matches its GPS device. Open the Vehicle record and go to the Telemetry tab. Enter the **Traccar IMEI** field with the device's unique identifier. This is typically the IMEI number printed on the GPS device or shown in Traccar's device list. When you save the Vehicle, Fleet checks Traccar for a device with that identifier. If one exists, Fleet links to it. If not, Fleet creates a new device in Traccar automatically. After saving, the **Traccar ID** field populates with Traccar's internal device ID. This confirms the connection is working. ## How Position Data Flows into ERPNext Fleet runs a background task every minute that checks each tracked vehicle's position in Traccar. When it finds new position data, it creates a Vehicle Log document with the coordinates, timestamp, and any telemetry the device reported. This means every position update becomes a permanent record in ERPNext. A user can review a vehicle's",{"id":250,"title":251,"content":252,"level":16},"\u002Fdocumentation\u002Fforecast\u002Fdate_binning\u002F","date_binning","# Date Binning with the `Period` Class The following code demonstrates various ways to use and apply the functionality in the `Period` class. In general, the class expects a date range defined with a `start_date` and `end_date`, and a `periodicity` (see options below). From there, it can generate date bins from `start_date` to `end_date` (inclusive by default) for the given `periodicity`. Date bins are in the form of a list of tuples, where each tuple contains that bin's start date and end date. The class can also convert given date bins from one periodicity to another, it can redistribute data from one periodicity to another given the data and original date bins, and can output pre-defined or custom labels. The class supports the following options for `periodicity`. The ISO options follow the ISO-8601 Standard. If a `periodicity` isn't provided, the default is \"ISO Week\". - \"ISO Week\" (default): weekly bins starting on a Monday - \"ISO Biweekly\": bins of 2 ISO week periods, grouping weeks 01 and 02, then 03 with 04, etc. - \"ISO Month (4 Weeks)\": monthly bins where months are defined by grouping ISO weeks within the ISO year in a pattern of 4 weeks each (this creates 13 months). Month 1 is weeks 01-04, month 2 is weeks 05-08, etc. - \"ISO Month (4 + 5 + 4)\": monthly bins where months are defined by grouping ISO weeks within the ISO year in a pattern of 4 weeks, 5 weeks, then 4 weeks. Month 1 is weeks 01-04, month 2 is weeks 05-09, etc. - \"ISO Month (4 + 4 + 5)\": monthly bins where months are defined by grouping ISO weeks within the ISO year in a pattern of 4 weeks, 4 weeks, then 5 weeks. Month 1 is weeks 01-04, month 2 is weeks 05-08, etc. - \"ISO Quarter (13 Weeks)\": quarterly bins of 13 ISO week periods. Quarter 1 is weeks 01-13, quarter 2 is weeks 14-26, etc. - \"ISO Semiannual (26 Weeks)\": semiannual bins of 26 ISO week periods. The first period is weeks 01-26 and second is weeks 27 to either 52 or 53, depending on the year - \"ISO Annual\": bins of full ISO years. If",{"id":254,"title":23,"content":255,"level":16},"\u002Fdocumentation\u002Fforecast\u002F","# Forecast Methods The `Forecast` class includes 12 methods to generate a forecast from the provided data, which are explained in detail below. The class expects all inputs to be of type `Decimal` and uses `Decimal` objects throughout the calculations for accuracy. The `data` attribute on the class holds the provided historical data to base the forecast on, and should be a sequence of sequences of values, preferably all the same length. The example calculations all use two calendar years' worth of monthly sales figures, so the `data` attribute is set on a `Forecast` object as a list of two lists in chronological order, each with 12 `Decimal` values. Only one forecasting method (`Calculated Percent Over Previous Period`) requires that the input `data` is comprised of two sequences of values, all other methods can work when `data` has only one sequence in it. The following example calculations lay out the math in Python, and utilize functionality from the `numpy`, `pandas`, and `scipy` packages for convenience, but note that the `Forecast` class implements the math without these packages. After the example calculation for each method, there's an example using the `Forecast` class. Note there are some small differences between the example calculation results and `Forecast` results, which are due to `float`-to-`Decimal` conversions and at what point those conversions are done in the calculation. After a forecasting method is called on an instance of `Forecast`, the forecast itself is available as a list in the `forecast` attribute. By default, every method generates a forecast with the same number of periods as the most recent sequence of values provided in `data`. In the examples below, the forecasts are all for 12 periods (12 months of a calendar year). However, all methods take an argument for `n` so users can specify a different number of periods in the forecast. **Table of Contents** - [Method 1: Percent Over Previous Period](#percentoverpreviousperiod) - [Method 2",{"id":257,"title":14,"content":258,"level":16},"\u002Fdocumentation\u002Ffrappe_vault\u002Fconfiguration\u002F","\u003C!-- Copyright (c) 2025, AgriTheory and contributors For license information, please see license.txt--> # Frappe Vault Site Configuration \u003Cdiv class=\"byline\"> Tyler Matteson 2026-03-07 \u003C\u002Fdiv> ## Site Config Options Add the following keys to your site's configuration file (`\u002Fsites\u002F{site_name}\u002Fsite_config.json`): ```json { \u002F\u002F Enable OpenBao storage for Frappe Password fields (API keys, secrets, etc.) \"vault_password_fields_enabled\": true, \u002F\u002F Enable OpenBao storage for user login passwords (hashed) \"enable_vault_user_passwords\": true, \u002F\u002F Enable the Vault Secret doctype, CRUD API, and desk UI \"vault_secrets_api_enabled\": true, \u002F\u002F OpenBao server URL \u002F\u002F Can also be set via BAO_ADDR or VAULT_ADDR environment variable \"vault_url\": \"http:\u002F\u002Flocalhost:8200\", \u002F\u002F OpenBao authentication token \u002F\u002F RECOMMENDED: Use BAO_TOKEN or VAULT_TOKEN environment variable instead for production \"vault_token\": \"bao.xxxxxxxxxxxxx\" } ``` ## Configuration Options Reference ### Core Settings | Key | Type | Default | Description | |-----|------|---------|-------------| | `vault_password_fields_enabled` | boolean | `false` | Enable OpenBao storage for Frappe Password-type fields (API keys, retrievable secrets) | | `enable_vault_user_passwords` | boolean | `false` | Enable OpenBao storage for user login passwords (hashed) | | `vault_secrets_api_enabled` | boolean | `false` | Enable the Vault Secret doctype, CRUD API, and desk UI | | `vault_url` | string | `http:\u002F\u002Flocalhost:8200` | OpenBao server URL | | `vault_token` | string | - | OpenBao authentication token | ### Proxy API Settings | Key | Type | Default | Description | |-----|------|---------|-------------| | `vault_proxy_enabled` | boolean | `false` | Enable the Vault proxy API for external access | | `vault_allowed_roles` | list | `[\"System Manager\"]` | Roles allowed to use the proxy API | ### Multi-Site Sync Settings | Key | Type | Default | Description | |-----|------|---------|-------------| | `vault_sync_enabled` | boolean | `false` | Enable ",{"id":260,"title":182,"content":261,"level":16},"\u002Fdocumentation\u002Ffrappe_vault\u002Fdevelopment\u002F","\u003C!-- Copyright (c) 2025, AgriTheory and contributors For license information, please see license.txt--> # Frappe Vault Developer Setup \u003Cdiv class=\"byline\"> Tyler Matteson 2026-03-07 \u003C\u002Fdiv> Before you begin, make sure that your Python version is 3.10 or later for Frappe version 15. ## Prerequisites - Python 3.10+ - Node.js 18+ - MariaDB 10.6+ - Redis - OpenBao (see [What is OpenBao?](#what-is-openbao)) ### What is OpenBao? [OpenBao](https:\u002F\u002Fopenbao.org) is an open-source fork of HashiCorp Vault (MPL-2.0 licensed), governed by the Open Source Security Foundation (OpenSSF). It provides identity-based secrets and encryption management with API compatibility to Vault OSS v1.14.x. ## Setup Instructions 1. **Set up a new bench** using [pyenv](https:\u002F\u002Fgithub.com\u002Fpyenv\u002Fpyenv) for managing Python environments: ```shell bench init --frappe-branch version-15 {{ bench name }} --python ~\u002F.pyenv\u002Fversions\u002F3.10.12\u002Fbin\u002Fpython3 ``` 2. **Create a new site**: ```shell cd {{ bench name }} bench new-site {{ site name }} --force --db-name {{ site name }} ``` 3. **Download the Frappe Vault application**: ```shell bench get-app frappe_vault https:\u002F\u002Fgithub.com\u002Fagritheory\u002Ffrappe_vault.git ``` 4. **Install the app to your site**: ```shell bench --site {{ site name }} install-app frappe_vault # Optional: Check that the app installed on your site bench --site {{ site name }} list-apps ``` 5. **Set developer mode** in `site_config.json`: ```shell nano sites\u002F{{ site name }}\u002Fsite_config.json # Add this line: \"developer_mode\": 1, ``` 6. **Add the site to your hosts file**: ```shell bench --site {{ site name }} add-to-hosts ``` 7. **Install OpenBao**: ```shell # macOS: brew install openbao # Linux (download .deb from GitHub releases): VERSION=\"2.4.4\" # Check https:\u002F\u002Fgithub.com\u002Fopenbao\u002Fopenbao\u002Freleases for latest wget https:\u002F\u002Fgithub.com\u002Fopenbao\u002Fopenbao\u002Freleases\u002Fdownload\u002Fv${VERSION}\u002Fbao-hsm_${VERSION}_linux_amd64.deb sudo dpkg -i bao-hsm_${VERSION}_linux_amd64.deb ``` 8. **Set up OpenBao**: ```shell ben",{"id":263,"title":23,"content":264,"level":16},"\u002Fdocumentation\u002Ffrappe_vault\u002F","\u003C!-- Copyright (c) 2025, AgriTheory and contributors For license information, please see license.txt--> # Frappe Vault Documentation \u003Cdiv class=\"byline\"> Tyler Matteson 2026-03-07 \u003C\u002Fdiv> Frappe Vault integrates OpenBao with Frappe Framework to provide enterprise-grade secret management for password fields. Instead of storing sensitive data in Frappe's database, secrets are securely stored in a dedicated OpenBao instance with full audit logging capabilities. ## What is OpenBao? [OpenBao](https:\u002F\u002Fopenbao.org) is an open-source fork of HashiCorp Vault, created after HashiCorp changed Vault's license from MPL-2.0 to BSL (Business Source License) in 2023. * **License**: MPL-2.0 (Mozilla Public License 2.0) - fully open source * **Governance**: Governed by the [Open Source Security Foundation (OpenSSF)](https:\u002F\u002Fopenssf.org\u002F) * **API Compatibility**: Maintains API compatibility with Vault OSS v1.14.x * **Purpose**: Identity-based secrets and encryption management OpenBao provides the same core functionality as Vault: secure secret storage, dynamic secrets, leasing and renewal, revocation, and encryption-as-a-service. ## Compliance This integration is designed to meet compliance requirements for DCAA, CMMC, HIPAA, and SOC2 by providing: * **Cryptographic isolation**: Secrets stored separately from application data * **Audit trails**: All secret access logged immutably in OpenBao * **Per-customer isolation**: Each deployment runs its own OpenBao instance * **Credential rotation**: Support for automated password rotation via OpenBao ## Documentation * [Developer Environment Setup](\u002Fdocumentation\u002Ffrappe_vault\u002Fdevelopment) * [Production Environment Setup](\u002Fdocumentation\u002Ffrappe_vault\u002Fproduction) * [Site Configuration](\u002Fdocumentation\u002Ffrappe_vault\u002Fconfiguration) * [OpenBao Setup Guide](\u002Fdocumentation\u002Ffrappe_vault\u002Fopenbao-setup) ## How It Works Frappe Vault intercepts Frappe's password storage and retrieval functions, routing them through OpenBao instead of Frappe's `__Auth` databa",{"id":266,"title":267,"content":268,"level":16},"\u002Fdocumentation\u002Ffrappe_vault\u002Fopenbao-setup\u002F","openbao-setup","\u003C!-- Copyright (c) 2025, AgriTheory and contributors For license information, please see license.txt--> # OpenBao Setup Guide \u003Cdiv class=\"byline\"> Tyler Matteson 2026-01-17 \u003C\u002Fdiv> This guide covers setting up OpenBao for use with Frappe Vault. ## What is OpenBao? [OpenBao](https:\u002F\u002Fopenbao.org) is an open-source fork of HashiCorp Vault, created after HashiCorp changed Vault's license from MPL-2.0 to BSL in 2023. It is governed by the [Open Source Security Foundation (OpenSSF)](https:\u002F\u002Fopenssf.org\u002F) and maintains API compatibility with Vault OSS v1.14.x. - **License**: MPL-2.0 (Mozilla Public License 2.0) - **CLI Command**: `bao` (instead of `vault`) - **Environment Variables**: `BAO_ADDR`, `BAO_TOKEN` (also supports legacy `VAULT_ADDR`, `VAULT_TOKEN`) ## Installation See the [official OpenBao installation guide](https:\u002F\u002Fopenbao.org\u002Fdocs\u002Finstall) for the latest instructions. ### macOS (Homebrew) ```shell brew install openbao ``` ### FreeBSD ```shell pkg install openbao ``` ### Linux (Manual Download) OpenBao does not yet have a Linux package repository. Download packages manually from the [GitHub releases page](https:\u002F\u002Fgithub.com\u002Fopenbao\u002Fopenbao\u002Freleases): ```shell # Example for Ubuntu\u002FDebian (amd64) VERSION=\"2.4.4\" # Check for latest version wget https:\u002F\u002Fgithub.com\u002Fopenbao\u002Fopenbao\u002Freleases\u002Fdownload\u002Fv${VERSION}\u002Fbao-hsm_${VERSION}_linux_amd64.deb sudo dpkg -i bao-hsm_${VERSION}_linux_amd64.deb ``` ### Container Images OpenBao provides pre-built container images: ```shell # Alpine-based (recommended) docker pull quay.io\u002Fopenbao\u002Fopenbao:latest # or docker pull ghcr.io\u002Fopenbao\u002Fopenbao:latest # or docker pull docker.io\u002Fopenbao\u002Fopenbao:latest # RHEL UBI-based docker pull quay.io\u002Fopenbao\u002Fopenbao-ubi:latest ``` ### Precompiled Binaries Download the appropriate binary for your system from the [releases page](https:\u002F\u002Fgithub.com\u002Fopenbao\u002Fopenbao\u002Freleases), unzip, and place the `bao` binary on your `PATH`. ## Development Setup For development, use the automated setup command: ```s",{"id":270,"title":196,"content":271,"level":16},"\u002Fdocumentation\u002Ffrappe_vault\u002Fproduction\u002F","\u003C!-- Copyright (c) 2025, AgriTheory and contributors For license information, please see license.txt--> # Frappe Vault Production Setup \u003Cdiv class=\"byline\"> Tyler Matteson 2026-03-07 \u003C\u002Fdiv> Before you begin, ensure your server meets the following requirements: - Python 3.10+ for Frappe version 15 - OpenBao installed and configured (see [OpenBao Setup Guide](\u002Fdocumentation\u002Ffrappe_vault\u002Fopenbao-setup)) ## Installation 1. **Set up a new bench**: ```shell bench init --frappe-branch version-15 {{ bench name }} --python ~\u002F.pyenv\u002Fversions\u002F3.10.12\u002Fbin\u002Fpython3 ``` 2. **Create a new site**: ```shell cd {{ bench name }} bench new-site {{ site name }} --force --db-name {{ site name }} ``` 3. **Download the Frappe Vault application**: ```shell bench get-app frappe_vault git@github.com:agritheory\u002Ffrappe_vault.git ``` 4. **Install the app to your site**: ```shell bench --site {{ site name }} install-app frappe_vault # Optional: Verify installation bench --site {{ site name }} list-apps ``` 5. **Set up OpenBao**: ```shell bench setup-openbao --production --site {{ site name }} ``` `bench setup-openbao` handles the full setup in one command: - Generates `config\u002Fopenbao.hcl` (static auto-unseal), `config\u002Fopenbao-seal.key`, and `config\u002Fopenbao-data\u002F` - Writes `\u002Fetc\u002Fsupervisor\u002Fconf.d\u002Fopenbao.conf` and reloads supervisor (uses `sudo tee` if not running as root) - Starts OpenBao via supervisor and waits for it to be ready - Initialises OpenBao and saves recovery keys to `config\u002Fopenbao-recovery-keys.txt` (0600) - Enables the KV v2 secrets engine at `secret\u002F` - Writes `vault_url` and `vault_token` to `{{ site name }}\u002Fsite_config.json` (feature flags are not enabled automatically) > **Security note**: `setup-openbao` writes the root token directly to `site_config.json` for convenience. For production, replace it with a restricted policy token once the site is running — see [OpenBao Token Policy](#openbao-token-policy) below. You can also supply the token via environment variable instead: >",{"id":273,"title":274,"content":275,"level":16},"\u002Fdocumentation\u002Finventory_tools\u002Falternate_workstation\u002F","alternate_workstation","\u003C!-- Copyright (c) 2025, AgriTheory and contributors For license information, please see license.txt--> # Alternative Workstation Functionality \u003Cdiv class=\"byline\"> Rohan Bansal, coleandreoli, IshwaryaM1030, Tyler Matteson, and Francisco Roldán 2026-09-01 \u003C\u002Fdiv> ## Overview Manufacturing operations often face bottlenecks when a workstation is unavailable (maintenance, overload, breakdown). To ensure flexibility, Inventory Tools now supports **Alternative Workstations**. - Each **Operation** can be linked with multiple alternative workstations. - A **Work Order** inherits these alternatives. - Users can quickly switch from the **primary workstation** to an **alternative** through the **Alternative Workstations Page**. --- ## How It Works ### 1. Define Alternatives in Operation In the **Operation Doctype**, a field **Alternative Workstations** is available. This allows selecting multiple workstations that can perform the same operation. **Example:** - Operation: Cutting - Primary Workstation: **ST1** - Alternatives: **ST2, ST3** --- ### 2. Work Order Setup When a **Work Order** is created: - Each operation inherits its **primary workstation**. - Alternatives remain available for assignment if needed. --- ### 3. Alternative Workstations Page Steps: 1. Navigate to **Alternative Workstations Page**. 2. Select a **Work Order** from the filter. 3. The system displays all operations under that Work Order, with: - **Primary Workstation** (currently assigned) - **Alternative Workstations** (from the Operation master) --- ### 4. Assigning an Alternative For each operation row, available alternatives are shown with a **“Use Alternative”** button. - ### Rendering - **Primary Workstation Card** - Shows workstation name, next available time, capacity, and planned start. - Card color logic: - **Purple:** Non-default workstation chosen. - **Green:** Default workstation available and earliest option. - **Yellow:** Default workstation is busy or not the earliest option. - **Alternativ",{"id":277,"title":278,"content":279,"level":16},"\u002Fdocumentation\u002Finventory_tools\u002Falternative_sales_workflow\u002F","alternative_sales_workflow","\u003C!-- Copyright (c) 2026, AgriTheory and contributors For license information, please see license.txt--> # Alternative Sales Workflow \u003Cdiv class=\"byline\"> Tyler Matteson 2026-09-02 \u003C\u002Fdiv> ## Purpose When **Enable Alternative Sales Workflow** is checked on [Inventory Tools Settings](\u002Fdocumentation\u002Finventory_tools\u002Findex), Inventory Tools adds these sales paths without removing any existing ERPNext Create buttons. Sites that want a narrower policy (for example, no Create → Delivery Note on the Sales Order) hide those buttons themselves. ## Enabled path graph These edges are all available at once; they are not an exclusive pipeline: \u003Cdiv class=\"mermaid-chart-container\"> \u003Cdiv class=\"mermaid-svg-version\">\u003Csvg id=\"mermaid-svg-0\" width=\"100%\" xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" xmlns:xlink=\"http:\u002F\u002Fwww.w3.org\u002F1999\u002Fxlink\" class=\"flowchart\" style=\"max-width: 926.84375px;\" viewBox=\"0 -35 926.84375 260\" role=\"graphics-document document\" aria-roledescription=\"flowchart-v2\">\u003Cstyle>#mermaid-svg-0{font-family:inherit;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-0 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-0 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-0 .error-icon{fill:#552222;}#mermaid-svg-0 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-0 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-0 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-0 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-0 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-0 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-0 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-0 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-0 .marker.cross{stroke:#333333;}#mermaid-svg-0 svg{font-fam",{"id":281,"title":282,"content":283,"level":16},"\u002Fdocumentation\u002Finventory_tools\u002Fcartonization\u002F","cartonization","\u003C!-- Copyright (c) 2026, AgriTheory and contributors For license information, please see license.txt--> # Cartonization Configuration & Validation Guide \u003Cdiv class=\"byline\"> AgriTheory 2026-09-07 \u003C\u002Fdiv> ## 1. Purpose of Cartonization Cartonization ensures that items involved in inventory transactions (Pick List, Stock Entry, Delivery Note, etc.) physically fit into their target containers (warehouses, bins, pallets, cartons). It validates packing feasibility using: - Physical dimensions of items - Physical dimensions of containers - Configurable packing algorithms - Configurable enforcement policies Validation runs on document **submission**, not on save. Documents can be saved freely; cartonization is only enforced at submit time. --- ## 2. Inventory Tools Settings – Cartonization Configuration Cartonization is configured from: **Inventory Tools Settings → Cartonization Tab** ### 2.1 Enable \u002F Disable | Field | Description | |-----|------------| | Enable Cartonization | Master switch. If unchecked, all cartonization logic is skipped | --- ### 2.2 Packing Mode Configuration | Field | Description | |-----|------------| | Default Packing Mode | Algorithm used to validate packing | Available modes: - 2D Floor Packing - 3D Volumetric - 3D Fitted --- ### 2.3 Validation Policies Each packing mode has an independent policy: | Policy | Behavior | |------|---------| | Ignore | Validation is skipped | | Warn | Validation runs, warning is shown, document proceeds | | Error | Validation runs, document submission is blocked | Configured fields: - Floor Packing Policy - Volumetric Policy - Fitted Policy --- ### 2.4 Additional Options | Field | Description | |-----|------------| | Allow Rotation | Allows item L\u002FW rotation in the 3D fitted solver | | Solver Timeout (Seconds) | Maximum time allowed for 3D fitted solver (default: 30) | | Weight Validation | Ignore \u002F Warn \u002F Error for weight limit checks | | Max Weight UOM | Unit used for weight comparison (informational) | --- ### 2.5 ",{"id":285,"title":286,"content":287,"level":16},"\u002Fdocumentation\u002Finventory_tools\u002Ffaceted_search\u002F","faceted_search","\u003C!-- Copyright (c) 2024, AgriTheory and contributors For license information, please see license.txt--> # Faceted Search \u003Cdiv class=\"byline\"> Rohan Bansal, Devarsh Bhatt, coleandreoli, Heather Kusmierz, Tyler Matteson, and Francisco Roldán 2026-09-01 \u003C\u002Fdiv> Faceted search works on top of ERPNext's Shopping Cart to add additional Ecommerce controls for marketplace users. This feature allows you to list your products under `\u002Fall-products` and filter them based on their specifications. # Manual Setup Follow the steps to create your first listed product with multiple specifications and their variations. ### Steps: 1. Items and Website Items should be configured according to the instructions provided for the [Ecommerce Module](https:\u002F\u002Fdocs.erpnext.com\u002Fdocs\u002Fuser\u002Fmanual\u002Fen\u002Fset_up_e_commerce) 2. To create Specifications for the Item: 1. Type `Specification` in Awesomebar > `Add Specification`. 2. Select `DocType` on which you would like to customize the specification. 3. Select `Apply On` based on the doctype or leave it blank to apply to all records of that DocType. This currently only works for Item. 4. Mark it `Enabled`. ![Screen shot of ](\u002Fdocumentation\u002Finventory_tools\u002Fassets\u002Fspecification.PNG) 5. Under `Attributes` table click `Add Row` > `Edit`. - Write unique `Attribute Name`. - Choose if the value is expected to be a `Date Value` or `Numeric Value`. - Select `Apply On` (In this case, we can choose `Item`). - Optionally select the `Field` on which the attribute should be applied. - Choose a `Component` based on the following criteria: 1. `FacetedSearchColorPicker`: if the attribute is related to colors. 2. `FacetedSearchDateRange`: if the attribute is related to date values. 3. `FacetedSearchNumericRange`: if the attribute is related to numeric values. 4. `AttributeFilter`: if the attribute doesn't belong to any of the above. ![Screen shot of ](\u002Fdocumentation\u002Finventory_tools\u002Fassets\u002Fspecification_attribute.PNG) - `Save` the Specification(s). 7. Create `Specification V",{"id":289,"title":23,"content":290,"level":16},"\u002Fdocumentation\u002Finventory_tools\u002F","\u003C!-- Copyright (c) 2024, AgriTheory and contributors For license information, please see license.txt--> # Inventory Tools Documentation \u003Cdiv class=\"byline\"> Rohan Bansal, Devarsh Bhatt, coleandreoli, IshwaryaM1030, Heather Kusmierz, Tyler Matteson, and Francisco Roldán 2026-09-01 \u003C\u002Fdiv> The Inventory Tools application enhances and extends inventory-related functionality and workflows in ERPNext. It includes the following features: - **[Material Demand](\u002Fdocumentation\u002Finventory_tools\u002Fmaterial_demand)**: a report-based interface to aggregate required Items across multiple sources, then optionally create Purchase Orders or Request for Quotations - **[Warehouse Path](\u002Fdocumentation\u002Finventory_tools\u002Fwarehouse_path)**: for any warehouse selection field, this features helps clearly identify warehouses by creating a warehouse path and adding a human-readable string under the warehouse name in the format \"parent warehouse(s)->warehouse\" - **[Quotation Demand](\u002Fdocumentation\u002Finventory_tools\u002Fquotation_demand)**: a report-based interface to aggregate required Items across multiple Quotations, Customers, and Companies, then create draft Sales Orders - **[Warehouse Path](\u002Fdocumentation\u002Finventory_tools\u002Fwarehouse_path)**: for any warehouse selection field, this feature helps clearly identify warehouses by creating a warehouse path and adding a human-readable string under the warehouse name in the format \"parent warehouse(s)->warehouse\" - **[Warehouse Plan](\u002Fdocumentation\u002Finventory_tools\u002Fwarehouse_plan)**: optimizes pick list walking paths within a warehouse using a 2D floor plan representation and shortest-path algorithms, with support for FIFO, LIFO, and bin depletion strategies - **[Subcontracting Workflow via Work Order](\u002Fdocumentation\u002Finventory_tools\u002Fwo_subcontracting)**: an alternative to ERPNext's subcontracting workflow that enables a user to employ Work Orders, subcontracting Purchase Orders, and manufacturing Stock Entries in lieu of Purchase Receipts or Subcontracting Orde",{"id":292,"title":293,"content":294,"level":16},"\u002Fdocumentation\u002Finventory_tools\u002Flanded_costing\u002F","landed_costing","\u003C!-- Copyright (c) 2024, AgriTheory and contributors For license information, please see license.txt--> # Inline Landed Costing \u003Cdiv class=\"byline\"> Rohan Bansal, coleandreoli, Heather Kusmierz, Tyler Matteson, and Francisco Roldán 2026-09-01 \u003C\u002Fdiv> Coming soon! ",{"id":296,"title":297,"content":298,"level":16},"\u002Fdocumentation\u002Finventory_tools\u002Fmanufacturing_capacity\u002F","manufacturing_capacity","\u003C!-- Copyright (c) 2024, AgriTheory and contributors For license information, please see license.txt--> # Manufacturing Capacity Report \u003Cdiv class=\"byline\"> Rohan Bansal, coleandreoli, Heather Kusmierz, Tyler Matteson, and Francisco Roldán 2026-09-01 \u003C\u002Fdiv> Manufacturing Capacity is a report-based interface that, given a BOM and Warehouse, displays the demand and in-stock quantities for the entire hierarchy of any BOM tree containing that BOM. Once the filters are set, the report traverses the BOM tree to find the top-level parents of the given BOM. From there, it finds total demand based on outstanding Sales Orders, Material Requests (of type \"Manufacture\"), and Work Orders, adjusting for any overlap. In stock quantities for each level are determined based on the selected Warehouse. The Parts Can Build quantity is based on what is in stock (for non-BOM\u002Fraw material rows) or the minimum Parts can Build of sub-levels for BOM rows. The Parts Can Build Qty is slightly different for non-BOM vs BOM rows. For non-BOM (raw material) rows, it's the In Stock Qty divided by the Qty per Parent BOM. For BOM rows, it's the minimum of the Parts Can Build for all sub-assemblies. So if a BOM row requires a raw material that isn't in stock, it will show 0 Parts Can Build Qty, even if there are other sub assemblies in stock. The Difference Qty calculation is also different for non-BOM and BOM rows. Since non-BOM rows account for the In Stock Qty in the Parts Can Build Qty number, the Difference Qty is the Parts Can Build less the Demanded Qty. For BOM rows, since the Parts Can Build Qty is based off available sub-assembly item quantities (and doesn't use the In Stock Qty in that calculation), the Difference Qty is the In Stock Qty plus Parts Can Build Qty less the Demanded Qty. ![Screen shot showing the Manufacturing Capacity report output for the Ambrosia Pie BOM and all Warehouses. There are rows for all levels of the BOM hierarchy - the Pie itself, sub-level rows for each sub-asse",{"id":300,"title":301,"content":302,"level":16},"\u002Fdocumentation\u002Finventory_tools\u002Fmaterial_demand\u002F","material_demand","\u003C!-- Copyright (c) 2024, AgriTheory and contributors For license information, please see license.txt--> # Material Demand \u003Cdiv class=\"byline\"> Rohan Bansal, coleandreoli, Heather Kusmierz, Tyler Matteson, and Francisco Roldán 2026-09-01 \u003C\u002Fdiv> Material Demand is a report-based interface that allows you to aggregate required Items across multiple Material Requests, Suppliers, and requesting Companies. From there, you can create draft Purchase Orders (PO), draft Request for Quotations (RFQ), or a combination of the two based on the Item's configuration. ![Screen shot of the Material Demand report showing rows of Items grouped by supplier with columns for the Supplier, Material Request document ID, Required By date, Item, MR Qty, Draft POs, Total Selected, UOM, Price, and Selected Amount](\u002Fdocumentation\u002Finventory_tools\u002Fassets\u002Fmd_report_view.png) The right-hand side of the report has selection boxes to indicate which rows of Items to include to create the documents. Ticking the top-level supplier box will automatically check all the Items for that supplier. ![Screen shot of a Material Demand Report with the boxes next to supplier Chelsea Fruit Co's Items all checked](\u002Fdocumentation\u002Finventory_tools\u002Fassets\u002Fmd_selection.png) Once you're satisfied with your selections, clicking the Create button will give you three options to generate draft documents: 1. Create PO(s) will create a Purchase Order for each supplier selected. If there is more than one company requesting materials from the same supplier, it marks the PO as a Multi-Company Purchase Order 2. Create RFQ(s) will create a Request for Quotation for each supplier-item combination 3. Create based on Item will create RFQs and\u002For POs depending on how the Item's supplier list is configured (in the Item master) All generated documents remain in draft status to allow you to make edits as needed before submitting them. ### Create Purchase Orders If you select the Create PO(s) option, a dialog window will appear to select the",{"id":304,"title":305,"content":306,"level":16},"\u002Fdocumentation\u002Finventory_tools\u002Fmulti_company_sales_order\u002F","multi_company_sales_order","\u003C!-- Copyright (c) 2024, AgriTheory and contributors For license information, please see license.txt--> # Multi-Company Sales Order \u003Cdiv class=\"byline\"> Tyler Matteson 2026-09-01 \u003C\u002Fdiv> ## Overview In multi-company ERPNext setups, a parent company may fulfill customer orders using inventory from multiple subsidiary companies. The standard ERPNext validation requires that all warehouses in a Sales Order belong to the same company as the Sales Order itself. This feature relaxes that constraint when the `Multi-Company Sales Order` flag is enabled. ## How It Works When a Sales Order has the `Multi-Company Sales Order` checkbox enabled: 1. **Warehouse Validation**: The system skips the company-warehouse validation, allowing warehouses from different companies to be used in the same Sales Order 2. **Quotation Validation**: The system skips company matching validation against linked Quotations, enabling cross-company order fulfillment This allows a central sales company to create orders that draw inventory from multiple subsidiaries while maintaining proper audit trails and accounting. ## Use Cases ### Centralized Sales with Distributed Inventory A holding company manages sales for multiple subsidiaries. When a customer places an order, the sales team can fulfill it using inventory from whichever subsidiary has the items in stock, without creating separate orders for each company. ### Regional Fulfillment A company with regional warehouses under different legal entities can fulfill orders from the nearest location to the customer, regardless of which company owns that warehouse. ### Inter-Company Transfers Combined with ERPNext's inter-company transaction features, this enables seamless order fulfillment across company boundaries while maintaining proper financial records. ",{"id":308,"title":309,"content":310,"level":16},"\u002Fdocumentation\u002Finventory_tools\u002Foverproduction_allowance\u002F","overproduction_allowance","\u003C!-- Copyright (c) 2024, AgriTheory and contributors For license information, please see license.txt--> # Overproduction Allowance \u003Cdiv class=\"byline\"> Tyler Matteson 2026-09-01 \u003C\u002Fdiv> ## Overview Manufacturing processes often produce slightly more or fewer items than planned due to process variability, yield differences, or operational efficiency. The Overproduction Allowance feature allows you to configure an acceptable percentage above the planned quantity that can be manufactured without triggering validation errors. This feature extends ERPNext's standard overproduction percentage setting by allowing configuration at multiple levels with a clear precedence hierarchy. ## Configuration Precedence The overproduction allowance percentage is determined using the following priority (highest to lowest): 1. **BOM Level**: The `Overproduction Percentage for Work Order` field on the Bill of Materials 2. **Company Level**: The `Overproduction Percentage for Work Order` field in Inventory Tools Settings 3. **Global Level**: Falls back to ERPNext's Manufacturing Settings if no company-specific setting exists This hierarchy allows you to set a default allowance for your company while overriding it for specific BOMs that may have different yield characteristics. ## Where Overproduction Is Enforced The overproduction allowance is validated across multiple manufacturing documents: ### Work Order - Validates that manufactured and transferred quantities don't exceed the Work Order quantity plus allowance - Validates that operation completed quantities stay within the allowed threshold - Displays the current overproduction percentage when the Work Order is loaded ### Job Card - Validates that the total completed quantity doesn't exceed the quantity to manufacture plus the allowance percentage - Allows partial completion while preventing over-manufacturing ### Stock Entry - **Material Transfer for Manufacture**: Validates that transferred quantities don't exceed what's needed for t",{"id":312,"title":313,"content":314,"level":16},"\u002Fdocumentation\u002Finventory_tools\u002Fquarantine_quality_control_workflows\u002F","quarantine_quality_control_workflows","\u003C!-- Copyright (c) 2026, AgriTheory and contributors For license information, please see license.txt--> # Quarantine Quality Control \u003Cdiv class=\"byline\"> IshwaryaM1030 and Tyler Matteson 2026-09-01 \u003C\u002Fdiv> ## Overview The Quarantine Quality Control feature allows inventory to be automatically moved to a quarantine warehouse for inspection, rather than requiring immediate quality checks during receipt or manufacturing. Items remain in quarantine until quality inspection is completed and approved. **Key Benefit**: Separates the receiving\u002Fmanufacturing process from quality inspection, improving operational efficiency while maintaining quality control. ## Setup ### 1. Enable the Feature Navigate to **Inventory Tools Settings** and enable **Enable Quarantine Workflow**. Optionally, set a **Default Quarantine Warehouse** as a fallback for items whose Quality Inspection Template does not specify a quarantine location. To prevent stock from leaving a quarantine warehouse through any means other than an accepted Quality Inspection, also enable **Block Issue from Quarantine**. See [Blocking Manual Removals](#blocking-manual-removals) below. ### 2. Configure Quality Inspection Templates For each template requiring quarantine workflow: 1. Open **Quality Inspection Template** 2. Set the **Quarantine Warehouse** field to your designated quarantine location 3. Configure inspection parameters as needed 4. Save the template ### 3. Configure Items Quality Inspection Template assignment and inspection requirements are configured at two levels: - **Quality Inspection Template**: Set on the **Item** master. This determines which inspection parameters apply and which quarantine warehouse to use (overriding the default). - **Inspection Required flags**: Set on **Item Default** (company-scoped). Item-level inspection fields are hidden. On **Item Default** for each company and item: 1. Check **Inspection Required Before Purchase** (for incoming materials via Purchase Receipt or Subcontractin",{"id":316,"title":317,"content":318,"level":16},"\u002Fdocumentation\u002Finventory_tools\u002Fquotation_demand\u002F","quotation_demand","\u003C!-- Copyright (c) 2024, AgriTheory and contributors For license information, please see license.txt--> # Quotation Demand \u003Cdiv class=\"byline\"> Rohan Bansal, coleandreoli, Tyler Matteson, and Francisco Roldán 2026-09-01 \u003C\u002Fdiv> Quotation Demand is a report-based interface that allows you to aggregate required Items across multiple Quotations, Customers, and requesting Companies. From there, you can create draft Sales Orders (SO). ![Screen shot of the Quotation Demand report showing rows of Items grouped by customer with columns for the Customer,Quotation document ID, Company, Date, Warehouse, and Item](\u002Fdocumentation\u002Finventory_tools\u002Fassets\u002Fqd_report_view.png) The right-hand side of the report has selection boxes to indicate which rows of Items to include to create the documents. Ticking the top-level customer box will automatically check all the Items for that customer. ![Screen shot of a Quotation Demand Report with the boxes next to customer Almacs Food Group Items all checked](\u002Fdocumentation\u002Finventory_tools\u002Fassets\u002Fqd_selection.png) Once you're satisfied with your selections, clicking the Create button will give you the option to generate draft documents: 1. Create SO(s) will create a Sales Order for each customer selected. If there is more than one company requesting items from the same customer, it marks the SO as a Multi-Company Sales Order All generated documents remain in draft status to allow you to make edits as needed before submitting them. ### Create Sales Orders If you select the Create SO(s) option, a dialog window will appear to select the Company if it hasn't already been supplied in the filter section. ![Screen shot of the dialog window to enter the Company for the Sales Orders](\u002Fdocumentation\u002Finventory_tools\u002Fassets\u002Fqd_dialog.png) You can find the new documents in the Sales Order listview. ![Screen shot of the Sales Order listview showing the new draft Sales Orders for Almacs Food Group](\u002Fdocumentation\u002Finventory_tools\u002Fassets\u002Fqd_sales_order.png) ## Co",{"id":320,"title":321,"content":322,"level":16},"\u002Fdocumentation\u002Finventory_tools\u002Fundeclared_uom\u002F","undeclared_uom","\u003C!-- Copyright (c) 2026, AgriTheory and contributors For license information, please see license.txt--> # Undeclared UOM \u003Cdiv class=\"byline\"> Tyler Matteson 2026-08-24 \u003C\u002Fdiv> ERPNext lets you post stock transactions in a UOM that is not listed on the Item's **UOM Conversion Detail** table (the Item child table named **UOMs**). When that happens, `get_conversion_factor` may fall back to a global conversion or default the factor to **1** — so quantities can be recorded as if 1 Kilometer equals 1 Pound. You can restrict UOM selection in the transaction UI by enabling **Stock Settings → Allow UOM with conversion rate defined in Item**; that setting is site-wide and applies to all Companies and Items. The **Undeclared UOM** report finds submitted (and optionally draft or cancelled) transaction lines whose UOM is missing from that Item's conversion table. It is a discovery tool only: it does not block saves, amend documents, or write conversion rows for you. ![Screenshot of the Undeclared UOM report grouped by UOM Pair, showing a Sales Order line for Cloudberry where Kilometer was used but the item's conversion table only declares Pound. The line has conversion factor 1 and Identity Conversion checked.](\u002Fdocumentation\u002Finventory_tools\u002Fassets\u002Fundeclared_uom.png) ## What counts as a finding A line is included when **all** of the following are true: - The line has an **Item** and a **UOM**. - That UOM is **not** a row on the Item's **UOM Conversion Detail** table (`parent` = item code, `uom` = line UOM). - The parent document matches the report filters (company, date range, status, and optional document type \u002F item \u002F UOM filters). This is the same membership test ERPNext uses when **Stock Settings → Allow UOM with conversion rate defined in Item** restricts the UOM picker in transactions. The report applies that test to **existing** lines across many document types. The report does **not** flag: - Lines where the UOM **is** on the conversion table but the stored **conversion ",{"id":324,"title":325,"content":326,"level":16},"\u002Fdocumentation\u002Finventory_tools\u002Fuom_category_curation\u002F","uom_category_curation","\u003C!-- Copyright (c) 2024, AgriTheory and contributors For license information, please see license.txt--> # UOM Category Curation \u003Cdiv class=\"byline\"> Tyler Matteson and Francisco Roldán 2026-09-01 \u003C\u002Fdiv> ERPNext’s bundled setup fixtures contribute **239** packaged **UOM** masters plus **235** **UOM Conversion Factor** rows spread across **17** categories and certainly not all of them apply in all business contexts. Inventory Tools adds an **overview** panel and **UOM curation** actions on the **UOM Category** DocType to allow you to bulk enable or disable UOMs within that category. ## Where to find it 1. Open **UOM Category** (Stock module or Awesome Bar). 2. Save the category. The Inventory Tools overview section loads from a cached scan or starts a new **usage scan** automatically. 3. Use the **Actions** toolbar group **UOM curation** for **Refresh usage scan**, bulk disable, or bulk enable. ## Overview table The table lists **one row per distinct UOM** that appears as **Conversion From UOM** or **Conversion To UOM** on any **UOM Conversion Factor** assigned to **this** category. If the category has no such factors yet, you see an empty-state message instead of a grid. On large sites, building the overview scans every Link-to-UOM field on Item and submittable documents. That work runs as a **background job** with a **progress bar** on the form (similar to Check Run). Results are cached so reopening the category can show the last scan without re-running it; use **Refresh usage scan** to run again. Columns: | Column | Meaning | |--------|---------| | **UOM** | The UOM’s label (and document name if it differs). | | **Is UOM Enabled?** | Whether the UOM master is enabled. | | **Referenced in other UOM Categories** | **Yes** if this UOM also appears on any **UOM Conversion Factor whose category is not** the one you are viewing (including both from and to sides). Rows that only exist on *this* category’s factors alone do **not** count here. | | **Transactional usage coun",{"id":328,"title":329,"content":330,"level":16},"\u002Fdocumentation\u002Finventory_tools\u002Fwarehouse_location_optimization\u002F","warehouse_location_optimization","\u003C!-- Copyright (c) 2026, AgriTheory and contributors For license information, please see license.txt--> # Warehouse Location Optimization \u003Cdiv class=\"byline\"> Tyler Matteson 2026-08-23 \u003C\u002Fdiv> Inbound path-based optimization takes a \"set and periodically correct course\" approach in Inventory Tools. Warehouse Location Optimization is a report that ranks items by how often they move in the area defined within a Warehouse Plan, then suggests storage locations for putaway. The goal is to place hotter items nearer the plan pickup point so receiving and replenishment walks stay short. The report works with a [Warehouse Plan](\u002Fdocumentation\u002Finventory_tools\u002Fwarehouse_plan): candidate bins must sit on that plan (when required in settings), and walk distance uses the plan pickup point and bin access paths. From the report you can: - Set each item’s **default warehouse** for the company to the suggested location - Create or update an ERPNext **Putaway Rule** for the suggested location, using **Slot Capacity** from physical dimensions In scenarios where the company operates more than one physical warehouse, Putaway Rule is recommended. ## Prerequisites 1. A **Warehouse Plan** with pickup point and warehouses placed on the plan (coordinates \u002F accessible path). See [Warehouse Plan](\u002Fdocumentation\u002Finventory_tools\u002Fwarehouse_plan). 2. **Stock Ledger** activity in the date range you care about (receipts, transfers, deliveries, and so on) for warehouses in scope. 3. For reliable fit and capacity: **Physical Dimension** records — item **Exterior** and warehouse **Interior** (same dimension model used by [Cartonization](\u002Fdocumentation\u002Finventory_tools\u002Fcartonization)). Without dimensions, Fit Status is `unverified` and Slot Capacity is blank; **Create Putaway Rule** will not run for those rows until dimensions exist. ## Running the report Open **Warehouse Location Optimization** (Script Report) and set: | Filter | Purpose | |--------|---------| | Company | Company whose stock and warehouse",{"id":332,"title":333,"content":334,"level":16},"\u002Fdocumentation\u002Finventory_tools\u002Fwarehouse_path\u002F","warehouse_path","\u003C!-- Copyright (c) 2024, AgriTheory and contributors For license information, please see license.txt--> # Warehouse Path \u003Cdiv class=\"byline\"> Rohan Bansal, coleandreoli, Heather Kusmierz, Tyler Matteson, and Francisco Roldán 2026-09-01 \u003C\u002Fdiv> ERPNext allows its user to construct hierarchial abstractions for their physical facilities. This can make it difficult to know when you are selecting a Warehouse if it is \"Bin A\" in the \"Storage Closet\" or if is \"Bin A\" from the \"Repair Supplies\" Warehouse. This feature encodes the Warehouse hierarchy into a string, which becomes searchable, and allows the user to more easily understand which Warehouse they are selecting. ## Example In this example there are two Warehouses that start with \"Refridger...\" and while they are different, they could be mixed up. ![Screen shot of the example company's Warehouse Tree. It includes a Refrigerated Display Warehouse (under the Baked Goods group) and a Refrigerator Warehouse](assets\u002Fwarehouse_tree.png) In the Link dropdown, the full path is given, omitting the root \"All Warehouses - APC\" and the company abbreviation at each level. ![Screen shot of a Target Warehouse field with \"Refr\" typed in, and two Warehouse options in the dropdown. The Refrigerated Display option has \"Baked Goods -> Refrigerated Display\" under its name, and the Refrigerator option has \"Refrigerator\" under its name](assets\u002Ffridge.png) This view shows the user-provided search text of \"Refr...\" matches the two similarly-named Warehouses. The Warehouse path under each option's name clearly distinguishes the choices by specifying each Warehouse's hierarchy. ## Configuration To enable this feature, check the \"Update Warehouse Path\" box in Inventory Tools Settings. ",{"id":336,"title":337,"content":338,"level":16},"\u002Fdocumentation\u002Finventory_tools\u002Fwarehouse_plan\u002F","warehouse_plan","\u003C!-- Copyright (c) 2025, AgriTheory and contributors For license information, please see license.txt--> # Warehouse Plan \u003Cdiv class=\"byline\"> Rohan Bansal, coleandreoli, Tyler Matteson, and Francisco Roldán 2026-09-01 \u003C\u002Fdiv> ## Overview The Warehouse Plan feature's goal is to optimize the walking time and calculate the shortest path of a pickup list within a warehouse. Additionally, `FIFO`, `LIFO`, `Deplete_Max_Bins`, and `Deplete_Min_Bins` rules can be applied to the available stock for optimal stock management. This is accomplished by using a physical representation layer and implementing a pathing algorithm to solve for the shortest path, combined with pickup rules. **Note**: In Frappe, a warehouse is anything that has storage and can contain internal *warehouses*. A building is a warehouse, which contains a bin, which is a warehouse, which contains a box, which is a warehouse. ## Methodology The physical representation is a 2D projection on top of a **floor plan drawing**. This 2D layer is then broken up into a **grid overlay**, defining walkable and non-walkable areas and internal wall and path geometries, stored in the **matrix**. The grid is ideally the lowest possible resolution (number of boxes) to cover walkable areas. The goal is to capture the spatial representation, which doesn't require high-definition mapping. Then the **Warehouses\u002FBins** locations and sizes are defined. They are meant to be placed on a non-walkable square with a defined access point on a walkable square. A **Pick lists** defines the items required for pickup; however, the order and rules are unoptimized. We then apply the pickup rules and pathing algorithm. The **pathing algorithm** then finds the shortest path with the connected (vertical and horizontal, not corner) walkable tiles, between access points of the bins. The pick list is then updated with the newly optimized list. **floor plan** -> **grid overlay** -> **walkable\u002Fnon-walkable matrix** -> **warehouses** -> **pick list** ->",{"id":340,"title":341,"content":342,"level":16},"\u002Fdocumentation\u002Finventory_tools\u002Fwo_subcontracting\u002F","wo_subcontracting","\u003C!-- Copyright (c) 2024, AgriTheory and contributors For license information, please see license.txt--> # Subcontracting Workflow via Work Order \u003Cdiv class=\"byline\"> Rohan Bansal, coleandreoli, Heather Kusmierz, Tyler Matteson, and Francisco Roldán 2026-09-01 \u003C\u002Fdiv> ERPNext's subcontracting workflow has changed substantially with each version release of the software, generally without backwards compatibility. This feature offers an alternative to using a Purchase Receipt or the Version-14 Subcontracting Order and Subcontracting Receipt documents. Instead, it allows you to manage the subcontracting process with Work Orders, Purchase Orders and Invoices, and Stock Entries. ## Configuration To enable this feature, check the \"Enable Work Order Subcontracting\" box in Inventory Tools Settings. The feature also has the following prerequisite configuration to get it up and running: - Items: - For any subcontracted Item, check the Supply Raw Materials for Purchase box. This is found in the Manufacturing section of the Item master - Optional: create a service Item (uncheck the Maintain Stock box in the Item master) to represent the services provided by the subcontractor. The ERPNext workflow requires service Items in subcontracted Purchase documents, however this is completely optional in this feature. Instead, when a subcontracted Purchase Order is created from a Work Order, the finished good received from the subcontractor will populate the Items section of the form - Warehouses: - create a dedicated warehouse for each subcontractor to track materials sent to them - Bill of Materials (BOM): - Create a BOM for the subcontracted Item that includes raw materials supplied to the subcontractor and check the Is Subcontracted box. This BOM should not include any operations, as they are done by the subcontractor - The feature supports processes done at times in-house and at times by a subcontractor. There should be separate BOMs for each process, with the appropriate one linked to ",{"id":344,"title":345,"content":346,"level":16},"\u002Fdocumentation\u002Finventory_tools\u002Fwork_order_subcontracting\u002F","work_order_subcontracting","\u003C!-- Copyright (c) 2024, AgriTheory and contributors For license information, please see license.txt--> # Work Order Subcontracting \u003Cdiv class=\"byline\"> Rohan Bansal, coleandreoli, Heather Kusmierz, Tyler Matteson, and Francisco Roldán 2026-09-01 \u003C\u002Fdiv> Material Demand is a report-based interface that allows a user to aggregate required items across multiple Material Requests, Suppliers, requesting Companies and create draft Purchase Orders in that process. ... describe selection process with screenshots ## Configuration Multi-company setup and workflow ",{"id":348,"title":349,"content":350,"level":16},"\u002Fdocumentation\u002Finventory_tools\u002Fworkstation_operating_cost\u002F","workstation_operating_cost","\u003C!-- Copyright (c) 2025, AgriTheory and contributors For license information, please see license.txt--> # Workstation Operating Cost \u003Cdiv class=\"byline\"> IshwaryaM1030, Heather Kusmierz, and Tyler Matteson 2026-09-01 \u003C\u002Fdiv> Workstation Operating Cost provides a flexible, time-based system for tracking and allocating manufacturing overhead to production operations. This system maintains historical cost data while automatically applying current rates or adding future rates to manufacturing transactions. When a new cost period begins, the previous period's end date is set to one day before the new period starts, ensuring complete coverage without gaps. The system validates that cost periods for the same account don't overlap, preventing duplicate or conflicting cost entries. ## ERNext's Default Manufacturing Costing vs. Workstation Operating Cost ERPNext's standard manufacturing process applies labor and overhead through a simplified aggregation model. As manufacturing occurs, Job Cards record the time spent at each workstation operation. When the system creates a Manufacture Stock Entry, it multiplies those recorded hours by the workstation's current rate, calculates a per-unit cost, and capitalizes the total into the finished goods valuation. This approach works well for straightforward operations but creates several limitations for businesses requiring detailed cost analysis or managing cost changes over time. The standard model aggregates all operating costs into a single \"Expenses Included in Valuation\" entry with minimal detail. When rates change midway through a production period, there is no mechanism to apply different rates to different manufacturing dates. Historical cost data is not explicitly maintained, making it difficult to understand how prior periods were costed or to analyze variances over time. Reconciling standard costs to actual expenses becomes challenging because the cost structure lacks sufficient granularity to isolate specific cost types or i",{"id":352,"title":23,"content":353,"level":16},"\u002Fdocumentation\u002Fsaml\u002F","\u003C!-- Copyright (c) 2025, AgriTheory and contributors For license information, please see license.txt--> # SAML Integration \u003Cdiv class=\"byline\"> Tyler Matteson 2026-06-15 \u003C\u002Fdiv> The SAML (Security Assertion Markup Language) integration for Frappe enables secure single sign-on (SSO) authentication between your Frappe application and your organization's Identity Provider (IdP). When a user attempts to access your Frappe application, the following authentication flow occurs: 1. The user tries to access a protected page or clicks on the SAML login button. 2. Frappe redirects the user to your configured Identity Provider (IdP) with a SAML authentication request. 3. The user authenticates with the IdP using their organizational credentials. 4. Upon successful authentication, the IdP generates a SAML response containing user information. 5. The user is redirected back to Frappe with this SAML response. 6. Frappe verifies the SAML response, extracts user information, and either logs in an existing user or creates a new user account. 7. The user is redirected to their intended destination within Frappe. This process enables secure authentication without requiring users to maintain separate credentials for your Frappe application. ## Setting Up SAML Integration This guide assumes you have already installed the SAML integration app. If you haven't, please refer to the [Installation Documentation](https:\u002F\u002Fgithub.com\u002Fagritheory\u002FsamlREADME.md). ### Configuring SAML Login Key To set up a SAML provider: 1. Go to Desk > SAML > SAML Login Key 2. Click \"New\" to create a new SAML provider configuration 3. Enter a descriptive \"Provider Name\" (e.g., \"Corporate SSO\" or \"Okta SSO\") 4. Check \"Enable SAML Login\" to activate this provider 5. Fill in the Service Provider and Identity Provider details as outlined in the following sections ### Auto SAML Login When **Auto SAML Login** is enabled on a SAML Login Key, guest requests matching the configured scope are sent to the IdP for silent SSO be",{"id":355,"title":356,"content":357,"level":16},"\u002Fdocumentation\u002Fshipstation_integration\u002F17track\u002F","17track","\u003C!-- Copyright (c) 2026, AgriTheory and contributors For license information, please see license.txt--> # 17Track Integration \u003Cdiv class=\"byline\"> lauty95 2026-05-21 \u003C\u002Fdiv> This integration connects [17TRACK](https:\u002F\u002Fwww.17track.net\u002F) global shipment tracking with ERPNext via the Shipstation Integration app. It enables automatic tracking, status sync, and comment logging for shipments handled via 17TRACK. --- ## Features - **Automatic tracking updates via webhook from 17TRACK** - **Carrier management** for fast lookup and autosuggest - **Configurable comment logging** on shipment status updates --- ## Setup ### Get a Seventeen Track API Key - Go to https:\u002F\u002Fadmin.17track.net\u002Fapi\u002Fsettings and login or register ![Screenshot of 17Track Settings.](\u002Fdocumentation\u002Fshipstation_integration\u002Fassets\u002Fapi_key.png) ### **Seventeen Track Doctype** - Go to **Seventeen Track** DocType. - **Fields:** - `Company`: The ERPNext company this configuration applies to. _(Required)_ - `API Key`: Your 17TRACK API key. _(Required)_ - `Webhook Callback URL`: The URL you must register in the 17TRACK dashboard under **API Settings → WebHook**. This field is read-only and is generated automatically from your site URL. - `Add Updates as Comments`: Enable to log each tracking status update as a comment on the Tracking Number record. - `Enable Geocoding`: When checked, events that do not include coordinates from the carrier are resolved via the configured geocoding service (default: Nominatim\u002FOpenStreetMap). Disable this if you do not want external geocoding calls or have not configured a provider. See the [Tracking Map](\u002Fdocumentation\u002Fshipstation_integration\u002Ftracking_map) documentation for details. ![Screenshot of the Seventeen Track doctype formview.](\u002Fdocumentation\u002Fshipstation_integration\u002Fassets\u002Fseventeentrack.png) --- ## Webhook Integration ### **Endpoint** `\u002Fapi\u002Fmethod\u002Fshipstation_integration.shipstation_integration.doctype.seventeen_track.seventeen_track.seventeentrack_webhook` #### **How it wo",{"id":359,"title":360,"content":361,"level":16},"\u002Fdocumentation\u002Fshipstation_integration\u002F","Shipstation Integration"," # Shipstation Integration - [17track](\u002Fdocumentation\u002Fshipstation_integration\u002F17track) - [parcel dimension uom convertion](\u002Fdocumentation\u002Fshipstation_integration\u002Fparcel_dimension_uom_convertion) - [tracking map](\u002Fdocumentation\u002Fshipstation_integration\u002Ftracking_map) ",{"id":363,"title":364,"content":365,"level":16},"\u002Fdocumentation\u002Fshipstation_integration\u002Fparcel_dimension_uom_convertion\u002F","parcel_dimension_uom_convertion","\u003C!-- Copyright (c) 2026, AgriTheory and contributors For license information, please see license.txt--> # Parcel Measurement UOM Preference – Feature Overview \u003Cdiv class=\"byline\"> Ishwarya, lauty95, and Tyler Matteson 2026-05-21 \u003C\u002Fdiv> ## Purpose This feature allows parcel dimensions and weight to be **stored in metric units** while displaying values to each user in their **preferred unit of measurement (UOM)**. It ensures consistent data storage across the system while providing a context-aware display experience. --- ## Where this applies * **Shipment Parcel Template** * **Parcel Dimensions** (child table inside Packing Slip) --- ## Key Concept All parcel measurements are stored in a **standard internal format**: * Length → Centimeter * Width → Centimeter * Height → Centimeter * Weight → Kilogram However, users may prefer to view values in different units (for example inches or pounds). This feature converts stored metric values into the user’s preferred units for display. --- ## User Preference Each user can select their preferred units: * Preferred Dimension UOM * Preferred Weight UOM These are stored on the **User** record and loaded during login. If a user has not selected anything, the system defaults to metric: * Length → Centimeter * Weight → Kilogram --- ## How It Works ### 1. Storage All parcel data is saved in metric units regardless of user preference. This ensures consistency for integrations, calculations, and APIs. ### 2. Display Conversion When a document is viewed: 1. The system checks the logged-in user’s preferred units. 2. It retrieves the appropriate conversion factor. 3. Stored metric values are converted to the user’s units. 4. Converted values are shown in read-only display fields. This happens for: * Shipment Parcel Template records * Parcel rows inside Packing Slip (child table) ### 3. Context-Aware Labels Field labels may change depending on the user’s chosen unit. For example: * Length (cm) → Length (in) * Weight (kg) → Weight (lb) This ",{"id":367,"title":368,"content":369,"level":16},"\u002Fdocumentation\u002Fshipstation_integration\u002Ftracking_map\u002F","tracking_map","\u003C!-- Copyright (c) 2026, AgriTheory and contributors For license information, please see license.txt--> # Tracking Map – Feature Overview \u003Cdiv class=\"byline\"> lauty95 2026-05-21 \u003C\u002Fdiv> ## Purpose This feature displays a **live map on the Tracking Number form** that plots the physical journey of a shipment based on carrier events received via 17Track webhooks. Each event with a known location is shown as a pin on the map, with the most recent one highlighted in red. --- ## Where this applies * **Tracking Number** (form view — Tracking Map section) * **Seventeen Track** settings (per company) --- ## How events are collected Every time 17Track sends a `TRACKING_UPDATED` webhook, the integration parses the events from each provider and appends new rows to the **Tracking Number Event** child table. Events are deduplicated by UTC timestamp (to second precision), so re-delivered webhooks never create duplicate rows. Each row stores: * Event time, stage, and description * Full address breakdown (country, state, city, street, postal code) * Raw location string as reported by the carrier * Latitude and longitude (if resolved) * Coordinates source: `API`, `Geocoded`, or empty * Provider name (e.g. UPS, FedEx) --- ## Coordinate resolution Not all carriers include coordinates in their event data. When coordinates are missing, the integration can call a geocoding service to resolve them from the address. The resolution order is: 1. **API coordinates** — if the carrier included `latitude`\u002F`longitude` in the event, those are used directly (`coordinates_source = API`). 2. **Geocoding hook** — if coordinates are absent and **Enable Geocoding** is checked on the Seventeen Track settings doc, the `seventeen_track_geocode_address` hook is called. The default implementation uses **Nominatim (OpenStreetMap)**. If it returns coordinates, they are stored with `coordinates_source = Geocoded`. 3. **No coordinates** — if geocoding is disabled or the hook returns nothing, the event is still rec",{"id":371,"title":23,"content":372,"level":16},"\u002Fdocumentation\u002Ftaxjar_erpnext\u002F","\u003C!-- Copyright (c) 2026, Washmore Development, AgriTheory and contributors For license information, please see license.txt--> # TaxJar ERPNext \u003Cdiv class=\"byline\"> Tyler Matteson 2026-06-23 \u003C\u002Fdiv> TaxJar ERPNext connects [ERPNext](https:\u002F\u002Ferpnext.com\u002F) selling documents to [TaxJar](https:\u002F\u002Fwww.taxjar.com\u002F) so US-based companies can calculate sales tax at quote, order, and invoice time without maintaining rate tables by hand. The integration respects nexus, product tax categories, and exemptions, then optionally reports completed sales back to TaxJar for compliance workflows such as AutoFile. Each company that uses TaxJar gets its own **TaxJar Account**: API credentials, nexus list, and GL mapping stay separate in multi-company sites. Tax is calculated on **Quotation**, **Sales Order**, and **Sales Invoice** when the ship-to destination is in a nexus state. Optional features extend that baseline—estimated tax on quotes for non-nexus states, ToDo alerts when orders ship outside nexus, and transaction sync when invoices are submitted. This documentation is the user guide and technical reference for installing, configuring, and operating the app. Start with [Setup](\u002Fdocumentation\u002Ftaxjar_erpnext\u002Fsetup) to install and configure a site; use [Integration](\u002Fdocumentation\u002Ftaxjar_erpnext\u002Fintegration) for hooks, data model, and API behavior; see [Troubleshooting and contributing](\u002Fdocumentation\u002Ftaxjar_erpnext\u002Ftroubleshooting) for common failures, development, and licensing. ## In this section - [Setup](\u002Fdocumentation\u002Ftaxjar_erpnext\u002Fsetup) — Installation, prerequisites, TaxJar Account configuration, and what to expect on each selling document. - [Integration](\u002Fdocumentation\u002Ftaxjar_erpnext\u002Fintegration) — Hooks, DocTypes, custom fields, calculation pipeline, transaction sync, and limitations. - [Troubleshooting and contributing](\u002Fdocumentation\u002Ftaxjar_erpnext\u002Ftroubleshooting) — Symptom checklist, running tests, license, and acknowledgements. --- ## Development and testing - Hooks e",{"id":374,"title":375,"content":376,"level":16},"\u002Fdocumentation\u002Ftaxjar_erpnext\u002Fintegration\u002F","integration","\u003C!-- Copyright (c) 2026, Washmore Development, AgriTheory and contributors For license information, please see license.txt--> # Integration \u003Cdiv class=\"byline\"> Tyler Matteson 2026-06-23 \u003C\u002Fdiv> [← Documentation index](\u002Fdocumentation\u002Ftaxjar_erpnext\u002Findex) · [Setup](\u002Fdocumentation\u002Ftaxjar_erpnext\u002Fsetup) Technical reference for how the app hooks into ERPNext and calls TaxJar. Configuration steps live in [Setup](\u002Fdocumentation\u002Ftaxjar_erpnext\u002Fsetup); expected UI behavior by document type is documented there as well. *** ## Architecture ### Document hooks Defined in [`hooks.py`](..\u002Ftaxjar_erpnext\u002Fhooks.py): | Document | Event | Handler | | ------------------------------------- | ----------- | ------------------------------ | | Quotation, Sales Order, Sales Invoice | `validate` | `set_sales_tax` | | Sales Invoice | `on_submit` | `create_transaction` | | Sales Invoice | `on_cancel` | `delete_transaction` | | Sales Order | `on_submit` | `notify_non_nexus_sales_order` | Business logic is in [`taxjar_erpnext.py`](..\u002Ftaxjar_erpnext\u002Ftaxjar_erpnext\u002Ftaxjar_erpnext.py): payload assembly (`get_tax_data`), nexus checks, exemptions, TaxJar API calls, tax row updates, transaction sync, and non-nexus notifications. \u003Cdiv class=\"mermaid-chart-container\"> \u003Cdiv class=\"mermaid-svg-version\">\u003Csvg id=\"mermaid-svg-0\" width=\"100%\" xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" xmlns:xlink=\"http:\u002F\u002Fwww.w3.org\u002F1999\u002Fxlink\" class=\"flowchart\" style=\"max-width: 910.671875px;\" viewBox=\"0 0 910.671875 752\" role=\"graphics-document document\" aria-roledescription=\"flowchart-v2\">\u003Cstyle>#mermaid-svg-0{font-family:inherit;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-0 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-0 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-lineca",{"id":378,"title":379,"content":380,"level":16},"\u002Fdocumentation\u002Ftaxjar_erpnext\u002Fsetup\u002F","setup","\u003C!-- Copyright (c) 2026, Washmore Development, AgriTheory and contributors For license information, please see license.txt--> # Setup \u003Cdiv class=\"byline\"> Tyler Matteson 2026-06-23 \u003C\u002Fdiv> [← Documentation index](\u002Fdocumentation\u002Ftaxjar_erpnext\u002Findex) This page covers installation and day-to-day configuration. For hooks, code paths, and API behavior, see [Integration](\u002Fdocumentation\u002Ftaxjar_erpnext\u002Fintegration). --- ## Requirements - **ERPNext v15** with a **United States** company. Tax is calculated only for US companies; other regions are ignored even if a TaxJar Account exists. - A [TaxJar](https:\u002F\u002Fwww.taxjar.com\u002F) account with Live or Sandbox API keys. - ERPNext **United States regional setup** applied on the site if you rely on sales tax exemption fields on Customer or selling documents. This app is a fork of Frappe’s [TaxJar Integration](https:\u002F\u002Fgithub.com\u002Ffrappe\u002Ftaxjar_integration). License and acknowledgements are in [Troubleshooting and contributing](\u002Fdocumentation\u002Ftaxjar_erpnext\u002Ftroubleshooting). --- ## Installation From your bench directory (commonly `frappe-bench`): ```bash bench get-app https:\u002F\u002Fgithub.com\u002Fwashmoredevelopment\u002Ftaxjar_erpnext.git bench --site your-site.localhost install-app taxjar_erpnext bench --site your-site.localhost migrate ``` --- ## Before you configure Complete these on each company that will use TaxJar: | Requirement | Where in ERPNext | |-------------|------------------| | TaxJar Account with **Enable Tax Calculation** | TaxJar Account (one per company) | | Default **company address** (ship-from) | Company | | **Shipping address** on selling documents (or customer address as fallback) | Quotation \u002F Sales Order \u002F Sales Invoice | | **Tax Account Head** and **Shipping Account Head** GL accounts | TaxJar Account | | **Product Tax Category** on item defaults | Item → Item Defaults (per company) | | Nexus list synced from TaxJar | TaxJar Account → **Update Nexus List** | Without a company address or a resolvable destination address, tax ca",{"id":382,"title":383,"content":384,"level":16},"\u002Fdocumentation\u002Ftaxjar_erpnext\u002Ftroubleshooting\u002F","troubleshooting","\u003C!-- Copyright (c) 2026, Washmore Development, AgriTheory and contributors For license information, please see license.txt--> # Troubleshooting and contributing \u003Cdiv class=\"byline\"> Tyler Matteson 2026-06-23 \u003C\u002Fdiv> [← Documentation index](\u002Fdocumentation\u002Ftaxjar_erpnext\u002Findex) · [Setup](\u002Fdocumentation\u002Ftaxjar_erpnext\u002Fsetup) · [Integration](\u002Fdocumentation\u002Ftaxjar_erpnext\u002Fintegration) ## Troubleshooting | Symptom | Things to check | |--------|-------------------| | No tax calculated | Company region United States; Enable Tax Calculation; items present; not exempt; addresses complete; nexus (unless quotation plus estimate-all-states). | | Exemption ignored | ERPNext US regional setup installed; `exempt_from_sales_tax` on document or Customer. | | Tax cleared after address change | `get_tax_data` returned `None` (for example missing address or country code); integration removes TaxJar tax rows. | | Missing Company Address | Set default company address on Company. | | State or ZIP errors | Shipping and company addresses: valid state for country; US state codes where enforced. | | TaxJar API errors on save | TaxJar Calculation Error vs TaxJar Transaction Error titles; message body is sanitized API `detail`. | | Transactions not created | Create TaxJar Transaction; non-zero tax on Tax Account Head; live vs sandbox keys and Sandbox Mode alignment. | | Nexus notifications missing | Notify checkbox; Notification Recipient; destination must be outside nexus; failures only in Error Log. | | Nexus list empty | Save TaxJar Account with valid keys, then Update Nexus List. | ",{"id":386,"title":387,"content":388,"level":16},"\u002Fdocumentation\u002Ftest_utils\u002Factions\u002Fcode-duplication\u002F","code-duplication","# Code Duplication The code duplication action runs [jscpd](https:\u002F\u002Fjscpd.dev\u002F) to detect copy-paste in Python, JavaScript, and TypeScript. It reports duplications on PRs, uploads HTML\u002FJSON artifacts when issues are found, and fails when clone\u002Fpercentage thresholds are exceeded. When **no duplications are detected**, the action does nothing: no summary, no artifact upload, no PR comment. ## Usage Add `.github\u002Fworkflows\u002Fcode-duplication.yml` to your repository: ```yaml name: Code Duplication on: push: branches: [\"*\"] pull_request: branches: [\"*\"] permissions: contents: read pull-requests: write issues: write jobs: duplication: runs-on: ubuntu-latest steps: - uses: actions\u002Fcheckout@v4 with: fetch-depth: 0 - uses: actions\u002Fsetup-node@v4 with: node-version: '18' - uses: agritheory\u002Ftest_utils\u002Factions\u002Fcode_duplication@main with: max_clones: 60 # Fail if clones exceed this (default: 60) max_percentage: 5.0 # Warn if duplication % exceeds this (default: 5.0) ``` ### Optional inputs | Input | Default | Description | |-------|---------|-------------| | `max_clones` | 60 | Fail the job if clone count exceeds this | | `max_percentage` | 5.0 | Warn if duplication percentage exceeds this | ## Ignoring false positives For configuration arrays (report columns, dialog fields) that jscpd flags as duplicated: ```javascript \u002F* jscpd:ignore-start *\u002F const dialogFields = [...]; \u002F* jscpd:ignore-end *\u002F ``` ```python # jscpd:ignore-start columns = [...] # jscpd:ignore-end ``` ## App detection The workflow detects the app name from: 1. A directory matching the repository name (e.g. `inventory_tools\u002F` for `agritheory\u002Finventory_tools`) 2. The `name` in `setup.py` if no such directory exists 3. The repository name as fallback ",{"id":390,"title":391,"content":392,"level":16},"\u002Fdocumentation\u002Ftest_utils\u002Factions\u002Fdiff_print_format\u002F","diff_print_format","# Print Format Diff This GitHub Action helps automate the process of comparing changes made to print formats in a Frappe app. It checks for changes in .json files within the print_format directory, compares them to the base branch, and then comments the diff on the pull request. ## Usage To use the `diff-print-format` GitHub Action in your workflow, follow these steps: ### 1. Create a Workflow File Create a new GitHub Actions workflow file in your repository, e.g., `.github\u002Fworkflows\u002Fdiff_print_format.yml`, and add the following content: ```yaml name: Diff Print Formats on: pull_request: jobs: diff_print_format: runs-on: ubuntu-latest name: Diff Print Formats steps: - name: Checkout the code uses: actions\u002Fcheckout@v4 with: fetch-depth: 0 - name: Checkout test_utils uses: actions\u002Fcheckout@v4 with: repository: agritheory\u002Ftest_utils ref: main path: test_utils - name: Diff Print Formats uses: .\u002Ftest_utils\u002Factions\u002Fdiff_print_format with: github-token: ${{ secrets.GITHUB_TOKEN }} ``` ",{"id":394,"title":395,"content":396,"level":16},"\u002Fdocumentation\u002Ftest_utils\u002Factions\u002Fgenerate_changelog-release-integration\u002F","generate_changelog-release-integration","# Integration with Release Tools This document covers how to integrate the Changelog Generator Action with various release tools. ## GitHub Releases Integration If you want to use the generated changelog for GitHub releases, create a workflow file at `.github\u002Fworkflows\u002Frelease.yml`: ```yaml name: Create Release on: pull_request: types: [closed] branches: - main - master jobs: create-release: # Only run when PR is merged (not just closed) if: github.event.pull_request.merged == true runs-on: ubuntu-latest permissions: contents: write pull-requests: read steps: - name: Checkout code uses: actions\u002Fcheckout@v4 - name: Get version id: get-version # This example assumes version is in a file like package.json, pyproject.toml, etc. # Modify as needed for your project run: | # Example for package.json VERSION=$(grep -m1 '\"version\":' package.json | cut -d'\"' -f4) echo \"version=v${VERSION}\" >> $GITHUB_OUTPUT - name: Find changelog comment id: find-changelog uses: actions\u002Fgithub-script@v6 with: script: | const prNumber = context.payload.pull_request.number; const comments = await github.rest.issues.listComments({ owner: context.repo.owner, repo: context.repo.repo, issue_number: prNumber }); const changelogHeaderPattern = \u002F## 📝 Draft Changelog Entry\u002F; const changelogComment = comments.data.find(comment => changelogHeaderPattern.test(comment.body) ); if (!changelogComment) { console.log('No changelog comment found'); return null; } \u002F\u002F Extract just the changelog content (without header and footer) const commentBody = changelogComment.body; const headerEndIndex = commentBody.indexOf('\\n\\n') + 2; const footerStartIndex = commentBody.lastIndexOf('\\n\\n_This changelog'); const changelogText = commentBody.substring( headerEndIndex, footerStartIndex > 0 ? footerStartIndex : undefined ).trim(); return changelogText; - name: Create Release uses: actions\u002Fgithub-script@v6 with: script: | const version = '${{ steps.get-version.outputs.version }}'; const changelogText = ${{ steps.find-changel",{"id":398,"title":399,"content":400,"level":16},"\u002Fdocumentation\u002Ftest_utils\u002Factions\u002Fgenerate_changelog\u002F","generate_changelog","# Changelog Generator Action This GitHub Action automatically generates a changelog entry as a PR comment by analyzing PR changes using an LLM. It supports Anthropic Claude, OpenAI, and Amazon Bedrock. ## Features - Automatically generates detailed changelog entries when a PR is opened or updated - Analyzes PR details including commits, files changed, and PR description - Identifies breaking changes, new features, bug fixes, and more - Adds context on user impact and required actions - Creates changelog as a PR comment that can be edited if needed - Only auto-generates one changelog per PR (no duplicate comments on updates) - Provides clear error messages when API issues occur - Reuses changelog content for GitHub releases - Allows generating changelogs on demand with a simple comment command ## Requirements - GitHub repository with Actions enabled - An API key or credentials for one of the supported LLM providers: - **Anthropic** (default): Anthropic API key - **OpenAI**: OpenAI API key - **Amazon Bedrock**: either a Bedrock API key (bearer token), an AWS IAM access key pair, or an OIDC role — with `bedrock:InvokeModel` permissions and model access enabled in your AWS account ## Setup ### 1. Configure GitHub Secrets Add the secrets for your chosen provider: **Anthropic (default)** - `ANTHROPIC_API_KEY`: Your Anthropic API key **OpenAI** - `OPENAI_API_KEY`: Your OpenAI API key **Amazon Bedrock** Option A — Bedrock API key (simpler): - `AWS_BEARER_TOKEN_BEDROCK`: Your Amazon Bedrock API key Option B — IAM credentials: - `AWS_ACCESS_KEY_ID`: Your AWS access key ID - `AWS_SECRET_ACCESS_KEY`: Your AWS secret access key ### 2. Create a Workflow File Create a workflow file at `.github\u002Fworkflows\u002Fgenerate-changelog.yml`. **Using Anthropic (default):** ```yaml name: Generate Changelog on: pull_request: types: [opened, reopened, synchronize] issue_comment: types: [created] jobs: generate-changelog: runs-on: ubuntu-latest permissions: contents: read pull-requests: write steps:",{"id":402,"title":403,"content":404,"level":16},"\u002Fdocumentation\u002Ftest_utils\u002Factions\u002Ftrack_overrides\u002F","track_overrides","# Track Overrides `track-overrides` is a GitHub Action designed to track method overrides in Python projects. It automatically detects the base branch from the pull request that triggers the action and compares the code changes in the pull request against the corresponding branch in the repository specified in the method annotations. This comparison is performed using the commit hash associated with each method. If the overridden method and the upstream method have different commit hashes, the action will indicate that the overridden method has changed. This seamless comparison capability enables efficient tracking of method overrides across different branches and repositories. ## Method Annotation To track the overrides, the methods must have a comment with the following structure: ``` \"\"\" APP: \u003Capp_name> HASH: \u003Ccommit_hash> REPO: \u003Crepository_url> PATH: \u003Cfile_path> METHOD: \u003Cmethod_name> \"\"\" ``` - **APP**: The app that contains this override (e.g. `frappe`, `inventory_tools`). Required for pre-commit to correctly scope checks when using `--app` or `--directory`. - **HASH**: Commit hash of the upstream version when this override was last validated. - **REPO**: Upstream repository URL. - **PATH**: Path to the file in the upstream repo. - **METHOD**: Method name being overridden. ### Example ```python def is_system_manager_disabled(user): \"\"\" APP: frappe HASH: 171e1d0159cda3b8d9415527590c9c3ca0c827be REPO: https:\u002F\u002Fgithub.com\u002Ffrappe\u002Ffrappe\u002F PATH: frappe\u002Fcore\u002Fdoctype\u002Fuser\u002Fuser.py METHOD: is_system_manager_disabled \"\"\" # Method implementation here pass ``` ## Pre-commit Usage For **monorepos** (bench structure with apps\u002Ffrappe, apps\u002Ferpnext, etc.), use `--directory .` to scan the entire workspace—matching GHA behavior. Optionally add `--app` to limit which apps are checked: ```yaml # Check all apps - id: track_overrides args: ['--directory', '.', '--base-branch', 'version-15'] # Or only frappe and erpnext (requires APP in annotations) - id: track_overrides args: ['--direc",{"id":406,"title":407,"content":408,"level":16},"\u002Fdocumentation\u002Ftest_utils\u002Factions\u002Ftranslate_docs\u002F","translate_docs","# Translate Docs Action This GitHub Action translates markdown files under `docs\u002F*\u002Fen\u002F` to other languages using Google Cloud Translation. When a PR modifies English docs, the action creates translation PRs for each configured language. ## Requirements - GitHub repository with Actions enabled - Google Cloud Translation API credentials (JSON key file) - Repository with a `hooks` module exposing `docs_languages` ## Repository Configuration ### 1. Add GitHub Secrets In your repository settings (Settings > Secrets and variables > Actions), add: | Secret | Description | |-------|-------------| | `GOOGLE_APPLICATION_CREDENTIALS` | The full JSON content of your Google Cloud service account credentials file | ### 2. Workflow Permissions Go to Settings > Actions > General > Workflow permissions and enable: - **Read and write permissions** (required for creating branches and PRs) - **Allow GitHub Actions to create and approve pull requests** (optional, for auto-merge) ### 3. Configure Languages In your app's `hooks` module, define `docs_languages` as a list of target language codes: ```python docs_languages = ['es', 'fr'] # Spanish and French ``` If the folder for a language does not exist under `docs\u002F{version}\u002F{language}\u002F`, it will be created. ## Usage Create a workflow file at `.github\u002Fworkflows\u002Ftranslate-docs.yml`: ```yaml name: Translate Docs on: pull_request: paths: - 'docs\u002F**\u002Fen\u002F**\u002F*.md' jobs: translate: runs-on: ubuntu-latest permissions: contents: write pull-requests: write steps: - uses: actions\u002Fcheckout@v4 - name: Translate Docs uses: agritheory\u002Ftest_utils\u002Factions\u002Ftranslate_docs@main with: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GOOGLE_APPLICATION_CREDENTIALS: ${{ secrets.GOOGLE_APPLICATION_CREDENTIALS }} GITHUB_REPOSITORY: ${{ github.repository }} GITHUB_BASE_REF: ${{ github.base_ref }} GITHUB_REF: ${{ github.ref }} ``` ## How It Works 1. When a PR modifies any `.md` file under `docs\u002F*\u002Fen\u002F`, the action runs. 2. The action fetches the modified files from the PR an",{"id":410,"title":411,"content":412,"level":16},"\u002Fdocumentation\u002Ftest_utils\u002Fcode_duplication\u002F","code_duplication","# Code Duplication Reporting Setup This guide covers setting up automated code duplication detection using `jscpd` for Frappe applications. ## Overview The duplication check system detects copy-paste problems and duplicated code across Python and JavaScript\u002FTypeScript files. It automatically: - Ignores tests, fixtures, and JSON files - Generates HTML and JSON reports - Provides thresholds for CI\u002FCD - Works with both GitHub Actions and pre-commit hooks - Auto-detects app name from repository structure ## Quick Start ### Option 1: GitHub Actions (Recommended) 1. Copy the workflow file to `.github\u002Fworkflows\u002Fcode-duplication.yml` 2. Push to your repository 3. The workflow runs automatically on push\u002FPR **View reports:** - GitHub Actions Summary tab shows a formatted table - Download HTML report from workflow artifacts - Reports are saved to `{app_name}\u002Ftests\u002Fjscpd\u002F` ### Option 2: Pre-commit Hook 1. Add to your `.pre-commit-config.yaml`: ```yaml repos: - repo: local hooks: - id: jscpd name: Check for code duplication entry: bash -c 'npx jscpd@4.2.4 . --format \"python,javascript,typescript\" --ignore \"**\u002Fnode_modules\u002F**,**\u002F.venv\u002F**,**\u002Fvenv\u002F**,**\u002F__pycache__\u002F**,**\u002Fdist\u002F**,**\u002Fbuild\u002F**,**\u002F*.bundle.js,**\u002Ftests\u002F**,**\u002Ftest_*.py,**\u002F*_test.py,**\u002F*.test.js,**\u002F*.spec.js,**\u002Ffixtures\u002F**,**\u002F*fixtures.py\" --min-lines 20 --min-tokens 150 --threshold 6 --exitCode 1 --reporters \"console\" --silent' language: system pass_filenames: false files: \\.(py|js|ts)$ stages: [commit] ``` 2. Install pre-commit hooks: ```bash pre-commit install ``` ### Option 3: Standalone Script 1. Make the script executable: ```bash chmod +x check_duplication.sh ``` 2. Run the check: ```bash .\u002Fcheck_duplication.sh ``` 3. With custom options: ```bash .\u002Fcheck_duplication.sh --max-clones 50 --max-percentage 4.0 --exit-on-fail ``` ## Configuration ### Thresholds **Default values:** - Maximum clones: 60 - Maximum percentage: 5.0% - Minimum lines for detection: 20 - Minimum tokens for detection: 150 **Customize in GitHub Ac",{"id":414,"title":23,"content":415,"level":16},"\u002Fdocumentation\u002Ftest_utils\u002F","# AgriTheory Test Utils — Documentation Index Test Utils is a collection of development tools for [Frappe](https:\u002F\u002Ffrappeframework.com) apps: test fixtures, pre-commit hooks, GitHub Action templates, and static analysis. It is maintained by [AgriTheory](https:\u002F\u002Fagritheory.dev) and published at [github.com\u002Fagritheory\u002Ftest_utils](https:\u002F\u002Fgithub.com\u002Fagritheory\u002Ftest_utils). --- ## Tools ### Pre-commit Hooks [`pre_commit_hooks.md`](\u002Fdocumentation\u002Ftest_utils\u002Fpre_commit_hooks) documents all available hooks. A summary: | Hook | Purpose | |------|---------| | `validate_copyright` | Add\u002Fcheck copyright headers in `.py`, `.js`, `.ts`, `.md` | | `clean_customized_doctypes` | Remove null values from customization JSON files | | `validate_javascript_dependencies` | Detect `package.json` version mismatches across installed apps | | `validate_python_dependencies` | Detect `pyproject.toml` version mismatches across installed apps | | `validate_customizations` | Validate Custom Fields and Property Setters ([details](\u002Fdocumentation\u002Ftest_utils\u002Fvalidate_customizations)) | | `update_pre_commit_config` | Keep pre-commit config pinned to the latest test_utils revision | | `mypy` | Run mypy with a preset configuration | | `track_overrides` | Track changes to override methods across branches | | `add_translations` | Extract untranslated strings and translate them | | `sql_docstring_formatter` | Format SQL in Python docstrings via sqlglot | | `sql_registry` | Register SQL operations for tracking | | `bylines` | Add git-history-derived bylines to Markdown files | | `validate_patches` | Validate `patches.txt` ordering and file presence | | `validate_frappe_project` | Validate `pyproject.toml` structure for Frappe apps | | `validate_doctype_python_types` | Require Frappe auto-generated DocType controller types (or an opt-out comment) when hooks export is enabled ([details](\u002Fdocumentation\u002Ftest_utils\u002Fvalidate_doctype_python_types)) | | `check_code_duplication` | Detect copy-paste duplication in Py",{"id":417,"title":418,"content":419,"level":16},"\u002Fdocumentation\u002Ftest_utils\u002Fmariadb_analytics\u002F","mariadb_analytics","# MariaDB performance analytics Portable MariaDB Performance Schema helpers for Frappe benches. Snapshots statement digests, wait events, and table I\u002FO into tables in the site database, then reports deltas between snapshots. Runs under `bench --site … console` or `bench execute`. Not a Frappe app hook or patch — call `enable()` once per site after installing `test_utils`. ## Prerequisites MariaDB with Performance Schema enabled. If it is off, `enable()` prints guidance and exits without failing. On Debian\u002FUbuntu, put **server-only** settings in `mariadb.conf.d` under `[mysqld]` — not in shared sections of `mariadb.cnf` (the client will reject them): ```bash sudo nano \u002Fetc\u002Fmysql\u002Fmariadb.conf.d\u002F99-performance-schema.cnf ``` ```ini [mysqld] performance_schema=ON event_scheduler=ON ``` Restart MariaDB after editing `my.cnf`. Instruments and consumers are turned on at runtime by `enable()` (superuser). You do not need the MySQL-style `performance-schema-instrument` \u002F `performance-schema-consumer-*` lines in `my.cnf` on MariaDB. For the optional MariaDB `EVENT` scheduler, `event_scheduler=ON` in `[mysqld]` is required if `SET GLOBAL event_scheduler=ON` is blocked. `enable()` tries the global SET using the superuser connection. ## Credentials Two MariaDB roles, same pattern as `bench new-site`: | Role | Connection | Used for | |------|------------|----------| | Site user | `frappe.db` (`db_name` \u002F `db_password` in site config) | Snapshot tables, summary reads, `snapshot()`, `top_*`, most of `status()` | | Superuser | Frappe `get_root_connection()` | `enable()` only — instrumentation, `CREATE EVENT`, and `GRANT SELECT` on Performance Schema summary tables for the site user | During `enable()`, the superuser grants the site database user `SELECT` on the Performance Schema tables used by `snapshot()` and `status()`. Without that grant, Frappe site users cannot read `events_statements_summary_by_digest` and similar tables. `enable()` uses Frappe’s `get_root_connection()`: 1. `",{"id":421,"title":422,"content":423,"level":16},"\u002Fdocumentation\u002Ftest_utils\u002Fmove_to_poetry\u002F","move_to_poetry","## Convert pyproject.toml to use poetry from flit_core The following is a guide on converting the pyproject.toml file of the Beam app to use poetry instead of flit_core. Changes made in the file to adapt it for poetry are outlined below: - Changed `[project]` to `[tool.poetry]` - Added version key to `[tool.poetry]` - Removed `requires-python` and `dynamic` - Changed format to specify Authors ### Required Fields for Frappe Apps with Poetry When using Poetry with Frappe apps, your `pyproject.toml` must include certain fields for proper bench compatibility: #### Add [project] Section for Better Compatibility For improved bench compatibility (especially with `bench get-app`), you can add both `[project]` and `[tool.poetry]` sections: ```toml [project] name = \"your_app_name\" authors = [ { name = \"Your Name\", email = \"your.email@example.com\" } ] description = \"Your app description\" requires-python = \">=3.10\" readme = \"README.md\" authors = [ { name = \"Your Name\", email = \"example@email.com\" } ] [tool.poetry] name = \"your_app_name\" version = \"1.0.0\" description = \"Your app description\" authors = [\"Your Name \u003Cexample@email.com>\"] readme = \"README.md\" ``` #### Changed build System | flit_core | poetry | | --- | --- | | ```[build-system]```\u003Cbr>```requires = [\"flit_core >=3.4,\u003C4\"]```\u003Cbr>```build-backend = \"flit_core.buildapi\"``` | ```[build-system]```\u003Cbr>```requires = [\"poetry-core\"]```\u003Cbr>```build-backend = \"poetry.core.masonry.api\"```| #### To add dependency ``` $ poetry add {python-package} Eg. $ poetry add pytest-cov ``` #### To add dev dependency ``` $ poetry add --group dev {python-package} Eg. $ poetry add --group dev pytest-cov ``` #### To remove dependency ``` $ poetry remove {python-package} Eg. $ poetry remove pytest-cov ``` In the above cases, it updates pyproject.toml. #### To validate pyproject.toml ``` $ poetry check ``` The above command validates pyproject.toml and reports if any error #### To rebuild poetry.lock file After making changes to `pyproject.toml`, ",{"id":425,"title":426,"content":427,"level":16},"\u002Fdocumentation\u002Ftest_utils\u002Fpartitions\u002F","partitions","## Using create_partition and restore_partitions ### Hooks available #### Partition DocTypes - `partition_doctypes` The `partition_doctypes` hook defines the tables (DocTypes) that will be partitioned and specifies the criteria for partitioning. Below is an example configuration: ```python partition_doctypes = { \"Sales Order\": { \"field\": \"transaction_date\", \"partition_by\": \"fiscal_year\", # Options: \"fiscal_year\", \"quarter\", \"month\", \"field\" }, \"Sales Invoice\": { \"field\": \"posting_date\", \"partition_by\": \"fiscal_year\", # Options: \"fiscal_year\", \"quarter\", \"month\", \"field\" }, \"Item\": { \"field\": \"disabled\", \"partition_by\": \"field\", # Options: \"fiscal_year\", \"quarter\", \"month\", \"field\" }, } ``` #### Exclude Tables - `exclude_tables` The `exclude_tables` hook specifies the tables that should be ignored during a full database backup. For example: ```python exclude_tables = [\"__global_search\", \"tabAccess Log\", \"tabActivity Log\", \"tabData Import\"] ``` ### Before Migrate #### hooks.py ```python before_migrate = \"your_app.utils.before_migrate\" ``` #### utils.py ```python import frappe from test_utils.utils.create_partition import create_partition def before_migrate(): create_partition(years_ahead=10) ``` ### Doc Events #### hooks.py ```python doc_events = { \"*\": { \"before_insert\": \"your_app.utils.populate_partition_fields\", \"before_save\": \"your_app.utils.populate_partition_fields\", } } ``` #### utils.py ```python import frappe from test_utils.utils.create_partition import populate_partition_fields as _populate_partition_fields def populate_partition_fields(doc, event): _populate_partition_fields(doc, event) ``` ## Create Partition The **Create Partition** utility uses the `partition_doctypes` hook to perform several actions: - **Add Custom Fields:** Introduces custom fields for child tables. - **Modify Primary Keys:** Adjusts primary keys to support partitioning. - **Populates Custom Fields:** Populates custom fields from child tables with existing data. - **Create Partitions:",{"id":429,"title":430,"content":431,"level":16},"\u002Fdocumentation\u002Ftest_utils\u002Fpre_commit_hooks\u002F","pre_commit_hooks","## Using test_utils with pre-commit Add this to your .pre-commit-config.yaml ### Hooks available ### Validate Copyright - `validate_copyright` Check all *.js, *.ts, *.py, and *.md files and add copyright in these files if copyright doesn't exist. ``` - repo: https:\u002F\u002Fgithub.com\u002Fagritheory\u002Ftest_utils\u002F rev: {rev} \u002F\u002F The revision or tag to clone. Example: rev: v0.11.0 hooks: - id: validate_copyright files: '\\.(js|ts|py|md)$' args: [\"--app\", \"{app_name}\"] ``` ### Clean customized doctypes - `clean_customized_doctypes` Remove unused keys in customizations. ``` - repo: https:\u002F\u002Fgithub.com\u002Fagritheory\u002Ftest_utils\u002F rev: {rev} \u002F\u002F The revision or tag to clone. Example: rev: v0.11.0 hooks: - id: clean_customized_doctypes args: [\"--app\", \"{app_name}\"] ``` ### Validate javascript dependencies - `validate_javascript_dependencies` Examine package.json across the installed apps on the site to detect any version mismatches ``` - repo: https:\u002F\u002Fgithub.com\u002Fagritheory\u002Ftest_utils\u002F rev: {rev} \u002F\u002F The revision or tag to clone. Example: rev: v0.11.0 hooks: - id: validate_javascript_dependencies ``` ### Validate python dependencies - `validate_python_dependencies` Examine pyproject.toml across the installed apps on the site to detect any version mismatches ``` - repo: https:\u002F\u002Fgithub.com\u002Fagritheory\u002Ftest_utils\u002F rev: {rev} \u002F\u002F The revision or tag to clone. Example: rev: v0.11.0 hooks: - id: validate_python_dependencies ``` ### Validate customizations - `validate_customizations` Validate Customizations ``` - repo: https:\u002F\u002Fgithub.com\u002Fagritheory\u002Ftest_utils\u002F rev: {rev} \u002F\u002F The revision or tag to clone. Example: rev: v0.11.0 hooks: - id: validate_customizations ``` ### Update pre-commit config - `update_pre_commit_config` Update test_utils pre-commit config to latest ``` - repo: https:\u002F\u002Fgithub.com\u002Fagritheory\u002Ftest_utils\u002F rev: {rev} \u002F\u002F The revision or tag to clone. Example: rev: v0.11.0 hooks: - id: update_pre_commit_config ``` ### Mypy - `mypy` Run mypy on the codebase using a preset configuration ``` - rep",{"id":433,"title":434,"content":435,"level":16},"\u002Fdocumentation\u002Ftest_utils\u002Fprinters\u002F","printers","# Printer mocks `test_utils.printers` provides a stdlib-only IPP codec and mock raw\u002FIPP print servers for integration tests and manual development. ## Install ```bash pip install \"git+https:\u002F\u002Fgithub.com\u002Fagritheory\u002Ftest_utils.git@v1.26.0\" ``` ## CLI ```bash mock-printer raw --save-dir \u002Ftmp\u002Fprints mock-printer ipp --save-dir \u002Ftmp\u002Fprints --name PDF --port 8631 mock-printer both --save-dir \u002Ftmp\u002Fprints ``` The CLI prints ready-to-copy URIs: ``` Raw: socket:\u002F\u002F127.0.0.1:44895 IPP: ipp:\u002F\u002F127.0.0.1:8631\u002Fipp\u002Fprint ``` ## Programmatic use Async (pytest-asyncio, Kenaf): ```python from test_utils.printers import raw_printer, ipp_printer async with raw_printer(save_dir=\"\u002Ftmp\u002Fprints\") as printer: print(printer.device_uri) async with ipp_printer(name=\"PDF\", save_dir=\"\u002Ftmp\u002Fprints\") as printer: print(printer.uri) ``` Sync (Frappe \u002F BEAM pytest): ```python from test_utils.printers import raw_printer_sync, ipp_printer_sync with raw_printer_sync(save_dir=\"\u002Ftmp\u002Fprints\") as printer: payload = printer.wait_for_payload() ``` ## CUPS registration Point CUPS queues at the mock URIs: ```bash lpadmin -p BEAM_TEST_RAW -E -v socket:\u002F\u002F127.0.0.1:9100 -m raw lpadmin -p BEAM_TEST_IPP -E -v ipp:\u002F\u002F127.0.0.1:8631\u002Fipp\u002Fprint -m everywhere cupsenable BEAM_TEST_RAW && cupsaccept BEAM_TEST_RAW ``` ## IPP codec The codec in `test_utils.printers.ipp.codec` is general-purpose (not test-only). Kenaf re-exports it from `src\u002Fipp_codec.py`. ## Kenaf codec duplication Default: Kenaf imports the shared codec from `test_utils` via a thin re-export. If the Kenaf appliance build cannot depend on `test_utils` at runtime, keep a vendored copy of `ipp\u002Fcodec.py` in Kenaf and sync it in CI. Mocks can remain a dev dependency. ",{"id":437,"title":438,"content":439,"level":16},"\u002Fdocumentation\u002Ftest_utils\u002Fsql_registry\u002F","sql_registry","# SQL Registry A tool for scanning, analyzing, and converting `frappe.db.sql` calls to Frappe Query Builder or ORM equivalents. ## Overview The SQL Registry scans Python files for `frappe.db.sql` calls, analyzes the SQL queries, and generates equivalent Query Builder or ORM code. This helps with: * **Auditing** - Understanding SQL usage across a codebase * **Migration** - Converting raw SQL to Query Builder for better security and maintainability * **Quick Wins** - Identifying simple queries that can use `frappe.get_all` instead Registry data is stored as **JSON** (`.sql_registry.json`), which is human-readable, diffable, and portable. If an existing `.sql_registry.pkl` (pickle) file is found and no JSON registry exists, it is automatically migrated on first load. ## Installation The `sql_registry` command is included with test_utils: ```bash pip install test_utils # or poetry add test_utils ``` ## CLI Commands ### Scan a Directory Scan Python files for SQL operations: ```bash sql_registry scan --directory \u002Fpath\u002Fto\u002Fapp [--registry .sql_registry.json] [--include-patches] ``` Options: * `--directory` - Directory to scan (default: current directory) * `--registry` - Registry file path (default: `.sql_registry.json`) * `--include-patches` - Include SQL in patch\u002Fmigration files. **Patches are excluded by default** since they are one-time migrations and typically don't need conversion. This creates a `.sql_registry.json` file containing all discovered SQL calls. ### List SQL Calls List all SQL calls in the registry: ```bash sql_registry list [--registry .sql_registry.json] [--file-filter myfile.py] ``` ### Show Call Details Show detailed information about a specific SQL call: ```bash sql_registry show \u003Ccall_id> [--registry .sql_registry.json] ``` Output includes: * Original SQL query * Extracted parameters * Query Builder equivalent * Status indicators (`✅ Query Builder`, `💡 ORM-ELIGIBLE`, `🔧 Manual Review`, `⚠️ HAS TODO`) ### List TODOs List calls that need manual revi",{"id":441,"title":442,"content":443,"level":16},"\u002Fdocumentation\u002Ftest_utils\u002Fstatic_analysis\u002F","static_analysis","# Frappe Static Analysis `static_analysis` is a suite of static checks for Frappe apps that runs entirely from the filesystem — no running bench, no imports. It validates that the paths and references scattered across a Frappe app's configuration files, frontend code, and Python source actually point to real, correctly-decorated code. ## Checks ### hooks Parses `hooks.py` with the AST and validates every dotted Python path it finds. Keys whose values are never Python paths (asset bundles, URL rules, app metadata, fixture lists, etc.) are excluded automatically. Errors when a referenced function, class, or attribute does not exist in the resolved file. Warns when a path resolves to a module rather than a callable. ### patches Parses `patches.txt` — including the `execute:` prefix format introduced in Frappe v14 and lines with trailing reload-doc suffixes — and validates each path. Frappe's convention of pointing a patch at a plain module (where `execute()` is called automatically) is handled: if the path resolves to a module, the validator checks that `execute()` exists inside it. ### frontend Scans all `.js`, `.ts`, `.vue`, `.jsx`, and `.tsx` files for `frappe.call(...)` and `frappe.xcall(...)` invocations and validates the referenced Python path. Errors when: - The target function does not exist - The function exists but is not decorated with `@frappe.whitelist()` The `method: \"...\"` dict-key pattern is also matched when the file already contains a `frappe.call` or `frappe.xcall` call. ### python_calls The same check as **frontend**, applied to Python files. Uses the AST to find `frappe.call` \u002F `frappe.xcall` invocations and supports positional string args, `{\"method\": \"...\"}` dicts, and `method=\"...\"` keyword arguments. ### jinja Validates template paths referenced in: - `frappe.get_template(\"path\")` - `frappe.render_template(\"path\", ...)` (when the first argument looks like a file path) - `{% include \"path\" %}` and `{% extends \"path\" %}` in HTML\u002FJinja files Searc",{"id":445,"title":446,"content":447,"level":16},"\u002Fdocumentation\u002Ftest_utils\u002Fvalidate_customizations\u002F","validate_customizations","# Frappe Customization Validation Documentation The `validate_customizations` hook is designed to keep Custom Fields and Property Setters with their respective apps. This has become increasingly necessary as the number of applications used in a typical ERPNext deployment increases. ## Validation Checks The validation system performs several checks to ensure customizations are properly organized and maintained: 1. **Custom Permissions Check** (`validate_no_custom_perms`) - Ensures no custom permissions are defined in customization files - Custom permissions should not be included in customizations - Changes to permissions through customizations create significant operational friction: * Changes must go through version control and CI pipelines, causing unnecessary delays * Custom permissions are reset during `bench migrate`, nullifying any manual changes made by the customer or system administrator * Permission changes often need to be immediate for business operations - Instead, manage permissions directly through the UI's Role Permission Manager 2. **Module Attribution** (`validate_module`) - Verifies that all Custom Fields and Property Setters have a valid module key - Ensures Property Setters are associated with the correct module and application 3. **System Generation Status** (`validate_system_generated`) - Identifies and flags system-generated Custom Fields that may be managed by internal Frappe\u002FERPNext APIs - Examples include barcode visibility in Stock Settings - The management of Accounting Dimension or Inventory Dimensions fields can be overridden if subsequent customization is required 4. **Own DocType Customization** (`validate_customizations_on_own_doctypes`) - Prevents customizing DocTypes that are already defined within the same app, ensuring modifications to an app's DocTypes are made in the source rather than through customizations 5. **Duplicate Customizations** (`validate_duplicate_customizations`) - Detects duplicate Custom Fields and Property Set",{"id":449,"title":450,"content":451,"level":16},"\u002Fdocumentation\u002Ftest_utils\u002Fvalidate_doctype_python_types\u002F","validate_doctype_python_types","# DocType Python types — `validate_doctype_python_types` Frappe can [auto-generate static type hints](https:\u002F\u002Ffrappeframework.com\u002Fdocs\u002Fuser\u002Fen\u002Fbasics\u002Fdoctypes\u002Fcontrollers) on DocType controllers when `export_python_type_annotations = True` is set in `hooks.py`. Saving a DocType in Desk (or calling `export_types_to_controller` on the DocType document) writes a `TYPE_CHECKING` block delimited by: - `# begin: auto-generated types` - `# end: auto-generated types` This matches [`frappe.types.exporter`](https:\u002F\u002Fgithub.com\u002Ffrappe\u002Ffrappe\u002Fblob\u002Fdevelop\u002Ffrappe\u002Ftypes\u002Fexporter.py). The pre-commit hook checks that every DocType controller either contains that block or an explicit opt-out comment, so teams using exported types do not accidentally commit controllers that fell out of sync with the schema. --- ## When the hook runs | Situation | Behavior | |-----------|----------| | `export_python_type_annotations` is **not** `True` in `hooks.py` | Exit **0**, message on stderr that the check was skipped. Safe for apps that do not use Frappe’s exporter yet. | | Flag is **True** (or you pass `--force`) | All matching controllers are scanned; missing block + opt-out → exit **1** with a file list. | `hooks.py` is resolved as `\u003Capp_root>\u002F\u003Cpackage>\u002Fhooks.py` first (e.g. `myapp\u002Fmyapp\u002Fhooks.py`), then `\u003Capp_root>\u002Fhooks.py`. --- ## Which files are checked Controllers matching: `\u003Capp_root>\u002F\u003Cpackage>\u002F**\u002Fdoctype\u002F*\u002F\u003Cmodule_name>.py` where the Python file name equals its parent directory name (Frappe’s usual layout, including nested modules such as `accounts\u002Fdoctype\u002Fsales_invoice\u002Fsales_invoice.py`). --- ## Satisfying the check **Option A — Frappe-generated block** Enable `export_python_type_annotations = True`, then for each listed DocType either re-save it in Desk or run `export_types_to_controller` (e.g. from a bench console). The controller must contain `# begin: auto-generated types`. **Option B — Opt-out (documented exception)** Add a *whole-line* comment near the top of the controller (afte",{"id":453,"title":454,"content":455,"level":16},"\u002Fideas\u002Fagritheory-newsletter-june-2026","AgriTheory Newsletter: June 2026","\u003Ch1 id=\"approvals\">Approvals\u003C\u002Fh1>\n\n\u003Cp>Approving documents is now smoother and more flexible. You can set up email reminders before approvals are due, and a Pending Approval Email Template makes those notifications more useful. Fallback approval roles produce clearer errors when something's misconfigured. Doctypes without a defined workflow can now use simple confirm-to-submit instead of relying on the more precise and customizable Workflow integration.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch1 id=\"beam\">BEAM\u003C\u002Fh1>\n\n\u003Cp>BEAM released version 15.11.0 with a focused feature addition: the scan-to-login functionality has been ported from the mobile_v15 branch into the main version-15 branch. When configured, users can scan a barcode or RFID to log in, if that barcode is present on their User profile. This feature can restricted by IP so it represents logins for a user who is on already on prem.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch1 id=\"check-run\">Check Run\u003C\u002Fh1>\n\n\u003Cp>After more than two years of design and iteration, Check Run v15.14.0 ships the Sales Tax Payable workflow — extending Check Run from vendor AP into a full sales tax remittance path for businesses that collect tax on Sales Invoices and owe it to government authorities.\u003C\u002Fp>\n\n\u003Cp>The workflow treats each Sales Taxes and Charges row on a Sales Tax Payable account as its own payable: tax authorities are modeled as Party on the tax row, Outstanding Amount is tracked per row on submit, and due dates follow the authority’s payment terms. Operators configure a bank account \u002F Sales Tax Payable account pair in Check Run Settings, enable Include Tax Payable from Sales Invoices, and remit the same way they already pay suppliers: by selecting open tax liabilities, run the Check Run, and generate Payment Entries. Returns and post-remittance credits are handled explicitly: return invoices produce negative outstanding amounts that can net against future remittances when \"Allow stand-alone debit notes?\" is enabled.\u003C\u002Fp>\n\n\u003Cp>Supporting this release is the new Sales Tax Remittance report, a rolling view of tax collected, customer-paid, remitted, and still outstanding — with summary rollups by authority and month and a detail mode that links each tax row back to its Sales Invoice and remittance Payment Entry. Remittance is intentionally routed through Check Run (not the standard Sales Invoice Payment Entry button, which targets receivables). The release also includes targeted fixes to Payment Entry reference amounts, Sales Invoice outstanding calculations, and Supplier Tax Certificate query ordering, plus documentation and a comprehensive test suite covering GL posting, Check Run processing, returns, and remittance reporting.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch1 id=\"communications\">Communications\u003C\u002Fh1>\n\n\u003Cp>Communications shipped three releases in June (v15.7.0, v15.8.0, v15.8.1), with three major capabilities: sendmail override routing, sliding window notification batching, and portal electronic signatures.\u003C\u002Fp>\n\n\u003Ch3 id=\"sendmail-override-and-alternate-notification-routing\">Sendmail override and alternate notification routing\u003C\u002Fh3>\n\n\u003Cp>Communications can now intercept core Frappe outbound emails and route them through configurable Notification records instead of stock frappe.sendmail. Admins set an Email Override on a Notification to match a specific email path — desk Notification Log types (assignments, mentions, shares, energy points, alerts), document-follow digests, workflow approval emails, or calendar event digests — then choose the delivery channel: Email, Slack DM, or Teams DM. The original subject, body, and context (who triggered it, which document, workflow actions, calendar events) are exposed as Jinja template variables, so a single assignment can become a Slack message, a Teams chat, or a formatted email without changing upstream Frappe code. v15.7.0 laid groundwork by relaxing required Notification fields when Email Override is set, so routing-only Notifications don't need doc-event triggers or recipient rows.\u003C\u002Fp>\n\n\u003Ch3 id=\"sliding-window-notification-batching\">Sliding window notification batching\u003C\u002Fh3>\n\n\u003Cp>Assignment notifications no longer have to arrive one email at a time. Sliding Window Notification Batching collects assignment (and related desk) notifications over a configurable time window — default 15 minutes, with optional caps on digest size — and delivers them as a single digest instead of a burst of individual messages. Delivery respects Notification Window Settings: enabled\u002Fdisabled, collection window length, delivery hours (e.g. 8:00–20:00 in a chosen timezone), and optional bypass for priority DocTypes. Queued items move through Sent, Failed, or Rescheduled states when they fall outside delivery hours; the batch processor can still hand off to the sendmail override path, so a digest can land in Slack or Teams as easily as in email. The goal is less notification fatigue while keeping the full set of assignments visible in one place.\u003C\u002Fp>\n\n\u003Ch3 id=\"electronic-signatures\">Electronic Signatures\u003C\u002Fh3>\n\n\u003Cp>The new Electronic Signature DocType lets organizations send any ERP document for signature through a portal signing flow. An admin links a business document (via Dynamic Link), selects a Print Format, adds signers from Contact records, and sends per-signer invitation emails from desk. Signers open a magic-link or portal URL (\u002Fsign), view the agreement rendered through the chosen print format (even when they lack read permission on the underlying document), and sign with an embedded signature pad; when every signer executes, status moves automatically to Completed. Sites wire parent DocTypes through Document Links on the Connections tab, optional Portal Settings sidebar entries, and the install-time Electronic Signature Request email template.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch1 id=\"inventory-tools\">Inventory Tools\u003C\u002Fh1>\n\n\u003Cp>Inventory Tools released version 15.13.2 with a single targeted bug fix: time calculations in Job Cards now correctly use the Job Card time rather than the Bill of Materials time. This ensures more accurate time tracking during manufacturing operations.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch1 id=\"saml\">SAML\u003C\u002Fh1>\n\n\u003Cp>SAML shipped two releases in June. v15.7.0 added Keycloak-backed integration tests for ACS, login, role mapping, and certificate handling in CI — groundwork before the larger SSO experience in v15.8.0.\u003C\u002Fp>\n\n\u003Ch3 id=\"auto-saml-login-and-seamless-sso-v1580\">Auto SAML Login and seamless SSO (v15.8.0)\u003C\u002Fh3>\n\n\u003Cp>The headline capability is Auto SAML Login: when enabled on a SAML Login Key, guest requests to in-scope routes (all guest pages, configured path wildcards, or desk-only \u002Fapp) trigger a passive SAML authentication request before ERPNext renders. If the user already has an IdP browser session, they land in the app with no password prompt; if not, the flow escalates to a full interactive SAML login. On \u002Flogin, passive SSO runs first while preserving redirect-to, but failure shows the normal sign-in form (with a one-time skip token) so local accounts and explicit “Login with {Provider}” buttons stay available. Only one provider may use Auto SAML at a time, and built-in exclusions keep \u002F, \u002Flogin, \u002Flogout, and static\u002FAPI paths out of silent redirect loops.\u003C\u002Fp>\n\n\u003Ch3 id=\"login-experience-logout-page-and-session-termination-v1580\">Login experience, logout page, and session termination (v15.8.0)\u003C\u002Fh3>\n\n\u003Cp>The login page override prepends SAML providers to Frappe’s standard sign-in UI as “Login with {Provider Name}” buttons, with domain-aware behavior that hides password login when the email domain matches configured SAML Domains. Logout is redesigned for SSO sites: instead of sending users to \u002Flogin (where passive SSO would immediately sign them back in), Auto SAML-enabled sites redirect to a dedicated \u002Flogout page with a clear Log in again action. When Terminate SAML Session on logout is enabled, the app sends SAML Single Logout to the IdP before landing there, so the next visit requires a fresh authentication. Desk logout honors the same redirect via boot flags and a patched desk logout handler.\u003C\u002Fp>\n\n\u003Ch3 id=\"idp-metadata-sync-and-security-hardening-v1580\">IdP metadata sync and security hardening (v15.8.0)\u003C\u002Fh3>\n\n\u003Cp>Scheduled IdP metadata synchronization keeps signing certificates current without manual copy-paste: each SAML Login Key can point at an IdP Metadata URL, run on a configurable cron schedule (with manual sync from desk), and update the stored certificate in the background. If a stale cert causes a signature failure during login, ACS can fetch fresh metadata once and retry automatically. Security defaults tightened as well: SAML validation is strict by default (destination, timing, audience, and correlation checks), with per-provider Allow Relaxed SAML Validation for legacy IdPs. Redirect sanitization blocks open redirects, ACS errors hide internal tracebacks outside developer mode, and forged passive-login skip tokens are rejected — together making seamless SSO workable without sacrificing control at entry and exit points.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch1 id=\"taxjar-erpnext\">Taxjar ERPNext\u003C\u002Fh1>\n\n\u003Cp>Taxjar ERPNext released version 15.1.0 with general maintenance and documentation improvements. Pre-commit configurations were updated and cleaned up across multiple commits, and documentation was refreshed to reflect current usage. A dedicated documentation feature commit rounds out the release.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch1 id=\"test-utils\">Test Utils\u003C\u002Fh1>\n\n\u003Cp>Test Utils shipped three releases in quick succession. Version 1.26.0 adjusted the Farm Chart of Accounts inventory adjustment entries and account types. Version 1.27.0 added Frappe type-checking validation for Doctypes and bumped Python support to include version 3.14. Version 1.28.0 added printer test utilities, expanding the toolkit available for testing print-related functionality across applications.\u003C\u002Fp>\n",{"id":457,"title":458,"content":459,"level":16},"\u002Fideas\u002Fagritheory-newsletter-may-2026","AgriTheory Newsletter: May 2026","\u003Ch2 id=\"cloud-storage\">Cloud Storage\u003C\u002Fh2>\n\n\u003Cp>File management is now more reliable: duplicate File records are prevented, and S3 keys are no longer lost when a file is re-uploaded. A smaller pipefail bug was also fixed, and an unnecessary commit step was removed to simplify the process. Test coverage was expanded to confirm file versioning and hash updates work correctly on re-upload.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch2 id=\"communications\">Communications\u003C\u002Fh2>\n\n\u003Cp>The latest release of Communications (v15.6.0) introduces a new feature that enqueues DMS operations, improving how document management system tasks are handled and processed within the application.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch2 id=\"inventory-tools\">Inventory Tools\u003C\u002Fh2>\n\n\u003Cp>You can now curate UOMs directly from the UOM Category page, and Items support UOM-specific dimensions for more granular unit-of-measure configuration. A bug causing an integer-access error has been fixed, along with a cartonization import issue that surfaced after the UOM changes.\u003C\u002Fp>\n\n\u003Cp>A follow-up patch in v15.13.1 addressed a cartonization import issue, ensuring that carton-related functionality continues to work reliably after the recent UOM enhancements.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch2 id=\"saml\">SAML\u003C\u002Fh2>\n\n\u003Cp>Ports are now stripped from URLs in production (non-developer-mode) environments, improving compatibility. A configuration bug affecting \u003Ccode>requestedAuthnContext\u003C\u002Fcode> has also been fixed. Documentation for the lxml installation guide was corrected.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch2 id=\"shipstation-integration\">Shipstation Integration\u003C\u002Fh2>\n\n\u003Cp>Shipstation Integration now supports 17track as a first-class carrier tracking source. New DocTypes for Seventeen Track settings and Tracking Number records replace the older ad-hoc structure, with seeded webhook configuration and refactored tracking-number handling so events can be stored and updated reliably as carriers report status. This is the foundation release: tracking numbers, webhook intake, and the data model the rest of the feature builds on.\u003C\u002Fp>\n\n\u003Cp>Building on that foundation, v1.14.0 adds map-based visualization. Tracking events are stored via Nominatim geocoding; the most recent event is highlighted with a red pin, and a map list view lets you see shipment locations without opening each record. Form-level map rendering, list-view coordinates, and guardrails for new\u002Funsubmitted records round out the UI.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch2 id=\"test-utils\">Test Utils\u003C\u002Fh2>\n\n\u003Cp>Site-specific customization validation is now more precise, checking only the current site. Our changlog sumarizer GitHub Action was expanded with a configurable base URL for OpenRouter and refinements to the Bedrock API. A code duplication threshold bug was also fixed.\u003C\u002Fp>\n",{"id":461,"title":462,"content":463,"level":16},"\u002Fideas\u002Fagritheory-newsletter-april-2026","AgriTheory Newsletter: April 2026","\u003Ch2 id=\"cloud-storage\">Cloud Storage\u003C\u002Fh2>\n\n\u003Cp>Version 15.9.4 makes File versioning more reliable when content changes are involved: version tracking sets up and records correctly, fixing issues that previously affected this behavior.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch2 id=\"communications\">Communications\u003C\u002Fh2>\n\n\u003Ch3 id=\"teams-notifier-via-bot-network\">Teams Notifier via Bot Network\u003C\u002Fh3>\n\n\u003Cp>Communications can now deliver notifications through Microsoft Teams using the MS BOTNetwork integration. Instead of relying on email alone or manual follow-up, teams can receive timely updates where they already work—inside Teams channels and conversations, similar in parity to Slack direct messages features. The Bot Network approach routes messages through a MS-hosted service so notification delivery stays consistent across environments and easier to manage as your Teams setup grows.\u003C\u002Fp>\n\n\u003Ch3 id=\"public-calendar-appointment-scheduling\">Public Calendar &amp; Appointment Scheduling\u003C\u002Fh3>\n\n\u003Cp>The Public Calendar is now built into Communications, replacing the standalone app. Each user can publish one or more shareable calendars with two views: a public availability page (\u002Fcalendar) where visitors see when someone is busy without private event details, and an authenticated booking page (\u002Fschedule) where logged-in users pick open slots and schedule appointments. Hosts configure working hours, slot length, buffer time between meetings, minimum notice, and how far ahead bookings are allowed; the system validates those rules before anything is booked. Appointments create Event records with email confirmations, optional ICS attachments, secure RSVP links for confirm\u002Fdecline\u002Fcancel, and hourly reminder notifications. Timezone handling runs end-to-end—display uses the viewer’s timezone, server-side conversion keeps slots accurate, and users can update their timezone from the booking UI—so events show at the right local time across regions. Query parameters on schedule links (task, subject, description, and related portal fields) let you launch scheduling from workflows like onboarding or support: the booking form opens pre-filled and can link the resulting event back to the source Task. Together, these pieces turn Communications into a single place to share availability, take bookings, and manage follow-through without juggling separate calendar tools.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch2 id=\"test-utils\">Test Utils\u003C\u002Fh2>\n\n\u003Cp>You can now generate a visual graph of your codebase, and static analysis reports are available as HTML with improved handling of overrides. New Semgrep-based linting rules — including custom AgriTheory rules — help catch security and code quality issues earlier.\u003C\u002Fp>\n",{"id":465,"title":466,"content":467,"level":16},"\u002Fideas\u002Fagritheory-newsletter-march-2026","AgriTheory Newsletter: March 2026","\u003Cp>\u003Cimg src=\"https:\u002F\u002Ferp.agritheory.com\u002Fapi\u002Fmethod\u002Fretrieve?key=ATERP\u002FNewsletter\u002Fagritheory-newsletter-march-2026\u002Fwhite-river-junction-vt.jpg\" alt=\"White River Junction, VT\" class=\"screenshot\" \u002F>\u003C\u002Fp>\n\n\u003Ch2 id=\"approvals\">Approvals\u003C\u002Fh2>\n\n\u003Cp>The Approvals application received documentation additions, with new docs merged as part of the \u003Cstrong>15.4.0\u003C\u002Fstrong> release. A translate documentation workflow file was also added to support internationalization efforts, laying the groundwork for broader language support.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch2 id=\"beam\">BEAM\u003C\u002Fh2>\n\n\u003Cp>BEAM saw productive development across multiple fronts. A bug fix addressed a default value being set at the wrong lifecycle stage (moved from schema to creation), and mobile repack tests were added — both landing in the \u003Cstrong>15.8.1\u003C\u002Fstrong> release. A new \u003Ccode>beam_barcode_resolver\u003C\u002Fcode> hook was introduced in \u003Cstrong>15.9.0\u003C\u002Fstrong>, and a bypass flag was added for recombine Handling Unit workflows in \u003Cstrong>15.10.0\u003C\u002Fstrong>. Subsequent work continued on shipping test infrastructure, including improvements to pytest ordering by file, normalization of that ordering, and a fix to ensure auto barcode generation works across all Document Types. Department field updates and ongoing branch integration work for the mobile and shipping test suites rounded out a strong period of development.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch2 id=\"check-run\">Check Run\u003C\u002Fh2>\n\n\u003Cp>Check Run development centered on expanding the application's accounting capabilities. New features include a \u003Cstrong>Sales Tax Payable\u003C\u002Fstrong> workflow, logic to ensure only accounts marked as payable include a party, and sensitivity for accounting dimensions — all accompanied by new tests. Additional work-in-progress commits addressed Payment Entry saves, setup scripting for submitting Sales Invoices, and handling of tax payable due dates, indicating active feature development heading into the next cycle.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch2 id=\"cloud-storage\">Cloud Storage\u003C\u002Fh2>\n\n\u003Cp>Cloud Storage received a series of improvements. Initial fixes addressed file preview functionality and hash checks for duplicate file names, landing in \u003Cstrong>release 15.9.3\u003C\u002Fstrong>. Subsequent work improved the filename display in File Preview, added 3D model preview support, and cleaned up the preview UI by removing an emoji. Tests were added to cover scenarios without S3 storage configured. A cleanup effort also removed post-migration customization logic, keeping the codebase leaner.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch2 id=\"communications\">Communications\u003C\u002Fh2>\n\n\u003Cp>A public calendar previously maintained elsewhere was ported into the Communications application, consolidating calendar functionality within the app.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch2 id=\"electronic-payments\">Electronic Payments\u003C\u002Fh2>\n\n\u003Cp>Electronic Payments received several maintenance and quality improvements. The Authorize.Net dependency was switched to a community fork, with the Poetry lock file updated accordingly. Network diagrams were added to the provider documentation, and a \u003Ccode>customize.py\u003C\u002Fcode> file was removed as part of a cleanup effort. Two separate refactoring passes addressed code duplication — one on the Python side and one targeting JavaScript — improving the overall maintainability of the integration layer.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch2 id=\"fleet\">Fleet\u003C\u002Fh2>\n\n\u003Cp>Fleet activity focused on test reliability and a documentation update. Fixes were applied to Department naming conventions and lookup logic within the test suite, and name and index keys were restored where they had been missing. These changes culminated in the \u003Cstrong>15.2.0\u003C\u002Fstrong> release, reflecting the stabilization work completed.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch2 id=\"inventory-tools\">Inventory Tools\u003C\u002Fh2>\n\n\u003Cp>Inventory Tools shipped three releases. A quarantine-related bug fix landed in \u003Cstrong>15.10.1\u003C\u002Fstrong>, followed by type improvements and better tracking of overrides in \u003Cstrong>15.10.2\u003C\u002Fstrong>. The \u003Cstrong>15.11.0\u003C\u002Fstrong> feature release optimizes the Warehouse Plan and adds a default value to the application settings, improving out-of-the-box usability.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch2 id=\"kenaf\">Kenaf\u003C\u002Fh2>\n\n\u003Cp>Kenaf saw a mix of documentation, new tooling, and dependency updates. Documentation was added, followed by the introduction of \u003Cstrong>Nuitka\u003C\u002Fstrong> support for compiled Python builds. Dependabot contributed several dependency upgrades, including bumps to Quart, Quart-CORS, Uvicorn, and Argon2-CFFI, keeping the project's dependency tree current and secure.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch2 id=\"shipstation-integration\">Shipstation Integration\u003C\u002Fh2>\n\n\u003Cp>Shipstation Integration had an active development periods, spanning packing workflows, LTL (Less-Than-Truckload) freight support, and new carrier integrations. On the packing side, a minimal UCC-128 barcode implementation was completed, packing slip enhancements were added, and the packing workflow was documented. LTL support was a major theme: work included refactoring to a base LTL class, adding insurance fields and sections, building out Bill of Lading (BOL) API support, and writing comprehensive tests and documentation for LTL configuration and workflows — all merged in \u003Cstrong>PR #87\u003C\u002Fstrong>.\u003C\u002Fp>\n\n\u003Cp>A new \u003Cstrong>Freight Carrier Settings\u003C\u002Fstrong> Document Type was introduced with accompanying tests, and initial integration work began for \u003Cstrong>17track\u003C\u002Fstrong>, including a new webhook, seed data, and foundational tests. Development closed with new API builds for WWEX, ODFL, and Banyan carriers, along with pre-commit and formatting housekeeping.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch2 id=\"test-utils\">Test Utils\u003C\u002Fh2>\n\n\u003Cp>Test Utils shipped four patch releases (\u003Cstrong>1.20.1\u003C\u002Fstrong> through \u003Cstrong>1.20.4\u003C\u002Fstrong>). A headline addition was a retrospective changelog generator with optional Ollama (local LLM) support, enabling automated changelog production from PR history. Additional fixes addressed path resolution, ignored patterns in method filtering, file validation and writing, and a percentage calculation error. Membership analysis was replaced with a more robust segment analysis approach, reflecting ongoing refinement of the testing and reporting utilities.\u003C\u002Fp>\n",{"id":469,"title":470,"content":471,"level":16},"\u002Fideas\u002Fagritheory-newsletter-february-2026","AgriTheory Newsletter: February 2026","\u003Cp>\u003Cimg src=\"https:\u002F\u002Ferp.agritheory.com\u002Fapi\u002Fmethod\u002Fretrieve?key=ATERP\u002FNewsletter\u002Fagritheory-newsletter-february-2026\u002Fsuncook-nh.png\" alt=\"Suncook, NH\" class=\"screenshot\" \u002F>\u003C\u002Fp>\n\n\u003Ch1 id=\"beam\">BEAM\u003C\u002Fh1>\n\n\u003Cp>BEAM has seen a busy release cycle with several notable improvements across printing, barcoding, and handling unit functionality. Barcode generation is now fully configurable through BEAM Settings, allowing users to specify barcode type, size, orientation, and color scheme, with updated documentation to match. The CUPS network printer connection has also been improved with the addition of custom network printer settings and refreshed print server documentation. On the bug fix side, a duplicate barcode creation issue on Item save has been resolved.\u003C\u002Fp>\n\n\u003Cp>Handling Unit management received meaningful enhancements as well. Handling Unit creation now respects per-Item configuration defined in BEAM Settings, and BEAM Settings are automatically created whenever a new Company is created. Additional improvements include serial number tracking integration within the Handling Unit workflow, support for printing standard Print Formats on Handling Units, and a fix to a UI bug in the recombine dialog that appeared during Stock Entry cancellation.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch1 id=\"cloud-storage\">Cloud Storage\u003C\u002Fh1>\n\n\u003Cp>Cloud Storage received a focused maintenance release (v15.9.2) that cleaned up leftover permissions code. Specifically, orphaned \u003Ccode>has_permissions\u003C\u002Fcode> overrides that were no longer needed following a permissions refactor have been removed from \u003Ccode>hooks.py\u003C\u002Fcode>. Supporting updates include refreshed \u003Ccode>pyproject.toml\u003C\u002Fcode> and pre-commit configurations, removal of the superseded permissions override, and the addition of a changelog generation workflow.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch1 id=\"electronic-payments\">Electronic Payments\u003C\u002Fh1>\n\n\u003Cp>Electronic Payments v15.8.3 delivers an important bug fix for users of the Authorize.net payment provider: transactions processed with the \"Charge Now\" option were being submitted twice, resulting in duplicate charges. This double-charge issue has been resolved, and documentation screenshots and images have been updated to reflect the current settings structure introduced in a recent refactor.\u003C\u002Fp>\n\n\u003Cp>Alongside the bug fix, general housekeeping was performed, including updates to \u003Ccode>pyproject.toml\u003C\u002Fcode> and pre-commit configuration, and the addition of several workflows covering backporting, code-duplication detection, changelog generation, and override tracking.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch1 id=\"inventory-tools\">Inventory Tools\u003C\u002Fh1>\n\n\u003Cp>Inventory Tools v15.10.0 introduces an enhancement to the three-way check feature, which can now detect Items added directly in Purchase Receipts and Purchase Invoices, along with new UI filters to support this capability. This makes the reconciliation process more robust for teams managing purchasing workflows.\u003C\u002Fp>\n\n\u003Cp>Supporting changes in this release include a migration of raw SQL queries in \u003Ccode>specification.py\u003C\u002Fcode> and \u003Ccode>faceted_search_query.py\u003C\u002Fcode> to use the Frappe Query Builder, a code-duplication detection workflow, and the usual updates to \u003Ccode>pyproject.toml\u003C\u002Fcode> and pre-commit configuration.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch1 id=\"test-utils\">Test Utils\u003C\u002Fh1>\n\n\u003Cp>Test Utils has seen an exceptionally active release period, shipping over a dozen versions with a wide range of new tooling and improvements. Highlights include a new static analysis tool for Frappe apps (v1.20.0) that checks Python code, frontend files, and Jinja templates for undecorated paths and unresolved references, with orphan detection via Vulture and configurable path allowlists. The SQL rewriter tool received multiple rounds of fixes and improvements, including better AST node positioning, support for HAVING clauses and inline math, JSON-based database storage for the SQL registry, and handling of IN\u002Ftuple patterns. A new \u003Ccode>validate_frappe_dependencies\u003C\u002Fcode> pre-commit hook was also added to verify that Frappe and ERPNext dependency version bounds are correctly specified in \u003Ccode>pyproject.toml\u003C\u002Fcode>.\u003C\u002Fp>\n\n\u003Cp>Further additions include a code-deduplication pre-commit hook and CI action, an allowlist for customizations in \u003Ccode>validate_customizations\u003C\u002Fcode>, a \u003Ccode>track_overrides\u003C\u002Fcode> utility module (including app name in override logs), and expanded validation checks in the Frappe project validator. The \u003Ccode>patch_linters\u003C\u002Fcode> hook was renamed to \u003Ccode>validate_patches\u003C\u002Fcode> and updated to support \u003Ccode>execute:\u003C\u002Fcode>-style inline patches in \u003Ccode>patches.txt\u003C\u002Fcode>. A guard clause was also added to prevent errors when no patches are found during patch validation.\u003C\u002Fp>\n",{"id":473,"title":474,"content":475,"level":16},"\u002Fideas\u002Fagritheory-newsletter-january-2026","AgriTheory Newsletter: January 2026","\u003Cp>\u003Cimg src=\"https:\u002F\u002Ferp.agritheory.com\u002Fapi\u002Fmethod\u002Fretrieve?key=ATERP\u002FNewsletter\u002Fagritheory-newsletter-january-2026\u002Flakeport-nh.png\" alt=\"Lakeport, NH\" class=\"screenshot\" \u002F>\u003C\u002Fp>\n\n\u003Ch2 id=\"inventory-tools\">Inventory Tools\u003C\u002Fh2>\n\n\u003Cp>The latest release of Inventory Tools (v15.9.2) addresses a notable bug in the Material Demand workflow where clicking the \"Create PO\" button was generating duplicate Purchase Orders. This fix ensures that procurement processes remain clean and accurate without requiring manual cleanup of redundant records. Additionally, all custom DocType JSON files have been refreshed, and a code-duplication workflow that was causing continuous integration issues has been removed, improving overall development stability.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch2 id=\"test-utils\">Test Utils\u003C\u002Fh2>\n\n\u003Cp>Test Utils has seen a significant wave of updates across multiple releases, with a strong focus on improving the partition management utility. Recent versions introduced phased partition population to handle large datasets in stages, added a scheduled partition field population hook, and incorporated support for partitioning via pt-online-schema-change (pt-osc). Additional enhancements include index creation support, ensuring the \u003Ccode>name\u003C\u002Fcode> column is indexed during partition creation, adding Payment Entry (PE) partition support, and introducing retry logic with parent-already-processed checks to make the utility more robust and reliable.\u003C\u002Fp>\n\n\u003Cp>Several bug fixes have also landed across these releases, resolving issues with non-partitioned tables being incorrectly processed, a partition index bug, a bug in the \u003Ccode>_populate_with_time_limit\u003C\u002Fcode> function, and cleanup of the \u003Ccode>DOCTYPE_DATE_FIELD_MAP\u003C\u002Fcode> along with unused code removal. On the quality-of-life side, the default value for \u003Ccode>posting_date\u003C\u002Fcode> on child DocTypes is now automatically set to today's date, and a code duplication detection GitHub Action has been added to help maintain code quality going forward.\u003C\u002Fp>\n",{"id":477,"title":478,"content":479,"level":16},"\u002Fideas\u002Fagritheory-newsletter-december-2025","AgriTheory Newsletter: December 2025","\u003Cp>\u003Cimg src=\"https:\u002F\u002Ferp.agritheory.com\u002Fapi\u002Fmethod\u002Fretrieve?key=ATERP\u002FNewsletter\u002Fagritheory-newsletter-december-2025\u002Fberlin-nh.jpg\" alt=\"Berlin, NH\" class=\"screenshot\" \u002F>\u003C\u002Fp>\n\n\u003Ch2 id=\"cloud-storage\">Cloud Storage\u003C\u002Fh2>\n\n\u003Cp>Recent releases of Cloud Storage have focused on reliability, storage path improvements, and expanded file handling capabilities. A significant update introduced a new default S3 path strategy along with a \u003Ccode>bench\u003C\u002Fcode> command to migrate existing files from legacy paths to the new format, with a legacy compatibility mode available for installations that need backward-compatible key structures. The \u003Ccode>s3_key\u003C\u002Fcode> field now supports a configurable data length to prevent truncation of longer S3 key paths. Additional enhancements include file versioning support — where uploading a file with a matching content hash links it to an existing File record instead of creating a duplicate — as well as preview support for PowerPoint, OpenDocument Presentation, and Keynote file types.\u003C\u002Fp>\n\n\u003Cp>Several important bug fixes have also been delivered. An issue was resolved where deleting a File did not first remove its associated File Association records, leaving orphaned child table rows in the database. Validation of the \u003Ccode>associated_doc\u003C\u002Fcode> field and the \u003Ccode>s3_key\u003C\u002Fcode> assignment for email attachments were also corrected, ensuring those files are properly stored and retrievable from S3. A fix was additionally made to allow files to be attached from the library within the Add Attachments dialog.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch2 id=\"inventory-tools\">Inventory Tools\u003C\u002Fh2>\n\n\u003Cp>Inventory Tools has seen a series of meaningful updates across several recent releases. A new Workstation Operating Cost Doctype was introduced, enabling per-workstation cost tracking that integrates directly into Stock Entry and Work Order processing, complete with an enable\u002Fdisable toggle in the UI and a fallback to the previous cost system. Faceted search functionality was also restored, and the plant floor section was removed from the application. A \u003Ccode>name\u003C\u002Fcode> key was added back to all custom JSON files to prevent a key error when running \u003Ccode>bench migrate\u003C\u002Fcode> through the \u003Ccode>customize.py\u003C\u002Fcode> script.\u003C\u002Fp>\n\n\u003Cp>Follow-up fixes to the Workstation Operating Cost feature corrected how \u003Ccode>time_in_mins\u003C\u002Fcode> is sourced — now pulled from Job Card with a fallback to Work Order — removed rounding that was zeroing out small per-unit costs, and removed an incompatible \u003Ccode>super()\u003C\u002Fcode> call. Override tracking changes were also implemented, and a code-duplication detection workflow was added and integrated into the custom JSON files.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch2 id=\"test-utils\">Test Utils\u003C\u002Fh2>\n\n\u003Cp>Test Utils received updates focused on database partition management and tooling improvements. Support was added for creating future partitions while skipping any that already exist, with a configurable years-ahead setting and a \u003Ccode>before_migrate\u003C\u002Fcode> hook to automate partition setup during migrations. Command line argument support was also added to the \u003Ccode>bylines\u003C\u002Fcode> pre-commit hook, and Poetry documentation was updated to clarify required fields in \u003Ccode>pyproject.toml\u003C\u002Fcode>.\u003C\u002Fp>\n\n\u003Cp>A targeted bug fix followed, correcting the \u003Ccode>clean_customized_doctypes\u003C\u002Fcode> function to preserve the \u003Ccode>name\u003C\u002Fcode> and \u003Ccode>idx\u003C\u002Fcode> keys that are required for successful reinstallation of customized Doctypes.\u003C\u002Fp>\n",{"id":481,"title":482,"content":483,"level":16},"\u002Fideas\u002Fagritheory-newsletter-november-2025","AgriTheory Newsletter: November 2025","\u003Ch2 id=\"electronic-payments\">Electronic Payments\u003C\u002Fh2>\n\n\u003Cp>The latest release of Electronic Payments (v15.8.2) includes a targeted bug fix addressing a configuration error in \u003Ccode>pyproject.toml\u003C\u002Fcode>. This update also refreshes the \u003Ccode>poetry.lock\u003C\u002Fcode> file and updates the pre-commit configuration to ensure a smoother development and deployment experience.\u003C\u002Fp>\n\n\u003Ch2 id=\"inventory-tools\">Inventory Tools\u003C\u002Fh2>\n\n\u003Cp>Inventory Tools saw several updates across three recent releases. The newest release (v15.7.0) introduces a fix to test fixtures ensuring all prices are correctly included on the Bakery Buying List, and updates \u003Ccode>customize.py\u003C\u002Fcode> to safely check for the \u003Ccode>modified\u003C\u002Fcode> key before attempting to remove it, preventing key errors during \u003Ccode>bench migrate\u003C\u002Fcode>. An earlier release (v15.6.2) resolved a visual bug where the grid and images would stretch when hovering over warehouses in the Warehouse Plan.\u003C\u002Fp>\n\n\u003Cp>The v15.6.1 release focused on improving the Production Plan experience by adding an informational message when Purchase Orders are missing, helping users quickly identify and address gaps in their planning workflow. This release also added the \u003Ccode>project\u003C\u002Fcode> field to \u003Ccode>pyproject.toml\u003C\u002Fcode> to keep project metadata up to date.\u003C\u002Fp>\n\n\u003Ch2 id=\"test-utils\">Test Utils\u003C\u002Fh2>\n\n\u003Cp>The latest release of Test Utils (v15.3.2) delivers several quality-of-life improvements and bug fixes. A notable fix resolves an invalid cross-device link error that could disrupt file operations, and the \u003Ccode>bylines\u003C\u002Fcode> hook has been updated to gracefully handle projects that contain no markdown files, preventing unexpected failures. Additionally, a new pre-commit hook has been introduced to automatically detect and replace hardcoded email literals in source files, improving code hygiene and reducing the risk of sensitive data being committed to version control.\u003C\u002Fp>\n",{"id":485,"title":486,"content":487,"level":16},"\u002Fideas\u002Fagritheory-newsletter-october-2025","AgriTheory Newsletter: October 2025","\u003Ch2 id=\"electronic-payments\">Electronic Payments\u003C\u002Fh2>\n\n\u003Cp>Version 15.8.0 introduced two notable improvements to the Electronic Payment Settings experience. The settings document has been reorganized so that each payment provider now has its own dedicated section, making configuration easier to navigate. A new \u003Ccode>BaseProvider\u003C\u002Fcode> class has also been introduced to define a shared interface and common transaction processing logic for all providers, streamlining the process of adding support for new payment providers in the future.\u003C\u002Fp>\n\n\u003Cp>Version 15.8.1 followed shortly after with a housekeeping change: the Stripe dependency has been removed from the project configuration, as Stripe is no longer bundled directly with the application.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch2 id=\"fleet\">Fleet\u003C\u002Fh2>\n\n\u003Cp>Version 15.1.1 delivers a mix of bug fixes, new functionality, and improved documentation. A bug that caused an error when creating a Location while Traccar syncing was disabled has been resolved — the system now only attempts to load location data when syncing is active. Route optimization for Delivery Trips has also been added using Pyvroom, which computes the most efficient stop sequence for a given set of destinations. Additionally, the installation documentation has been updated with troubleshooting guidance to help users work through common setup issues.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch2 id=\"inventory-tools\">Inventory Tools\u003C\u002Fh2>\n\n\u003Cp>Version 15.6.0 is a major release centered on the introduction of a Warehouse Management System (WMS). The new WMS page features an interactive, Konva-powered grid that allows users to place and rotate Warehouse shapes, designate walkable paths, search for specific Warehouses, and view the plan in a read-only mode for users without edit permissions. Supporting this feature are new Physical Dimension and Item Dimension Doctypes, additional plan-related fields on the Warehouse Doctype, a plan toolbar, a Warehouse preview dialog, and accessible cell pathing.\u003C\u002Fp>\n\n\u003Cp>Beyond the WMS, this release also adds an alternative Workstation page with a branch view and Work Order operation customizations, refactors Alternative Workstations to support generalization and fallbacks, and introduces CI override tracking via GitHub Actions for Production Plans, Purchase Orders, Sales Orders, Stock Entries, Work Orders, and Workstations. Several UX and code quality improvements round out the release, including fixes to the warehouse hover popup, permissions-based edit mode toggling, and unsaved-change tracking on grid edits.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch2 id=\"test-utils\">Test Utils\u003C\u002Fh2>\n\n\u003Cp>Three releases of Test Utils landed in quick succession this cycle, all focused on the \u003Ccode>clean_customized_doctypes\u003C\u002Fcode> function. Version 1.2.0 introduced the \u003Ccode>clean_customized_doctypes\u003C\u002Fcode> pre-commit hook. Version 1.3.0 refined it to preserve special keys that are required for reinstallation. Version 1.3.1 then fixed a scoping issue so that the function only processes Doctype customizations belonging to the current app, preventing unintended modifications to customizations owned by other applications.\u003C\u002Fp>\n",{"id":489,"title":490,"content":491,"level":16},"\u002Fideas\u002Fagritheory-newsletter-september-2025","AgriTheory Newsletter: September 2025","\u003Ch2 id=\"autoreader\">Autoreader\u003C\u002Fh2>\n\n\u003Cp>Version 15.5.0 brings two notable additions to Autoreader. Twilio SMS integration has been added, enabling notifications to be sent via text message when new expenses are added — to take advantage of this feature, a Twilio phone number must be configured with a webhook pointing to the Autoreader SMS handler endpoint. Email body handling has also been improved overall.\u003C\u002Fp>\n\n\u003Cp>Additionally, a new rule has been introduced to handle forwarded emails, ensuring that forwarded messages are correctly identified and processed by the Autoreader mapping system.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch2 id=\"check-run\">Check Run\u003C\u002Fh2>\n\n\u003Cp>Version 15.10.0 delivers a significant set of improvements to Check Run, with a focus on payment term discounts. New features include automatic discount calculation via a dedicated \u003Ccode>calculate_payment_term_discount\u003C\u002Fcode> function, discount application on submit, and a new Payment Discount Account field. Supporting test data and tests for discount scenarios have also been added.\u003C\u002Fp>\n\n\u003Cp>Several bug fixes accompany these features, addressing date control handling, mandatory field validation, posting date formatting and type conversion, and the correct display of discount and due date information. The Paid Amount field now correctly reflects any applied discount.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch2 id=\"electronic-payments\">Electronic Payments\u003C\u002Fh2>\n\n\u003Cp>Version 15.7.0 introduces the ability to create Payment Methods directly from a Supplier or Customer record, streamlining the setup process for electronic payments. Error messages displayed during Payment Method deletion have been improved to provide clearer guidance, and the Company field has been removed from the add Payment Method flow to simplify the experience - new payment methods are added for all companies with properly-configured Electronic Payment Settings.\u003C\u002Fp>\n\n\u003Cp>A minor bug fix was also applied to remove an unintended company option, alongside internal code formatting updates.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch2 id=\"inventory-tools\">Inventory Tools\u003C\u002Fh2>\n\n\u003Cp>Version 15.5.0 marks an important transition for Inventory Tools: the custom strict UOM feature has been deprecated in favor of ERPNext's native UOM enforcement. Any affected settings and data have been migrated as part of this update, allowing users to continue managing unit-of-measure restrictions without relying on the custom implementation.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch2 id=\"test-utils\">Test Utils\u003C\u002Fh2>\n\n\u003Cp>Version 1.1.0 adds a \u003Ccode>bylines\u003C\u002Fcode> pre-commit hook that automatically generates author bylines in markdown files. Several other pre-commit hook improvements were also made, including a new translations validation hook, email literal detection within the customization validation hook, and extended copyright validation to cover SQL files.\u003C\u002Fp>\n\n\u003Cp>On the bug fix side, \u003Ccode>clean_customized_doctypes\u003C\u002Fcode> cleaning behavior has been corrected, and the \u003Ccode>validate_customizations\u003C\u002Fcode> app lookup in GitHub Actions pre-commit runs has been fixed to resolve issues encountered in CI environments.\u003C\u002Fp>\n",{"id":493,"title":494,"content":495,"level":16},"\u002Fideas\u002Fagritheory-newsletter-august-2025","AgriTheory Newsletter: August 2025","\u003Ch1 id=\"autoreader\">Autoreader\u003C\u002Fh1>\n\n\u003Cp>Version 15.4.0 brings several significant enhancements to Autoreader. Individual Email Inboxes can now be configured to process incoming ICS file attachments, automatically creating Frappe Calendar Events and adding participants whose User records exist in the system. Image processing has also been improved with the addition of major and skew rotation correction, allowing distorted document images to be straightened before OCR processing. Documentation has been updated with screenshots to illustrate the correction workflow.\u003C\u002Fp>\n\n\u003Cp>This release also introduces a Work Queue component embedded within Frappe's workspace, displaying Autoreader task data in a table using the Stonecrop component library. On the infrastructure side, the project has been migrated to Poetry for dependency management, numpy has been added as a dependency, and various CI, pre-commit, and package configuration updates have been applied. The previous v15.3.0 release added the ability to exclude Auto Repeat Documents from deduplication match results within Autoreader Settings, ensuring that system-generated Auto Repeat Documents are omitted from candidate lists during Autoreader matching.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch1 id=\"beam\">BEAM\u003C\u002Fh1>\n\n\u003Cp>Version 15.5.0 of BEAM introduces time log scanning support for mobile users, expanding the mobile workflow capabilities available in version 15. A type annotation issue with \u003Ccode>str | None\u003C\u002Fcode> in scan operations was also resolved as part of this update.\u003C\u002Fp>\n\n\u003Cp>Additionally, this release cycle included warehouse scanning support in the Stock Reconciliation Doctype, along with a fix for unavailable valuation rates encountered in demo data.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch1 id=\"check-run\">Check Run\u003C\u002Fh1>\n\n\u003Cp>Version 15.9.1 of Check Run addresses a bug where saving was permitted before the table had finished rendering, along with a correction to the Mode Of Payment summary display. Several recent updates have also strengthened the overall quality and maintainability of the project, including new tests for checking increments, an updated README with full MIT license text, and improvements to the automated Changelog generation workflow.\u003C\u002Fp>\n",{"id":497,"title":498,"content":499,"level":16},"\u002Fideas\u002Fagritheory-newsletter-july-2025","AgriTheory Newsletter: July 2025","\u003Ch2 id=\"approvals\">Approvals\u003C\u002Fh2>\n\n\u003Cp>Recent updates to the Approvals application have focused on improving audit visibility, workflow correctness, and rule management. Documents now automatically generate comments whenever an approver is added or removed, creating a clear and visible audit trail of approval changes. Approvers also receive a notification when they are added to a document's approval workflow. Additionally, cache-busting support has been added to ensure the Vue-based approvals interface always reflects the latest build without requiring a manual cache clear.\u003C\u002Fp>\n\n\u003Cp>Document Approval Rules have received several enhancements as well. The condition field now validates Python syntax before saving, and a dry-run option allows administrators to test whether a rule would apply to a given document without committing any changes. Error messages have also been improved to provide clearer feedback when conditions fail to evaluate correctly.\u003C\u002Fp>\n\n\u003Ch2 id=\"check-run\">Check Run\u003C\u002Fh2>\n\n\u003Cp>The Check Run application has received several improvements focused on data integrity and usability. The Positive Pay feature now includes an amount field, providing more complete payment data in generated files. Nacha file generation has been updated to ensure unique Payment Entries, eliminating potential duplicates and improving overall data integrity. Additionally, the select-all option has been restored and an on-hold filter has been added, giving users more flexibility when managing payment runs.\u003C\u002Fp>\n\n\u003Ch2 id=\"electronic-payments\">Electronic Payments\u003C\u002Fh2>\n\n\u003Cp>The Electronic Payments application has seen meaningful improvements to both the payment dialog experience and multi-company portal support. The payment dialog now auto-fills the party's billing address and email when a new payment method is created, both on the desk and portal sides. Save-only and save-and-process options are now available when adding a payment method on the desk side, and the primary action button label updates dynamically to reflect the selected action.\u003C\u002Fp>\n\n\u003Cp>Multi-company portal behavior has also been refined. When a customer adds a new payment method through the portal, it is now associated with all companies with Electronic Payment Settings configured to accept payment (or send payments for suppliers). Account fields in Electronic Payment Settings are filtered by company, which helps the user avoid errors linking to an account associated with a different company in the system, and the Customer ID is now retrieved from the Electronic Payment Profile rather than from the Customer or Supplier record directly.\u003C\u002Fp>\n",{"id":501,"title":502,"content":503,"level":16},"\u002Fideas\u002Fagritheory-newsletter-june-2025","AgriTheory Newsletter: June 2025","\u003Ch2 id=\"check-run\">Check Run\u003C\u002Fh2>\n\n\u003Cp>Recent releases bring significant improvements to invoice management and payment workflows. On-hold invoices are now correctly excluded from preselection during payment runs, preventing unintended payments and giving users greater control over their payables process. The Check Run UI has also been updated to clearly indicate when Purchase Invoices are on hold, and a \"select all\" option has been restored alongside a dedicated on-hold filter for easier navigation.\u003C\u002Fp>\n\n\u003Cp>Several new features round out this release cycle. The Example Voucher MICR print format is now based on Payment Entry, and users can optionally display days past due instead of the due date in the selection UI for clearer deadline management. Check Run Settings now supports a quick entry override, and an option has been added to automatically attach Positive Pay reports upon Check Run completion. Users can also configure whether cancelled Payment Entries are excluded from checks, and filter improvements provide a more refined payment selection experience overall.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch2 id=\"electronic-payments\">Electronic Payments\u003C\u002Fh2>\n\n\u003Cp>Electronic Payments has expanded its provider ecosystem and deepened its integration with Check Run. Mercury has been added as a sending payment provider, with the Mercury API fully integrated and Wire payment method information stored on Recipient records. Wise has also been added as a sending provider, complete with Wise API integration, batch group transfer support, and dropdown-limited fields for state, country, and account currency. The settings document now cleanly separates sending and accepting provider configurations into distinct sections, and the Authorize.net integration has been updated to use the official SDK.\u003C\u002Fp>\n\n\u003Cp>Check Run integration has been further strengthened: when a Check Run is submitted with an electronic payments mode of payment, the system automatically loops over the related Payment Entries and dispatches payments to each party. Additionally, a new \u003Ccode>enable_accepting\u003C\u002Fcode> checkbox in Electronic Payment Settings conditions accepting-related fields on its state, and Account ID validations have been moved to the \u003Ccode>on_update\u003C\u002Fcode> hook to provide informational messages rather than blocking errors.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch2 id=\"test-utils\">Test Utils\u003C\u002Fh2>\n\n\u003Cp>Test Utils has reached its v1.0.0 milestone, bringing several meaningful additions. A GitHub Actions workflow and pre-commit hook have been introduced to generate AI-assisted changelog entries for pull requests using the Anthropic API, with configurable model, token, and temperature parameters. The project has also been upgraded to Poetry v2, and a \u003Ccode>track_overrides\u003C\u002Fcode> GitHub Action and pre-commit hook have been added to support customization validation workflows.\u003C\u002Fp>\n\n\u003Cp>On the data management side, a \u003Ccode>populate_partition_fields_for_existing_data\u003C\u002Fcode> utility has been added to backfill partition fields in child tables, and \u003Ccode>create_partition\u003C\u002Fcode> has been updated to create partitions per DocType starting from the first year with existing data. The partition helper now includes the DocType name in partition names and logs each partition as it is created. Python 3.13 is now officially supported, and documentation has been expanded to cover both the partition helper and customization validation workflows.\u003C\u002Fp>\n",{"id":505,"title":506,"content":507,"level":16},"\u002Fideas\u002Fagritheory-newsletter-may-2025","AgriTheory Newsletter: May 2025","\u003Ch2 id=\"check-run\">Check Run\u003C\u002Fh2>\n\n\u003Cp>Version 15.4.0 of Check Run brings several notable improvements focused on security, usability, and workflow enhancements. A new permissioned signature API has been introduced, giving administrators greater control over who can authorize actions within the application. Complementing this, permission checks have been added to custom buttons such as \"Process Check Run,\" \"Download Checks,\" and \"Download NACHA,\" ensuring users can only perform the actions they are authorized to execute.\u003C\u002Fp>\n\n\u003Cp>This release also delivers meaningful improvements to day-to-day operations. ACH Prenote Report functionality has been added, along with fixes to report rendering and conditional queries. Users will benefit from new keyboard shortcuts for navigating and selecting rows, improved handling of timestamp mismatches across both Python and Vue.js components, and enhancements to the approval workflow and validation processes. Additional updates include fixes to file assignment, improvements to Bank Account setup user experience, and updated approval workflow documentation.\u003C\u002Fp>\n\n\u003Ch2 id=\"fleet\">Fleet\u003C\u002Fh2>\n\n\u003Cp>Version 15.1.0 of Fleet introduces a series of powerful integrations and visual improvements that significantly expand the application's capabilities. Traccar GPS integration has been added, allowing vehicles to be created and managed using IMEI codes, with devices automatically created in Traccar if they do not already exist and Vehicle data pushed to Traccar upon creation. Building on this foundation, Asset and Vehicle records are now linked so that when a tracked vehicle triggers a Traccar diagnostic alert, a draft Asset Repair document is automatically created for review.\u003C\u002Fp>\n\n\u003Cp>Geofence support has also been introduced, enabling polygons, rectangles, and polylines to be drawn on a map within ERPNext Location records. These geofences can be synced with Traccar and linked to multiple vehicles to enable entry and exit alerting. On the visual side, custom HTML block tab styling in the Fleet workspace has been updated to align with the design of standard form tabs, and a new Fleet icon has been added for a more polished appearance.\u003C\u002Fp>\n",{"id":509,"title":510,"content":511,"level":16},"\u002Fideas\u002Fagritheory-newsletter-april-2025","AgriTheory Newsletter: April 2025","\u003Ch2 id=\"check-run\">Check Run\u003C\u002Fh2>\n\n\u003Cp>Recent updates to Check Run bring a mix of new features, bug fixes, and improved data validation. A notable addition is the ability to make the Posting Date field read-only when the \u003Cstrong>Set Payment Entry Posting Date\u003C\u002Fstrong> setting is configured to use today's date, preventing accidental modifications to payment scheduling. Mandatory fields for Company, Bank Account, and Payable Account have also been introduced in \u003Cstrong>Check Run Settings\u003C\u002Fstrong>, ensuring all required information is captured before proceeding with check runs.\u003C\u002Fp>\n\n\u003Cp>On the bug fix side, an issue where the settings date configuration was not being respected has been resolved, giving users more accurate control over date preferences. Additional fixes address a problem where non-check Payment Entries were incorrectly appearing in print views — now only check payments are displayed. Users can also validate Bank Accounts and account numbers prior to generating NACHA files, with descriptive error messages to help diagnose any issues encountered during validation. Test coverage for posting date configuration in Settings has also been expanded to support these improvements.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch2 id=\"electronic-payments\">Electronic Payments\u003C\u002Fh2>\n\n\u003Cp>The latest update to Electronic Payments focuses on improving payment gateway support and modernizing the development toolchain. A key fix adds proper support for the Authorize.net production endpoint, with the \u003Ccode>endpoint\u003C\u002Fcode> field in \u003Cstrong>Settings\u003C\u002Fstrong> now marked as required and automatically pre-populated with the sandbox endpoint in test environments. This ensures a smoother and more reliable transition between testing and production configurations.\u003C\u002Fp>\n\n\u003Cp>On the infrastructure side, the project has been updated to Poetry 2.0, with refreshed pre-commit hooks, added coverage reporting, backport configuration, and override-tracking workflows. These changes improve the overall reliability of the development and release process without affecting end-user functionality directly.\u003C\u002Fp>\n",{"id":513,"title":514,"content":515,"level":16},"\u002Fideas\u002Fagritheory-newsletter-march-2025","AgriTheory Newsletter: March 2025","\u003Ch1 id=\"march-2025-development-newsletter\">March 2025 Development Newsletter\u003C\u002Fh1>\n\n\u003Chr \u002F>\n\n\u003Ch2 id=\"autoreader\">Autoreader\u003C\u002Fh2>\n\n\u003Cp>Autoreader gained a Twilio SMS integration for outbound text message notifications. Follow-up work addressed phone number formatting, improved message body content, and resolved a bug with attachment handling.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch2 id=\"beam\">BEAM\u003C\u002Fh2>\n\n\u003Cp>BEAM Mobile development received significant updates across scanning, reconciliation, and list view functionality. Dependencies were updated and a configurable scan output component was introduced, providing users with greater control over what is displayed during scanning workflows. The debug UI received context improvements, and documentation restructuring began toward the end of March.\u003C\u002Fp>\n\n\u003Cp>Stock Reconciliation was a primary focus: incremental item counting was added, warehouse assignment logic was improved and stabilized, empty Item Code filtering was corrected, and a dedicated Reconciliation page was built out — including proper handling for Stock Reconciliation Item warehouse scans and general style and code quality improvements.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch2 id=\"check-run\">Check Run\u003C\u002Fh2>\n\n\u003Cp>Check Run received a fix ensuring that Payment Entries where the Mode of Payment is not \"Check\" are excluded from print and render operations, preventing unintended output. Supporting maintenance work included a pre-commit configuration update and a \u003Ccode>pyproject.toml\u003C\u002Fcode> correction.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch2 id=\"fleet\">Fleet\u003C\u002Fh2>\n\n\u003Cp>Fleet saw extensive feature development centered on Traccar integration. Initial work removed the welcome email for Traccar users and updated Docker documentation with environment variable guidance. New API calls were added alongside expanded test coverage for vehicles, customers, logs, and locations — including a simulation loop for location routes.\u003C\u002Fp>\n\n\u003Cp>Subsequent development introduced an Asset–Vehicle integration, a custom cron job (running every two minutes) for vehicle sync, a Vehicle override, and a Fleet Manager role scoped to the Traccar user for proper permissions. Additional improvements included switching from socket-based to POST-based communication, adding driver support, introducing new unit of measure fields, updating vehicle sync and Vehicle Log logic, and fixing battery voltage data display and map visibility. The Traccar simulator and Asset integration branches were merged into the main version-15 branch at the close of March.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch2 id=\"inventory-tools\">Inventory Tools\u003C\u002Fh2>\n\n\u003Cp>Inventory Tools had one of its most active development periods, with substantial progress across warehouse mapping, pathfinding, and demand planning.\u003C\u002Fp>\n\n\u003Cp>In Warehouse Plan warehouses can now be drawn and saved directly in each Warehouse record. Pathfinding support was added, including accessible cell detection, walkable path fixtures, and the ability to select the nearest accessible cell. The UI received several improvements: cell position and walkable status are shown on hover, right-click default browser behavior is suppressed on warehouse shapes, a warehouse search was added to the floor plan, a preview dialog was introduced, and context menu styling was aligned with popups. A debounce was applied to the warehouse hover popup for smoother interaction, and the overlay was moved into a fixed footer element. Read-only mode is now enforced for users without edit permissions. LIFO\u002FFIFO bin depletion rules were introduced in an initial version, with max\u002Fmin bin depletion logic also added. Bug fixes addressed posting time, settings, and fixture data.\u003C\u002Fp>\n\n\u003Cp>The Material Demand report can now optionally be driven from Sales Orders, Material Requests, or both.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch2 id=\"saml\">SAML\u003C\u002Fh2>\n\n\u003Cp>We have a released a new application to integrate SAML-based authentication integration for Frappe. Keycloak test and demo fixtures were added to support local testing, and role mapping was implemented — allowing SAML roles to be mapped to Frappe user roles and Role Profiles. Test infrastructure was expanded with a setup function, bench port detection for realm export file generation, and CI configuration to provision test data via bench services. A Role Profile fixture and early work on a logout hook rounded out the effort.\u003C\u002Fp>\n",{"id":517,"title":518,"content":519,"level":16},"\u002Fideas\u002Fagritheory-newsletter-february-2025","AgriTheory Newsletter: February 2025","\u003Ch2 id=\"beam\">BEAM\u003C\u002Fh2>\n\n\u003Cp>Version 15.4.0 brings ZPL utility support to BEAM, backporting a set of powerful label-printing tools into the v15 line. This includes \u003Ccode>labelary\u003C\u002Fcode> print preview functionality for rendering labels as images, as well as \u003Ccode>py-zebra-zpl\u003C\u002Fcode> wrappers exposed as Jinja methods, supporting both text-based and object-oriented interfaces for generating ZPL content.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch2 id=\"inventory-tools\">Inventory Tools\u003C\u002Fh2>\n\n\u003Cp>Version 15.4.0 introduces an important architectural improvement by replacing the global \u003Ccode>get_item_details\u003C\u002Fcode> monkey patch with a targeted Purchase Order method override. This change resolves an issue where creating a Subcontracting Purchase Order from a Work Order would incorrectly fail to validate non-stock items.\u003C\u002Fp>\n\n\u003Cp>Version 15.3.1 delivers a bug fix that adds previously missing physical dimension fields to both the Physical Dimension Doctype JSON definition and its corresponding Python model. Building on this, version 15.3.0 introduced the Physical Dimension Doctype itself, providing a dedicated structure for tracking item physical dimensions. The Doctype was renamed from its original Item Dimension name and updated to enforce non-negative dimension values, ensuring data integrity across inventory records.\u003C\u002Fp>\n",{"id":521,"title":522,"content":523,"level":16},"\u002Fideas\u002Fagritheory-newsletter-january-2025","AgriTheory Newsletter: January 2025","\u003Ch2 id=\"check-run\">Check Run\u003C\u002Fh2>\n\n\u003Cp>Version 15.2.0 brings several notable improvements to Check Run. A new MICR Encoding Print Format has been added, complete with documentation, making it easier to produce properly formatted physical checks. Users can now configure the posting date for Payment Entries directly through Check Run settings, allowing for backdating or forward-dating of payments to ensure accurate financial records. Additionally, documentation has been translated into Spanish, broadening accessibility for users who prefer that language.\u003C\u002Fp>\n\n\u003Cp>Behind the scenes, this release also includes several housekeeping updates. Pre-commit configuration has been refreshed, old customization validations have been removed, and tracking overrides have been improved. Backporting workflows for versions 14 and 15 have been streamlined through updated configuration files and GitHub Actions automation, and translation documentation has been enhanced by skipping code blocks across multiple files.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch2 id=\"electronic-payments\">Electronic Payments\u003C\u002Fh2>\n\n\u003Cp>Version 15.0.1 addresses a bug that caused customizations to fail on load, improving stability for users relying on custom configurations. Installation instructions have also been updated to reflect version 15 requirements, and a yarn lock file has been added to improve dependency management.\u003C\u002Fp>\n\n\u003Cp>On the continuous integration side, release versioning has been brought into alignment and the site configuration has been updated. Test reliability has also been improved, with fixes applied to rounding sequence handling and float comparison issues that affected version 14 compatibility.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch2 id=\"inventory-tools\">Inventory Tools\u003C\u002Fh2>\n\n\u003Cp>Version 15.2.1 delivers a targeted bug fix, resolving an undefined global variable in the Purchase Invoice customization JavaScript that could cause unexpected behavior for users working with purchase workflows.\u003C\u002Fp>\n\n\u003Cp>Version 15.2.0 introduced a new styled warehouse tree view, giving users improved visual clarity when navigating warehouse structures. The enhanced layout includes custom options for warehouse type and workstation configuration, making it easier to manage complex inventory setups at a glance.\u003C\u002Fp>\n",{"id":525,"title":526,"content":527,"level":16},"\u002Fideas\u002Fagritheory-newsletter-december-2024","AgriTheory Newsletter: December 2024","\u003Ch2 id=\"test-utils\">Test Utils\u003C\u002Fh2>\n\n\u003Cp>The latest release of Test Utils (v0.17.0) introduces a new database partition helper, providing developers with a powerful utility for managing data partitioning strategies. The helper supports partitioning by month, quarter, field value, and Child Doctypes, making it a flexible solution for a variety of use cases. Additional backup and restore utilities are included, along with optional compression support, giving teams greater control over their data management workflows.\u003C\u002Fp>\n\n\u003Cp>In a previous patch release (v0.16.1), a bug affecting HRMS customization handling was resolved. This fix addressed issues with HRMS Customize, ensuring that customization configurations are applied correctly and reliably across environments.\u003C\u002Fp>\n",{"id":529,"title":530,"content":531,"level":16},"\u002Fideas\u002Fagritheory-newsletter-november-2024","AgriTheory Newsletter: November 2024","\u003Ch2 id=\"fleet\">Fleet\u003C\u002Fh2>\n\n\u003Cp>Fleet has reached a major milestone with the release of version 15.0.0, launched on November 27, 2024. As the first major version release, it brings the core features of real-time vehicle tracking into ERPNext. Instead of switching between a GPS tracking system and ERPNext, fleet managers can monitor vehicles and track deliveries from a single interface.\u003C\u002Fp>\n\n\u003Cp>Given the significance of a major version bump, users are encouraged to review the official Fleet documentation and release notes for a comprehensive list of changes, migration guides, and any deprecations that may impact existing workflows and configurations.\u003C\u002Fp>\n",{"id":533,"title":534,"content":535,"level":16},"\u002Fideas\u002Fagritheory-newsletter-october-2024","AgriTheory Newsletter: October 2024","\u003Ch1 id=\"approvals\">Approvals\u003C\u002Fh1>\n\n\u003Cp>Version 15.2.0 brings a meaningful improvement to the approval workflow: rejected requests now require a rejection reason, which is recorded and displayed in the document's approval history. This ensures greater accountability and transparency throughout the approval process. The project has also been migrated to Poetry for dependency management, with updates to pre-commit hooks and backport configurations.\u003C\u002Fp>\n\n\u003Cp>On the version 14 branch, version 14.2.3 introduces several notable enhancements. A new validation layer has been added to the condition field in Document Approval Rule, helping prevent errors before they occur. Rejection notifications have been improved with a dedicated rejection user and fallback support, and a backported reminder email feature now sends scheduled reminders for pending approvals using a configurable hour interval. Additionally, a fix ensures that Document Status is properly checked for submittable documents, and the client script requirement has been removed to simplify setup.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch1 id=\"beam\">BEAM\u003C\u002Fh1>\n\n\u003Cp>BEAM version 15.3.1 delivers a targeted fix to the devcontainer initialization script, ensuring that branch selection specified in the devcontainer configuration is correctly respected during setup. This resolves an inconsistency that could affect development environment initialization.\u003C\u002Fp>\n\n\u003Cp>Recent prior releases (v15.3.0 and v15.2.0) added the ability to define per-item handling unit configurations directly within BEAM Settings, applied automatically during document processing. A full devcontainer setup using Docker Compose was also introduced, complete with initialization scripts and updated README documentation, alongside a migration of \u003Ccode>pyproject.toml\u003C\u002Fcode> to Poetry.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch1 id=\"inventory-tools\">Inventory Tools\u003C\u002Fh1>\n\n\u003Cp>Version 15.1.2 of Inventory Tools addresses a bug in the faceted search functionality. Filters were not being correctly processed when passed as route query parameters, which could result in unexpected or missing search results. This fix ensures that filter values derived from URL query parameters are now handled accurately, improving the reliability of search and navigation throughout the application.\u003C\u002Fp>\n",{"id":537,"title":538,"content":539,"level":16},"\u002Fideas\u002Fagritheory-newsletter-september-2024","AgriTheory Newsletter: September 2024","\u003Ch2 id=\"test-utils\">Test Utils\u003C\u002Fh2>\n\n\u003Cp>Version 0.16.0 of Test Utils introduces a new warehouse management capability to the testing toolkit. A \u003Ccode>create_warehouses\u003C\u002Fcode> fixture builder function has been added, making it easier to set up Warehouse test environments programmatically.\u003C\u002Fp>\n\n\u003Cp>This update streamlines the process of creating test data related to Warehouses, allowing developers to more efficiently scaffold the necessary infrastructure when writing and running tests. The new fixture builder follows the established patterns within the library, ensuring a consistent and familiar experience for existing users.\u003C\u002Fp>\n",{"id":541,"title":542,"content":543,"level":16},"\u002Fideas\u002Fagritheory-newsletter-august-2024","AgriTheory Newsletter: August 2024","\u003Ch1 id=\"autoreader\">Autoreader\u003C\u002Fh1>\n\n\u003Cp>AutoReader Settings has been updated to include a new option that allows users to exclude Auto Repeat documents from deduplication match results. When this option is enabled, documents generated by the Auto Repeat system are omitted from the candidate list during AutoReader matching, giving users more precise control over how deduplication is handled.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch2 id=\"beam\">BEAM\u003C\u002Fh2>\n\n\u003Cp>Two updates have been made in this release of BEAM. A bug fix corrects an issue where \u003Ccode>basic_rate\u003C\u002Fcode> was being assigned as a string rather than evaluated as a number in the \u003Ccode>add_or_associate\u003C\u002Fcode> function, ensuring accurate rate calculations. Additionally, the documentation has been expanded to include a network printer settings configuration example, making it easier for users to set up network printing.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch2 id=\"cloud-storage\">Cloud Storage\u003C\u002Fh2>\n\n\u003Cp>Cloud Storage received several improvements across recent releases. A custom \u003Ccode>validate\u003C\u002Fcode> method was added to the File Doctype override to properly handle direct file uploads that are not attached to a document, applying custom validation rules in those cases. The \u003Ccode>file_content\u003C\u002Fcode> method was also updated with the \u003Ccode>@frappe.whitelist\u003C\u002Fcode> decorator, allowing it to be called from the client side without triggering a permission error.\u003C\u002Fp>\n\n\u003Cp>On the infrastructure side, the backport configuration was updated, a codespell pre-commit hook was added, and the pre-commit configuration for Test Utils was refreshed to improve code quality and maintainability.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch2 id=\"inventory-tools\">Inventory Tools\u003C\u002Fh2>\n\n\u003Cp>Inventory Tools received a significant set of updates in this release. The most notable addition is a new faceted search feature that enables attribute-based filtering for items, complete with color picker, date range, and numeric range filter components. A company field was also added to Workstation customizations, and alternative workstations were made configurable with support for name-based searching.\u003C\u002Fp>\n\n\u003Cp>On the maintenance side, backport configuration was added alongside a codespell pre-commit hook, CI override tracking was introduced for purchase, stock, and manufacturing cycles, and various pre-commit fixes and cleanups were applied to improve overall code quality.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch2 id=\"test-utils\">Test Utils\u003C\u002Fh2>\n\n\u003Cp>Test Utils has been updated with the addition of a quarantine Warehouse fixture. This new fixture expands the available testing resources, making it easier to set up and manage warehouse-related test scenarios within the Test Utils framework.\u003C\u002Fp>\n",{"id":545,"title":546,"content":547,"level":16},"\u002Fideas\u002Fagritheory-newsletter-july-2024","AgriTheory Newsletter: July 2024","\u003Ch1 id=\"agritheory-applications-newsletter\">AgriTheory Applications Newsletter\u003C\u002Fh1>\n\n\u003Ch2 id=\"autoreader\">Autoreader\u003C\u002Fh2>\n\n\u003Cp>Version 15.2.0 introduces fuzzy matching capabilities to the Autoreader mapping layer, powered by RapidFuzz. This enhancement allows documents to be matched even when field values contain minor spelling or formatting differences, making the matching process more robust and flexible. The scorer and related configuration options are now customizable on a per-doctype and per-field basis, giving users greater control over matching behavior.\u003C\u002Fp>\n\n\u003Cp>As part of this release, the Deduplication Settings document has been renamed to AutoReader Settings, better reflecting its expanded scope. A bug fix was also included to address an incorrect Docstatus filter that was affecting non-submittable Doctypes.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch2 id=\"check-run\">Check Run\u003C\u002Fh2>\n\n\u003Cp>Version 15.1.2 delivers several important fixes and enhancements to Check Run. Serialization issues for null transactions have been resolved, and Payment Entry handling has been updated throughout the codebase. Additionally, a fix was applied to correctly calculate Payment Schedule outstanding amounts, along with the introduction of an \u003Ccode>on_cancel\u003C\u002Fcode> hook with supporting tests.\u003C\u002Fp>\n\n\u003Cp>This release also adds the ability to allow or disallow standalone Debit Notes within a Check Run, providing more flexibility in how payment runs are configured and processed.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch2 id=\"inventory-tools\">Inventory Tools\u003C\u002Fh2>\n\n\u003Cp>Version 15.1.0 brings several infrastructure and feature improvements to Inventory Tools. The \u003Ccode>release.yaml\u003C\u002Fcode> configuration has been updated to support both version 14 and version 15 branches, and Inventory Tools Settings have been added to the boot process for version 15. The project has also been migrated from a standard \u003Ccode>pyproject.toml\u003C\u002Fcode> setup to Poetry for improved dependency management.\u003C\u002Fp>\n\n\u003Cp>On the version 14 side, release 14.6.1 introduces a fix to make weight required when a weight UOM is present and vice versa. CI override tracking has been expanded to cover stock, manufacturing, and purchase cycles (Purchase Order, Purchase Invoice, and Purchase Receipt), and the alternative workstation feature has been backported to version 14 with configurable workstation names and search support.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch2 id=\"test-utils\">Test Utils\u003C\u002Fh2>\n\n\u003Cp>Test Utils saw a series of incremental releases with meaningful improvements across versions 0.12.0 through 0.14.1. New fixture builders were added for Bank, Bank Account, Mode of Payment, and Holiday List (with country-based filtering), along with alternative Chart of Accounts fixtures supporting Farm and IFRS variants. An \u003Ccode>update_pre_commit_config\u003C\u002Fcode> utility was introduced to automatically keep pre-commit hook versions up to date in project configuration files.\u003C\u002Fp>\n\n\u003Cp>Additional pre-commit hook improvements were shipped across multiple releases, including a new mypy hook with default arguments, improved exit codes and error messages in customization hooks, and the removal of \u003Ccode>set-module\u003C\u002Fcode> from customization validation logic. These updates collectively improve the developer experience and code quality tooling across AgriTheory projects.\u003C\u002Fp>\n",{"id":549,"title":550,"content":551,"level":16},"\u002Fideas\u002Fagritheory-newsletter-june-2024","AgriTheory Newsletter: June 2024","\u003Ch1 id=\"agritheory-application-updates-newsletter\">AgriTheory Application Updates Newsletter\u003C\u002Fh1>\n\n\u003Chr \u002F>\n\n\u003Ch2 id=\"approvals\">Approvals\u003C\u002Fh2>\n\n\u003Cp>Version 15.0.1 brings a pair of targeted improvements to the Approvals application. A bug fix ensures that Server Scripts are properly enabled before invoices are created during test setup, resolving CI pipeline failures that were caused by scripts running in an inactive state. This change improves the reliability of automated testing across the board.\u003C\u002Fp>\n\n\u003Cp>On the infrastructure side, the test configuration has been updated to use JSON instead of YAML for test fixtures, simplifying how configuration is handled in the test suite and aligning Approvals with the broader tooling standards used across AgriTheory applications.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch2 id=\"autoreader\">Autoreader\u003C\u002Fh2>\n\n\u003Cp>Version 15.1.0 introduces two meaningful additions to the Autoreader application. A new custom background job queue has been added, allowing Autoreader processing to run in a dedicated queue separate from the default Frappe job queue. This improves throughput and prevents email processing tasks from competing with other background jobs.\u003C\u002Fp>\n\n\u003Cp>Comprehensive demo and test data has also been added, including HTML and PDF Invoice fixtures for Blanket Orders and Purchase Orders, per-supplier contact configuration, and an assignment rule to support automated routing of incoming email processing. These additions make it significantly easier to set up and validate Autoreader in development and staging environments.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch2 id=\"beam\">BEAM\u003C\u002Fh2>\n\n\u003Cp>BEAM has seen a busy release cycle, with updates shipping across both version 14 and version 15. On the version 15 side, highlights include updated printing dependencies with corrected serialization for printing settings, a configurable barcode font size setting in BEAM Settings, and the successful port of Handling Unit tests from version 14 — covering null value handling in the Handling Unit list, Stock Entry cancellation dialog improvements, subcontracting process tracking, and mandatory Handling Unit validation. CI improvements include a refactored environment variable setup and an updated conftest now using JSON format. A typo fix in the hooked List View was also shipped in the most recent patch release (v15.1.2).\u003C\u002Fp>\n\n\u003Cp>On the version 14 side, version 14.8.6 delivered a replacement of raw \u003Ccode>frappe.db.sql\u003C\u002Fcode> calls with the safer \u003Ccode>frappe.get_all\u003C\u002Fcode> API, alongside fixes for net quantity and Handling Unit tests. Mandatory Handling Unit validation was also improved, providing clearer and more reliable enforcement of Handling Unit requirements during document submission workflows.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch2 id=\"test-utils\">Test Utils\u003C\u002Fh2>\n\n\u003Cp>Test Utils has had an active release period, shipping eight versions in quick succession focused on expanding the fixture builder library and improving developer tooling. New fixture builders have been added for Employees (with company assignment from settings), Companies (reading from a \u003Ccode>company.json\u003C\u002Fcode> configuration file), Bills of Materials, Customers and Customer Groups, and Suppliers and Supplier Groups (with address creation support). These additions make it easier to build consistent, repeatable test environments across AgriTheory applications.\u003C\u002Fp>\n\n\u003Cp>On the tooling side, several pre-commit hook improvements were shipped: \u003Ccode>validate_customizations\u003C\u002Fcode>, \u003Ccode>clean_customized_doctypes\u003C\u002Fcode>, and \u003Ccode>validate_javascript_dependencies\u003C\u002Fcode> have all been updated to function as pre-commit hooks with configurable rules. Additional improvements include a progress bar for \u003Ccode>load_customizations\u003C\u002Fcode>, the addition of flynt (an f-string formatter) to pre-commit configuration, and commit message spell checking configured to ignore false positives. CI workflows for building, pre-commit, and release were also updated during this cycle.\u003C\u002Fp>\n",{"id":553,"title":554,"content":555,"level":16},"\u002Fideas\u002Fagritheory-newsletter-may-2024","AgriTheory Newsletter: May 2024","\u003Ch2 id=\"autoreader\">Autoreader\u003C\u002Fh2>\n\n\u003Cp>Autoreader's initial v15.0.0 release introduced a robust deduplication system featuring configurable RapidFuzz matching parameters, field weights, and scoring options on a per-company and per-Doctype basis. This system also supports optional processing functions for specific field types, depending on whether the field is a number, currency, or text. Matching rules can be configured to match text (numeric fields are treated a strings), to be within a given percent for numbers or time delta for dates, or to convert currency, numbers, or dates into words then match. Users can also run a new background report to scan for duplicates for a configured doctype. Test data setup was also improved with named Payment Terms Templates, and an HRMS dependency compatibility issue was resolved.\u003C\u002Fp>\n\n\u003Cp>Autoreader v15.0.1 brings important CI and bug fixes to the version-15 branch. The CI workflow has been updated to properly handle dictionary objects in the \u003Ccode>validate_customizations\u003C\u002Fcode> script and to enable automated tag and release creation for main branches. Additionally, a deduplication scoring option that returned an incompatible result compared to other scoring options has been removed, resolving errors that occurred when that scorer was selected.\u003C\u002Fp>\n\n\u003Ch2 id=\"check-run\">Check Run\u003C\u002Fh2>\n\n\u003Cp>Check Run v15.1.1 delivers several notable improvements across testing, security, and core functionality. File download access for bulk ACH downloads has been restricted to specific roles, enhancing security around sensitive financial files. A typing issue with the Bank Account field has been corrected, Cypress tests have been replaced with a more maintainable test suite, and CI configuration has been updated to improve reliability.\u003C\u002Fp>\n\n\u003Cp>Beyond the versioned release, several Pull Requests have introduced meaningful new features. A workflow to track overrides for Payment Entry has been added, along with a new \"Allow stand-alone debit notes?\" field that controls whether users can create Debit Notes independently — hiding the \u003Ccode>is_return\u003C\u002Fcode> checkbox on Purchase Invoices when disabled. Documentation and tests for returns against Purchase Invoices in a Check Run have also been added, and a previously missing supplier bank field has been restored.\u003C\u002Fp>\n\n\u003Ch2 id=\"cloud-storage\">Cloud Storage\u003C\u002Fh2>\n\n\u003Cp>Cloud Storage v15.1.0 focuses on improved developer experience and code clarity. The File override class has been renamed for greater descriptiveness, and the project's dependency management has been migrated from \u003Ccode>pyproject.toml\u003C\u002Fcode> to Poetry, complete with a \u003Ccode>poetry.lock\u003C\u002Fcode> file for reproducible builds. CI tooling has also been enhanced with coverage reporting and updated linting configuration.\u003C\u002Fp>\n\n\u003Cp>The preceding v14.4.1 release addressed a URL encoding bug in the \u003Ccode>get_content\u003C\u002Fcode> function, ensuring that file URLs containing special characters are handled correctly. Additionally, the version-15 test suite was established during this period, incorporating fixes for the delete file test, the addition of Frappe Black to CI, and Redis configuration for the test environment.\u003C\u002Fp>\n\n\u003Ch2 id=\"electronic-payments\">Electronic Payments\u003C\u002Fh2>\n\n\u003Cp>Electronic Payments v15.0.0 marks the application's initial release on the version-15 branch. This release includes comprehensive updates to bring the application in line with version-15 requirements, including updates to order pages, installation routines, and handling for maximum field length limitations. A new test suite has also been introduced, covering both payment sending workflows and common processing functions.\u003C\u002Fp>\n\n\u003Cp>On the version-14 side, v14.3.1 fixed an issue to show the user the amount to pay, which wasn't being set if no default payment method were present. The v14.3.0 release added Self Service Payment Methods where a customer or supplier can manage payment methods via the portal. The release included support for \"billed per agreement\" in Shopping Cart checkout, where the payments due on an invoice display based on the invoice's payment terms, including discounts and multiple terms. Finally, the release added the ability to send Electronic Payments to suppliers via Authorize.\u003C\u002Fp>\n\n\u003Ch2 id=\"test-utils\">Test Utils\u003C\u002Fh2>\n\n\u003Cp>Test Utils v0.3.0 introduces two useful enhancements for development workflows. The \u003Ccode>validate_copyright\u003C\u002Fcode> utility has been upgraded to function as a pre-commit hook, making copyright validation easier to enforce automatically. Item and Item Group fixture builders have also been added, expanding the available test data tooling.\u003C\u002Fp>\n\n\u003Cp>Earlier releases in the v0.2.x series addressed several foundational issues. Customization sync was corrected to include HRMS customizations only when HRMS is actually installed, and the codebase was restructured to separate pre-commit, CLI, and one-time utility functions into a shared \u003Ccode>customize.py\u003C\u002Fcode> module. A CI workflow for building and publishing the project wheel was also introduced alongside a fix for the package name.\u003C\u002Fp>\n",{"id":557,"title":558,"content":559,"level":16},"\u002Fideas\u002Fagritheory-newsletter-april-2024","AgriTheory Newsletter: April 2024","\u003Ch2 id=\"test-utils\">Test Utils\u003C\u002Fh2>\n\n\u003Cp>Version 0.2.0 of Test Utils brings a series of enhancements focused on improving developer tooling, code quality enforcement, and project automation. A GitHub Actions release workflow has been added to streamline the release process, and documentation has been updated to use Poetry in place of flit_core for dependency management. A \u003Ccode>conftest.py\u003C\u002Fcode> boilerplate generator has also been introduced to help developers get up and running with testing configurations more quickly.\u003C\u002Fp>\n\n\u003Cp>This release places a strong emphasis on pre-commit hooks, with several new additions to help maintain code standards across projects. New hooks include \u003Ccode>clean_customized_doctypes\u003C\u002Fcode> for managing Customized Doctypes, \u003Ccode>validate_copyright\u003C\u002Fcode> with directory exclusion support, and \u003Ccode>validate_customizations\u003C\u002Fcode> for enforcing customization integrity. Additionally, pre-commit hooks for validating JavaScript and Python dependency versions have been introduced, making it easier to keep dependencies consistent and up to date.\u003C\u002Fp>\n",{"id":561,"title":562,"content":563,"level":16},"\u002Fideas\u002Fagritheory-newsletter-march-2024","AgriTheory Newsletter: March 2024","\u003Ch2 id=\"beam\">BEAM\u003C\u002Fh2>\n\n\u003Cp>Version 15.1.0 of BEAM introduces the new BEAM Settings DocType, providing users with a dedicated configuration document for managing application settings. This addition enhances the overall configurability of the application for version 15.\u003C\u002Fp>\n\n\u003Cp>This release also includes an important fix for the Recombination Dialog, resolving an issue where the dialog would not appear when no Handling Units were present, ensuring a smoother and more reliable user experience.\u003C\u002Fp>\n\n\u003Chr \u002F>\n\n\u003Ch2 id=\"check-run\">Check Run\u003C\u002Fh2>\n\n\u003Cp>Version 15.1.0 of Check Run brings several improvements to both the end-user experience and the development pipeline. Progress bars have been introduced for the \"Process Check Run\" and \"Rendering Checks\" operations, giving users clear visual feedback during these processes and significantly improving the overall user experience.\u003C\u002Fp>\n\n\u003Cp>Frappe Black has been added to the CI pipeline, along with updated linting and formatting scripts, helping to maintain consistent code quality across the project.\u003C\u002Fp>\n",{"id":565,"title":566,"content":567,"level":16},"\u002Fideas\u002Fagritheory-newsletter-february-2024","AgriTheory Newsletter: February 2024","\u003Ch2 id=\"enet\">eNET\u003C\u002Fh2>\n\n\u003Cp>Recent updates to eNET have focused on improving reliability and accuracy in data processing and event handling. A scheduler issue was resolved to ensure all data is properly checked before threshold calculations are performed, along with an additional safeguard to verify all required information is present before attempting variance calculations. These fixes help ensure more consistent and accurate results during automated processing.\u003C\u002Fp>\n\n\u003Cp>Earlier updates addressed a duplicate check issue with the eNET Machine Event, preventing redundant records from being created. Additionally, an operation time variance check was introduced, enhancing the system's ability to monitor and flag deviations in operational timing. A timestamp conversion fix was also applied across the application to ensure all time-related data is handled in a uniform and consistent manner.\u003C\u002Fp>\n",{"id":569,"title":570,"content":571,"level":16},"\u002Fideas\u002Fagritheory-newsletter-january-2024","AgriTheory Newsletter: January 2024","\u003Ch2 id=\"enet\">eNET\u003C\u002Fh2>\n\n\u003Cp>The latest releases of eNET bring a series of meaningful improvements to manufacturing operations and machine event tracking. Version 14.1.0 introduced several notable features, including a threshold variance check for operation time, a scheduler-based collection of eNET machine events, and timezone-aware timestamp conversion. These updates lay a stronger foundation for accurate, automated tracking of shop floor activity.\u003C\u002Fp>\n\n\u003Cp>Subsequent releases in versions 14.1.1 and 14.1.2 focused on refinements and fixes. Variance configuration was updated to use a percentage-based format at the Workstation level and in Settings, while automatic Stock Entry creation for Material Transfer for Manufacture was disabled to provide users with greater control over the manufacturing workflow. Additionally, operation time calculations were adjusted to properly account for Bill Of Materials quantity. The most recent release also removed Tag Link code and expanded documentation to include configuration and Settings guidance, ensuring users have clearer reference material as they work with the application.\u003C\u002Fp>\n",{"id":573,"title":574,"content":575,"level":16},"\u002Fideas\u002Fagritheory-newsletter-may-2023","AgriTheory Newsletter: May 2023","\u003Ch2 id=\"enet\">eNET\u003C\u002Fh2>\n\n\u003Cp>Version 14.0.0 marks the initial release of the eNET application, which integrates with ERPNext's manufacturing module to capture data from eNET. This release establishes the foundational setup of the app, including the initialization of the application itself and the addition of a \u003Ccode>customize.py\u003C\u002Fcode> module, which enables customization capabilities within the platform.\u003C\u002Fp>\n\n\u003Cp>This release also includes the configuration of continuous integration (CI) pipelines to support ongoing development workflows, as well as updates to the readme documentation and hooks setup to ensure the app is properly structured and ready for future development.\u003C\u002Fp>\n",{"id":577,"title":578,"content":579,"level":16},"\u002Fideas\u002Fagritheory-newsletter-april-2023","AgriTheory Newsletter: April 2023","\u003Ch2 id=\"stonecrop\">Stonecrop\u003C\u002Fh2>\n\n\u003Cp>We are excited to announce the initial publication of the Stonecrop packages! This release marks a significant milestone as both the \u003Cstrong>Desktop\u003C\u002Fstrong> and \u003Cstrong>Stonecrop\u003C\u002Fstrong> core packages have been officially published and are now available for use.\u003C\u002Fp>\n\n\u003Cp>This launch establishes the foundational distribution of the Stonecrop ecosystem, making it easier for developers and users to access and integrate these packages into their workflows. Stay tuned for future updates as the project continues to grow and evolve.\u003C\u002Fp>\n",{"id":4,"title":6,"content":10,"level":16},1793826652500]