From 9551f213aedf055ec779ee1ad37eb7fdf6753b8f Mon Sep 17 00:00:00 2001 From: shariquerik Date: Wed, 2 Sep 2026 19:20:00 +0530 Subject: [PATCH 1/2] feat(desk-v2): ship ERPNext's module-primary rail and its module sidebars The module-primary half of frappe/frappe#42226's charter point 2, opposite CRM's doctype-primary rail: the same table, the same resolver and the same item kinds, with modules as the rail's primary items. One `Rail` record of 20 items -- 18 `Sidebar` items over a module sidebar each, and two `Module` items for the modules whose sidebar would hold one row or none. The sidebars are authored, not derived: the module *page* keeps deriving from module contents and the two lists differ on purpose, which is what desk v1's own curation already says -- 107 doctypes sit on a module page and not in that module's sidebar, and 101 sidebar links point outside their module. The rows are converted from desk v1's module sidebars, which stay untouched and keep serving v1. 486 v1 rows become 317: `Report`, `Dashboard`, `Workspace` and `Page` items have no desk v2 destination and are not authored, headings left over nothing are dropped, and two duplicate rows in Accounts go. `Portal` is on v1's dock and is not authored at all -- it holds no doctypes, so it has neither a sidebar to open nor a module page to land on. ERPNext ships no navigation code: the rows arrive through `sync_for`'s app-rooted walk at migrate. Co-Authored-By: Claude Opus 5 (1M context) --- erpnext/hooks.py | 10 + erpnext/rail/erpnext/erpnext.json | 276 +++++ .../module_def_accounts.json | 940 ++++++++++++++++++ .../module_def_assets/module_def_assets.json | 206 ++++ .../module_def_bulk_transaction.json | 43 + .../module_def_buying/module_def_buying.json | 320 ++++++ .../module_def_crm/module_def_crm.json | 370 +++++++ .../module_def_edi/module_def_edi.json | 43 + .../module_def_maintenance.json | 43 + .../module_def_manufacturing.json | 295 ++++++ .../module_def_projects.json | 155 +++ .../module_def_quality_management.json | 153 +++ .../module_def_regional.json | 55 + .../module_def_selling.json | 502 ++++++++++ .../module_def_setup/module_def_setup.json | 392 ++++++++ .../module_def_stock/module_def_stock.json | 461 +++++++++ .../module_def_subcontracting.json | 67 ++ .../module_def_support.json | 141 +++ .../module_def_telephony.json | 67 ++ .../module_def_utilities.json | 55 + erpnext/tests/test_navigation.py | 252 +++++ 21 files changed, 4846 insertions(+) create mode 100644 erpnext/rail/erpnext/erpnext.json create mode 100644 erpnext/sidebar/module_def_accounts/module_def_accounts.json create mode 100644 erpnext/sidebar/module_def_assets/module_def_assets.json create mode 100644 erpnext/sidebar/module_def_bulk_transaction/module_def_bulk_transaction.json create mode 100644 erpnext/sidebar/module_def_buying/module_def_buying.json create mode 100644 erpnext/sidebar/module_def_crm/module_def_crm.json create mode 100644 erpnext/sidebar/module_def_edi/module_def_edi.json create mode 100644 erpnext/sidebar/module_def_maintenance/module_def_maintenance.json create mode 100644 erpnext/sidebar/module_def_manufacturing/module_def_manufacturing.json create mode 100644 erpnext/sidebar/module_def_projects/module_def_projects.json create mode 100644 erpnext/sidebar/module_def_quality_management/module_def_quality_management.json create mode 100644 erpnext/sidebar/module_def_regional/module_def_regional.json create mode 100644 erpnext/sidebar/module_def_selling/module_def_selling.json create mode 100644 erpnext/sidebar/module_def_setup/module_def_setup.json create mode 100644 erpnext/sidebar/module_def_stock/module_def_stock.json create mode 100644 erpnext/sidebar/module_def_subcontracting/module_def_subcontracting.json create mode 100644 erpnext/sidebar/module_def_support/module_def_support.json create mode 100644 erpnext/sidebar/module_def_telephony/module_def_telephony.json create mode 100644 erpnext/sidebar/module_def_utilities/module_def_utilities.json create mode 100644 erpnext/tests/test_navigation.py diff --git a/erpnext/hooks.py b/erpnext/hooks.py index 51ccc25d50d..a6918a3f50b 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -10,6 +10,16 @@ source_link = "https://github.com/frappe/erpnext" app_logo_url = "/assets/erpnext/images/erpnext-logo.svg" app_home = "/desk/home" +# ERPNext addresses its doctypes through their module: /apps/erpnext/accounts/ +# sales-invoice/SI-001 (frappe/frappe#42211). The shape is fixed per app rather than per +# doctype, foreign doctypes included, because a shape that varied inside one app would be +# unparseable. +# +# desk v2 only. On `develop` this is dead config, and it is what the module rail below +# needs to have anywhere to land: a `Module` item resolves to a module page, and a +# non-modular prefix has no module route at all. +app_modular = True + add_to_apps_screen = [ { "name": app_name, diff --git a/erpnext/rail/erpnext/erpnext.json b/erpnext/rail/erpnext/erpnext.json new file mode 100644 index 00000000000..0018663311a --- /dev/null +++ b/erpnext/rail/erpnext/erpnext.json @@ -0,0 +1,276 @@ +{ + "app": "erpnext", + "creation": "2026-09-02 22:15:00.000000", + "docstatus": 0, + "doctype": "Rail", + "extends": "", + "idx": 0, + "items": [ + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "icon": "landmark", + "item_type": "Sidebar", + "keep_closed": 0, + "key": "accounts", + "label": "Accounts", + "link_doctype": "Sidebar", + "link_to": "module_def_accounts", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "icon": "handshake", + "item_type": "Sidebar", + "keep_closed": 0, + "key": "crm", + "label": "CRM", + "link_doctype": "Sidebar", + "link_to": "module_def_crm", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "icon": "shopping-cart", + "item_type": "Sidebar", + "keep_closed": 0, + "key": "buying", + "label": "Buying", + "link_doctype": "Sidebar", + "link_to": "module_def_buying", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "icon": "folder-kanban", + "item_type": "Sidebar", + "keep_closed": 0, + "key": "projects", + "label": "Projects", + "link_doctype": "Sidebar", + "link_to": "module_def_projects", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "icon": "store", + "item_type": "Sidebar", + "keep_closed": 0, + "key": "selling", + "label": "Selling", + "link_doctype": "Sidebar", + "link_to": "module_def_selling", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "icon": "sliders-horizontal", + "item_type": "Sidebar", + "keep_closed": 0, + "key": "setup", + "label": "Setup", + "link_doctype": "Sidebar", + "link_to": "module_def_setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "icon": "building-2", + "item_type": "Sidebar", + "keep_closed": 0, + "key": "manufacturing", + "label": "Manufacturing", + "link_doctype": "Sidebar", + "link_to": "module_def_manufacturing", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "icon": "package", + "item_type": "Sidebar", + "keep_closed": 0, + "key": "stock", + "label": "Stock", + "link_doctype": "Sidebar", + "link_to": "module_def_stock", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "icon": "headset", + "item_type": "Sidebar", + "keep_closed": 0, + "key": "support", + "label": "Support", + "link_doctype": "Sidebar", + "link_to": "module_def_support", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "icon": "pocket-knife", + "item_type": "Sidebar", + "keep_closed": 0, + "key": "utilities", + "label": "Utilities", + "link_doctype": "Sidebar", + "link_to": "module_def_utilities", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "icon": "archive", + "item_type": "Sidebar", + "keep_closed": 0, + "key": "assets", + "label": "Assets", + "link_doctype": "Sidebar", + "link_to": "module_def_assets", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "icon": "wrench", + "item_type": "Sidebar", + "keep_closed": 0, + "key": "maintenance", + "label": "Maintenance", + "link_doctype": "Sidebar", + "link_to": "module_def_maintenance", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "icon": "globe", + "item_type": "Sidebar", + "keep_closed": 0, + "key": "regional", + "label": "Regional", + "link_doctype": "Sidebar", + "link_to": "module_def_regional", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "icon": "plug", + "item_type": "Module", + "keep_closed": 0, + "key": "erpnext-integrations", + "label": "Integrations", + "link_doctype": "Module Def", + "link_to": "ERPNext Integrations", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "icon": "shield-check", + "item_type": "Sidebar", + "keep_closed": 0, + "key": "quality-management", + "label": "Quality", + "link_doctype": "Sidebar", + "link_to": "module_def_quality_management", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "icon": "messages-square", + "item_type": "Module", + "keep_closed": 0, + "key": "communication", + "label": "Communication", + "link_doctype": "Module Def", + "link_to": "Communication", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "icon": "phone", + "item_type": "Sidebar", + "keep_closed": 0, + "key": "telephony", + "label": "Telephony", + "link_doctype": "Sidebar", + "link_to": "module_def_telephony", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "icon": "layers", + "item_type": "Sidebar", + "keep_closed": 0, + "key": "bulk-transaction", + "label": "Bulk Transaction", + "link_doctype": "Sidebar", + "link_to": "module_def_bulk_transaction", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "icon": "factory", + "item_type": "Sidebar", + "keep_closed": 0, + "key": "subcontracting", + "label": "Subcontracting", + "link_doctype": "Sidebar", + "link_to": "module_def_subcontracting", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "icon": "file-code", + "item_type": "Sidebar", + "keep_closed": 0, + "key": "edi", + "label": "EDI", + "link_doctype": "Sidebar", + "link_to": "module_def_edi", + "switches_app": 0 + } + ], + "modified": "2026-09-02 22:15:00.000000", + "modified_by": "Administrator", + "name": "erpnext", + "owner": "Administrator", + "standard": 1, + "user": "" +} diff --git a/erpnext/sidebar/module_def_accounts/module_def_accounts.json b/erpnext/sidebar/module_def_accounts/module_def_accounts.json new file mode 100644 index 00000000000..f5f400f6f71 --- /dev/null +++ b/erpnext/sidebar/module_def_accounts/module_def_accounts.json @@ -0,0 +1,940 @@ +{ + "app": "erpnext", + "creation": "2026-09-02 22:15:00.000000", + "docstatus": 0, + "doctype": "Sidebar", + "idx": 0, + "items": [], + "link_doctype": "Module Def", + "link_to": "Accounts", + "modified": "2026-09-02 22:15:00.000000", + "modified_by": "Administrator", + "name": "module_def_accounts", + "navigation_items": [ + { + "added": 0, + "collapsible": 1, + "hidden": 0, + "item_type": "Section", + "keep_closed": 0, + "key": "section-setup", + "label": "Setup", + "link_doctype": "", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "account", + "label": "Chart of Accounts", + "link_doctype": "DocType", + "link_to": "Account", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "cost-center", + "label": "Chart of Cost Centers", + "link_doctype": "DocType", + "link_to": "Cost Center", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "account-category", + "label": "Account Category", + "link_doctype": "DocType", + "link_to": "Account Category", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "accounting-dimension", + "label": "Accounting Dimension", + "link_doctype": "DocType", + "link_to": "Accounting Dimension", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "currency", + "label": "Currency", + "link_doctype": "DocType", + "link_to": "Currency", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "currency-exchange", + "label": "Currency Exchange", + "link_doctype": "DocType", + "link_to": "Currency Exchange", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "finance-book", + "label": "Finance Book", + "link_doctype": "DocType", + "link_to": "Finance Book", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "mode-of-payment", + "label": "Mode of Payment", + "link_doctype": "DocType", + "link_to": "Mode of Payment", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "payment-term", + "label": "Payment Term", + "link_doctype": "DocType", + "link_to": "Payment Term", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "journal-entry-template", + "label": "Journal Entry Template", + "link_doctype": "DocType", + "link_to": "Journal Entry Template", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "terms-and-conditions", + "label": "Terms and Conditions", + "link_doctype": "DocType", + "link_to": "Terms and Conditions", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "company", + "label": "Company", + "link_doctype": "DocType", + "link_to": "Company", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "fiscal-year", + "label": "Fiscal Year", + "link_doctype": "DocType", + "link_to": "Fiscal Year", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 1, + "hidden": 0, + "item_type": "Section", + "keep_closed": 1, + "key": "section-opening-closing", + "label": "Opening & Closing", + "link_doctype": "", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "chart-of-accounts-importer", + "label": "COA Importer", + "link_doctype": "DocType", + "link_to": "Chart of Accounts Importer", + "parent_key": "section-opening-closing", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "opening-invoice-creation-tool", + "label": "Opening Invoice Tool", + "link_doctype": "DocType", + "link_to": "Opening Invoice Creation Tool", + "parent_key": "section-opening-closing", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "accounting-period", + "label": "Accounting Period", + "link_doctype": "DocType", + "link_to": "Accounting Period", + "parent_key": "section-opening-closing", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "exchange-rate-revaluation", + "label": "FX Revaluation", + "link_doctype": "DocType", + "link_to": "Exchange Rate Revaluation", + "parent_key": "section-opening-closing", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "period-closing-voucher", + "label": "Period Closing Voucher", + "link_doctype": "DocType", + "link_to": "Period Closing Voucher", + "parent_key": "section-opening-closing", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 1, + "hidden": 0, + "item_type": "Section", + "keep_closed": 1, + "key": "section-taxes", + "label": "Taxes", + "link_doctype": "", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "sales-taxes-and-charges-template", + "label": "Sales Tax Template", + "link_doctype": "DocType", + "link_to": "Sales Taxes and Charges Template", + "parent_key": "section-taxes", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "purchase-taxes-and-charges-template", + "label": "Purchase Tax Template", + "link_doctype": "DocType", + "link_to": "Purchase Taxes and Charges Template", + "parent_key": "section-taxes", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "item-tax-template", + "label": "Item Tax Template", + "link_doctype": "DocType", + "link_to": "Item Tax Template", + "parent_key": "section-taxes", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "tax-category", + "label": "Tax Category", + "link_doctype": "DocType", + "link_to": "Tax Category", + "parent_key": "section-taxes", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "tax-rule", + "label": "Tax Rule", + "link_doctype": "DocType", + "link_to": "Tax Rule", + "parent_key": "section-taxes", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "tax-withholding-category", + "label": "Tax Withholding Category", + "link_doctype": "DocType", + "link_to": "Tax Withholding Category", + "parent_key": "section-taxes", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "tax-withholding-group", + "label": "Tax Withholding Group", + "link_doctype": "DocType", + "link_to": "Tax Withholding Group", + "parent_key": "section-taxes", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "lower-deduction-certificate", + "label": "Deduction Certificate", + "link_doctype": "DocType", + "link_to": "Lower Deduction Certificate", + "parent_key": "section-taxes", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 1, + "hidden": 0, + "item_type": "Section", + "keep_closed": 1, + "key": "section-budgeting", + "label": "Budgeting", + "link_doctype": "", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "budget", + "label": "Budget", + "link_doctype": "DocType", + "link_to": "Budget", + "parent_key": "section-budgeting", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "cost-center-allocation", + "label": "Cost Center Allocation", + "link_doctype": "DocType", + "link_to": "Cost Center Allocation", + "parent_key": "section-budgeting", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 1, + "hidden": 0, + "item_type": "Section", + "keep_closed": 1, + "key": "section-share-management", + "label": "Share Management", + "link_doctype": "", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "shareholder", + "label": "Shareholder", + "link_doctype": "DocType", + "link_to": "Shareholder", + "parent_key": "section-share-management", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "share-transfer", + "label": "Share Transfer", + "link_doctype": "DocType", + "link_to": "Share Transfer", + "parent_key": "section-share-management", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 1, + "hidden": 0, + "item_type": "Section", + "keep_closed": 1, + "key": "section-subscriptions", + "label": "Subscriptions", + "link_doctype": "", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "subscription", + "label": "Subscription", + "link_doctype": "DocType", + "link_to": "Subscription", + "parent_key": "section-subscriptions", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "subscription-plan", + "label": "Subscription Plan", + "link_doctype": "DocType", + "link_to": "Subscription Plan", + "parent_key": "section-subscriptions", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "subscription-settings", + "label": "Subscription Settings", + "link_doctype": "DocType", + "link_to": "Subscription Settings", + "parent_key": "section-subscriptions", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 1, + "hidden": 0, + "item_type": "Section", + "keep_closed": 1, + "key": "section-settings", + "label": "Settings", + "link_doctype": "", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "accounts-settings", + "label": "Accounts Settings", + "link_doctype": "DocType", + "link_to": "Accounts Settings", + "parent_key": "section-settings", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "currency-exchange-settings", + "label": "Currency Exchange Settings", + "link_doctype": "DocType", + "link_to": "Currency Exchange Settings", + "parent_key": "section-settings", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 1, + "hidden": 0, + "item_type": "Section", + "keep_closed": 0, + "key": "section-receivables", + "label": "Receivables", + "link_doctype": "", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "customer", + "label": "Customer", + "link_doctype": "DocType", + "link_to": "Customer", + "parent_key": "section-receivables", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "sales-invoice", + "label": "Sales Invoice", + "link_doctype": "DocType", + "link_to": "Sales Invoice", + "parent_key": "section-receivables", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 1, + "hidden": 0, + "item_type": "Section", + "keep_closed": 0, + "key": "section-payables", + "label": "Payables", + "link_doctype": "", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "supplier", + "label": "Supplier", + "link_doctype": "DocType", + "link_to": "Supplier", + "parent_key": "section-payables", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "purchase-invoice", + "label": "Purchase Invoice", + "link_doctype": "DocType", + "link_to": "Purchase Invoice", + "parent_key": "section-payables", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 1, + "hidden": 0, + "item_type": "Section", + "keep_closed": 0, + "key": "section-payments", + "label": "Payments", + "link_doctype": "", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "payment-entry", + "label": "Payment Entry", + "link_doctype": "DocType", + "link_to": "Payment Entry", + "parent_key": "section-payments", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "journal-entry", + "label": "Journal Entry", + "link_doctype": "DocType", + "link_to": "Journal Entry", + "parent_key": "section-payments", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "payment-request", + "label": "Payment Request", + "link_doctype": "DocType", + "link_to": "Payment Request", + "parent_key": "section-payments", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "payment-order", + "label": "Payment Order", + "link_doctype": "DocType", + "link_to": "Payment Order", + "parent_key": "section-payments", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "payment-reconciliation", + "label": "Payment Reconciliation", + "link_doctype": "DocType", + "link_to": "Payment Reconciliation", + "parent_key": "section-payments", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "unreconcile-payment", + "label": "Unreconcile Payment", + "link_doctype": "DocType", + "link_to": "Unreconcile Payment", + "parent_key": "section-payments", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "process-payment-reconciliation", + "label": "Process Payment Reconciliation", + "link_doctype": "DocType", + "link_to": "Process Payment Reconciliation", + "parent_key": "section-payments", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "repost-accounting-ledger", + "label": "Repost Accounting Ledger", + "link_doctype": "DocType", + "link_to": "Repost Accounting Ledger", + "parent_key": "section-payments", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "repost-payment-ledger", + "label": "Repost Payment Ledger", + "link_doctype": "DocType", + "link_to": "Repost Payment Ledger", + "parent_key": "section-payments", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 1, + "hidden": 0, + "item_type": "Section", + "keep_closed": 0, + "key": "section-banking", + "label": "Banking", + "link_doctype": "", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "bank-clearance", + "label": "Bank Clearance", + "link_doctype": "DocType", + "link_to": "Bank Clearance", + "parent_key": "section-banking", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "bank-reconciliation-tool", + "label": "Bank Reconciliation", + "link_doctype": "DocType", + "link_to": "Bank Reconciliation Tool", + "parent_key": "section-banking", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 1, + "hidden": 0, + "item_type": "Section", + "keep_closed": 1, + "key": "section-banking-setup", + "label": "Banking Setup", + "link_doctype": "", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "bank", + "label": "Bank", + "link_doctype": "DocType", + "link_to": "Bank", + "parent_key": "section-banking-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "bank-account", + "label": "Bank Account", + "link_doctype": "DocType", + "link_to": "Bank Account", + "parent_key": "section-banking-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "bank-account-type", + "label": "Bank Account Type", + "link_doctype": "DocType", + "link_to": "Bank Account Type", + "parent_key": "section-banking-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "bank-account-subtype", + "label": "Bank Account Subtype", + "link_doctype": "DocType", + "link_to": "Bank Account Subtype", + "parent_key": "section-banking-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "bank-guarantee", + "label": "Bank Guarantee", + "link_doctype": "DocType", + "link_to": "Bank Guarantee", + "parent_key": "section-banking-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "plaid-settings", + "label": "Plaid Settings", + "link_doctype": "DocType", + "link_to": "Plaid Settings", + "parent_key": "section-banking-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 1, + "hidden": 0, + "item_type": "Section", + "keep_closed": 1, + "key": "section-dunning", + "label": "Dunning", + "link_doctype": "", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "dunning", + "label": "Dunning", + "link_doctype": "DocType", + "link_to": "Dunning", + "parent_key": "section-dunning", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "dunning-type", + "label": "Dunning Type", + "link_doctype": "DocType", + "link_to": "Dunning Type", + "parent_key": "section-dunning", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 1, + "hidden": 0, + "item_type": "Section", + "keep_closed": 0, + "key": "section-financial-reports", + "label": "Financial Reports", + "link_doctype": "", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "financial-report-template", + "label": "Financial Report Template", + "link_doctype": "DocType", + "link_to": "Financial Report Template", + "parent_key": "section-financial-reports", + "switches_app": 0 + } + ], + "owner": "Administrator", + "standard": 1, + "title": "Accounts", + "user": "" +} diff --git a/erpnext/sidebar/module_def_assets/module_def_assets.json b/erpnext/sidebar/module_def_assets/module_def_assets.json new file mode 100644 index 00000000000..5b8273d5160 --- /dev/null +++ b/erpnext/sidebar/module_def_assets/module_def_assets.json @@ -0,0 +1,206 @@ +{ + "app": "erpnext", + "creation": "2026-09-02 22:15:00.000000", + "docstatus": 0, + "doctype": "Sidebar", + "idx": 0, + "items": [], + "link_doctype": "Module Def", + "link_to": "Assets", + "modified": "2026-09-02 22:15:00.000000", + "modified_by": "Administrator", + "name": "module_def_assets", + "navigation_items": [ + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "asset", + "label": "Asset", + "link_doctype": "DocType", + "link_to": "Asset", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "asset-depreciation-schedule", + "label": "Depreciation Schedule", + "link_doctype": "DocType", + "link_to": "Asset Depreciation Schedule", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "asset-capitalization", + "label": "Asset Capitalization", + "link_doctype": "DocType", + "link_to": "Asset Capitalization", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "asset-movement", + "label": "Asset Movement", + "link_doctype": "DocType", + "link_to": "Asset Movement", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 1, + "hidden": 0, + "item_type": "Section", + "keep_closed": 1, + "key": "section-maintenance", + "label": "Maintenance", + "link_doctype": "", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "asset-maintenance-team", + "label": "Asset Maintenance Team", + "link_doctype": "DocType", + "link_to": "Asset Maintenance Team", + "parent_key": "section-maintenance", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "asset-maintenance", + "label": "Asset Maintenance", + "link_doctype": "DocType", + "link_to": "Asset Maintenance", + "parent_key": "section-maintenance", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "asset-maintenance-log", + "label": "Asset Maintenance Log", + "link_doctype": "DocType", + "link_to": "Asset Maintenance Log", + "parent_key": "section-maintenance", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "asset-value-adjustment", + "label": "Asset Value Adjustment", + "link_doctype": "DocType", + "link_to": "Asset Value Adjustment", + "parent_key": "section-maintenance", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "asset-repair", + "label": "Asset Repair", + "link_doctype": "DocType", + "link_to": "Asset Repair", + "parent_key": "section-maintenance", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 1, + "hidden": 0, + "item_type": "Section", + "keep_closed": 1, + "key": "section-setup", + "label": "Setup", + "link_doctype": "", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "item", + "label": "Item", + "link_doctype": "DocType", + "link_to": "Item", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "asset-category", + "label": "Asset Category", + "link_doctype": "DocType", + "link_to": "Asset Category", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "location", + "label": "Location", + "link_doctype": "DocType", + "link_to": "Location", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "accounts-settings", + "label": "Settings", + "link_doctype": "DocType", + "link_to": "Accounts Settings", + "parent_key": "section-setup", + "switches_app": 0 + } + ], + "owner": "Administrator", + "standard": 1, + "title": "Assets", + "user": "" +} diff --git a/erpnext/sidebar/module_def_bulk_transaction/module_def_bulk_transaction.json b/erpnext/sidebar/module_def_bulk_transaction/module_def_bulk_transaction.json new file mode 100644 index 00000000000..d6151f7fcc3 --- /dev/null +++ b/erpnext/sidebar/module_def_bulk_transaction/module_def_bulk_transaction.json @@ -0,0 +1,43 @@ +{ + "app": "erpnext", + "creation": "2026-09-02 22:15:00.000000", + "docstatus": 0, + "doctype": "Sidebar", + "idx": 0, + "items": [], + "link_doctype": "Module Def", + "link_to": "Bulk Transaction", + "modified": "2026-09-02 22:15:00.000000", + "modified_by": "Administrator", + "name": "module_def_bulk_transaction", + "navigation_items": [ + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "bulk-transaction-log-detail", + "label": "Bulk Transaction Log Detail", + "link_doctype": "DocType", + "link_to": "Bulk Transaction Log Detail", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "bulk-transaction-log", + "label": "Bulk Transaction Log", + "link_doctype": "DocType", + "link_to": "Bulk Transaction Log", + "switches_app": 0 + } + ], + "owner": "Administrator", + "standard": 1, + "title": "Bulk Transaction", + "user": "" +} diff --git a/erpnext/sidebar/module_def_buying/module_def_buying.json b/erpnext/sidebar/module_def_buying/module_def_buying.json new file mode 100644 index 00000000000..7a253da5e8a --- /dev/null +++ b/erpnext/sidebar/module_def_buying/module_def_buying.json @@ -0,0 +1,320 @@ +{ + "app": "erpnext", + "creation": "2026-09-02 22:15:00.000000", + "docstatus": 0, + "doctype": "Sidebar", + "idx": 0, + "items": [], + "link_doctype": "Module Def", + "link_to": "Buying", + "modified": "2026-09-02 22:15:00.000000", + "modified_by": "Administrator", + "name": "module_def_buying", + "navigation_items": [ + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "material-request", + "label": "Material Request", + "link_doctype": "DocType", + "link_to": "Material Request", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "request-for-quotation", + "label": "Request for Quotation", + "link_doctype": "DocType", + "link_to": "Request for Quotation", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "supplier-quotation", + "label": "Supplier Quotation", + "link_doctype": "DocType", + "link_to": "Supplier Quotation", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "purchase-order", + "label": "Purchase Order", + "link_doctype": "DocType", + "link_to": "Purchase Order", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "purchase-invoice", + "label": "Purchase Invoice", + "link_doctype": "DocType", + "link_to": "Purchase Invoice", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 1, + "hidden": 0, + "item_type": "Section", + "keep_closed": 1, + "key": "section-setup", + "label": "Setup", + "link_doctype": "", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "supplier", + "label": "Supplier", + "link_doctype": "DocType", + "link_to": "Supplier", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "supplier-group", + "label": "Supplier Group", + "link_doctype": "DocType", + "link_to": "Supplier Group", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "item", + "label": "Item", + "link_doctype": "DocType", + "link_to": "Item", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "price-list", + "label": "Price List", + "link_doctype": "DocType", + "link_to": "Price List", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "address", + "label": "Address", + "link_doctype": "DocType", + "link_to": "Address", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "contact", + "label": "Contacts", + "link_doctype": "DocType", + "link_to": "Contact", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "supplier-scorecard", + "label": "Supplier Scorecard", + "link_doctype": "DocType", + "link_to": "Supplier Scorecard", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "supplier-scorecard-criteria", + "label": "Supplier Scorecard Criteria", + "link_doctype": "DocType", + "link_to": "Supplier Scorecard Criteria", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "supplier-scorecard-variable", + "label": "Supplier Scorecard Variable", + "link_doctype": "DocType", + "link_to": "Supplier Scorecard Variable", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "supplier-scorecard-standing", + "label": "Supplier Scorecard Standing", + "link_doctype": "DocType", + "link_to": "Supplier Scorecard Standing", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 1, + "hidden": 0, + "item_type": "Section", + "keep_closed": 1, + "key": "section-subcontracting", + "label": "Subcontracting", + "link_doctype": "", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "subcontracting-bom", + "label": "Subcontracting BOM", + "link_doctype": "DocType", + "link_to": "Subcontracting BOM", + "parent_key": "section-subcontracting", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "subcontracting-inward-order", + "label": "Subcontracting Inward Order", + "link_doctype": "DocType", + "link_to": "Subcontracting Inward Order", + "parent_key": "section-subcontracting", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "stock-entry", + "label": "Subcontracting Delivery", + "link_doctype": "DocType", + "link_to": "Stock Entry", + "parent_key": "section-subcontracting", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "subcontracting-order", + "label": "Subcontracting Order", + "link_doctype": "DocType", + "link_to": "Subcontracting Order", + "parent_key": "section-subcontracting", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "subcontracting-receipt", + "label": "Subcontracting Receipt", + "link_doctype": "DocType", + "link_to": "Subcontracting Receipt", + "parent_key": "section-subcontracting", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 1, + "hidden": 0, + "item_type": "Section", + "keep_closed": 1, + "key": "section-reports", + "label": "Reports", + "link_doctype": "", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "buying-settings", + "label": "Settings", + "link_doctype": "DocType", + "link_to": "Buying Settings", + "parent_key": "section-reports", + "switches_app": 0 + } + ], + "owner": "Administrator", + "standard": 1, + "title": "Buying", + "user": "" +} diff --git a/erpnext/sidebar/module_def_crm/module_def_crm.json b/erpnext/sidebar/module_def_crm/module_def_crm.json new file mode 100644 index 00000000000..f19caa71316 --- /dev/null +++ b/erpnext/sidebar/module_def_crm/module_def_crm.json @@ -0,0 +1,370 @@ +{ + "app": "erpnext", + "creation": "2026-09-02 22:15:00.000000", + "docstatus": 0, + "doctype": "Sidebar", + "idx": 0, + "items": [], + "link_doctype": "Module Def", + "link_to": "CRM", + "modified": "2026-09-02 22:15:00.000000", + "modified_by": "Administrator", + "name": "module_def_crm", + "navigation_items": [ + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "lead", + "label": "Lead", + "link_doctype": "DocType", + "link_to": "Lead", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "opportunity", + "label": "Opportunity", + "link_doctype": "DocType", + "link_to": "Opportunity", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "customer", + "label": "Customer", + "link_doctype": "DocType", + "link_to": "Customer", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 1, + "hidden": 0, + "item_type": "Section", + "keep_closed": 1, + "key": "section-maintenance", + "label": "Maintenance", + "link_doctype": "", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "maintenance-schedule", + "label": "Maintenance Schedule", + "link_doctype": "DocType", + "link_to": "Maintenance Schedule", + "parent_key": "section-maintenance", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "maintenance-visit", + "label": "Maintenance Visit", + "link_doctype": "DocType", + "link_to": "Maintenance Visit", + "parent_key": "section-maintenance", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "warranty-claim", + "label": "Warranty Claim", + "link_doctype": "DocType", + "link_to": "Warranty Claim", + "parent_key": "section-maintenance", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 1, + "hidden": 0, + "item_type": "Section", + "keep_closed": 1, + "key": "section-sales-pipeline", + "label": "Sales Pipeline", + "link_doctype": "", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "contract", + "label": "Contract", + "link_doctype": "DocType", + "link_to": "Contract", + "parent_key": "section-sales-pipeline", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "appointment", + "label": "Appointment", + "link_doctype": "DocType", + "link_to": "Appointment", + "parent_key": "section-sales-pipeline", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "communication", + "label": "Communication", + "link_doctype": "DocType", + "link_to": "Communication", + "parent_key": "section-sales-pipeline", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 1, + "hidden": 0, + "item_type": "Section", + "keep_closed": 1, + "key": "section-campaign", + "label": "Campaign", + "link_doctype": "", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "campaign", + "label": "Campaign", + "link_doctype": "DocType", + "link_to": "Campaign", + "parent_key": "section-campaign", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "email-campaign", + "label": "Email Campaign", + "link_doctype": "DocType", + "link_to": "Email Campaign", + "parent_key": "section-campaign", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "sms-center", + "label": "SMS Center", + "link_doctype": "DocType", + "link_to": "SMS Center", + "parent_key": "section-campaign", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "sms-log", + "label": "SMS Log", + "link_doctype": "DocType", + "link_to": "SMS Log", + "parent_key": "section-campaign", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "email-group", + "label": "Email Group", + "link_doctype": "DocType", + "link_to": "Email Group", + "parent_key": "section-campaign", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 1, + "hidden": 0, + "item_type": "Section", + "keep_closed": 1, + "key": "section-setup", + "label": "Setup", + "link_doctype": "", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "territory", + "label": "Territory", + "link_doctype": "DocType", + "link_to": "Territory", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "customer-group", + "label": "Customer Group", + "link_doctype": "DocType", + "link_to": "Customer Group", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "contact", + "label": "Contact", + "link_doctype": "DocType", + "link_to": "Contact", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "prospect", + "label": "Prospect", + "link_doctype": "DocType", + "link_to": "Prospect", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "sales-person", + "label": "Sales Person", + "link_doctype": "DocType", + "link_to": "Sales Person", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "sales-stage", + "label": "Sales Stage", + "link_doctype": "DocType", + "link_to": "Sales Stage", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "utm-source", + "label": "Lead Source", + "link_doctype": "DocType", + "link_to": "UTM Source", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 1, + "hidden": 0, + "item_type": "Section", + "keep_closed": 1, + "key": "section-settings", + "label": "Settings", + "link_doctype": "", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "crm-settings", + "label": "CRM Settings", + "link_doctype": "DocType", + "link_to": "CRM Settings", + "parent_key": "section-settings", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "sms-settings", + "label": "SMS Settings", + "link_doctype": "DocType", + "link_to": "SMS Settings", + "parent_key": "section-settings", + "switches_app": 0 + } + ], + "owner": "Administrator", + "standard": 1, + "title": "CRM", + "user": "" +} diff --git a/erpnext/sidebar/module_def_edi/module_def_edi.json b/erpnext/sidebar/module_def_edi/module_def_edi.json new file mode 100644 index 00000000000..4d948202b99 --- /dev/null +++ b/erpnext/sidebar/module_def_edi/module_def_edi.json @@ -0,0 +1,43 @@ +{ + "app": "erpnext", + "creation": "2026-09-02 22:15:00.000000", + "docstatus": 0, + "doctype": "Sidebar", + "idx": 0, + "items": [], + "link_doctype": "Module Def", + "link_to": "EDI", + "modified": "2026-09-02 22:15:00.000000", + "modified_by": "Administrator", + "name": "module_def_edi", + "navigation_items": [ + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "code-list", + "label": "Code List", + "link_doctype": "DocType", + "link_to": "Code List", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "common-code", + "label": "Common Code", + "link_doctype": "DocType", + "link_to": "Common Code", + "switches_app": 0 + } + ], + "owner": "Administrator", + "standard": 1, + "title": "EDI", + "user": "" +} diff --git a/erpnext/sidebar/module_def_maintenance/module_def_maintenance.json b/erpnext/sidebar/module_def_maintenance/module_def_maintenance.json new file mode 100644 index 00000000000..056699d21ae --- /dev/null +++ b/erpnext/sidebar/module_def_maintenance/module_def_maintenance.json @@ -0,0 +1,43 @@ +{ + "app": "erpnext", + "creation": "2026-09-02 22:15:00.000000", + "docstatus": 0, + "doctype": "Sidebar", + "idx": 0, + "items": [], + "link_doctype": "Module Def", + "link_to": "Maintenance", + "modified": "2026-09-02 22:15:00.000000", + "modified_by": "Administrator", + "name": "module_def_maintenance", + "navigation_items": [ + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "maintenance-schedule", + "label": "Maintenance Schedule", + "link_doctype": "DocType", + "link_to": "Maintenance Schedule", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "maintenance-visit", + "label": "Maintenance Visit", + "link_doctype": "DocType", + "link_to": "Maintenance Visit", + "switches_app": 0 + } + ], + "owner": "Administrator", + "standard": 1, + "title": "Maintenance", + "user": "" +} diff --git a/erpnext/sidebar/module_def_manufacturing/module_def_manufacturing.json b/erpnext/sidebar/module_def_manufacturing/module_def_manufacturing.json new file mode 100644 index 00000000000..bf0c0f5638c --- /dev/null +++ b/erpnext/sidebar/module_def_manufacturing/module_def_manufacturing.json @@ -0,0 +1,295 @@ +{ + "app": "erpnext", + "creation": "2026-09-02 22:15:00.000000", + "docstatus": 0, + "doctype": "Sidebar", + "idx": 0, + "items": [], + "link_doctype": "Module Def", + "link_to": "Manufacturing", + "modified": "2026-09-02 22:15:00.000000", + "modified_by": "Administrator", + "name": "module_def_manufacturing", + "navigation_items": [ + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "bom", + "label": "BOM", + "link_doctype": "DocType", + "link_to": "BOM", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "work-order", + "label": "Work Order", + "link_doctype": "DocType", + "link_to": "Work Order", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "job-card", + "label": "Job Card", + "link_doctype": "DocType", + "link_to": "Job Card", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "stock-entry", + "label": "Stock Entry", + "link_doctype": "DocType", + "link_to": "Stock Entry", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 1, + "hidden": 0, + "item_type": "Section", + "keep_closed": 1, + "key": "section-material-planning", + "label": "Material Planning", + "link_doctype": "", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "item-lead-time", + "label": "Item Lead Time", + "link_doctype": "DocType", + "link_to": "Item Lead Time", + "parent_key": "section-material-planning", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "production-plan", + "label": "Production Plan", + "link_doctype": "DocType", + "link_to": "Production Plan", + "parent_key": "section-material-planning", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "master-production-schedule", + "label": "Master Production Schedule", + "link_doctype": "DocType", + "link_to": "Master Production Schedule", + "parent_key": "section-material-planning", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "sales-forecast", + "label": "Sales Forecast", + "link_doctype": "DocType", + "link_to": "Sales Forecast", + "parent_key": "section-material-planning", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 1, + "hidden": 0, + "item_type": "Section", + "keep_closed": 1, + "key": "section-tools", + "label": "Tools", + "link_doctype": "", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "bom-creator", + "label": "BOM Creator", + "link_doctype": "DocType", + "link_to": "BOM Creator", + "parent_key": "section-tools", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "bom-update-tool", + "label": "BOM Update Tool", + "link_doctype": "DocType", + "link_to": "BOM Update Tool", + "parent_key": "section-tools", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "downtime-entry", + "label": "Downtime Entry", + "link_doctype": "DocType", + "link_to": "Downtime Entry", + "parent_key": "section-tools", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 1, + "hidden": 0, + "item_type": "Section", + "keep_closed": 1, + "key": "section-setup", + "label": "Setup", + "link_doctype": "", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "item", + "label": "Item", + "link_doctype": "DocType", + "link_to": "Item", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "warehouse", + "label": "Warehouse", + "link_doctype": "DocType", + "link_to": "Warehouse", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "operation", + "label": "Operation", + "link_doctype": "DocType", + "link_to": "Operation", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "workstation", + "label": "Workstation", + "link_doctype": "DocType", + "link_to": "Workstation", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "workstation-type", + "label": "Workstation Type", + "link_doctype": "DocType", + "link_to": "Workstation Type", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "plant-floor", + "label": "Plant Floor", + "link_doctype": "DocType", + "link_to": "Plant Floor", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "routing", + "label": "Routing", + "link_doctype": "DocType", + "link_to": "Routing", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "manufacturing-settings", + "label": "Settings", + "link_doctype": "DocType", + "link_to": "Manufacturing Settings", + "parent_key": "section-setup", + "switches_app": 0 + } + ], + "owner": "Administrator", + "standard": 1, + "title": "Manufacturing", + "user": "" +} diff --git a/erpnext/sidebar/module_def_projects/module_def_projects.json b/erpnext/sidebar/module_def_projects/module_def_projects.json new file mode 100644 index 00000000000..c214a9cd0bd --- /dev/null +++ b/erpnext/sidebar/module_def_projects/module_def_projects.json @@ -0,0 +1,155 @@ +{ + "app": "erpnext", + "creation": "2026-09-02 22:15:00.000000", + "docstatus": 0, + "doctype": "Sidebar", + "idx": 0, + "items": [], + "link_doctype": "Module Def", + "link_to": "Projects", + "modified": "2026-09-02 22:15:00.000000", + "modified_by": "Administrator", + "name": "module_def_projects", + "navigation_items": [ + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "project", + "label": "Project", + "link_doctype": "DocType", + "link_to": "Project", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "task", + "label": "Task", + "link_doctype": "DocType", + "link_to": "Task", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "timesheet", + "label": "Timesheet", + "link_doctype": "DocType", + "link_to": "Timesheet", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 1, + "hidden": 0, + "item_type": "Section", + "keep_closed": 1, + "key": "section-setup", + "label": "Setup", + "link_doctype": "", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "activity-type", + "label": "Activity Type", + "link_doctype": "DocType", + "link_to": "Activity Type", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "activity-cost", + "label": "Activity Cost", + "link_doctype": "DocType", + "link_to": "Activity Cost", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "project-template", + "label": "Project Template", + "link_doctype": "DocType", + "link_to": "Project Template", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "project-type", + "label": "Project Type", + "link_doctype": "DocType", + "link_to": "Project Type", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "project-update", + "label": "Project Update", + "link_doctype": "DocType", + "link_to": "Project Update", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 1, + "hidden": 0, + "item_type": "Section", + "keep_closed": 1, + "key": "section-reports", + "label": "Reports", + "link_doctype": "", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "projects-settings", + "label": "Settings", + "link_doctype": "DocType", + "link_to": "Projects Settings", + "parent_key": "section-reports", + "switches_app": 0 + } + ], + "owner": "Administrator", + "standard": 1, + "title": "Projects", + "user": "" +} diff --git a/erpnext/sidebar/module_def_quality_management/module_def_quality_management.json b/erpnext/sidebar/module_def_quality_management/module_def_quality_management.json new file mode 100644 index 00000000000..53e23a87bcc --- /dev/null +++ b/erpnext/sidebar/module_def_quality_management/module_def_quality_management.json @@ -0,0 +1,153 @@ +{ + "app": "erpnext", + "creation": "2026-09-02 22:15:00.000000", + "docstatus": 0, + "doctype": "Sidebar", + "idx": 0, + "items": [], + "link_doctype": "Module Def", + "link_to": "Quality Management", + "modified": "2026-09-02 22:15:00.000000", + "modified_by": "Administrator", + "name": "module_def_quality_management", + "navigation_items": [ + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "quality-inspection", + "label": "Quality Inspection", + "link_doctype": "DocType", + "link_to": "Quality Inspection", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "quality-goal", + "label": "Quality Goal", + "link_doctype": "DocType", + "link_to": "Quality Goal", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "quality-review", + "label": "Quality Review", + "link_doctype": "DocType", + "link_to": "Quality Review", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "quality-action", + "label": "Quality Action", + "link_doctype": "DocType", + "link_to": "Quality Action", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "non-conformance", + "label": "Non Conformance", + "link_doctype": "DocType", + "link_to": "Non Conformance", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "quality-feedback", + "label": "Quality Feedback", + "link_doctype": "DocType", + "link_to": "Quality Feedback", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "quality-meeting", + "label": "Quality Meeting", + "link_doctype": "DocType", + "link_to": "Quality Meeting", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 1, + "hidden": 0, + "item_type": "Section", + "keep_closed": 1, + "key": "section-setup", + "label": "Setup", + "link_doctype": "", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "quality-procedure", + "label": "Quality Procedure", + "link_doctype": "DocType", + "link_to": "Quality Procedure", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "quality-feedback-template", + "label": "Feedback Template", + "link_doctype": "DocType", + "link_to": "Quality Feedback Template", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "quality-inspection-template", + "label": "Quality Inspection Template", + "link_doctype": "DocType", + "link_to": "Quality Inspection Template", + "parent_key": "section-setup", + "switches_app": 0 + } + ], + "owner": "Administrator", + "standard": 1, + "title": "Quality", + "user": "" +} diff --git a/erpnext/sidebar/module_def_regional/module_def_regional.json b/erpnext/sidebar/module_def_regional/module_def_regional.json new file mode 100644 index 00000000000..86fa9af3ead --- /dev/null +++ b/erpnext/sidebar/module_def_regional/module_def_regional.json @@ -0,0 +1,55 @@ +{ + "app": "erpnext", + "creation": "2026-09-02 22:15:00.000000", + "docstatus": 0, + "doctype": "Sidebar", + "idx": 0, + "items": [], + "link_doctype": "Module Def", + "link_to": "Regional", + "modified": "2026-09-02 22:15:00.000000", + "modified_by": "Administrator", + "name": "module_def_regional", + "navigation_items": [ + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "lower-deduction-certificate", + "label": "Lower Deduction Certificate", + "link_doctype": "DocType", + "link_to": "Lower Deduction Certificate", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "uae-vat-settings", + "label": "UAE VAT Settings", + "link_doctype": "DocType", + "link_to": "UAE VAT Settings", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "south-africa-vat-settings", + "label": "South Africa VAT Settings", + "link_doctype": "DocType", + "link_to": "South Africa VAT Settings", + "switches_app": 0 + } + ], + "owner": "Administrator", + "standard": 1, + "title": "Regional", + "user": "" +} diff --git a/erpnext/sidebar/module_def_selling/module_def_selling.json b/erpnext/sidebar/module_def_selling/module_def_selling.json new file mode 100644 index 00000000000..c7f8d338cd4 --- /dev/null +++ b/erpnext/sidebar/module_def_selling/module_def_selling.json @@ -0,0 +1,502 @@ +{ + "app": "erpnext", + "creation": "2026-09-02 22:15:00.000000", + "docstatus": 0, + "doctype": "Sidebar", + "idx": 0, + "items": [], + "link_doctype": "Module Def", + "link_to": "Selling", + "modified": "2026-09-02 22:15:00.000000", + "modified_by": "Administrator", + "name": "module_def_selling", + "navigation_items": [ + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "quotation", + "label": "Quotation", + "link_doctype": "DocType", + "link_to": "Quotation", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "sales-order", + "label": "Sales Order", + "link_doctype": "DocType", + "link_to": "Sales Order", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "sales-invoice", + "label": "Sales Invoice", + "link_doctype": "DocType", + "link_to": "Sales Invoice", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 1, + "hidden": 0, + "item_type": "Section", + "keep_closed": 1, + "key": "section-pos", + "label": "POS", + "link_doctype": "", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "pos-profile", + "label": "POS Profile", + "link_doctype": "DocType", + "link_to": "POS Profile", + "parent_key": "section-pos", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "pos-invoice", + "label": "POS Invoice", + "link_doctype": "DocType", + "link_to": "POS Invoice", + "parent_key": "section-pos", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "pos-opening-entry", + "label": "POS Opening Entry", + "link_doctype": "DocType", + "link_to": "POS Opening Entry", + "parent_key": "section-pos", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "pos-closing-entry", + "label": "POS Closing Entry", + "link_doctype": "DocType", + "link_to": "POS Closing Entry", + "parent_key": "section-pos", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "pos-invoice-merge-log", + "label": "POS Invoice Merge Log", + "link_doctype": "DocType", + "link_to": "POS Invoice Merge Log", + "parent_key": "section-pos", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "pos-settings", + "label": "POS Settings", + "link_doctype": "DocType", + "link_to": "POS Settings", + "parent_key": "section-pos", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "loyalty-program", + "label": "Loyalty Program", + "link_doctype": "DocType", + "link_to": "Loyalty Program", + "parent_key": "section-pos", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "loyalty-point-entry", + "label": "Loyalty Point Entry", + "link_doctype": "DocType", + "link_to": "Loyalty Point Entry", + "parent_key": "section-pos", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 1, + "hidden": 0, + "item_type": "Section", + "keep_closed": 1, + "key": "section-items-pricing", + "label": "Items & Pricing", + "link_doctype": "", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "item", + "label": "Item", + "link_doctype": "DocType", + "link_to": "Item", + "parent_key": "section-items-pricing", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "item-group", + "label": "Item Group", + "link_doctype": "DocType", + "link_to": "Item Group", + "parent_key": "section-items-pricing", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "price-list", + "label": "Price List", + "link_doctype": "DocType", + "link_to": "Price List", + "parent_key": "section-items-pricing", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "item-price", + "label": "Item Price", + "link_doctype": "DocType", + "link_to": "Item Price", + "parent_key": "section-items-pricing", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "pricing-rule", + "label": "Pricing Rule", + "link_doctype": "DocType", + "link_to": "Pricing Rule", + "parent_key": "section-items-pricing", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "promotional-scheme", + "label": "Promotional Scheme", + "link_doctype": "DocType", + "link_to": "Promotional Scheme", + "parent_key": "section-items-pricing", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "coupon-code", + "label": "Coupon Code", + "link_doctype": "DocType", + "link_to": "Coupon Code", + "parent_key": "section-items-pricing", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "blanket-order", + "label": "Blanket Order", + "link_doctype": "DocType", + "link_to": "Blanket Order", + "parent_key": "section-items-pricing", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 1, + "hidden": 0, + "item_type": "Section", + "keep_closed": 1, + "key": "section-setup", + "label": "Setup", + "link_doctype": "", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "customer", + "label": "Customer", + "link_doctype": "DocType", + "link_to": "Customer", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "customer-group", + "label": "Customer Group", + "link_doctype": "DocType", + "link_to": "Customer Group", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "address", + "label": "Address", + "link_doctype": "DocType", + "link_to": "Address", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "contact", + "label": "Contact", + "link_doctype": "DocType", + "link_to": "Contact", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "territory", + "label": "Territory", + "link_doctype": "DocType", + "link_to": "Territory", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "campaign", + "label": "Campaign", + "link_doctype": "DocType", + "link_to": "Campaign", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "sales-person", + "label": "Sales Person", + "link_doctype": "DocType", + "link_to": "Sales Person", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "sales-partner", + "label": "Sales Partner", + "link_doctype": "DocType", + "link_to": "Sales Partner", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "monthly-distribution", + "label": "Monthly Distribution", + "link_doctype": "DocType", + "link_to": "Monthly Distribution", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "terms-and-conditions", + "label": "Terms Template", + "link_doctype": "DocType", + "link_to": "Terms and Conditions", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "sales-taxes-and-charges-template", + "label": "Tax Template", + "link_doctype": "DocType", + "link_to": "Sales Taxes and Charges Template", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "product-bundle", + "label": "Product Bundle", + "link_doctype": "DocType", + "link_to": "Product Bundle", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "utm-source", + "label": "UTM Source", + "link_doctype": "DocType", + "link_to": "UTM Source", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "shipping-rule", + "label": "Shipping Rule", + "link_doctype": "DocType", + "link_to": "Shipping Rule", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 1, + "hidden": 0, + "item_type": "Section", + "keep_closed": 1, + "key": "section-reports", + "label": "Reports", + "link_doctype": "", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "selling-settings", + "label": "Settings", + "link_doctype": "DocType", + "link_to": "Selling Settings", + "parent_key": "section-reports", + "switches_app": 0 + } + ], + "owner": "Administrator", + "standard": 1, + "title": "Selling", + "user": "" +} diff --git a/erpnext/sidebar/module_def_setup/module_def_setup.json b/erpnext/sidebar/module_def_setup/module_def_setup.json new file mode 100644 index 00000000000..2e7cafcb3ee --- /dev/null +++ b/erpnext/sidebar/module_def_setup/module_def_setup.json @@ -0,0 +1,392 @@ +{ + "app": "erpnext", + "creation": "2026-09-02 22:15:00.000000", + "docstatus": 0, + "doctype": "Sidebar", + "idx": 0, + "items": [], + "link_doctype": "Module Def", + "link_to": "Setup", + "modified": "2026-09-02 22:15:00.000000", + "modified_by": "Administrator", + "name": "module_def_setup", + "navigation_items": [ + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "global-defaults", + "label": "Global Defaults", + "link_doctype": "DocType", + "link_to": "Global Defaults", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "system-settings", + "label": "System Settings", + "link_doctype": "DocType", + "link_to": "System Settings", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "accounts-settings", + "label": "Accounts Settings", + "link_doctype": "DocType", + "link_to": "Accounts Settings", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "pos-settings", + "label": "POS Settings", + "link_doctype": "DocType", + "link_to": "POS Settings", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "selling-settings", + "label": "Selling Settings", + "link_doctype": "DocType", + "link_to": "Selling Settings", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "buying-settings", + "label": "Buying Settings", + "link_doctype": "DocType", + "link_to": "Buying Settings", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "stock-settings", + "label": "Stock Settings", + "link_doctype": "DocType", + "link_to": "Stock Settings", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "manufacturing-settings", + "label": "Manufacturing Settings", + "link_doctype": "DocType", + "link_to": "Manufacturing Settings", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "projects-settings", + "label": "Projects Settings", + "link_doctype": "DocType", + "link_to": "Projects Settings", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "crm-settings", + "label": "CRM Settings", + "link_doctype": "DocType", + "link_to": "CRM Settings", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "support-settings", + "label": "Support Settings", + "link_doctype": "DocType", + "link_to": "Support Settings", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 1, + "hidden": 0, + "item_type": "Section", + "keep_closed": 1, + "key": "section-other-settings", + "label": "Other Settings", + "link_doctype": "", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "subscription-settings", + "label": "Subscription Settings", + "link_doctype": "DocType", + "link_to": "Subscription Settings", + "parent_key": "section-other-settings", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "item-variant-settings", + "label": "Item Variant Settings", + "link_doctype": "DocType", + "link_to": "Item Variant Settings", + "parent_key": "section-other-settings", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "delivery-settings", + "label": "Delivery Settings", + "link_doctype": "DocType", + "link_to": "Delivery Settings", + "parent_key": "section-other-settings", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "currency-exchange-settings", + "label": "Currency Exchange Settings", + "link_doctype": "DocType", + "link_to": "Currency Exchange Settings", + "parent_key": "section-other-settings", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "appointment-booking-settings", + "label": "Appointment Booking Settings", + "link_doctype": "DocType", + "link_to": "Appointment Booking Settings", + "parent_key": "section-other-settings", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "stock-reposting-settings", + "label": "Stock Reposting Settings", + "link_doctype": "DocType", + "link_to": "Stock Reposting Settings", + "parent_key": "section-other-settings", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 1, + "hidden": 0, + "item_type": "Section", + "keep_closed": 1, + "key": "section-organization", + "label": "Organization", + "link_doctype": "", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "company", + "label": "Company", + "link_doctype": "DocType", + "link_to": "Company", + "parent_key": "section-organization", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "letter-head", + "label": "Letter Head", + "link_doctype": "DocType", + "link_to": "Letter Head", + "parent_key": "section-organization", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "department", + "label": "Department", + "link_doctype": "DocType", + "link_to": "Department", + "parent_key": "section-organization", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "branch", + "label": "Branch", + "link_doctype": "DocType", + "link_to": "Branch", + "parent_key": "section-organization", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "user", + "label": "User", + "link_doctype": "DocType", + "link_to": "User", + "parent_key": "section-organization", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "email-account", + "label": "Email Account", + "link_doctype": "DocType", + "link_to": "Email Account", + "parent_key": "section-organization", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 1, + "hidden": 0, + "item_type": "Section", + "keep_closed": 1, + "key": "section-home", + "label": "Home", + "link_doctype": "", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "item", + "label": "Item", + "link_doctype": "DocType", + "link_to": "Item", + "parent_key": "section-home", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "customer", + "label": "Customer", + "link_doctype": "DocType", + "link_to": "Customer", + "parent_key": "section-home", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "supplier", + "label": "Supplier", + "link_doctype": "DocType", + "link_to": "Supplier", + "parent_key": "section-home", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "sales-invoice", + "label": "Sales Invoice", + "link_doctype": "DocType", + "link_to": "Sales Invoice", + "parent_key": "section-home", + "switches_app": 0 + } + ], + "owner": "Administrator", + "standard": 1, + "title": "Setup", + "user": "" +} diff --git a/erpnext/sidebar/module_def_stock/module_def_stock.json b/erpnext/sidebar/module_def_stock/module_def_stock.json new file mode 100644 index 00000000000..ecf07056b2a --- /dev/null +++ b/erpnext/sidebar/module_def_stock/module_def_stock.json @@ -0,0 +1,461 @@ +{ + "app": "erpnext", + "creation": "2026-09-02 22:15:00.000000", + "docstatus": 0, + "doctype": "Sidebar", + "idx": 0, + "items": [], + "link_doctype": "Module Def", + "link_to": "Stock", + "modified": "2026-09-02 22:15:00.000000", + "modified_by": "Administrator", + "name": "module_def_stock", + "navigation_items": [ + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "stock-entry", + "label": "Stock Entry", + "link_doctype": "DocType", + "link_to": "Stock Entry", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "purchase-receipt", + "label": "Purchase Receipt", + "link_doctype": "DocType", + "link_to": "Purchase Receipt", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "delivery-note", + "label": "Delivery Note", + "link_doctype": "DocType", + "link_to": "Delivery Note", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "material-request", + "label": "Material Request", + "link_doctype": "DocType", + "link_to": "Material Request", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "pick-list", + "label": "Pick List", + "link_doctype": "DocType", + "link_to": "Pick List", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 1, + "hidden": 0, + "item_type": "Section", + "keep_closed": 1, + "key": "section-tools", + "label": "Tools", + "link_doctype": "", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "stock-reconciliation", + "label": "Stock Reconciliation", + "link_doctype": "DocType", + "link_to": "Stock Reconciliation", + "parent_key": "section-tools", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "landed-cost-voucher", + "label": "Landed Cost Voucher", + "link_doctype": "DocType", + "link_to": "Landed Cost Voucher", + "parent_key": "section-tools", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "repost-item-valuation", + "label": "Repost Item Valuation", + "link_doctype": "DocType", + "link_to": "Repost Item Valuation", + "parent_key": "section-tools", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "packing-slip", + "label": "Packing Slip", + "link_doctype": "DocType", + "link_to": "Packing Slip", + "parent_key": "section-tools", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "quality-inspection", + "label": "Quality Inspection", + "link_doctype": "DocType", + "link_to": "Quality Inspection", + "parent_key": "section-tools", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 1, + "hidden": 0, + "item_type": "Section", + "keep_closed": 1, + "key": "section-setup", + "label": "Setup", + "link_doctype": "", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "item", + "label": "Item", + "link_doctype": "DocType", + "link_to": "Item", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "item-group", + "label": "Item Group", + "link_doctype": "DocType", + "link_to": "Item Group", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "item-attribute", + "label": "Item Attribute", + "link_doctype": "DocType", + "link_to": "Item Attribute", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "brand", + "label": "Brand", + "link_doctype": "DocType", + "link_to": "Brand", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "warehouse", + "label": "Warehouse", + "link_doctype": "DocType", + "link_to": "Warehouse", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "uom", + "label": "Unit of Measure (UOM)", + "link_doctype": "DocType", + "link_to": "UOM", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "uom-conversion-factor", + "label": "UOM Conversion Factor", + "link_doctype": "DocType", + "link_to": "UOM Conversion Factor", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "serial-no", + "label": "Serial No", + "link_doctype": "DocType", + "link_to": "Serial No", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "batch", + "label": "Batch No", + "link_doctype": "DocType", + "link_to": "Batch", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "serial-and-batch-bundle", + "label": "Serial and Batch Bundle", + "link_doctype": "DocType", + "link_to": "Serial and Batch Bundle", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "item-standard-cost", + "label": "Item Standard Cost", + "link_doctype": "DocType", + "link_to": "Item Standard Cost", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "inventory-dimension", + "label": "Inventory Dimension", + "link_doctype": "DocType", + "link_to": "Inventory Dimension", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "shipping-rule", + "label": "Shipping Rule", + "link_doctype": "DocType", + "link_to": "Shipping Rule", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "item-alternative", + "label": "Item Alternative", + "link_doctype": "DocType", + "link_to": "Item Alternative", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "quality-inspection-template", + "label": "Quality Inspection Template", + "link_doctype": "DocType", + "link_to": "Quality Inspection Template", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "delivery-trip", + "label": "Delivery Trip", + "link_doctype": "DocType", + "link_to": "Delivery Trip", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 1, + "hidden": 0, + "item_type": "Section", + "keep_closed": 1, + "key": "section-reports", + "label": "Reports", + "link_doctype": "", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "quick-stock-balance", + "label": "Quick Stock Balance", + "link_doctype": "DocType", + "link_to": "Quick Stock Balance", + "parent_key": "section-reports", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 1, + "hidden": 0, + "item_type": "Section", + "keep_closed": 1, + "key": "section-settings", + "label": "Settings", + "link_doctype": "", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "stock-settings", + "label": "Stock Settings", + "link_doctype": "DocType", + "link_to": "Stock Settings", + "parent_key": "section-settings", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "item-variant-settings", + "label": "Item Variant Settings", + "link_doctype": "DocType", + "link_to": "Item Variant Settings", + "parent_key": "section-settings", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "stock-reposting-settings", + "label": "Stock Reposting Settings", + "link_doctype": "DocType", + "link_to": "Stock Reposting Settings", + "parent_key": "section-settings", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "delivery-settings", + "label": "Delivery Settings", + "link_doctype": "DocType", + "link_to": "Delivery Settings", + "parent_key": "section-settings", + "switches_app": 0 + } + ], + "owner": "Administrator", + "standard": 1, + "title": "Stock", + "user": "" +} diff --git a/erpnext/sidebar/module_def_subcontracting/module_def_subcontracting.json b/erpnext/sidebar/module_def_subcontracting/module_def_subcontracting.json new file mode 100644 index 00000000000..3ec7684852a --- /dev/null +++ b/erpnext/sidebar/module_def_subcontracting/module_def_subcontracting.json @@ -0,0 +1,67 @@ +{ + "app": "erpnext", + "creation": "2026-09-02 22:15:00.000000", + "docstatus": 0, + "doctype": "Sidebar", + "idx": 0, + "items": [], + "link_doctype": "Module Def", + "link_to": "Subcontracting", + "modified": "2026-09-02 22:15:00.000000", + "modified_by": "Administrator", + "name": "module_def_subcontracting", + "navigation_items": [ + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "subcontracting-order", + "label": "Subcontracting Order", + "link_doctype": "DocType", + "link_to": "Subcontracting Order", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "subcontracting-receipt", + "label": "Subcontracting Receipt", + "link_doctype": "DocType", + "link_to": "Subcontracting Receipt", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "subcontracting-bom", + "label": "Subcontracting BOM", + "link_doctype": "DocType", + "link_to": "Subcontracting BOM", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "subcontracting-inward-order", + "label": "Subcontracting Inward Order", + "link_doctype": "DocType", + "link_to": "Subcontracting Inward Order", + "switches_app": 0 + } + ], + "owner": "Administrator", + "standard": 1, + "title": "Subcontracting", + "user": "" +} diff --git a/erpnext/sidebar/module_def_support/module_def_support.json b/erpnext/sidebar/module_def_support/module_def_support.json new file mode 100644 index 00000000000..3f7957ec7d0 --- /dev/null +++ b/erpnext/sidebar/module_def_support/module_def_support.json @@ -0,0 +1,141 @@ +{ + "app": "erpnext", + "creation": "2026-09-02 22:15:00.000000", + "docstatus": 0, + "doctype": "Sidebar", + "idx": 0, + "items": [], + "link_doctype": "Module Def", + "link_to": "Support", + "modified": "2026-09-02 22:15:00.000000", + "modified_by": "Administrator", + "name": "module_def_support", + "navigation_items": [ + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "issue", + "label": "Issue", + "link_doctype": "DocType", + "link_to": "Issue", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "maintenance-schedule", + "label": "Maintenance Schedule", + "link_doctype": "DocType", + "link_to": "Maintenance Schedule", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "maintenance-visit", + "label": "Maintenance Visit", + "link_doctype": "DocType", + "link_to": "Maintenance Visit", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "warranty-claim", + "label": "Warranty Claim", + "link_doctype": "DocType", + "link_to": "Warranty Claim", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 1, + "hidden": 0, + "item_type": "Section", + "keep_closed": 1, + "key": "section-setup", + "label": "Setup", + "link_doctype": "", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "issue-type", + "label": "Issue Type", + "link_doctype": "DocType", + "link_to": "Issue Type", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "issue-priority", + "label": "Issue Priority", + "link_doctype": "DocType", + "link_to": "Issue Priority", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "service-level-agreement", + "label": "Service Level Agreement", + "link_doctype": "DocType", + "link_to": "Service Level Agreement", + "parent_key": "section-setup", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 1, + "hidden": 0, + "item_type": "Section", + "keep_closed": 1, + "key": "section-reports", + "label": "Reports", + "link_doctype": "", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "support-settings", + "label": "Settings", + "link_doctype": "DocType", + "link_to": "Support Settings", + "parent_key": "section-reports", + "switches_app": 0 + } + ], + "owner": "Administrator", + "standard": 1, + "title": "Support", + "user": "" +} diff --git a/erpnext/sidebar/module_def_telephony/module_def_telephony.json b/erpnext/sidebar/module_def_telephony/module_def_telephony.json new file mode 100644 index 00000000000..2f2e35d665c --- /dev/null +++ b/erpnext/sidebar/module_def_telephony/module_def_telephony.json @@ -0,0 +1,67 @@ +{ + "app": "erpnext", + "creation": "2026-09-02 22:15:00.000000", + "docstatus": 0, + "doctype": "Sidebar", + "idx": 0, + "items": [], + "link_doctype": "Module Def", + "link_to": "Telephony", + "modified": "2026-09-02 22:15:00.000000", + "modified_by": "Administrator", + "name": "module_def_telephony", + "navigation_items": [ + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "incoming-call-settings", + "label": "Incoming Call Settings", + "link_doctype": "DocType", + "link_to": "Incoming Call Settings", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "voice-call-settings", + "label": "Voice Call Settings", + "link_doctype": "DocType", + "link_to": "Voice Call Settings", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "call-log", + "label": "Call Log", + "link_doctype": "DocType", + "link_to": "Call Log", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "telephony-call-type", + "label": "Telephony Call Type", + "link_doctype": "DocType", + "link_to": "Telephony Call Type", + "switches_app": 0 + } + ], + "owner": "Administrator", + "standard": 1, + "title": "Telephony", + "user": "" +} diff --git a/erpnext/sidebar/module_def_utilities/module_def_utilities.json b/erpnext/sidebar/module_def_utilities/module_def_utilities.json new file mode 100644 index 00000000000..f681fb57109 --- /dev/null +++ b/erpnext/sidebar/module_def_utilities/module_def_utilities.json @@ -0,0 +1,55 @@ +{ + "app": "erpnext", + "creation": "2026-09-02 22:15:00.000000", + "docstatus": 0, + "doctype": "Sidebar", + "idx": 0, + "items": [], + "link_doctype": "Module Def", + "link_to": "Utilities", + "modified": "2026-09-02 22:15:00.000000", + "modified_by": "Administrator", + "name": "module_def_utilities", + "navigation_items": [ + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "rename-tool", + "label": "Rename Tool", + "link_doctype": "DocType", + "link_to": "Rename Tool", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "video", + "label": "Video", + "link_doctype": "DocType", + "link_to": "Video", + "switches_app": 0 + }, + { + "added": 0, + "collapsible": 0, + "hidden": 0, + "item_type": "DocType", + "keep_closed": 0, + "key": "video-settings", + "label": "Video Settings", + "link_doctype": "DocType", + "link_to": "Video Settings", + "switches_app": 0 + } + ], + "owner": "Administrator", + "standard": 1, + "title": "Utilities", + "user": "" +} diff --git a/erpnext/tests/test_navigation.py b/erpnext/tests/test_navigation.py new file mode 100644 index 00000000000..d9208718461 --- /dev/null +++ b/erpnext/tests/test_navigation.py @@ -0,0 +1,252 @@ +# Copyright (c) 2026, Frappe Technologies Pvt. Ltd. and Contributors +# License: GNU General Public License v3. See license.txt + +"""ERPNext's shipped desk v2 navigation: one Rail record and eighteen module Sidebars. + +These are fixture tests. ERPNext ships no navigation code at all -- the rows arrive as JSON at +`bench migrate` and the framework resolves them -- so what there is to get wrong is the content +of those rows: a rail item naming a sidebar nobody ships, a row pointing at a doctype this site +does not have, or two rows claiming one key. Each of those resolves to a quietly shorter list +rather than to an error, which is why they are asserted here. + +This is the module-primary half of charter point 2 (frappe/frappe#42226): the same table, the +same resolver and the same item kinds that give CRM a doctype-primary rail, giving ERPNext one +made of modules. The rail is a `Sidebar` item per module that has an authored sidebar and a +`Module` item per module that does not. + +Every test runs as somebody other than Administrator. The permission filter short-circuits for +an administrator (`frappe/shell/navigation_filter.py`), so an Administrator suite would pass +against a rail that is not being filtered at all. +""" + +import frappe +from frappe.shell.navigation import resolve_navigation +from frappe.tests import IntegrationTestCase + +APP = "erpnext" + +# The rail, in the order it is authored -- which is the order ERPNext already curated for desk +# v1's dock, since that list is what a person using ERPNext expects to see. +RAIL = ( + "accounts", + "crm", + "buying", + "projects", + "selling", + "setup", + "manufacturing", + "stock", + "support", + "utilities", + "assets", + "maintenance", + "regional", + "erpnext-integrations", + "quality-management", + "communication", + "telephony", + "bulk-transaction", + "subcontracting", + "edi", +) + +# The two modules whose authored sidebar would hold one row or none, so none is shipped. Their +# rail item is a `Module`, which lands on the module page -- a list derived from the module's +# contents, which is a different list on purpose (frappe/frappe#42357). +# +# `Portal` is on desk v1's dock and is deliberately not here: it holds no doctypes at all, so +# it has neither a sidebar to open nor a module page to land on, and the renderer would find no +# address and skip the row. +INDEPENDENT = ("erpnext-integrations", "communication") + +# Every other module ships a sidebar, addressed at its `Module Def`. The scrubbed address is +# both the standard record's name and the key boot files it under, and it is the string the +# rail item of type `Sidebar` carries in `link_to`. +LINKED = tuple(key for key in RAIL if key not in INDEPENDENT) + + +def rail_of(user: str) -> list[dict]: + frappe.set_user(user) + try: + return resolve_navigation(APP)["rail"] + finally: + frappe.set_user("Administrator") + + +class TestERPNextNavigation(IntegrationTestCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.user = make_erpnext_user("erpnext.navigation.test@example.com") + + def setUp(self): + frappe.set_user(self.user) + self.addCleanup(frappe.set_user, "Administrator") + # `IntegrationTestCase` rolls back once per CLASS, so a `Block Module` row written by one + # test is still there for the next -- and three tests below block the same module, so the + # one that asserts what the rail looks like *before* the block would depend on running + # first. Cleared here rather than in a cleanup, so it holds however the tests are ordered. + self.unblock() + self.addCleanup(self.unblock) + + def unblock(self): + """Give every module back, and clear the cache the block is read through.""" + frappe.set_user("Administrator") + doc = frappe.get_doc("User", self.user) + if doc.block_modules: + doc.set("block_modules", []) + doc.save(ignore_permissions=True) + frappe.clear_cache(user=self.user) + frappe.set_user(self.user) + + def test_the_rail_is_the_twenty_authored_items(self): + """As Administrator, who is filtered by nothing, so this is the shipped list itself.""" + frappe.set_user("Administrator") + + self.assertEqual(tuple(item["key"] for item in resolve_navigation(APP)["rail"]), RAIL) + + def test_a_linked_item_names_a_sidebar_this_app_ships(self): + """A typo in `link_to` costs the item its panel and nothing else, so nothing reports it. + + `Sidebar` declares the `Derived From Children` permission rule, so an item naming an + address that resolves to no rows is dropped by the server's own cascade -- silently, and + correctly, because that is also what an emptied sidebar has to do. + """ + frappe.set_user("Administrator") + navigation = resolve_navigation(APP) + linked = [item for item in navigation["rail"] if item["item_type"] == "Sidebar"] + + self.assertEqual(tuple(item["key"] for item in linked), LINKED) + for item in linked: + self.assertIn(item["link_to"], navigation["sidebars"]) + + def test_an_independent_item_is_a_module_and_opens_nothing(self): + """Charter point 1 makes independent a first-class state, and needs no field to say so: + a `Module` item lands on the module page and has no sidebar to open.""" + frappe.set_user("Administrator") + navigation = resolve_navigation(APP) + rail = {item["key"]: item for item in navigation["rail"]} + + for key in INDEPENDENT: + self.assertEqual(rail[key]["item_type"], "Module") + self.assertNotIn(frappe.scrub(f"Module Def {rail[key]['link_to']}"), navigation["sidebars"]) + + def test_every_sidebar_is_addressed_at_a_module_that_exists(self): + """The address is the module, not the desk v1 sidebar the rows were curated for -- and + those two differ: v1's `Quality` sidebar belongs to the `Quality Management` module.""" + for name in frappe.get_all( + "Sidebar", filters={"app": APP, "standard": 1, "link_doctype": "Module Def"}, pluck="name" + ): + module = frappe.db.get_value("Sidebar", name, "link_to") + self.assertTrue(frappe.db.exists("Module Def", module), name) + self.assertEqual(name, frappe.scrub(f"Module Def {module}")) + + def test_every_destination_is_a_doctype_this_site_has(self): + """A row naming a doctype that is gone is dropped by the filter, not refused at import.""" + frappe.set_user("Administrator") + navigation = resolve_navigation(APP) + rows = [*navigation["rail"], *(row for rows in navigation["sidebars"].values() for row in rows)] + + for row in rows: + if row["item_type"] == "DocType": + self.assertTrue(frappe.db.exists("DocType", row["link_to"]), row["key"]) + + def test_keys_are_unique_within_each_container(self): + """Every site and user edit is filed against a key, so two rows sharing one collide.""" + frappe.set_user("Administrator") + navigation = resolve_navigation(APP) + + for rows in (navigation["rail"], *navigation["sidebars"].values()): + keys = [row["key"] for row in rows] + self.assertEqual(len(keys), len(set(keys))) + + def test_no_section_is_shipped_over_nothing(self): + """A heading with no rows under it is dropped by the cascade at read time, so shipping + one would mean shipping a row that can never render. They are left out at authoring.""" + frappe.set_user("Administrator") + navigation = resolve_navigation(APP) + + for rows in navigation["sidebars"].values(): + parents = {row.get("parent_key") for row in rows} + for row in rows: + if row["item_type"] == "Section": + self.assertIn(row["key"], parents, row["key"]) + + def test_a_real_user_sees_fewer_modules_than_administrator(self): + """The filter is doing something, which is the one thing an Administrator suite cannot + show. An `Accounts User` has no reason to be offered `Regional` or `Telephony`.""" + frappe.set_user("Administrator") + everything = len(resolve_navigation(APP)["rail"]) + + self.assertLess(len(rail_of(self.user)), everything) + + def test_a_blocked_module_ships_nothing(self): + """The veto on a module-primary rail, which is what this rail is here to exercise. + + `block_modules` gates module-derived items, and a module-primary rail reaches a module + through a `Sidebar` item holding `DocType` rows -- so before frappe/frappe#42423 blocking + Accounts left all 73 rows and the rail item standing. The block now names the sidebar's + *address*, and the rail item goes with it through the cascade it already ran under. + """ + before = [item["key"] for item in rail_of(self.user)] + self.assertIn("accounts", before) + + block("Accounts", self.user) + after = rail_of(self.user) + + self.assertEqual([item["key"] for item in after], [key for key in before if key != "accounts"]) + + def test_a_blocked_module_takes_its_sidebar_with_it(self): + block("Accounts", self.user) + frappe.set_user(self.user) + + self.assertNotIn("module_def_accounts", resolve_navigation(APP)["sidebars"]) + + def test_a_doctype_in_a_blocked_module_is_still_reachable(self): + """Hiding a module hides the way to a document, never the document. `Sales Invoice` is + an Accounts doctype and ERPNext's Selling sidebar links it, which is one of the 101 rows + that point outside their own module.""" + block("Accounts", self.user) + frappe.set_user(self.user) + sidebars = resolve_navigation(APP)["sidebars"] + + self.assertTrue( + any( + row.get("link_to") == "Sales Invoice" + for address, rows in sidebars.items() + if address != "module_def_accounts" + for row in rows + ) + ) + + +def block(module: str, user: str): + """Withdraw a module from one person, the way an administrator does on the User form. + + `tabBlock Module` holds no rows on either bench site, so the veto cannot be observed without + seeding one -- which is why it had never been watched on a real rail. + """ + frappe.set_user("Administrator") + doc = frappe.get_doc("User", user) + doc.append("block_modules", {"module": module}) + doc.save(ignore_permissions=True) + frappe.clear_cache(user=user) + frappe.set_user(user) + + +def make_erpnext_user(email: str) -> str: + """Somebody who works in a few of ERPNext's modules and not in the rest of them.""" + if frappe.db.exists("User", email): + return email + + user = frappe.get_doc( + { + "doctype": "User", + "email": email, + "first_name": "ERPNext Navigation", + "user_type": "System User", + "roles": [{"role": "Accounts User"}, {"role": "Stock User"}, {"role": "Sales User"}], + } + ).insert(ignore_permissions=True) + + return user.name From 8b93d2582482035745cfdfac1b02882d3f6ac1fe Mon Sep 17 00:00:00 2001 From: shariquerik Date: Wed, 2 Sep 2026 19:32:06 +0530 Subject: [PATCH 2/2] test: assert the shipped rows, not what the resolver made of them Greptile P2, and right: the fixture checks read `resolve_navigation`, which has already dropped a row naming a missing doctype, a heading over nothing and a linked item whose sidebar emptied. Against that output they were asserting that the resolver works, which is frappe's test. They now read the standard `Rail` and `Sidebar` rows as authored. Checked that each can fail: an orphan `parent_key` and an empty section both insert happily. A missing doctype does not -- `link_to` is a Dynamic Link and `_validate_links` refuses the row at import -- so that test now says what it is actually for, a doctype removed after the rows were imported. Adds one: every `parent_key` names a section beside it. An orphan is promoted to the top level rather than dropped, so it loses its nesting in silence. Co-Authored-By: Claude Opus 5 (1M context) --- erpnext/tests/test_navigation.py | 100 +++++++++++++++++++++---------- 1 file changed, 69 insertions(+), 31 deletions(-) diff --git a/erpnext/tests/test_navigation.py b/erpnext/tests/test_navigation.py index d9208718461..0d87a2e2ce0 100644 --- a/erpnext/tests/test_navigation.py +++ b/erpnext/tests/test_navigation.py @@ -108,17 +108,18 @@ class TestERPNextNavigation(IntegrationTestCase): def test_a_linked_item_names_a_sidebar_this_app_ships(self): """A typo in `link_to` costs the item its panel and nothing else, so nothing reports it. - `Sidebar` declares the `Derived From Children` permission rule, so an item naming an - address that resolves to no rows is dropped by the server's own cascade -- silently, and - correctly, because that is also what an emptied sidebar has to do. + Read off the **shipped rows**, not the resolved payload. `Sidebar` declares the + `Derived From Children` permission rule, so an item naming an address that resolves to no + rows is dropped by the server's own cascade -- silently, and correctly, because that is + also what an emptied sidebar has to do. Asserting against the resolved list would + therefore be asserting that the cascade works, which is frappe's test and not this one. """ - frappe.set_user("Administrator") - navigation = resolve_navigation(APP) - linked = [item for item in navigation["rail"] if item["item_type"] == "Sidebar"] + linked = [row for row in shipped("Rail", "erpnext") if row.item_type == "Sidebar"] + addresses = set(frappe.get_all("Sidebar", filters={"app": APP, "standard": 1}, pluck="name")) - self.assertEqual(tuple(item["key"] for item in linked), LINKED) - for item in linked: - self.assertIn(item["link_to"], navigation["sidebars"]) + self.assertEqual(tuple(row.key for row in linked), LINKED) + for row in linked: + self.assertIn(row.link_to, addresses, row.key) def test_an_independent_item_is_a_module_and_opens_nothing(self): """Charter point 1 makes independent a first-class state, and needs no field to say so: @@ -142,35 +143,45 @@ class TestERPNextNavigation(IntegrationTestCase): self.assertEqual(name, frappe.scrub(f"Module Def {module}")) def test_every_destination_is_a_doctype_this_site_has(self): - """A row naming a doctype that is gone is dropped by the filter, not refused at import.""" - frappe.set_user("Administrator") - navigation = resolve_navigation(APP) - rows = [*navigation["rail"], *(row for rows in navigation["sidebars"].values() for row in rows)] + """Read off the shipped rows rather than the resolved payload, which has already dropped + any row it could not place. - for row in rows: - if row["item_type"] == "DocType": - self.assertTrue(frappe.db.exists("DocType", row["link_to"]), row["key"]) + A typo cannot get this far: `link_to` is a Dynamic Link, so `_validate_links` refuses the + row at import with `Could not find Row #N: Link To` -- checked, not assumed. What is left + for this to catch is a doctype removed *after* the rows were imported, which arrives as a + quietly shorter sidebar and nothing else. + """ + for container, address in every_container(): + for row in shipped(container, address): + if row.item_type == "DocType": + self.assertTrue(frappe.db.exists("DocType", row.link_to), f"{address}/{row.key}") def test_keys_are_unique_within_each_container(self): """Every site and user edit is filed against a key, so two rows sharing one collide.""" - frappe.set_user("Administrator") - navigation = resolve_navigation(APP) - - for rows in (navigation["rail"], *navigation["sidebars"].values()): - keys = [row["key"] for row in rows] - self.assertEqual(len(keys), len(set(keys))) + for container, address in every_container(): + keys = [row.key for row in shipped(container, address)] + self.assertEqual(len(keys), len(set(keys)), address) def test_no_section_is_shipped_over_nothing(self): - """A heading with no rows under it is dropped by the cascade at read time, so shipping - one would mean shipping a row that can never render. They are left out at authoring.""" - frappe.set_user("Administrator") - navigation = resolve_navigation(APP) - - for rows in navigation["sidebars"].values(): - parents = {row.get("parent_key") for row in rows} + """A heading with no rows under it is dropped by the cascade at read time, so shipping one + would mean shipping a row that can never render. Left out at authoring instead -- and read + here off the shipped rows, since the cascade would have hidden it either way.""" + for container, address in every_container(): + rows = shipped(container, address) + parents = {row.parent_key for row in rows} for row in rows: - if row["item_type"] == "Section": - self.assertIn(row["key"], parents, row["key"]) + if row.item_type == "Section": + self.assertIn(row.key, parents, f"{address}/{row.key}") + + def test_every_parent_key_names_a_section_beside_it(self): + """A row filed under a heading that is not there loses its nesting silently: the resolver + promotes an orphan to the top level rather than dropping it.""" + for container, address in every_container(): + rows = shipped(container, address) + sections = {row.key for row in rows if row.item_type == "Section"} + for row in rows: + if row.parent_key: + self.assertIn(row.parent_key, sections, f"{address}/{row.key}") def test_a_real_user_sees_fewer_modules_than_administrator(self): """The filter is doing something, which is the one thing an Administrator suite cannot @@ -220,6 +231,33 @@ class TestERPNextNavigation(IntegrationTestCase): ) +def every_container() -> list[tuple[str, str]]: + """Every standard record ERPNext ships, as `(doctype, name)`.""" + return [("Rail", "erpnext")] + [ + ("Sidebar", name) + for name in frappe.get_all("Sidebar", filters={"app": APP, "standard": 1}, pluck="name") + ] + + +def shipped(container: str, address: str) -> list: + """The rows as authored, before the resolver has filtered or cascaded anything away. + + The distinction matters for every fixture assertion below: `resolve_navigation` drops a row + naming a doctype that is gone, a heading over nothing and a linked item whose sidebar + emptied. Read against its output, a test for those is asserting that the resolver works. + """ + return frappe.get_all( + "Navigation Item", + filters={ + "parenttype": container, + "parent": address, + "parentfield": "items" if container == "Rail" else "navigation_items", + }, + fields=["key", "parent_key", "item_type", "link_doctype", "link_to"], + order_by="idx asc", + ) + + def block(module: str, user: str): """Withdraw a module from one person, the way an administrator does on the User form.