From b649c50eccc3280168a7a69523d1aac829f4f71a Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Wed, 17 Jan 2024 20:52:16 +0530 Subject: [PATCH 01/15] fix: duplicate name error while making variant (cherry picked from commit d7e6b83e6432a6c46ce6e374252d25c0438c2205) --- erpnext/controllers/item_variant.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/erpnext/controllers/item_variant.py b/erpnext/controllers/item_variant.py index ea7fb23cb6..1eee9eaa9d 100644 --- a/erpnext/controllers/item_variant.py +++ b/erpnext/controllers/item_variant.py @@ -56,7 +56,11 @@ def make_variant_based_on_manufacturer(template, manufacturer, manufacturer_part copy_attributes_to_variant(template, variant) - variant.item_code = append_number_if_name_exists("Item", template.name) + variant_name = f"{template.name} - {manufacturer}" + if manufacturer_part_no: + variant_name += f" - {manufacturer_part_no}" + + variant.item_code = append_number_if_name_exists("Item", variant_name) variant.flags.ignore_mandatory = True variant.save() From 74613c7fe822f06448ea8595a048390b58c8f5bb Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Thu, 18 Jan 2024 14:33:10 +0530 Subject: [PATCH 02/15] fix: set unallocated amount after base tax (cherry picked from commit e9bc63aacf20dd83cb7e15494bb8f2f025491991) --- erpnext/accounts/doctype/payment_entry/payment_entry.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js index 9402e3da09..2954d2fc3f 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.js +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js @@ -933,7 +933,7 @@ frappe.ui.form.on('Payment Entry', { if(frm.doc.payment_type == "Receive" && frm.doc.base_total_allocated_amount < frm.doc.base_received_amount + total_deductions && frm.doc.total_allocated_amount < frm.doc.paid_amount + (total_deductions / frm.doc.source_exchange_rate)) { - unallocated_amount = (frm.doc.base_received_amount + total_deductions + flt(frm.doc.base_total_taxes_and_charges) + unallocated_amount = (frm.doc.base_received_amount + total_deductions - flt(frm.doc.base_total_taxes_and_charges) - frm.doc.base_total_allocated_amount) / frm.doc.source_exchange_rate; } else if (frm.doc.payment_type == "Pay" && frm.doc.base_total_allocated_amount < frm.doc.base_paid_amount - total_deductions From 86f3f62e009ff1aae0979c8f084ad55046b06ae2 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Thu, 18 Jan 2024 15:05:19 +0530 Subject: [PATCH 03/15] fix: linting issue (cherry picked from commit 99b94af49ffd34bccb76b73c2f06187540444a44) --- .../gross_and_net_profit_report/gross_and_net_profit_report.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/report/gross_and_net_profit_report/gross_and_net_profit_report.py b/erpnext/accounts/report/gross_and_net_profit_report/gross_and_net_profit_report.py index f0ca405401..5ccd4f0f16 100644 --- a/erpnext/accounts/report/gross_and_net_profit_report/gross_and_net_profit_report.py +++ b/erpnext/accounts/report/gross_and_net_profit_report/gross_and_net_profit_report.py @@ -134,7 +134,7 @@ def get_revenue(data, period_list, include_in_gross=1): def remove_parent_with_no_child(data): data_to_be_removed = False - for parent in data: + for parent in list(data): if "is_group" in parent and parent.get("is_group") == 1: have_child = False for child in data: From 00a3ee313bd048cda773422b3b7c5283cc22cf3d Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Fri, 19 Jan 2024 12:40:25 +0530 Subject: [PATCH 04/15] refactor(UX): Accounts workspace cleanup (backport #39232) (#39456) * refactor(UX): Accounts workspace cleanup (#39232) * refactor(UX): Accounts workspace cleanup * chore: move asset workspace outside accounting * fix: remove redundant links from parent workspace * chore: change icons for payable & receivable workspaces * chore: remove redundant links from subworkspaces (cherry picked from commit 35067282cfeaf88a1e4251e3725f7557d3b2d356) * chore: fix conflicts --------- Co-authored-by: Rucha Mahabal --- .../workspace/accounting/accounting.json | 889 ++++-------------- .../financial_reports/financial_reports.json | 277 ++++++ .../accounts/workspace/payables/payables.json | 204 ++++ .../workspace/receivables/receivables.json | 254 +++++ erpnext/assets/workspace/assets/assets.json | 6 +- 5 files changed, 945 insertions(+), 685 deletions(-) create mode 100644 erpnext/accounts/workspace/financial_reports/financial_reports.json create mode 100644 erpnext/accounts/workspace/payables/payables.json create mode 100644 erpnext/accounts/workspace/receivables/receivables.json diff --git a/erpnext/accounts/workspace/accounting/accounting.json b/erpnext/accounts/workspace/accounting/accounting.json index dfdae1dec6..45ab92e2c5 100644 --- a/erpnext/accounts/workspace/accounting/accounting.json +++ b/erpnext/accounts/workspace/accounting/accounting.json @@ -5,7 +5,7 @@ "label": "Profit and Loss" } ], - "content": "[{\"id\":\"MmUf9abwxg\",\"type\":\"onboarding\",\"data\":{\"onboarding_name\":\"Accounts\",\"col\":12}},{\"id\":\"VVvJ1lUcfc\",\"type\":\"number_card\",\"data\":{\"number_card_name\":\"Total Outgoing Bills\",\"col\":3}},{\"id\":\"Vlj2FZtlHV\",\"type\":\"number_card\",\"data\":{\"number_card_name\":\"Total Incoming Bills\",\"col\":3}},{\"id\":\"VVVjQVAhPf\",\"type\":\"number_card\",\"data\":{\"number_card_name\":\"Total Incoming Payment\",\"col\":3}},{\"id\":\"DySNdlysIW\",\"type\":\"number_card\",\"data\":{\"number_card_name\":\"Total Outgoing Payment\",\"col\":3}},{\"id\":\"i0EtSjDAXq\",\"type\":\"chart\",\"data\":{\"chart_name\":\"Profit and Loss\",\"col\":12}},{\"id\":\"X78jcbq1u3\",\"type\":\"spacer\",\"data\":{\"col\":12}},{\"id\":\"vikWSkNm6_\",\"type\":\"header\",\"data\":{\"text\":\"Your Shortcuts\",\"col\":12}},{\"id\":\"pMywM0nhlj\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Chart of Accounts\",\"col\":3}},{\"id\":\"_pRdD6kqUG\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Sales Invoice\",\"col\":3}},{\"id\":\"G984SgVRJN\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Purchase Invoice\",\"col\":3}},{\"id\":\"1ArNvt9qhz\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Journal Entry\",\"col\":3}},{\"id\":\"F9f4I1viNr\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Payment Entry\",\"col\":3}},{\"id\":\"4IBBOIxfqW\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Accounts Receivable\",\"col\":3}},{\"id\":\"El2anpPaFY\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"General Ledger\",\"col\":3}},{\"id\":\"1nwcM9upJo\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Trial Balance\",\"col\":3}},{\"id\":\"OF9WOi1Ppc\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Dashboard\",\"col\":3}},{\"id\":\"iAwpe-Chra\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Learn Accounting\",\"col\":3}},{\"id\":\"B7-uxs8tkU\",\"type\":\"spacer\",\"data\":{\"col\":12}},{\"id\":\"tHb3yxthkR\",\"type\":\"header\",\"data\":{\"text\":\"Reports & Masters\",\"col\":12}},{\"id\":\"DnNtsmxpty\",\"type\":\"card\",\"data\":{\"card_name\":\"Accounting Masters\",\"col\":4}},{\"id\":\"nKKr6fjgjb\",\"type\":\"card\",\"data\":{\"card_name\":\"General Ledger\",\"col\":4}},{\"id\":\"xOHTyD8b5l\",\"type\":\"card\",\"data\":{\"card_name\":\"Accounts Receivable\",\"col\":4}},{\"id\":\"_Cb7C8XdJJ\",\"type\":\"card\",\"data\":{\"card_name\":\"Accounts Payable\",\"col\":4}},{\"id\":\"p7NY6MHe2Y\",\"type\":\"card\",\"data\":{\"card_name\":\"Financial Statements\",\"col\":4}},{\"id\":\"KlqilF5R_V\",\"type\":\"card\",\"data\":{\"card_name\":\"Taxes\",\"col\":4}},{\"id\":\"jTUy8LB0uw\",\"type\":\"card\",\"data\":{\"card_name\":\"Cost Center and Budgeting\",\"col\":4}},{\"id\":\"Wn2lhs7WLn\",\"type\":\"card\",\"data\":{\"card_name\":\"Multi Currency\",\"col\":4}},{\"id\":\"PAQMqqNkBM\",\"type\":\"card\",\"data\":{\"card_name\":\"Bank Statement\",\"col\":4}},{\"id\":\"Q_hBCnSeJY\",\"type\":\"card\",\"data\":{\"card_name\":\"Reports\",\"col\":4}},{\"id\":\"3AK1Zf0oew\",\"type\":\"card\",\"data\":{\"card_name\":\"Profitability\",\"col\":4}},{\"id\":\"kxhoaiqdLq\",\"type\":\"card\",\"data\":{\"card_name\":\"Opening and Closing\",\"col\":4}},{\"id\":\"q0MAlU2j_Z\",\"type\":\"card\",\"data\":{\"card_name\":\"Subscription Management\",\"col\":4}},{\"id\":\"ptm7T6Hwu-\",\"type\":\"card\",\"data\":{\"card_name\":\"Share Management\",\"col\":4}},{\"id\":\"OX7lZHbiTr\",\"type\":\"card\",\"data\":{\"card_name\":\"Settings\",\"col\":4}}]", + "content": "[{\"id\":\"MmUf9abwxg\",\"type\":\"onboarding\",\"data\":{\"onboarding_name\":\"Accounts\",\"col\":12}},{\"id\":\"nDhfcJYbKH\",\"type\":\"chart\",\"data\":{\"chart_name\":\"Profit and Loss\",\"col\":12}},{\"id\":\"VVvJ1lUcfc\",\"type\":\"number_card\",\"data\":{\"number_card_name\":\"Total Outgoing Bills\",\"col\":3}},{\"id\":\"Vlj2FZtlHV\",\"type\":\"number_card\",\"data\":{\"number_card_name\":\"Total Incoming Bills\",\"col\":3}},{\"id\":\"VVVjQVAhPf\",\"type\":\"number_card\",\"data\":{\"number_card_name\":\"Total Incoming Payment\",\"col\":3}},{\"id\":\"DySNdlysIW\",\"type\":\"number_card\",\"data\":{\"number_card_name\":\"Total Outgoing Payment\",\"col\":3}},{\"id\":\"9k1rDm2C0l\",\"type\":\"spacer\",\"data\":{\"col\":12}},{\"id\":\"vikWSkNm6_\",\"type\":\"header\",\"data\":{\"text\":\"Shortcuts\",\"col\":12}},{\"id\":\"pMywM0nhlj\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Chart of Accounts\",\"col\":3}},{\"id\":\"_pRdD6kqUG\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Sales Invoice\",\"col\":3}},{\"id\":\"G984SgVRJN\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Purchase Invoice\",\"col\":3}},{\"id\":\"1ArNvt9qhz\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Journal Entry\",\"col\":3}},{\"id\":\"F9f4I1viNr\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Payment Entry\",\"col\":3}},{\"id\":\"4IBBOIxfqW\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Accounts Receivable\",\"col\":3}},{\"id\":\"El2anpPaFY\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"General Ledger\",\"col\":3}},{\"id\":\"1nwcM9upJo\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Trial Balance\",\"col\":3}},{\"id\":\"OF9WOi1Ppc\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Dashboard\",\"col\":3}},{\"id\":\"iAwpe-Chra\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Learn Accounting\",\"col\":3}},{\"id\":\"B7-uxs8tkU\",\"type\":\"spacer\",\"data\":{\"col\":12}},{\"id\":\"tHb3yxthkR\",\"type\":\"header\",\"data\":{\"text\":\"Reports & Masters\",\"col\":12}},{\"id\":\"DnNtsmxpty\",\"type\":\"card\",\"data\":{\"card_name\":\"Accounting Masters\",\"col\":4}},{\"id\":\"nKKr6fjgjb\",\"type\":\"card\",\"data\":{\"card_name\":\"Payments\",\"col\":4}},{\"id\":\"KlqilF5R_V\",\"type\":\"card\",\"data\":{\"card_name\":\"Tax Masters\",\"col\":4}},{\"id\":\"jTUy8LB0uw\",\"type\":\"card\",\"data\":{\"card_name\":\"Cost Center and Budgeting\",\"col\":4}},{\"id\":\"Wn2lhs7WLn\",\"type\":\"card\",\"data\":{\"card_name\":\"Multi Currency\",\"col\":4}},{\"id\":\"PAQMqqNkBM\",\"type\":\"card\",\"data\":{\"card_name\":\"Banking\",\"col\":4}},{\"id\":\"kxhoaiqdLq\",\"type\":\"card\",\"data\":{\"card_name\":\"Opening and Closing\",\"col\":4}},{\"id\":\"q0MAlU2j_Z\",\"type\":\"card\",\"data\":{\"card_name\":\"Subscription Management\",\"col\":4}},{\"id\":\"ptm7T6Hwu-\",\"type\":\"card\",\"data\":{\"card_name\":\"Share Management\",\"col\":4}}]", "creation": "2020-03-02 15:41:59.515192", "custom_blocks": [], "docstatus": 0, @@ -14,562 +14,10 @@ "hide_custom": 0, "icon": "accounting", "idx": 0, + "indicator_color": "", "is_hidden": 0, "label": "Accounting", "links": [ - { - "hidden": 0, - "is_query_report": 0, - "label": "Accounting Masters", - "link_count": 0, - "onboard": 0, - "type": "Card Break" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Company", - "link_count": 0, - "link_to": "Company", - "link_type": "DocType", - "onboard": 1, - "type": "Link" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Chart of Accounts", - "link_count": 0, - "link_to": "Account", - "link_type": "DocType", - "onboard": 1, - "type": "Link" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Accounts Settings", - "link_count": 0, - "link_to": "Accounts Settings", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Fiscal Year", - "link_count": 0, - "link_to": "Fiscal Year", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Accounting Dimension", - "link_count": 0, - "link_to": "Accounting Dimension", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Finance Book", - "link_count": 0, - "link_to": "Finance Book", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Accounting Period", - "link_count": 0, - "link_to": "Accounting Period", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Payment Term", - "link_count": 0, - "link_to": "Payment Term", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "hidden": 0, - "is_query_report": 0, - "label": "General Ledger", - "link_count": 0, - "onboard": 0, - "type": "Card Break" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Journal Entry", - "link_count": 0, - "link_to": "Journal Entry", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Journal Entry Template", - "link_count": 0, - "link_to": "Journal Entry Template", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "GL Entry", - "hidden": 0, - "is_query_report": 1, - "label": "General Ledger", - "link_count": 0, - "link_to": "General Ledger", - "link_type": "Report", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "Sales Invoice", - "hidden": 0, - "is_query_report": 1, - "label": "Customer Ledger Summary", - "link_count": 0, - "link_to": "Customer Ledger Summary", - "link_type": "Report", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "Sales Invoice", - "hidden": 0, - "is_query_report": 1, - "label": "Supplier Ledger Summary", - "link_count": 0, - "link_to": "Supplier Ledger Summary", - "link_type": "Report", - "onboard": 0, - "type": "Link" - }, - { - "hidden": 0, - "is_query_report": 0, - "label": "Accounts Receivable", - "link_count": 0, - "onboard": 0, - "type": "Card Break" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Sales Invoice", - "link_count": 0, - "link_to": "Sales Invoice", - "link_type": "DocType", - "onboard": 1, - "type": "Link" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Customer", - "link_count": 0, - "link_to": "Customer", - "link_type": "DocType", - "onboard": 1, - "type": "Link" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Payment Entry", - "link_count": 0, - "link_to": "Payment Entry", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Payment Request", - "link_count": 0, - "link_to": "Payment Request", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "hidden": 0, - "is_query_report": 0, - "label": "Payment Reconciliation", - "link_count": 0, - "link_to": "Payment Reconciliation", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "Sales Invoice", - "hidden": 0, - "is_query_report": 1, - "label": "Accounts Receivable", - "link_count": 0, - "link_to": "Accounts Receivable", - "link_type": "Report", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "Sales Invoice", - "hidden": 0, - "is_query_report": 1, - "label": "Accounts Receivable Summary", - "link_count": 0, - "link_to": "Accounts Receivable Summary", - "link_type": "Report", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "Sales Invoice", - "hidden": 0, - "is_query_report": 1, - "label": "Sales Register", - "link_count": 0, - "link_to": "Sales Register", - "link_type": "Report", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "Sales Invoice", - "hidden": 0, - "is_query_report": 1, - "label": "Item-wise Sales Register", - "link_count": 0, - "link_to": "Item-wise Sales Register", - "link_type": "Report", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "Sales Invoice", - "hidden": 0, - "is_query_report": 1, - "label": "Sales Order Analysis", - "link_count": 0, - "link_to": "Sales Order Analysis", - "link_type": "Report", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "Sales Invoice", - "hidden": 0, - "is_query_report": 1, - "label": "Delivered Items To Be Billed", - "link_count": 0, - "link_to": "Delivered Items To Be Billed", - "link_type": "Report", - "onboard": 0, - "type": "Link" - }, - { - "hidden": 0, - "is_query_report": 0, - "label": "Accounts Payable", - "link_count": 0, - "onboard": 0, - "type": "Card Break" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Purchase Invoice", - "link_count": 0, - "link_to": "Purchase Invoice", - "link_type": "DocType", - "onboard": 1, - "type": "Link" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Supplier", - "link_count": 0, - "link_to": "Supplier", - "link_type": "DocType", - "onboard": 1, - "type": "Link" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Payment Entry", - "link_count": 0, - "link_to": "Payment Entry", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "hidden": 0, - "is_query_report": 0, - "label": "Payment Reconciliation", - "link_count": 0, - "link_to": "Payment Reconciliation", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "Purchase Invoice", - "hidden": 0, - "is_query_report": 1, - "label": "Accounts Payable", - "link_count": 0, - "link_to": "Accounts Payable", - "link_type": "Report", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "Purchase Invoice", - "hidden": 0, - "is_query_report": 1, - "label": "Accounts Payable Summary", - "link_count": 0, - "link_to": "Accounts Payable Summary", - "link_type": "Report", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "Purchase Invoice", - "hidden": 0, - "is_query_report": 1, - "label": "Purchase Register", - "link_count": 0, - "link_to": "Purchase Register", - "link_type": "Report", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "Purchase Invoice", - "hidden": 0, - "is_query_report": 1, - "label": "Item-wise Purchase Register", - "link_count": 0, - "link_to": "Item-wise Purchase Register", - "link_type": "Report", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "Purchase Order", - "hidden": 0, - "is_query_report": 1, - "label": "Purchase Order Analysis", - "link_count": 0, - "link_to": "Purchase Order Analysis", - "link_type": "Report", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "Purchase Invoice", - "hidden": 0, - "is_query_report": 1, - "label": "Received Items To Be Billed", - "link_count": 0, - "link_to": "Received Items To Be Billed", - "link_type": "Report", - "onboard": 0, - "type": "Link" - }, - { - "hidden": 0, - "is_query_report": 0, - "label": "Reports", - "link_count": 0, - "onboard": 0, - "type": "Card Break" - }, - { - "dependencies": "GL Entry", - "hidden": 0, - "is_query_report": 1, - "label": "Trial Balance for Party", - "link_count": 0, - "link_to": "Trial Balance for Party", - "link_type": "Report", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "Journal Entry", - "hidden": 0, - "is_query_report": 1, - "label": "Payment Period Based On Invoice Date", - "link_count": 0, - "link_to": "Payment Period Based On Invoice Date", - "link_type": "Report", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "Sales Invoice", - "hidden": 0, - "is_query_report": 1, - "label": "Sales Partners Commission", - "link_count": 0, - "link_to": "Sales Partners Commission", - "link_type": "Report", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "Customer", - "hidden": 0, - "is_query_report": 1, - "label": "Customer Credit Balance", - "link_count": 0, - "link_to": "Customer Credit Balance", - "link_type": "Report", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "Sales Invoice", - "hidden": 0, - "is_query_report": 1, - "label": "Sales Payment Summary", - "link_count": 0, - "link_to": "Sales Payment Summary", - "link_type": "Report", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "Address", - "hidden": 0, - "is_query_report": 1, - "label": "Address And Contacts", - "link_count": 0, - "link_to": "Address And Contacts", - "link_type": "Report", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "GL Entry", - "hidden": 0, - "is_query_report": 1, - "label": "UAE VAT 201", - "link_count": 0, - "link_to": "UAE VAT 201", - "link_type": "Report", - "onboard": 0, - "only_for": "United Arab Emirates", - "type": "Link" - }, - { - "hidden": 0, - "is_query_report": 0, - "label": "Financial Statements", - "link_count": 0, - "onboard": 0, - "type": "Card Break" - }, - { - "dependencies": "GL Entry", - "hidden": 0, - "is_query_report": 1, - "label": "Trial Balance", - "link_count": 0, - "link_to": "Trial Balance", - "link_type": "Report", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "GL Entry", - "hidden": 0, - "is_query_report": 1, - "label": "Profit and Loss Statement", - "link_count": 0, - "link_to": "Profit and Loss Statement", - "link_type": "Report", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "GL Entry", - "hidden": 0, - "is_query_report": 1, - "label": "Balance Sheet", - "link_count": 0, - "link_to": "Balance Sheet", - "link_type": "Report", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "GL Entry", - "hidden": 0, - "is_query_report": 1, - "label": "Cash Flow", - "link_count": 0, - "link_to": "Cash Flow", - "link_type": "Report", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "GL Entry", - "hidden": 0, - "is_query_report": 1, - "label": "Consolidated Financial Statement", - "link_count": 0, - "link_to": "Consolidated Financial Statement", - "link_type": "Report", - "onboard": 0, - "type": "Link" - }, { "hidden": 0, "is_query_report": 0, @@ -611,110 +59,6 @@ "onboard": 0, "type": "Link" }, - { - "hidden": 0, - "is_query_report": 0, - "label": "Settings", - "link_count": 0, - "onboard": 0, - "type": "Card Break" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Payment Gateway Account", - "link_count": 0, - "link_to": "Payment Gateway Account", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Terms and Conditions Template", - "link_count": 0, - "link_to": "Terms and Conditions", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Mode of Payment", - "link_count": 0, - "link_to": "Mode of Payment", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "hidden": 0, - "is_query_report": 0, - "label": "Bank Statement", - "link_count": 0, - "onboard": 0, - "type": "Card Break" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Bank", - "link_count": 0, - "link_to": "Bank", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Bank Account", - "link_count": 0, - "link_to": "Bank Account", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Bank Clearance", - "link_count": 0, - "link_to": "Bank Clearance", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Bank Reconciliation Tool", - "link_count": 0, - "link_to": "Bank Reconciliation Tool", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "GL Entry", - "hidden": 0, - "is_query_report": 1, - "label": "Bank Reconciliation Statement", - "link_count": 0, - "link_to": "Bank Reconciliation Statement", - "link_type": "Report", - "onboard": 0, - "type": "Link" - }, { "hidden": 0, "is_query_report": 0, @@ -926,8 +270,83 @@ { "hidden": 0, "is_query_report": 0, - "label": "Taxes", + "label": "Banking", + "link_count": 6, + "link_type": "DocType", + "onboard": 0, + "type": "Card Break" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 0, + "label": "Bank", "link_count": 0, + "link_to": "Bank", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 0, + "label": "Bank Account", + "link_count": 0, + "link_to": "Bank Account", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 0, + "label": "Bank Clearance", + "link_count": 0, + "link_to": "Bank Clearance", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 0, + "label": "Bank Reconciliation Tool", + "link_count": 0, + "link_to": "Bank Reconciliation Tool", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "GL Entry", + "hidden": 0, + "is_query_report": 1, + "label": "Bank Reconciliation Statement", + "link_count": 0, + "link_to": "Bank Reconciliation Statement", + "link_type": "Report", + "onboard": 0, + "type": "Link" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Plaid Settings", + "link_count": 0, + "link_to": "Plaid Settings", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Tax Masters", + "link_count": 7, + "link_type": "DocType", "onboard": 0, "type": "Card Break" }, @@ -1011,57 +430,163 @@ { "hidden": 0, "is_query_report": 0, - "label": "Profitability", - "link_count": 0, + "label": "Accounting Masters", + "link_count": 8, + "link_type": "DocType", "onboard": 0, "type": "Card Break" }, { - "dependencies": "Sales Invoice", + "dependencies": "", "hidden": 0, - "is_query_report": 1, - "label": "Gross Profit", + "is_query_report": 0, + "label": "Company", "link_count": 0, - "link_to": "Gross Profit", - "link_type": "Report", + "link_to": "Company", + "link_type": "DocType", + "onboard": 1, + "type": "Link" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 0, + "label": "Chart of Accounts", + "link_count": 0, + "link_to": "Account", + "link_type": "DocType", + "onboard": 1, + "type": "Link" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 0, + "label": "Accounts Settings", + "link_count": 0, + "link_to": "Accounts Settings", + "link_type": "DocType", "onboard": 0, "type": "Link" }, { - "dependencies": "GL Entry", + "dependencies": "", "hidden": 0, - "is_query_report": 1, - "label": "Profitability Analysis", + "is_query_report": 0, + "label": "Fiscal Year", "link_count": 0, - "link_to": "Profitability Analysis", - "link_type": "Report", + "link_to": "Fiscal Year", + "link_type": "DocType", "onboard": 0, "type": "Link" }, { - "dependencies": "Sales Invoice", + "dependencies": "", "hidden": 0, - "is_query_report": 1, - "label": "Sales Invoice Trends", + "is_query_report": 0, + "label": "Accounting Dimension", "link_count": 0, - "link_to": "Sales Invoice Trends", - "link_type": "Report", + "link_to": "Accounting Dimension", + "link_type": "DocType", "onboard": 0, "type": "Link" }, { - "dependencies": "Purchase Invoice", + "dependencies": "", "hidden": 0, - "is_query_report": 1, - "label": "Purchase Invoice Trends", + "is_query_report": 0, + "label": "Finance Book", "link_count": 0, - "link_to": "Purchase Invoice Trends", - "link_type": "Report", + "link_to": "Finance Book", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 0, + "label": "Accounting Period", + "link_count": 0, + "link_to": "Accounting Period", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 0, + "label": "Payment Term", + "link_count": 0, + "link_to": "Payment Term", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Payments", + "link_count": 5, + "link_type": "DocType", + "onboard": 0, + "type": "Card Break" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Payment Entry", + "link_count": 0, + "link_to": "Payment Entry", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 0, + "label": "Journal Entry", + "link_count": 0, + "link_to": "Journal Entry", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 0, + "label": "Journal Entry Template", + "link_count": 0, + "link_to": "Journal Entry Template", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Terms and Conditions", + "link_count": 0, + "link_to": "Terms and Conditions", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Mode of Payment", + "link_count": 0, + "link_to": "Mode of Payment", + "link_type": "DocType", "onboard": 0, "type": "Link" } ], - "modified": "2023-08-10 17:41:14.059005", + "modified": "2024-01-18 22:15:40.941711", "modified_by": "Administrator", "module": "Accounts", "name": "Accounting", diff --git a/erpnext/accounts/workspace/financial_reports/financial_reports.json b/erpnext/accounts/workspace/financial_reports/financial_reports.json new file mode 100644 index 0000000000..3ab4a3e22d --- /dev/null +++ b/erpnext/accounts/workspace/financial_reports/financial_reports.json @@ -0,0 +1,277 @@ +{ + "charts": [], + "content": "[{\"id\":\"nKKr6fjgjb\",\"type\":\"card\",\"data\":{\"card_name\":\"Ledgers\",\"col\":4}},{\"id\":\"p7NY6MHe2Y\",\"type\":\"card\",\"data\":{\"card_name\":\"Financial Statements\",\"col\":4}},{\"id\":\"3AK1Zf0oew\",\"type\":\"card\",\"data\":{\"card_name\":\"Profitability\",\"col\":4}},{\"id\":\"Q_hBCnSeJY\",\"type\":\"card\",\"data\":{\"card_name\":\"Other Reports\",\"col\":4}}]", + "creation": "2024-01-05 16:09:16.766939", + "custom_blocks": [], + "docstatus": 0, + "doctype": "Workspace", + "for_user": "", + "hide_custom": 0, + "icon": "file", + "idx": 0, + "indicator_color": "", + "is_hidden": 0, + "label": "Financial Reports", + "links": [ + { + "hidden": 0, + "is_query_report": 0, + "label": "Profitability", + "link_count": 0, + "link_type": "DocType", + "onboard": 0, + "type": "Card Break" + }, + { + "dependencies": "Sales Invoice", + "hidden": 0, + "is_query_report": 1, + "label": "Gross Profit", + "link_count": 0, + "link_to": "Gross Profit", + "link_type": "Report", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "GL Entry", + "hidden": 0, + "is_query_report": 1, + "label": "Profitability Analysis", + "link_count": 0, + "link_to": "Profitability Analysis", + "link_type": "Report", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "Sales Invoice", + "hidden": 0, + "is_query_report": 1, + "label": "Sales Invoice Trends", + "link_count": 0, + "link_to": "Sales Invoice Trends", + "link_type": "Report", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "Purchase Invoice", + "hidden": 0, + "is_query_report": 1, + "label": "Purchase Invoice Trends", + "link_count": 0, + "link_to": "Purchase Invoice Trends", + "link_type": "Report", + "onboard": 0, + "type": "Link" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Financial Statements", + "link_count": 5, + "link_type": "DocType", + "onboard": 0, + "type": "Card Break" + }, + { + "dependencies": "GL Entry", + "hidden": 0, + "is_query_report": 1, + "label": "Trial Balance", + "link_count": 0, + "link_to": "Trial Balance", + "link_type": "Report", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "GL Entry", + "hidden": 0, + "is_query_report": 1, + "label": "Profit and Loss Statement", + "link_count": 0, + "link_to": "Profit and Loss Statement", + "link_type": "Report", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "GL Entry", + "hidden": 0, + "is_query_report": 1, + "label": "Balance Sheet", + "link_count": 0, + "link_to": "Balance Sheet", + "link_type": "Report", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "GL Entry", + "hidden": 0, + "is_query_report": 1, + "label": "Cash Flow", + "link_count": 0, + "link_to": "Cash Flow", + "link_type": "Report", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "GL Entry", + "hidden": 0, + "is_query_report": 1, + "label": "Consolidated Financial Statement", + "link_count": 0, + "link_to": "Consolidated Financial Statement", + "link_type": "Report", + "onboard": 0, + "type": "Link" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Ledgers", + "link_count": 3, + "link_type": "DocType", + "onboard": 0, + "type": "Card Break" + }, + { + "dependencies": "GL Entry", + "hidden": 0, + "is_query_report": 1, + "label": "General Ledger", + "link_count": 0, + "link_to": "General Ledger", + "link_type": "Report", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "Sales Invoice", + "hidden": 0, + "is_query_report": 1, + "label": "Customer Ledger Summary", + "link_count": 0, + "link_to": "Customer Ledger Summary", + "link_type": "Report", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "Sales Invoice", + "hidden": 0, + "is_query_report": 1, + "label": "Supplier Ledger Summary", + "link_count": 0, + "link_to": "Supplier Ledger Summary", + "link_type": "Report", + "onboard": 0, + "type": "Link" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Other Reports", + "link_count": 7, + "link_type": "DocType", + "onboard": 0, + "type": "Card Break" + }, + { + "dependencies": "GL Entry", + "hidden": 0, + "is_query_report": 1, + "label": "Trial Balance for Party", + "link_count": 0, + "link_to": "Trial Balance for Party", + "link_type": "Report", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "Journal Entry", + "hidden": 0, + "is_query_report": 1, + "label": "Payment Period Based On Invoice Date", + "link_count": 0, + "link_to": "Payment Period Based On Invoice Date", + "link_type": "Report", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "Sales Invoice", + "hidden": 0, + "is_query_report": 1, + "label": "Sales Partners Commission", + "link_count": 0, + "link_to": "Sales Partners Commission", + "link_type": "Report", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "Customer", + "hidden": 0, + "is_query_report": 1, + "label": "Customer Credit Balance", + "link_count": 0, + "link_to": "Customer Credit Balance", + "link_type": "Report", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "Sales Invoice", + "hidden": 0, + "is_query_report": 1, + "label": "Sales Payment Summary", + "link_count": 0, + "link_to": "Sales Payment Summary", + "link_type": "Report", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "Address", + "hidden": 0, + "is_query_report": 1, + "label": "Address And Contacts", + "link_count": 0, + "link_to": "Address And Contacts", + "link_type": "Report", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "GL Entry", + "hidden": 0, + "is_query_report": 1, + "label": "UAE VAT 201", + "link_count": 0, + "link_to": "UAE VAT 201", + "link_type": "Report", + "onboard": 0, + "only_for": "United Arab Emirates", + "type": "Link" + } + ], + "modified": "2024-01-18 22:13:07.596844", + "modified_by": "Administrator", + "module": "Accounts", + "name": "Financial Reports", + "number_cards": [], + "owner": "Administrator", + "parent_page": "Accounting", + "public": 1, + "quick_lists": [], + "restrict_to_domain": "", + "roles": [], + "sequence_id": 5.0, + "shortcuts": [], + "title": "Financial Reports" +} \ No newline at end of file diff --git a/erpnext/accounts/workspace/payables/payables.json b/erpnext/accounts/workspace/payables/payables.json new file mode 100644 index 0000000000..f8c8564875 --- /dev/null +++ b/erpnext/accounts/workspace/payables/payables.json @@ -0,0 +1,204 @@ +{ + "charts": [], + "content": "[{\"id\":\"rMMsfn2eB4\",\"type\":\"header\",\"data\":{\"text\":\"Shortcuts\",\"col\":12}},{\"id\":\"G984SgVRJN\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Purchase Invoice\",\"col\":3}},{\"id\":\"F9f4I1viNr\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Payment Entry\",\"col\":3}},{\"id\":\"1ArNvt9qhz\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Journal Entry\",\"col\":3}},{\"id\":\"4IBBOIxfqW\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Accounts Payable\",\"col\":3}},{\"id\":\"B7-uxs8tkU\",\"type\":\"spacer\",\"data\":{\"col\":12}},{\"id\":\"jAcOH-cC-Q\",\"type\":\"header\",\"data\":{\"text\":\"Reports & Masters\",\"col\":12}},{\"id\":\"7dj93PEUjW\",\"type\":\"card\",\"data\":{\"card_name\":\"Invoicing\",\"col\":4}},{\"id\":\"_Cb7C8XdJJ\",\"type\":\"card\",\"data\":{\"card_name\":\"Payments\",\"col\":4}},{\"id\":\"9yseIkdG50\",\"type\":\"card\",\"data\":{\"card_name\":\"Reports\",\"col\":4}}]", + "creation": "2024-01-05 15:29:11.144373", + "custom_blocks": [], + "docstatus": 0, + "doctype": "Workspace", + "for_user": "", + "hide_custom": 0, + "icon": "arrow-left", + "idx": 0, + "indicator_color": "", + "is_hidden": 0, + "label": "Payables", + "links": [ + { + "hidden": 0, + "is_query_report": 0, + "label": "Invoicing", + "link_count": 2, + "link_type": "DocType", + "onboard": 0, + "type": "Card Break" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Purchase Invoice", + "link_count": 0, + "link_to": "Purchase Invoice", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Supplier", + "link_count": 0, + "link_to": "Supplier", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Payments", + "link_count": 3, + "link_type": "DocType", + "onboard": 0, + "type": "Card Break" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 0, + "label": "Payment Entry", + "link_count": 0, + "link_to": "Payment Entry", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Journal Entry", + "link_count": 0, + "link_to": "Journal Entry", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Payment Reconciliation", + "link_count": 0, + "link_to": "Payment Reconciliation", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Reports", + "link_count": 7, + "link_type": "DocType", + "onboard": 0, + "type": "Card Break" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Accounts Payable", + "link_count": 0, + "link_to": "Accounts Payable", + "link_type": "Report", + "onboard": 0, + "type": "Link" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Accounts Payable Summary", + "link_count": 0, + "link_to": "Accounts Payable Summary", + "link_type": "Report", + "onboard": 0, + "type": "Link" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Purchase Register", + "link_count": 0, + "link_to": "Purchase Register", + "link_type": "Report", + "onboard": 0, + "type": "Link" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Item-wise Purchase Register", + "link_count": 0, + "link_to": "Item-wise Purchase Register", + "link_type": "Report", + "onboard": 0, + "type": "Link" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Purchase Order Analysis", + "link_count": 0, + "link_to": "Purchase Order Analysis", + "link_type": "Report", + "onboard": 0, + "type": "Link" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Received Items To Be Billed", + "link_count": 0, + "link_to": "Received Items To Be Billed", + "link_type": "Report", + "onboard": 0, + "type": "Link" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Supplier Ledger Summary", + "link_count": 0, + "link_to": "Supplier Ledger Summary", + "link_type": "Report", + "onboard": 0, + "type": "Link" + } + ], + "modified": "2024-01-18 22:09:46.221549", + "modified_by": "Administrator", + "module": "Accounts", + "name": "Payables", + "number_cards": [], + "owner": "Administrator", + "parent_page": "Accounting", + "public": 1, + "quick_lists": [], + "restrict_to_domain": "", + "roles": [], + "sequence_id": 3.0, + "shortcuts": [ + { + "doc_view": "", + "label": "Accounts Payable", + "link_to": "Accounts Payable", + "type": "Report" + }, + { + "doc_view": "", + "label": "Purchase Invoice", + "link_to": "Purchase Invoice", + "type": "DocType" + }, + { + "doc_view": "", + "label": "Journal Entry", + "link_to": "Journal Entry", + "type": "DocType" + }, + { + "doc_view": "", + "label": "Payment Entry", + "link_to": "Payment Entry", + "type": "DocType" + } + ], + "title": "Payables" +} \ No newline at end of file diff --git a/erpnext/accounts/workspace/receivables/receivables.json b/erpnext/accounts/workspace/receivables/receivables.json new file mode 100644 index 0000000000..6fa8c099a4 --- /dev/null +++ b/erpnext/accounts/workspace/receivables/receivables.json @@ -0,0 +1,254 @@ +{ + "charts": [], + "content": "[{\"id\":\"vikWSkNm6_\",\"type\":\"header\",\"data\":{\"text\":\"Shortcuts\",\"col\":12}},{\"id\":\"G984SgVRJN\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Sales Invoice\",\"col\":3}},{\"id\":\"5yHldR0JNk\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"POS Invoice\",\"col\":3}},{\"id\":\"F9f4I1viNr\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Payment Entry\",\"col\":3}},{\"id\":\"1ArNvt9qhz\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Journal Entry\",\"col\":3}},{\"id\":\"4IBBOIxfqW\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Accounts Receivable\",\"col\":3}},{\"id\":\"ILlIxJuexy\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Cost Center\",\"col\":3}},{\"id\":\"B7-uxs8tkU\",\"type\":\"spacer\",\"data\":{\"col\":12}},{\"id\":\"tHb3yxthkR\",\"type\":\"header\",\"data\":{\"text\":\"Reports & Masters\",\"col\":12}},{\"id\":\"jLgv00c6ek\",\"type\":\"card\",\"data\":{\"card_name\":\"Invoicing\",\"col\":4}},{\"id\":\"npwfXlz0u1\",\"type\":\"card\",\"data\":{\"card_name\":\"Payments\",\"col\":4}},{\"id\":\"am70C27Jrb\",\"type\":\"card\",\"data\":{\"card_name\":\"Dunning\",\"col\":4}},{\"id\":\"xOHTyD8b5l\",\"type\":\"card\",\"data\":{\"card_name\":\"Reports\",\"col\":4}}]", + "creation": "2024-01-05 15:29:21.084241", + "custom_blocks": [], + "docstatus": 0, + "doctype": "Workspace", + "for_user": "", + "hide_custom": 0, + "icon": "arrow-right", + "idx": 0, + "indicator_color": "", + "is_hidden": 0, + "label": "Receivables", + "links": [ + { + "hidden": 0, + "is_query_report": 0, + "label": "Invoicing", + "link_count": 2, + "link_type": "DocType", + "onboard": 0, + "type": "Card Break" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Sales Invoice", + "link_count": 0, + "link_to": "Sales Invoice", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Customer", + "link_count": 0, + "link_to": "Customer", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Payments", + "link_count": 4, + "link_type": "DocType", + "onboard": 0, + "type": "Card Break" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Payment Entry", + "link_count": 0, + "link_to": "Payment Entry", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Payment Request", + "link_count": 0, + "link_to": "Payment Request", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Payment Reconciliation", + "link_count": 0, + "link_to": "Payment Reconciliation", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Payment Gateway Account", + "link_count": 0, + "link_to": "Payment Gateway Account", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Dunning", + "link_count": 2, + "link_type": "DocType", + "onboard": 0, + "type": "Card Break" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Dunning", + "link_count": 0, + "link_to": "Dunning", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Dunning Type", + "link_count": 0, + "link_to": "Dunning Type", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Reports", + "link_count": 6, + "link_type": "DocType", + "onboard": 0, + "type": "Card Break" + }, + { + "dependencies": "Sales Invoice", + "hidden": 0, + "is_query_report": 1, + "label": "Accounts Receivable", + "link_count": 0, + "link_to": "Accounts Receivable", + "link_type": "Report", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "Sales Invoice", + "hidden": 0, + "is_query_report": 1, + "label": "Accounts Receivable Summary", + "link_count": 0, + "link_to": "Accounts Receivable Summary", + "link_type": "Report", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "Sales Invoice", + "hidden": 0, + "is_query_report": 1, + "label": "Sales Register", + "link_count": 0, + "link_to": "Sales Register", + "link_type": "Report", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "Sales Invoice", + "hidden": 0, + "is_query_report": 1, + "label": "Item-wise Sales Register", + "link_count": 0, + "link_to": "Item-wise Sales Register", + "link_type": "Report", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "Sales Invoice", + "hidden": 0, + "is_query_report": 1, + "label": "Sales Order Analysis", + "link_count": 0, + "link_to": "Sales Order Analysis", + "link_type": "Report", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "Sales Invoice", + "hidden": 0, + "is_query_report": 1, + "label": "Delivered Items To Be Billed", + "link_count": 0, + "link_to": "Delivered Items To Be Billed", + "link_type": "Report", + "onboard": 0, + "type": "Link" + } + ], + "modified": "2024-01-18 22:11:51.474477", + "modified_by": "Administrator", + "module": "Accounts", + "name": "Receivables", + "number_cards": [], + "owner": "Administrator", + "parent_page": "Accounting", + "public": 1, + "quick_lists": [], + "restrict_to_domain": "", + "roles": [], + "sequence_id": 4.0, + "shortcuts": [ + { + "color": "Grey", + "doc_view": "List", + "label": "POS Invoice", + "link_to": "POS Invoice", + "stats_filter": "[]", + "type": "DocType" + }, + { + "color": "Grey", + "doc_view": "List", + "label": "Cost Center", + "link_to": "Cost Center", + "type": "DocType" + }, + { + "doc_view": "", + "label": "Sales Invoice", + "link_to": "Sales Invoice", + "stats_filter": "[]", + "type": "DocType" + }, + { + "doc_view": "", + "label": "Journal Entry", + "link_to": "Journal Entry", + "type": "DocType" + }, + { + "doc_view": "", + "label": "Payment Entry", + "link_to": "Payment Entry", + "type": "DocType" + }, + { + "doc_view": "", + "label": "Accounts Receivable", + "link_to": "Accounts Receivable", + "type": "Report" + } + ], + "title": "Receivables" +} \ No newline at end of file diff --git a/erpnext/assets/workspace/assets/assets.json b/erpnext/assets/workspace/assets/assets.json index c6b321e9c1..26e8d8a2a4 100644 --- a/erpnext/assets/workspace/assets/assets.json +++ b/erpnext/assets/workspace/assets/assets.json @@ -196,18 +196,18 @@ "type": "Link" } ], - "modified": "2023-05-24 14:47:20.243146", + "modified": "2024-01-05 17:40:34.570041", "modified_by": "Administrator", "module": "Assets", "name": "Assets", "number_cards": [], "owner": "Administrator", - "parent_page": "Accounting", + "parent_page": "", "public": 1, "quick_lists": [], "restrict_to_domain": "", "roles": [], - "sequence_id": 4.0, + "sequence_id": 7.0, "shortcuts": [ { "label": "Asset", From ddb84d9036d5f383af9cee1e0e6a83f97fe8d2ea Mon Sep 17 00:00:00 2001 From: Gursheen Kaur Anand <40693548+GursheenK@users.noreply.github.com> Date: Wed, 17 Jan 2024 12:25:03 +0530 Subject: [PATCH 05/15] Revert "fix(minor): financial statements period end date" (cherry picked from commit 73625a2622f29a83c98179c0b5048a29e61ce243) --- erpnext/accounts/report/financial_statements.py | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/erpnext/accounts/report/financial_statements.py b/erpnext/accounts/report/financial_statements.py index 004a9299ea..aadd8731ca 100644 --- a/erpnext/accounts/report/financial_statements.py +++ b/erpnext/accounts/report/financial_statements.py @@ -8,17 +8,7 @@ import re import frappe from frappe import _ -from frappe.utils import ( - add_days, - add_months, - cint, - cstr, - flt, - formatdate, - get_first_day, - getdate, - today, -) +from frappe.utils import add_days, add_months, cint, cstr, flt, formatdate, get_first_day, getdate from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( get_accounting_dimensions, @@ -53,8 +43,6 @@ def get_period_list( year_start_date = getdate(period_start_date) year_end_date = getdate(period_end_date) - year_end_date = getdate(today()) if year_end_date > getdate(today()) else year_end_date - months_to_add = {"Yearly": 12, "Half-Yearly": 6, "Quarterly": 3, "Monthly": 1}[periodicity] period_list = [] From b388adcb2e49a96a2233c29de42ac274be0b2113 Mon Sep 17 00:00:00 2001 From: David Arnold Date: Mon, 8 Jan 2024 22:07:46 +0100 Subject: [PATCH 06/15] fix: use most reliable section reference per report line (cherry picked from commit b5be17c6dfc9ab10e9eb57669f697fbb5576489c) --- .../tax_withholding_details.py | 106 ++++++++++-------- 1 file changed, 60 insertions(+), 46 deletions(-) diff --git a/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py b/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py index 9513f2c153..0c324c8bf1 100644 --- a/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py +++ b/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py @@ -46,12 +46,10 @@ def get_result( out = [] for name, details in gle_map.items(): - tax_amount, total_amount, grand_total, base_total = 0, 0, 0, 0 - bill_no, bill_date = "", "" - tax_withholding_category = tax_category_map.get(name) - rate = tax_rate_map.get(tax_withholding_category) - for entry in details: + tax_amount, total_amount, grand_total, base_total = 0, 0, 0, 0 + tax_withholding_category, rate = None, None + bill_no, bill_date = "", "" party = entry.party or entry.against posting_date = entry.posting_date voucher_type = entry.voucher_type @@ -61,12 +59,19 @@ def get_result( if party_list: party = party_list[0] - if not tax_withholding_category: - tax_withholding_category = party_map.get(party, {}).get("tax_withholding_category") - rate = tax_rate_map.get(tax_withholding_category) - - if entry.account in tds_accounts: + if entry.account in tds_accounts.keys(): tax_amount += entry.credit - entry.debit + # infer tax withholding category from the account if it's the single account for this category + tax_withholding_category = tds_accounts.get(entry.account) + rate = tax_rate_map.get(tax_withholding_category) + # or else the consolidated value from the voucher document + if not tax_withholding_category: + # or else from the party default + tax_withholding_category = tax_category_map.get(name) + rate = tax_rate_map.get(tax_withholding_category) + if not tax_withholding_category: + tax_withholding_category = party_map.get(party, {}).get("tax_withholding_category") + rate = tax_rate_map.get(tax_withholding_category) if net_total_map.get(name): if voucher_type == "Journal Entry": @@ -80,41 +85,41 @@ def get_result( else: total_amount += entry.credit - if tax_amount: - if party_map.get(party, {}).get("party_type") == "Supplier": - party_name = "supplier_name" - party_type = "supplier_type" - else: - party_name = "customer_name" - party_type = "customer_type" + if tax_amount: + if party_map.get(party, {}).get("party_type") == "Supplier": + party_name = "supplier_name" + party_type = "supplier_type" + else: + party_name = "customer_name" + party_type = "customer_type" - row = { - "pan" - if frappe.db.has_column(filters.party_type, "pan") - else "tax_id": party_map.get(party, {}).get("pan"), - "party": party_map.get(party, {}).get("name"), - } - - if filters.naming_series == "Naming Series": - row.update({"party_name": party_map.get(party, {}).get(party_name)}) - - row.update( - { - "section_code": tax_withholding_category or "", - "entity_type": party_map.get(party, {}).get(party_type), - "rate": rate, - "total_amount": total_amount, - "grand_total": grand_total, - "base_total": base_total, - "tax_amount": tax_amount, - "transaction_date": posting_date, - "transaction_type": voucher_type, - "ref_no": name, - "supplier_invoice_no": bill_no, - "supplier_invoice_date": bill_date, + row = { + "pan" + if frappe.db.has_column(filters.party_type, "pan") + else "tax_id": party_map.get(party, {}).get("pan"), + "party": party_map.get(party, {}).get("name"), } - ) - out.append(row) + + if filters.naming_series == "Naming Series": + row.update({"party_name": party_map.get(party, {}).get(party_name)}) + + row.update( + { + "section_code": tax_withholding_category or "", + "entity_type": party_map.get(party, {}).get(party_type), + "rate": rate, + "total_amount": total_amount, + "grand_total": grand_total, + "base_total": base_total, + "tax_amount": tax_amount, + "transaction_date": posting_date, + "transaction_type": voucher_type, + "ref_no": name, + "supplier_invoice_no": bill_no, + "supplier_invoice_date": bill_date, + } + ) + out.append(row) out.sort(key=lambda x: x["section_code"]) @@ -282,11 +287,20 @@ def get_tds_docs(filters): journal_entry_party_map = frappe._dict() bank_accounts = frappe.get_all("Account", {"is_group": 0, "account_type": "Bank"}, pluck="name") - tds_accounts = frappe.get_all( - "Tax Withholding Account", {"company": filters.get("company")}, pluck="account" + _tds_accounts = frappe.get_all( + "Tax Withholding Account", + {"company": filters.get("company")}, + ["account", "parent"], ) + tds_accounts = {} + for tds_acc in _tds_accounts: + # if it turns out not to be the only tax withholding category, then don't include in the map + if tds_accounts.get(tds_acc["account"]): + tds_accounts[tds_acc["account"]] = None + else: + tds_accounts[tds_acc["account"]] = tds_acc["parent"] - tds_docs = get_tds_docs_query(filters, bank_accounts, tds_accounts).run(as_dict=True) + tds_docs = get_tds_docs_query(filters, bank_accounts, list(tds_accounts.keys())).run(as_dict=True) for d in tds_docs: if d.voucher_type == "Purchase Invoice": From b4981f8816071eaab346801e60aaf7ea850fa787 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Sun, 21 Jan 2024 18:05:20 +0530 Subject: [PATCH 07/15] fix: key error during reposting (cherry picked from commit ebc8230d4564385b151e19f21d57172afe803108) --- erpnext/stock/stock_ledger.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py index b19a34a354..a221e006af 100644 --- a/erpnext/stock/stock_ledger.py +++ b/erpnext/stock/stock_ledger.py @@ -439,7 +439,7 @@ def get_distinct_item_warehouse(args=None, doc=None, reposting_data=None): reposting_data = get_reposting_data(doc.reposting_data_file) if reposting_data and reposting_data.distinct_item_and_warehouse: - return reposting_data.distinct_item_and_warehouse + return parse_distinct_items_and_warehouses(reposting_data.distinct_item_and_warehouse) distinct_item_warehouses = {} @@ -457,6 +457,16 @@ def get_distinct_item_warehouse(args=None, doc=None, reposting_data=None): return distinct_item_warehouses +def parse_distinct_items_and_warehouses(distinct_items_and_warehouses): + new_dict = frappe._dict({}) + + # convert string keys to tuple + for k, v in distinct_items_and_warehouses.items(): + new_dict[frappe.safe_eval(k)] = frappe._dict(v) + + return new_dict + + def get_affected_transactions(doc, reposting_data=None) -> Set[Tuple[str, str]]: if not reposting_data and doc and doc.reposting_data_file: reposting_data = get_reposting_data(doc.reposting_data_file) From 96e1db80ac0d864d6454b6c3ad45ff8e6994b222 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Sun, 21 Jan 2024 19:47:53 +0530 Subject: [PATCH 08/15] fix: added button to make serial / batch from Purchase Invoice (cherry picked from commit b4393bc03d68769f57678bb56a09baf7b4ec3dc0) --- .../purchase_invoice_item/purchase_invoice_item.json | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json index 9cf4e4fd7c..26984d96ef 100644 --- a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json +++ b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json @@ -64,6 +64,7 @@ "warehouse", "from_warehouse", "quality_inspection", + "add_serial_batch_bundle", "serial_and_batch_bundle", "serial_no", "col_br_wh", @@ -913,12 +914,18 @@ "fieldtype": "Link", "label": "WIP Composite Asset", "options": "Asset" + }, + { + "depends_on": "eval:parent.update_stock === 1", + "fieldname": "add_serial_batch_bundle", + "fieldtype": "Button", + "label": "Add Serial / Batch No" } ], "idx": 1, "istable": 1, "links": [], - "modified": "2023-12-25 22:00:28.043555", + "modified": "2024-01-21 19:46:25.537861", "modified_by": "Administrator", "module": "Accounts", "name": "Purchase Invoice Item", From b0e872aad40431918e8d15bebf5e8e7dd73efec1 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Sun, 21 Jan 2024 20:59:38 +0530 Subject: [PATCH 09/15] test: fixed test (cherry picked from commit 63ffce58cce6c68c210572287024da9ca414aca9) --- erpnext/manufacturing/doctype/work_order/test_work_order.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/erpnext/manufacturing/doctype/work_order/test_work_order.py b/erpnext/manufacturing/doctype/work_order/test_work_order.py index 19d8b9a1b2..c8f3872622 100644 --- a/erpnext/manufacturing/doctype/work_order/test_work_order.py +++ b/erpnext/manufacturing/doctype/work_order/test_work_order.py @@ -997,12 +997,6 @@ class TestWorkOrder(FrappeTestCase): make_job_card(wo_order.name, operations) job_card = frappe.db.get_value("Job Card", {"work_order": wo_order.name, "docstatus": 0}, "name") - update_job_card(job_card, 10, 2) - - stock_entry = frappe.get_doc(make_stock_entry(wo_order.name, "Manufacture", 10)) - for row in stock_entry.items: - if row.is_scrap_item: - self.assertEqual(row.qty, 2) def test_close_work_order(self): items = [ From 80e3597338de30df4fc20b2ae452f6374c7f1cb5 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Thu, 18 Jan 2024 18:03:16 +0530 Subject: [PATCH 10/15] refactor: delete transactions in background (cherry picked from commit a50808a077b8d6475ff360b611cd5f0a8cb37d65) --- erpnext/setup/doctype/company/company.js | 66 ++++++++++++++---------- erpnext/setup/doctype/company/company.py | 34 +++++++++++- 2 files changed, 70 insertions(+), 30 deletions(-) diff --git a/erpnext/setup/doctype/company/company.js b/erpnext/setup/doctype/company/company.js index 15944a56f0..3359835358 100644 --- a/erpnext/setup/doctype/company/company.js +++ b/erpnext/setup/doctype/company/company.js @@ -140,38 +140,48 @@ frappe.ui.form.on("Company", { }, delete_company_transactions: function(frm) { - frappe.verify_password(function() { - var d = frappe.prompt({ - fieldtype:"Data", - fieldname: "company_name", - label: __("Please enter the company name to confirm"), - reqd: 1, - description: __("Please make sure you really want to delete all the transactions for this company. Your master data will remain as it is. This action cannot be undone.") + frappe.call({ + method: "erpnext.setup.doctype.company.company.is_deletion_job_running", + args: { + company: frm.doc.name }, - function(data) { - if(data.company_name !== frm.doc.name) { - frappe.msgprint(__("Company name not same")); - return; + freeze: true, + callback: function(r) { + if(!r.exc) { + frappe.verify_password(function() { + var d = frappe.prompt({ + fieldtype:"Data", + fieldname: "company_name", + label: __("Please enter the company name to confirm"), + reqd: 1, + description: __("Please make sure you really want to delete all the transactions for this company. Your master data will remain as it is. This action cannot be undone.") + }, + function(data) { + if(data.company_name !== frm.doc.name) { + frappe.msgprint(__("Company name not same")); + return; + } + frappe.call({ + method: "erpnext.setup.doctype.company.company.create_transaction_deletion_request", + args: { + company: data.company_name + }, + freeze: true, + callback: function(r, rt) { }, + onerror: function() { + frappe.msgprint(__("Wrong Password")); + } + }); + }, + __("Delete all the Transactions for this Company"), __("Delete") + ); + d.get_primary_btn().addClass("btn-danger"); + }); } - frappe.call({ - method: "erpnext.setup.doctype.company.company.create_transaction_deletion_request", - args: { - company: data.company_name - }, - freeze: true, - callback: function(r, rt) { - if(!r.exc) - frappe.msgprint(__("Successfully deleted all transactions related to this company!")); - }, - onerror: function() { - frappe.msgprint(__("Wrong Password")); - } - }); + }, - __("Delete all the Transactions for this Company"), __("Delete") - ); - d.get_primary_btn().addClass("btn-danger"); }); + } }); diff --git a/erpnext/setup/doctype/company/company.py b/erpnext/setup/doctype/company/company.py index 6b6dba4f1d..27d7df33a3 100644 --- a/erpnext/setup/doctype/company/company.py +++ b/erpnext/setup/doctype/company/company.py @@ -11,7 +11,8 @@ from frappe.cache_manager import clear_defaults_cache from frappe.contacts.address_and_contact import load_address_and_contact from frappe.custom.doctype.property_setter.property_setter import make_property_setter from frappe.desk.page.setup_wizard.setup_wizard import make_records -from frappe.utils import cint, formatdate, get_timestamp, today +from frappe.utils import cint, formatdate, get_link_to_form, get_timestamp, today +from frappe.utils.background_jobs import get_job, is_job_enqueued from frappe.utils.nestedset import NestedSet, rebuild_tree from erpnext.accounts.doctype.account.account import get_account_currency @@ -903,8 +904,37 @@ def get_default_company_address(name, sort_key="is_primary_address", existing_ad return None +def generate_id_for_deletion_job(company): + return "delete_company_transactions_" + company + + +@frappe.whitelist() +def is_deletion_job_running(company): + job_id = generate_id_for_deletion_job(company) + job_name = get_job(job_id).get_id() # job name will have site prefix + if is_job_enqueued(job_id): + frappe.throw( + _("A Transaction Deletion Job: {0} is already running for {1}").format( + frappe.bold(get_link_to_form("RQ Job", job_name)), frappe.bold(company) + ) + ) + + @frappe.whitelist() def create_transaction_deletion_request(company): + is_deletion_job_running(company) + job_id = generate_id_for_deletion_job(company) + tdr = frappe.get_doc({"doctype": "Transaction Deletion Record", "company": company}) tdr.insert() - tdr.submit() + + frappe.enqueue( + "frappe.utils.background_jobs.run_doc_method", + doctype=tdr.doctype, + name=tdr.name, + doc_method="submit", + job_id=job_id, + queue="long", + enqueue_after_commit=True, + ) + frappe.msgprint(_("A Transaction Deletion Job is triggered for {0}").format(frappe.bold(company))) From 9a0834987cae93428f5daa813d09c19262fd0ad0 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Fri, 19 Jan 2024 17:08:02 +0530 Subject: [PATCH 11/15] fix: party field in pdf html (cherry picked from commit b2d9380596dd8ca134777148337ef039f10cc2ca) --- .../accounts_receivable/accounts_receivable.html | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.html b/erpnext/accounts/report/accounts_receivable/accounts_receivable.html index ed3b991559..7d8d33c46b 100644 --- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.html +++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.html @@ -10,10 +10,8 @@

{%= __(report.report_name) %}

- {% if (filters.customer_name) { %} - {%= filters.customer_name %} - {% } else { %} - {%= filters.customer || filters.supplier %} + {% if (filters.party) { %} + {%= __(filters.party) %} {% } %}

@@ -141,7 +139,7 @@ {%= __("Reference") %} {% } %} {% if(!filters.show_future_payments) { %} - {%= (filters.customer || filters.supplier) ? __("Remarks"): __("Party") %} + {%= (filters.party) ? __("Remarks"): __("Party") %} {% } %} {%= __("Invoiced Amount") %} {% if(!filters.show_future_payments) { %} @@ -158,7 +156,7 @@ {%= __("Remaining Balance") %} {% } %} {% } else { %} - {%= (filters.customer || filters.supplier) ? __("Remarks"): __("Party") %} + {%= (filters.party) ? __("Remarks"): __("Party") %} {%= __("Total Invoiced Amount") %} {%= __("Total Paid Amount") %} {%= report.report_name === "Accounts Receivable Summary" ? __('Credit Note Amount') : __('Debit Note Amount') %} @@ -187,7 +185,7 @@ {% if(!filters.show_future_payments) { %} - {% if(!(filters.customer || filters.supplier)) { %} + {% if(!(filters.party)) { %} {%= data[i]["party"] %} {% if(data[i]["customer_name"] && data[i]["customer_name"] != data[i]["party"]) { %}
{%= data[i]["customer_name"] %} @@ -260,7 +258,7 @@ {% if(data[i]["party"]|| " ") { %} {% if(!data[i]["is_total_row"]) { %} - {% if(!(filters.customer || filters.supplier)) { %} + {% if(!(filters.party)) { %} {%= data[i]["party"] %} {% if(data[i]["customer_name"] && data[i]["customer_name"] != data[i]["party"]) { %}
{%= data[i]["customer_name"] %} From 0acbbefa8b5473c51328af950e363e32e02955ac Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 22 Jan 2024 14:43:15 +0530 Subject: [PATCH 12/15] refactor: move 'project' set_query to sales_common.js (cherry picked from commit 52814724eb3e7d0a350ddeb01214ba3855a1ccc9) --- erpnext/public/js/utils/sales_common.js | 11 ++++++++++- erpnext/selling/doctype/sales_order/sales_order.js | 9 --------- erpnext/stock/doctype/delivery_note/delivery_note.js | 9 --------- 3 files changed, 10 insertions(+), 19 deletions(-) diff --git a/erpnext/public/js/utils/sales_common.js b/erpnext/public/js/utils/sales_common.js index b92b02e826..b8ec77f8e5 100644 --- a/erpnext/public/js/utils/sales_common.js +++ b/erpnext/public/js/utils/sales_common.js @@ -22,6 +22,15 @@ erpnext.sales_common = { } }; }); + + this.frm.set_query('project', function(doc) { + return { + query: "erpnext.controllers.queries.get_project_name", + filters: { + 'customer': doc.customer + } + } + }); } setup_queries() { @@ -439,4 +448,4 @@ erpnext.pre_sales = { } }); } -} \ No newline at end of file +} diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js index 56c745c00a..2bb093dbaf 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.js +++ b/erpnext/selling/doctype/sales_order/sales_order.js @@ -144,15 +144,6 @@ frappe.ui.form.on("Sales Order", { }; }); - frm.set_query('project', function(doc, cdt, cdn) { - return { - query: "erpnext.controllers.queries.get_project_name", - filters: { - 'customer': doc.customer - } - } - }); - frm.set_query('warehouse', 'items', function(doc, cdt, cdn) { let row = locals[cdt][cdn]; let query = { diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.js b/erpnext/stock/doctype/delivery_note/delivery_note.js index ec68549846..14aedca39e 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.js +++ b/erpnext/stock/doctype/delivery_note/delivery_note.js @@ -31,15 +31,6 @@ frappe.ui.form.on("Delivery Note", { }); erpnext.queries.setup_warehouse_query(frm); - frm.set_query('project', function(doc) { - return { - query: "erpnext.controllers.queries.get_project_name", - filters: { - 'customer': doc.customer - } - } - }) - frm.set_query('transporter', function() { return { filters: { From c7d58570144da48c993f76140f12f2f72b1e2b43 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Mon, 22 Jan 2024 16:43:54 +0530 Subject: [PATCH 13/15] fix: UOM needs to be whole number not being checked in quotations (cherry picked from commit aaf83da3e9a28244c0f57f01a86b98257bdf503b) --- erpnext/selling/doctype/quotation/quotation.py | 3 ++- .../selling/doctype/quotation/test_quotation.py | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/erpnext/selling/doctype/quotation/quotation.py b/erpnext/selling/doctype/quotation/quotation.py index ab74f7f738..654f2978fe 100644 --- a/erpnext/selling/doctype/quotation/quotation.py +++ b/erpnext/selling/doctype/quotation/quotation.py @@ -127,7 +127,8 @@ class Quotation(SellingController): def validate(self): super(Quotation, self).validate() self.set_status() - self.validate_uom_is_integer("stock_uom", "qty") + self.validate_uom_is_integer("stock_uom", "stock_qty") + self.validate_uom_is_integer("uom", "qty") self.validate_valid_till() self.set_customer_name() if self.items: diff --git a/erpnext/selling/doctype/quotation/test_quotation.py b/erpnext/selling/doctype/quotation/test_quotation.py index 590cd3d0cf..41463eb2e5 100644 --- a/erpnext/selling/doctype/quotation/test_quotation.py +++ b/erpnext/selling/doctype/quotation/test_quotation.py @@ -581,6 +581,22 @@ class TestQuotation(FrappeTestCase): quotation.reload() self.assertEqual(quotation.status, "Ordered") + def test_uom_validation(self): + from erpnext.stock.doctype.item.test_item import make_item + + item = "_Test Item FOR UOM Validation" + make_item(item, {"is_stock_item": 1}) + + if not frappe.db.exists("UOM", "lbs"): + frappe.get_doc({"doctype": "UOM", "uom_name": "lbs", "must_be_whole_number": 1}).insert() + else: + frappe.db.set_value("UOM", "lbs", "must_be_whole_number", 1) + + quotation = make_quotation(item_code=item, qty=1, rate=100, do_not_submit=1) + quotation.items[0].uom = "lbs" + quotation.items[0].conversion_factor = 2.23 + self.assertRaises(frappe.ValidationError, quotation.save) + test_records = frappe.get_test_records("Quotation") From c76145985d0962272756814ecbdb12bf2c68a6ab Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Sun, 21 Jan 2024 20:46:57 +0530 Subject: [PATCH 14/15] fix: UX improvements for Serial and Batch Bundle (cherry picked from commit 5d94f0bde55329411c419c242749e0260d3bb7c9) --- .../js/utils/serial_no_batch_selector.js | 71 ++++++++++++++++++- .../serial_and_batch_bundle.py | 16 +++++ 2 files changed, 84 insertions(+), 3 deletions(-) diff --git a/erpnext/public/js/utils/serial_no_batch_selector.js b/erpnext/public/js/utils/serial_no_batch_selector.js index bf362e338e..6c775f0db8 100644 --- a/erpnext/public/js/utils/serial_no_batch_selector.js +++ b/erpnext/public/js/utils/serial_no_batch_selector.js @@ -179,11 +179,52 @@ erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate { label = __('Serial Nos / Batch Nos'); } - return [ + let fields = [ { fieldtype: 'Section Break', label: __('{0} {1} via CSV File', [primary_label, label]) - }, + } + ] + + if (this.item?.has_serial_no) { + fields = [...fields, + { + fieldtype: 'Check', + label: __('Upload Using CSV file'), + fieldname: 'upload_using_csv', + default: 0, + }, + { + fieldtype: 'Section Break', + depends_on: 'eval:doc.upload_using_csv === 0', + }, + { + fieldtype: 'Small Text', + label: __('Serial Nos'), + fieldname: 'upload_serial_nos', + depends_on: 'eval:doc.upload_using_csv === 0', + }, + { + fieldtype: 'Column Break', + depends_on: 'eval:doc.upload_using_csv === 0', + }, + { + fieldtype: 'Button', + fieldname: 'make_serial_nos', + label: __('Create Serial Nos'), + depends_on: 'eval:doc.upload_using_csv === 0', + click: () => { + this.create_serial_nos(); + } + }, + { + fieldtype: 'Section Break', + depends_on: 'eval:doc.upload_using_csv === 1', + } + ]; + } + + fields = [...fields, { fieldtype: 'Button', fieldname: 'download_csv', @@ -199,7 +240,31 @@ erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate { label: __('Attach CSV File'), onchange: () => this.upload_csv_file() } - ] + ]; + + return fields; + } + + create_serial_nos() { + let {upload_serial_nos} = this.dialog.get_values(); + + if (!upload_serial_nos) { + frappe.throw(__('Please enter Serial Nos')); + } + + frappe.call({ + method: 'erpnext.stock.doctype.serial_and_batch_bundle.serial_and_batch_bundle.create_serial_nos', + args: { + item_code: this.item.item_code, + serial_nos: upload_serial_nos + }, + callback: (r) => { + if (r.message) { + this.dialog.fields_dict.entries.df.data = []; + this.set_data(r.message); + } + } + }); } download_csv_file() { diff --git a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py index 2b87fcd175..856f1811e6 100644 --- a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py +++ b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py @@ -999,9 +999,25 @@ def get_serial_batch_from_data(item_code, kwargs): make_serial_nos(item_code, serial_nos) + if kwargs.get("_has_serial_nos"): + return serial_nos + return serial_nos, batch_nos +@frappe.whitelist() +def create_serial_nos(item_code, serial_nos): + serial_nos = get_serial_batch_from_data( + item_code, + { + "serial_nos": serial_nos, + "_has_serial_nos": True, + }, + ) + + return serial_nos + + def make_serial_nos(item_code, serial_nos): item = frappe.get_cached_value("Item", item_code, ["description", "item_code"], as_dict=1) From ca93f671df5f31468c2d39bdc0f500fe0860a525 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Mon, 22 Jan 2024 12:50:24 +0530 Subject: [PATCH 15/15] fix: auto create serial no on scan (cherry picked from commit fc0d2aeeffed9a2f87be0d87f0a0af0e837c5955) --- erpnext/public/js/utils/barcode_scanner.js | 93 ++++++++++++------- .../js/utils/serial_no_batch_selector.js | 43 +++++++-- .../serial_and_batch_bundle.js | 2 +- .../serial_and_batch_bundle.py | 29 ++++++ 4 files changed, 120 insertions(+), 47 deletions(-) diff --git a/erpnext/public/js/utils/barcode_scanner.js b/erpnext/public/js/utils/barcode_scanner.js index cf7fab89ff..aacab0fe6c 100644 --- a/erpnext/public/js/utils/barcode_scanner.js +++ b/erpnext/public/js/utils/barcode_scanner.js @@ -105,32 +105,47 @@ erpnext.utils.BarcodeScanner = class BarcodeScanner { this.frm.has_items = false; } - if (serial_no && this.is_duplicate_serial_no(row, item_code, serial_no)) { - this.clean_up(); - reject(); - return; + if (serial_no) { + this.is_duplicate_serial_no(row, item_code, serial_no) + .then((is_duplicate) => { + if (!is_duplicate) { + this.run_serially_tasks(row, data, resolve); + } else { + this.clean_up(); + reject(); + return; + } + }); + } else { + this.run_serially_tasks(row, data, resolve); } - frappe.run_serially([ - () => this.set_serial_and_batch(row, item_code, serial_no, batch_no), - () => this.set_barcode(row, barcode), - () => this.set_item(row, item_code, barcode, batch_no, serial_no).then(qty => { - this.show_scan_message(row.idx, row.item_code, qty); - }), - () => this.set_barcode_uom(row, uom), - () => this.clean_up(), - () => resolve(row), - () => { - if (row.serial_and_batch_bundle && !this.frm.is_new()) { - this.frm.save(); - } - frappe.flags.trigger_from_barcode_scanner = false; - } - ]); }); } + run_serially_tasks(row, data, resolve) { + const {item_code, barcode, batch_no, serial_no, uom} = data; + + frappe.run_serially([ + () => this.set_serial_and_batch(row, item_code, serial_no, batch_no), + () => this.set_barcode(row, barcode), + () => this.set_item(row, item_code, barcode, batch_no, serial_no).then(qty => { + this.show_scan_message(row.idx, row.item_code, qty); + }), + () => this.set_barcode_uom(row, uom), + () => this.clean_up(), + () => { + if (row.serial_and_batch_bundle && !this.frm.is_new()) { + this.frm.save(); + } + + frappe.flags.trigger_from_barcode_scanner = false; + }, + () => resolve(row), + ]); + } + set_item(row, item_code, barcode, batch_no, serial_no) { return new Promise(resolve => { const increment = async (value = 1) => { @@ -475,26 +490,32 @@ erpnext.utils.BarcodeScanner = class BarcodeScanner { } } - is_duplicate_serial_no(row, item_code, serial_no) { - if (this.frm.is_new() || !row.serial_and_batch_bundle) { - let is_duplicate = this.check_duplicate_serial_no_in_localstorage(item_code, serial_no); - if (is_duplicate) { - this.show_alert(__("Serial No {0} is already added", [serial_no]), "orange"); - } - - return is_duplicate; - } else if (row.serial_and_batch_bundle) { - this.check_duplicate_serial_no_in_db(row, serial_no, (r) => { - if (r.message) { + async is_duplicate_serial_no(row, item_code, serial_no) { + let is_duplicate = false; + const promise = new Promise((resolve, reject) => { + if (this.frm.is_new() || !row.serial_and_batch_bundle) { + is_duplicate = this.check_duplicate_serial_no_in_localstorage(item_code, serial_no); + if (is_duplicate) { this.show_alert(__("Serial No {0} is already added", [serial_no]), "orange"); } - return r.message; - }) - } + resolve(is_duplicate); + } else if (row.serial_and_batch_bundle) { + this.check_duplicate_serial_no_in_db(row, serial_no, (r) => { + if (r.message) { + this.show_alert(__("Serial No {0} is already added", [serial_no]), "orange"); + } + + is_duplicate = r.message; + resolve(is_duplicate); + }) + } + }); + + return await promise; } - async check_duplicate_serial_no_in_db(row, serial_no, response) { + check_duplicate_serial_no_in_db(row, serial_no, response) { frappe.call({ method: "erpnext.stock.doctype.serial_and_batch_bundle.serial_and_batch_bundle.is_duplicate_serial_no", args: { @@ -504,7 +525,7 @@ erpnext.utils.BarcodeScanner = class BarcodeScanner { callback(r) { response(r); } - }) + }); } check_duplicate_serial_no_in_localstorage(item_code, serial_no) { diff --git a/erpnext/public/js/utils/serial_no_batch_selector.js b/erpnext/public/js/utils/serial_no_batch_selector.js index 6c775f0db8..44a4957b41 100644 --- a/erpnext/public/js/utils/serial_no_batch_selector.js +++ b/erpnext/public/js/utils/serial_no_batch_selector.js @@ -135,7 +135,7 @@ erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate { filters: this.get_serial_no_filters() }; }, - onchange: () => this.update_serial_batch_no() + onchange: () => this.scan_barcode_data() }); } @@ -145,7 +145,7 @@ erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate { options: 'Barcode', fieldname: 'scan_batch_no', label: __('Scan Batch No'), - onchange: () => this.update_serial_batch_no() + onchange: () => this.scan_barcode_data() }); } @@ -190,36 +190,38 @@ erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate { fields = [...fields, { fieldtype: 'Check', - label: __('Upload Using CSV file'), - fieldname: 'upload_using_csv', + label: __('Import Using CSV file'), + fieldname: 'import_using_csv_file', default: 0, }, { fieldtype: 'Section Break', - depends_on: 'eval:doc.upload_using_csv === 0', + label: __('{0} {1} Manually', [primary_label, label]), + depends_on: 'eval:doc.import_using_csv_file === 0', }, { fieldtype: 'Small Text', - label: __('Serial Nos'), + label: __('Enter Serial Nos'), fieldname: 'upload_serial_nos', - depends_on: 'eval:doc.upload_using_csv === 0', + depends_on: 'eval:doc.import_using_csv_file === 0', + description: __('Enter each serial no in a new line'), }, { fieldtype: 'Column Break', - depends_on: 'eval:doc.upload_using_csv === 0', + depends_on: 'eval:doc.import_using_csv_file === 0', }, { fieldtype: 'Button', fieldname: 'make_serial_nos', label: __('Create Serial Nos'), - depends_on: 'eval:doc.upload_using_csv === 0', + depends_on: 'eval:doc.import_using_csv_file === 0', click: () => { this.create_serial_nos(); } }, { fieldtype: 'Section Break', - depends_on: 'eval:doc.upload_using_csv === 1', + depends_on: 'eval:doc.import_using_csv_file === 1', } ]; } @@ -262,6 +264,7 @@ erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate { if (r.message) { this.dialog.fields_dict.entries.df.data = []; this.set_data(r.message); + this.update_bundle_entries(); } } }); @@ -439,6 +442,26 @@ erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate { } } + scan_barcode_data() { + const { scan_serial_no, scan_batch_no } = this.dialog.get_values(); + + if (scan_serial_no || scan_batch_no) { + frappe.call({ + method: 'erpnext.stock.doctype.serial_and_batch_bundle.serial_and_batch_bundle.is_serial_batch_no_exists', + args: { + item_code: this.item.item_code, + type_of_transaction: this.item.type_of_transaction, + serial_no: scan_serial_no, + batch_no: scan_batch_no, + }, + callback: (r) => { + this.update_serial_batch_no(); + } + + }) + } + } + update_serial_batch_no() { const { scan_serial_no, scan_batch_no } = this.dialog.get_values(); diff --git a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.js b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.js index 9f01ee9ae6..91b743016b 100644 --- a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.js +++ b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.js @@ -74,7 +74,7 @@ frappe.ui.form.on('Serial and Batch Bundle', { let fields = [ { - "label": __("Using CSV File"), + "label": __("Import Using CSV file"), "fieldname": "using_csv_file", "default": 1, "fieldtype": "Check", diff --git a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py index 856f1811e6..63cc938c09 100644 --- a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py +++ b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py @@ -2095,6 +2095,35 @@ def get_batch_no_from_serial_no(serial_no): return frappe.get_cached_value("Serial No", serial_no, "batch_no") +@frappe.whitelist() +def is_serial_batch_no_exists(item_code, type_of_transaction, serial_no=None, batch_no=None): + if serial_no and not frappe.db.exists("Serial No", serial_no): + if type_of_transaction != "Inward": + frappe.throw(_("Serial No {0} does not exists").format(serial_no)) + + make_serial_no(serial_no, item_code) + + if batch_no and frappe.db.exists("Batch", batch_no): + if type_of_transaction != "Inward": + frappe.throw(_("Batch No {0} does not exists").format(batch_no)) + + make_batch_no(batch_no, item_code) + + +def make_serial_no(serial_no, item_code): + serial_no_doc = frappe.new_doc("Serial No") + serial_no_doc.serial_no = serial_no + serial_no_doc.item_code = item_code + serial_no_doc.save(ignore_permissions=True) + + +def make_batch_no(batch_no, item_code): + batch_doc = frappe.new_doc("Batch") + batch_doc.batch_id = batch_no + batch_doc.item = item_code + batch_doc.save(ignore_permissions=True) + + @frappe.whitelist() def is_duplicate_serial_no(bundle_id, serial_no): return frappe.db.exists("Serial and Batch Entry", {"parent": bundle_id, "serial_no": serial_no})