From ad2d6a16258235a20d041174458e32bb6ebad8f7 Mon Sep 17 00:00:00 2001 From: sameer Chauhan Date: Fri, 13 Sep 2024 17:32:44 +0530 Subject: [PATCH 01/32] fix: Payment Ledger Report currency fieldtype fix --- erpnext/accounts/report/payment_ledger/payment_ledger.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/report/payment_ledger/payment_ledger.py b/erpnext/accounts/report/payment_ledger/payment_ledger.py index 9852c6e7ab99..d4f0f0a107d9 100644 --- a/erpnext/accounts/report/payment_ledger/payment_ledger.py +++ b/erpnext/accounts/report/payment_ledger/payment_ledger.py @@ -210,7 +210,7 @@ def get_columns(self): ) ) self.columns.append( - dict(label=_("Currency"), fieldname="currency", fieldtype="Currency", hidden=True) + dict(label=_("Currency"), fieldname="currency", fieldtype="Link", options="Currency", hidden=True) ) def run(self): From 73d98addbcbdb236cda9da130ff9a59a1f942a37 Mon Sep 17 00:00:00 2001 From: "Nihantra C. Patel" <141945075+Nihantra-Patel@users.noreply.github.com> Date: Wed, 18 Sep 2024 21:36:02 +0530 Subject: [PATCH 02/32] fix: Translation for button SO to PO (cherry picked from commit a5275e9f28bb54c286cad7ae697ab37f9e5e8794) --- erpnext/selling/doctype/sales_order/sales_order.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js index cdcd1047bd89..5387286c7099 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.js +++ b/erpnext/selling/doctype/sales_order/sales_order.js @@ -1251,7 +1251,7 @@ erpnext.selling.SalesOrderController = class SalesOrderController extends erpnex ], }, ], - primary_action_label: "Create Purchase Order", + primary_action_label: __("Create Purchase Order"), primary_action(args) { if (!args) return; From 557ef5d214abee8b7e7a7838a940a40e6f8d1477 Mon Sep 17 00:00:00 2001 From: Shariq Ansari Date: Wed, 18 Sep 2024 21:53:27 +0530 Subject: [PATCH 03/32] fix: create_address is failing (cherry picked from commit acc1d52ac8e51a4fd87cdfcfc7f5c0639157fad9) --- erpnext/crm/frappe_crm_api.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/erpnext/crm/frappe_crm_api.py b/erpnext/crm/frappe_crm_api.py index 53f58ed57eb1..a00f0ba798db 100644 --- a/erpnext/crm/frappe_crm_api.py +++ b/erpnext/crm/frappe_crm_api.py @@ -95,6 +95,8 @@ def create_contacts(contacts, organization=None, link_doctype=None, link_docname def create_address(doctype, docname, address): if not address: return + if isinstance(address, str): + address = json.loads(address) try: _address = frappe.db.exists("Address", address.get("name")) if not _address: @@ -105,6 +107,7 @@ def create_address(doctype, docname, address): "address_line1", "address_line2", "city", + "county", "state", "pincode", "country", From 84e26e21abbbe0c8a8ab508d4d408e89e2e79467 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Do=C4=9Fancan?= <37839267+doancan@users.noreply.github.com> Date: Wed, 18 Sep 2024 17:06:07 +0300 Subject: [PATCH 04/32] fix: translate in js (cherry picked from commit 25faec5662b317a19e99ad41b589380067b9fa53) --- erpnext/assets/doctype/asset/asset.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/assets/doctype/asset/asset.js b/erpnext/assets/doctype/asset/asset.js index 0a21516c1773..c6e76abb0b59 100644 --- a/erpnext/assets/doctype/asset/asset.js +++ b/erpnext/assets/doctype/asset/asset.js @@ -213,7 +213,7 @@ frappe.ui.form.on("Asset", {
- Failed to post depreciation entries + ${__("Failed to post depreciation entries")}
`; From f6725e2eed39c326bd031ebc969bd40adf6235e1 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Thu, 19 Sep 2024 09:35:54 +0530 Subject: [PATCH 05/32] fix: incorrect stock balance for inventory dimension (backport #43284) (#43290) fix: incorrect stock balance for inventory dimension (#43284) (cherry picked from commit 3e7a7a54bf0cda871e0814deb8776238270769b2) Co-authored-by: rohitwaghchaure --- erpnext/stock/report/stock_balance/stock_balance.js | 6 ++++++ erpnext/stock/report/stock_balance/stock_balance.py | 5 ++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/erpnext/stock/report/stock_balance/stock_balance.js b/erpnext/stock/report/stock_balance/stock_balance.js index d80261895aa5..1d86634fd951 100644 --- a/erpnext/stock/report/stock_balance/stock_balance.js +++ b/erpnext/stock/report/stock_balance/stock_balance.js @@ -107,6 +107,12 @@ frappe.query_reports["Stock Balance"] = { fieldtype: "Check", default: 0, }, + { + fieldname: "show_dimension_wise_stock", + label: __("Show Dimension Wise Stock"), + fieldtype: "Check", + default: 0, + }, ], formatter: function (value, row, column, data, default_formatter) { diff --git a/erpnext/stock/report/stock_balance/stock_balance.py b/erpnext/stock/report/stock_balance/stock_balance.py index 2694ba03c8be..8ea07338cf1b 100644 --- a/erpnext/stock/report/stock_balance/stock_balance.py +++ b/erpnext/stock/report/stock_balance/stock_balance.py @@ -252,7 +252,10 @@ def get_group_by_key(self, row) -> tuple: group_by_key = [row.company, row.item_code, row.warehouse] for fieldname in self.inventory_dimensions: - if self.filters.get(fieldname): + if not row.get(fieldname): + continue + + if self.filters.get(fieldname) or self.filters.get("show_dimension_wise_stock"): group_by_key.append(row.get(fieldname)) return tuple(group_by_key) From 86ae64457474108ba4575a93aad4bc1380b9d1e9 Mon Sep 17 00:00:00 2001 From: HENRY Florian Date: Sat, 21 Sep 2024 03:16:57 +0200 Subject: [PATCH 06/32] refactor: use common functionality to validate account number (#42842) feat: Allow unique Account number by root type (not unique for accros all Accounts) (cherry picked from commit 40d97f4fe9da3b16e8c67d0d06ccdb41bdc63c99) --- erpnext/accounts/doctype/account/account.py | 35 +++++++++++---------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/erpnext/accounts/doctype/account/account.py b/erpnext/accounts/doctype/account/account.py index 1a5ee36b95af..2c876e09725f 100644 --- a/erpnext/accounts/doctype/account/account.py +++ b/erpnext/accounts/doctype/account/account.py @@ -103,14 +103,12 @@ def autoname(self): self.name = get_autoname_with_number(self.account_number, self.account_name, self.company) def validate(self): - from erpnext.accounts.utils import validate_field_number - if frappe.local.flags.allow_unverified_charts: return self.validate_parent() self.validate_parent_child_account_type() self.validate_root_details() - validate_field_number("Account", self.name, self.account_number, self.company, "account_number") + self.validate_account_number() self.validate_group_or_ledger() self.set_root_and_report_type() self.validate_mandatory() @@ -311,6 +309,22 @@ def validate_account_currency(self): if frappe.db.get_value("GL Entry", {"account": self.name}): frappe.throw(_("Currency can not be changed after making entries using some other currency")) + def validate_account_number(self, account_number=None): + if not account_number: + account_number = self.account_number + + if account_number: + account_with_same_number = frappe.db.get_value( + "Account", + {"account_number": account_number, "company": self.company, "name": ["!=", self.name]}, + ) + if account_with_same_number: + frappe.throw( + _("Account Number {0} already used in account {1}").format( + account_number, account_with_same_number + ) + ) + def create_account_for_child_company(self, parent_acc_name_map, descendants, parent_acc_name): for company in descendants: company_bold = frappe.bold(company) @@ -464,19 +478,6 @@ def get_account_autoname(account_number, account_name, company): return " - ".join(parts) -def validate_account_number(name, account_number, company): - if account_number: - account_with_same_number = frappe.db.get_value( - "Account", {"account_number": account_number, "company": company, "name": ["!=", name]} - ) - if account_with_same_number: - frappe.throw( - _("Account Number {0} already used in account {1}").format( - account_number, account_with_same_number - ) - ) - - @frappe.whitelist() def update_account_number(name, account_name, account_number=None, from_descendant=False): account = frappe.get_cached_doc("Account", name) @@ -517,7 +518,7 @@ def update_account_number(name, account_name, account_number=None, from_descenda frappe.throw(message, title=_("Rename Not Allowed")) - validate_account_number(name, account_number, account.company) + account.validate_account_number(account_number) if account_number: frappe.db.set_value("Account", name, "account_number", account_number.strip()) else: From 7e6d6f08a20a03ff5603d9b991d4ea69960780c5 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Sun, 22 Sep 2024 11:18:42 +0530 Subject: [PATCH 07/32] fix: ui clean-up (backport #43305) (#43312) * fix: ui clean-up (#43305) fix: ui cleanup (cherry picked from commit b127a0c8b7fd4e1dede7c23c3f59e0562c4945b2) # Conflicts: # erpnext/manufacturing/doctype/bom_creator/bom_creator.json # erpnext/manufacturing/doctype/plant_floor/plant_floor.json # erpnext/public/js/templates/visual_plant_floor_template.html * chore: fix conflicts * chore: fix conflicts * chore: fix conflicts --------- Co-authored-by: rohitwaghchaure --- .../doctype/bom_creator/bom_creator.json | 3 +- .../doctype/plant_floor/plant_floor.js | 21 ++++++++++ .../doctype/plant_floor/plant_floor.json | 5 ++- .../doctype/work_order/work_order.js | 2 +- .../bom_configurator.bundle.js | 12 +++++- .../visual_plant_floor_template.html | 20 +++++++-- erpnext/public/scss/erpnext.scss | 41 +++++++++++++++++++ 7 files changed, 95 insertions(+), 9 deletions(-) diff --git a/erpnext/manufacturing/doctype/bom_creator/bom_creator.json b/erpnext/manufacturing/doctype/bom_creator/bom_creator.json index 9d2384e31a0e..65664be2bead 100644 --- a/erpnext/manufacturing/doctype/bom_creator/bom_creator.json +++ b/erpnext/manufacturing/doctype/bom_creator/bom_creator.json @@ -280,6 +280,7 @@ "read_only": 1 } ], + "hide_toolbar": 1, "icon": "fa fa-sitemap", "is_submittable": 1, "links": [ @@ -288,7 +289,7 @@ "link_fieldname": "bom_creator" } ], - "modified": "2024-04-02 16:30:59.779190", + "modified": "2024-09-21 09:05:52.945112", "modified_by": "Administrator", "module": "Manufacturing", "name": "BOM Creator", diff --git a/erpnext/manufacturing/doctype/plant_floor/plant_floor.js b/erpnext/manufacturing/doctype/plant_floor/plant_floor.js index becdbdb9c95a..3d18900b70cb 100644 --- a/erpnext/manufacturing/doctype/plant_floor/plant_floor.js +++ b/erpnext/manufacturing/doctype/plant_floor/plant_floor.js @@ -6,6 +6,22 @@ frappe.ui.form.on("Plant Floor", { frm.trigger("setup_queries"); }, + add_workstation(frm) { + frm.add_custom_button(__("Create Workstation"), () => { + var doc = frappe.model.get_new_doc("Workstation"); + doc.plant_floor = frm.doc.name; + doc.status = "Off"; + frappe.ui.form.make_quick_entry( + "Workstation", + () => { + frm.trigger("prepare_workstation_dashboard"); + }, + null, + doc + ); + }).addClass("btn-primary"); + }, + setup_queries(frm) { frm.set_query("warehouse", (doc) => { if (!doc.company) { @@ -24,6 +40,11 @@ frappe.ui.form.on("Plant Floor", { refresh(frm) { frm.trigger("prepare_stock_dashboard"); frm.trigger("prepare_workstation_dashboard"); + + if (!frm.is_new()) { + frm.trigger("add_workstation"); + frm.disable_save(); + } }, prepare_workstation_dashboard(frm) { diff --git a/erpnext/manufacturing/doctype/plant_floor/plant_floor.json b/erpnext/manufacturing/doctype/plant_floor/plant_floor.json index be0052c47bf5..c1c167c395b6 100644 --- a/erpnext/manufacturing/doctype/plant_floor/plant_floor.json +++ b/erpnext/manufacturing/doctype/plant_floor/plant_floor.json @@ -69,9 +69,10 @@ "options": "Company" } ], + "hide_toolbar": 1, "index_web_pages_for_search": 1, "links": [], - "modified": "2024-01-30 11:59:07.508535", + "modified": "2024-09-19 19:06:36.481625", "modified_by": "Administrator", "module": "Manufacturing", "name": "Plant Floor", @@ -94,4 +95,4 @@ "sort_field": "modified", "sort_order": "DESC", "states": [] -} \ No newline at end of file +} diff --git a/erpnext/manufacturing/doctype/work_order/work_order.js b/erpnext/manufacturing/doctype/work_order/work_order.js index ae888c797144..df72b1e6b510 100644 --- a/erpnext/manufacturing/doctype/work_order/work_order.js +++ b/erpnext/manufacturing/doctype/work_order/work_order.js @@ -201,7 +201,7 @@ frappe.ui.form.on("Work Order", { frm.doc.produced_qty > 0 ) { frm.add_custom_button( - __("Disassembly Order"), + __("Disassemble Order"), () => { frm.trigger("make_disassembly_order"); }, diff --git a/erpnext/public/js/bom_configurator/bom_configurator.bundle.js b/erpnext/public/js/bom_configurator/bom_configurator.bundle.js index 5061be9d20a2..21aa70fe7ae5 100644 --- a/erpnext/public/js/bom_configurator/bom_configurator.bundle.js +++ b/erpnext/public/js/bom_configurator/bom_configurator.bundle.js @@ -25,6 +25,9 @@ class BOMConfigurator { }; frappe.views.trees["BOM Configurator"] = new frappe.views.TreeView(options); + let node = frappe.views.trees["BOM Configurator"].tree.root_node; + frappe.views.trees["BOM Configurator"].tree.show_toolbar(node); + frappe.views.trees["BOM Configurator"].tree.load_children(node, true); this.tree_view = frappe.views.trees["BOM Configurator"]; } @@ -137,7 +140,7 @@ class BOMConfigurator { btnClass: "hidden-xs", }, { - label: __("Expand All"), + label: __("Collapse All"), click: function (node) { let view = frappe.views.trees["BOM Configurator"]; @@ -283,6 +286,13 @@ class BOMConfigurator { fieldtype: "Float", reqd: 1, read_only: read_only, + change() { + this.layout.fields_dict.items.grid.data.forEach((row) => { + row.qty = flt(this.value); + }); + + this.layout.fields_dict.items.grid.refresh(); + }, }, { fieldtype: "Section Break" }, { diff --git a/erpnext/public/js/templates/visual_plant_floor_template.html b/erpnext/public/js/templates/visual_plant_floor_template.html index 2e67085c0221..a1639f073702 100644 --- a/erpnext/public/js/templates/visual_plant_floor_template.html +++ b/erpnext/public/js/templates/visual_plant_floor_template.html @@ -1,5 +1,16 @@ {% $.each(workstations, (idx, row) => { %}
+
+ {% if(row.status == "Production") { %} +
+
+
+
+ {% } %} + + {{row.status}} + +
-
-

{{row.status}}

-
{{row.workstation_name}}
+
+ + {{row.workstation_name}} +
-{% }); %} \ No newline at end of file +{% }); %} diff --git a/erpnext/public/scss/erpnext.scss b/erpnext/public/scss/erpnext.scss index 03dd31104e1e..29a2696470f4 100644 --- a/erpnext/public/scss/erpnext.scss +++ b/erpnext/public/scss/erpnext.scss @@ -507,6 +507,47 @@ body[data-route="pos"] { position: relative; } +.ring-container { + position: relative; +} + +.circle { + width: 9px; + height: 9px; + background-color: #278f5e; + border-radius: 50%; + position: absolute; + left: 9px; + top: 8px; +} + +@keyframes pulsate { + 0% { + -webkit-transform: scale(0.1, 0.1); + opacity: 0; + } + 50% { + opacity: 1; + } + 100% { + -webkit-transform: scale(1.2, 1.2); + opacity: 0; + } +} + +.ringring { + border: 2px solid #62bd19; + -webkit-border-radius: 40px; + height: 15px; + width: 15px; + position: absolute; + left: 6px; + top: 5px; + -webkit-animation: pulsate 3s ease-out; + -webkit-animation-iteration-count: infinite; + opacity: 0; +} + .plant-floor { padding-bottom: 25px; } From 63d4fddb493e4ba1ec1b178464f5fd671da1fd8c Mon Sep 17 00:00:00 2001 From: venkat102 Date: Mon, 23 Sep 2024 12:37:40 +0530 Subject: [PATCH 08/32] fix: make to tax category on tax rule to filter with percent (cherry picked from commit 3aaa13cb2925cadae926ab7241559b80b0a9d0bd) --- erpnext/accounts/doctype/tax_rule/tax_rule.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/tax_rule/tax_rule.py b/erpnext/accounts/doctype/tax_rule/tax_rule.py index ed623c6635e6..1c0c0a3c1d61 100644 --- a/erpnext/accounts/doctype/tax_rule/tax_rule.py +++ b/erpnext/accounts/doctype/tax_rule/tax_rule.py @@ -185,7 +185,7 @@ def get_tax_template(posting_date, args): conditions.append("(from_date is null) and (to_date is null)") conditions.append( - "ifnull(tax_category, '') = {}".format(frappe.db.escape(cstr(args.get("tax_category")))) + "ifnull(tax_category, '') = {}".format(frappe.db.escape(cstr(args.get("tax_category")), False)) ) if "tax_category" in args.keys(): del args["tax_category"] From 40459288f6c4bdcb88dc284c6874b1294a6b88a5 Mon Sep 17 00:00:00 2001 From: ljain112 Date: Sat, 21 Sep 2024 15:02:40 +0530 Subject: [PATCH 09/32] fix: handle missing liability account scenario in `set_liability_account` (cherry picked from commit ee7ab4b065a2a76cbfa5e5f78ffd3c0b0275dacf) --- .../doctype/payment_entry/payment_entry.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index 13baff9e7a82..625608b5374b 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -145,9 +145,21 @@ def set_liability_account(self): self.is_opening = "No" return - liability_account = get_party_account( - self.party_type, self.party, self.company, include_advance=True - )[1] + accounts = get_party_account(self.party_type, self.party, self.company, include_advance=True) + + liability_account = accounts[1] if len(accounts) > 1 else None + fieldname = ( + "default_advance_received_account" + if self.party_type == "Customer" + else "default_advance_paid_account" + ) + + if not liability_account: + throw( + _("Please set default {0} in Company {1}").format( + frappe.bold(frappe.get_meta("Company").get_label(fieldname)), frappe.bold(self.company) + ) + ) self.set(self.party_account_field, liability_account) From a7ccc9420ba8fa30b7809b299a91ae3501d0b4fb Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 23 Sep 2024 14:37:12 +0530 Subject: [PATCH 10/32] fix: transaction exchange rate on GL's for Multi currency Journals (cherry picked from commit 8cd9ad53617f6e5bb7a35e8f05fa9fd0cb4d3330) --- erpnext/controllers/accounts_controller.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 92efa5168f3b..44a9813c89eb 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -1036,7 +1036,9 @@ def get_gl_dict(self, args, account_currency=None, item=None): gl_dict.update( { "transaction_currency": self.get("currency") or self.company_currency, - "transaction_exchange_rate": self.get("conversion_rate", 1), + "transaction_exchange_rate": item.get("exchange_rate", 1) + if self.doctype == "Journal Entry" and item + else self.get("conversion_rate", 1), "debit_in_transaction_currency": self.get_value_in_transaction_currency( account_currency, gl_dict, "debit" ), From 2d9142832ded129093f2418c7e3f6f7cf887f113 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 23 Sep 2024 17:12:31 +0530 Subject: [PATCH 11/32] test: transaction exchange rate on multi-currency journals (cherry picked from commit c524825d2d7f1a385defb679c2e0df978dade742) --- .../doctype/journal_entry/test_journal_entry.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/erpnext/accounts/doctype/journal_entry/test_journal_entry.py b/erpnext/accounts/doctype/journal_entry/test_journal_entry.py index c53faf9ff390..3d4b182d52dc 100644 --- a/erpnext/accounts/doctype/journal_entry/test_journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/test_journal_entry.py @@ -515,6 +515,23 @@ def test_negative_debit_and_credit_with_same_account_head(self): self.assertEqual(row.debit_in_account_currency, 100) self.assertEqual(row.credit_in_account_currency, 100) + def test_transaction_exchange_rate_on_journals(self): + jv = make_journal_entry("_Test Bank - _TC", "_Test Receivable USD - _TC", 100, save=False) + jv.accounts[0].update({"debit_in_account_currency": 8500, "exchange_rate": 1}) + jv.accounts[1].update({"party_type": "Customer", "party": "_Test Customer USD", "exchange_rate": 85}) + jv.submit() + actual = frappe.db.get_all( + "GL Entry", + filters={"voucher_no": jv.name, "is_cancelled": 0}, + fields=["account", "transaction_exchange_rate"], + order_by="account", + ) + expected = [ + {"account": "_Test Bank - _TC", "transaction_exchange_rate": 1.0}, + {"account": "_Test Receivable USD - _TC", "transaction_exchange_rate": 85.0}, + ] + self.assertEqual(expected, actual) + def make_journal_entry( account1, From f89a3dbb6562bed6fa22088a63cd363f612ffbfd Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Sat, 21 Sep 2024 12:27:53 +0530 Subject: [PATCH 12/32] fix: incorrect outstanding on non-pos invoice with write_off_account (cherry picked from commit d5e2906e5974117d91dd265319186a99b2835023) --- erpnext/accounts/doctype/sales_invoice/sales_invoice.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 1214ddee8cd2..010d3b8bcd5c 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -340,6 +340,7 @@ def validate(self): ): validate_loyalty_points(self, self.loyalty_points) + self.allow_write_off_only_on_pos() self.reset_default_field_value("set_warehouse", "items", "warehouse") def validate_accounts(self): @@ -1021,6 +1022,10 @@ def validate_delivery_note(self): raise_exception=1, ) + def allow_write_off_only_on_pos(self): + if not self.is_pos and self.write_off_account: + self.write_off_account = None + def validate_write_off_account(self): if flt(self.write_off_amount) and not self.write_off_account: self.write_off_account = frappe.get_cached_value("Company", self.company, "write_off_account") From e5ae828580693d0f4b370868f39d70b649de4a7c Mon Sep 17 00:00:00 2001 From: venkat102 Date: Fri, 20 Sep 2024 11:43:00 +0530 Subject: [PATCH 13/32] fix: show chart tool tip in report currency (cherry picked from commit 827b3f454241a6e2b9e4a0bcc8bb15bfb4e7ef3e) --- erpnext/accounts/report/balance_sheet/balance_sheet.py | 8 ++++++-- erpnext/accounts/report/cash_flow/cash_flow.py | 6 ++++-- .../profit_and_loss_statement.py | 8 +++++--- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/erpnext/accounts/report/balance_sheet/balance_sheet.py b/erpnext/accounts/report/balance_sheet/balance_sheet.py index e89a177a8671..274c8a7a3714 100644 --- a/erpnext/accounts/report/balance_sheet/balance_sheet.py +++ b/erpnext/accounts/report/balance_sheet/balance_sheet.py @@ -95,7 +95,7 @@ def execute(filters=None): filters.periodicity, period_list, filters.accumulated_values, company=filters.company ) - chart = get_chart_data(filters, columns, asset, liability, equity) + chart = get_chart_data(filters, columns, asset, liability, equity, currency) report_summary, primitive_summary = get_report_summary( period_list, asset, liability, equity, provisional_profit_loss, currency, filters @@ -221,7 +221,7 @@ def get_report_summary( ], (net_asset - net_liability + net_equity) -def get_chart_data(filters, columns, asset, liability, equity): +def get_chart_data(filters, columns, asset, liability, equity, currency): labels = [d.get("label") for d in columns[2:]] asset_data, liability_data, equity_data = [], [], [] @@ -249,4 +249,8 @@ def get_chart_data(filters, columns, asset, liability, equity): else: chart["type"] = "line" + chart["fieldtype"] = "Currency" + chart["options"] = "currency" + chart["currency"] = currency + return chart diff --git a/erpnext/accounts/report/cash_flow/cash_flow.py b/erpnext/accounts/report/cash_flow/cash_flow.py index c034f95ec002..9b4416714158 100644 --- a/erpnext/accounts/report/cash_flow/cash_flow.py +++ b/erpnext/accounts/report/cash_flow/cash_flow.py @@ -111,7 +111,7 @@ def execute(filters=None): ) columns = get_columns(filters.periodicity, period_list, filters.accumulated_values, filters.company) - chart = get_chart_data(columns, data) + chart = get_chart_data(columns, data, company_currency) report_summary = get_report_summary(summary_data, company_currency) @@ -252,7 +252,7 @@ def get_report_summary(summary_data, currency): return report_summary -def get_chart_data(columns, data): +def get_chart_data(columns, data, currency): labels = [d.get("label") for d in columns[2:]] datasets = [ { @@ -267,5 +267,7 @@ def get_chart_data(columns, data): chart = {"data": {"labels": labels, "datasets": datasets}, "type": "bar"} chart["fieldtype"] = "Currency" + chart["options"] = "currency" + chart["currency"] = currency return chart diff --git a/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py b/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py index 58610b22a93c..35453f2ec442 100644 --- a/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py +++ b/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py @@ -59,11 +59,11 @@ def execute(filters=None): columns = get_columns(filters.periodicity, period_list, filters.accumulated_values, filters.company) - chart = get_chart_data(filters, columns, income, expense, net_profit_loss) - currency = filters.presentation_currency or frappe.get_cached_value( "Company", filters.company, "default_currency" ) + chart = get_chart_data(filters, columns, income, expense, net_profit_loss, currency) + report_summary, primitive_summary = get_report_summary( period_list, filters.periodicity, income, expense, net_profit_loss, currency, filters ) @@ -152,7 +152,7 @@ def get_net_profit_loss(income, expense, period_list, company, currency=None, co return net_profit_loss -def get_chart_data(filters, columns, income, expense, net_profit_loss): +def get_chart_data(filters, columns, income, expense, net_profit_loss, currency): labels = [d.get("label") for d in columns[2:]] income_data, expense_data, net_profit = [], [], [] @@ -181,5 +181,7 @@ def get_chart_data(filters, columns, income, expense, net_profit_loss): chart["type"] = "line" chart["fieldtype"] = "Currency" + chart["options"] = "currency" + chart["currency"] = currency return chart From 927f80035d4796bb1f75cede6c7aba16035bb5b7 Mon Sep 17 00:00:00 2001 From: venkat102 Date: Fri, 20 Sep 2024 12:22:03 +0530 Subject: [PATCH 14/32] fix: add currency in financial statement (cherry picked from commit 91a27bda842cc6d86f65daa35bcc9d68921ab805) --- .../consolidated_financial_statement.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py b/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py index 2931b728a424..e6aa215924d1 100644 --- a/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py +++ b/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py @@ -115,7 +115,7 @@ def get_balance_sheet_data(fiscal_year, companies, columns, filters): True, ) - chart = get_chart_data(filters, columns, asset, liability, equity) + chart = get_chart_data(filters, columns, asset, liability, equity, company_currency) return data, message, chart, report_summary @@ -173,7 +173,7 @@ def get_profit_loss_data(fiscal_year, companies, columns, filters): if net_profit_loss: data.append(net_profit_loss) - chart = get_pl_chart_data(filters, columns, income, expense, net_profit_loss) + chart = get_pl_chart_data(filters, columns, income, expense, net_profit_loss, company_currency) report_summary, primitive_summary = get_pl_summary( companies, "", income, expense, net_profit_loss, company_currency, filters, True From 05c92cce71152f944086c272199540a2d323703b Mon Sep 17 00:00:00 2001 From: venkat102 Date: Fri, 20 Sep 2024 10:53:45 +0530 Subject: [PATCH 15/32] fix: change dynamic link doctype fieldtype to data (cherry picked from commit 1e46f7344af08a89b8daf82c0dba394290b1bf7b) --- .../general_and_payment_ledger_comparison.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/report/general_and_payment_ledger_comparison/general_and_payment_ledger_comparison.py b/erpnext/accounts/report/general_and_payment_ledger_comparison/general_and_payment_ledger_comparison.py index 89cf7e504f0c..9d079eb9ebd2 100644 --- a/erpnext/accounts/report/general_and_payment_ledger_comparison/general_and_payment_ledger_comparison.py +++ b/erpnext/accounts/report/general_and_payment_ledger_comparison/general_and_payment_ledger_comparison.py @@ -199,8 +199,7 @@ def get_columns(self): dict( label=_("Voucher Type"), fieldname="voucher_type", - fieldtype="Link", - options="DocType", + fieldtype="Data", width="100", ) ) @@ -219,8 +218,7 @@ def get_columns(self): dict( label=_("Party Type"), fieldname="party_type", - fieldtype="Link", - options="DocType", + fieldtype="Data", width="100", ) ) From b99ca7d9e988a09e32a9f85848184c829b805648 Mon Sep 17 00:00:00 2001 From: "Nihantra C. Patel" <141945075+Nihantra-Patel@users.noreply.github.com> Date: Tue, 17 Sep 2024 14:51:26 +0530 Subject: [PATCH 16/32] fix: partial return on POS invoice (cherry picked from commit 76289fa8dcf3ee670d9c6976e4d53e7ce230cb6c) --- erpnext/accounts/doctype/pos_invoice/pos_invoice.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py index d517c9d6da22..ce3da4ac7dd3 100644 --- a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py +++ b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py @@ -452,8 +452,8 @@ def validate_payment_amount(self): if self.is_return: invoice_total = self.rounded_total or self.grand_total total_amount_in_payments = flt(total_amount_in_payments, self.precision("grand_total")) - if total_amount_in_payments and total_amount_in_payments < invoice_total: - frappe.throw(_("Total payments amount can't be greater than {}").format(-invoice_total)) + if total_amount_in_payments and total_amount_in_payments > invoice_total: + frappe.throw(_("Total payments amount can't be greater than {}").format(invoice_total)) def validate_company_with_pos_company(self): if self.company != frappe.db.get_value("POS Profile", self.pos_profile, "company"): From 998fef779bc2aba5ebd7e3b7d98189c1a8f388f3 Mon Sep 17 00:00:00 2001 From: "Nihantra C. Patel" <141945075+Nihantra-Patel@users.noreply.github.com> Date: Tue, 17 Sep 2024 15:35:07 +0530 Subject: [PATCH 17/32] fix: partial return on POS invoice (cherry picked from commit 18bdd06652ff3cc772214fa7c6ed620554eddbb7) --- erpnext/accounts/doctype/pos_invoice/pos_invoice.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py index ce3da4ac7dd3..17e777197cb0 100644 --- a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py +++ b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py @@ -449,11 +449,11 @@ def validate_payment_amount(self): if self.is_return and entry.amount > 0: frappe.throw(_("Row #{0} (Payment Table): Amount must be negative").format(entry.idx)) - if self.is_return: + if self.is_return and self.docstatus != 0: invoice_total = self.rounded_total or self.grand_total total_amount_in_payments = flt(total_amount_in_payments, self.precision("grand_total")) - if total_amount_in_payments and total_amount_in_payments > invoice_total: - frappe.throw(_("Total payments amount can't be greater than {}").format(invoice_total)) + if total_amount_in_payments and total_amount_in_payments < invoice_total: + frappe.throw(_("Total payments amount can't be greater than {}").format(-invoice_total)) def validate_company_with_pos_company(self): if self.company != frappe.db.get_value("POS Profile", self.pos_profile, "company"): From e06a01fae5dd5b42f54fcccf9c8c38106087b37e Mon Sep 17 00:00:00 2001 From: barredterra <14891507+barredterra@users.noreply.github.com> Date: Thu, 19 Sep 2024 13:57:55 +0200 Subject: [PATCH 18/32] fix(Payment Reconciliation): German translations (cherry picked from commit 32d4f96e025875492fadfdd2c776f2230d5b93b3) --- erpnext/translations/de.csv | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/erpnext/translations/de.csv b/erpnext/translations/de.csv index b9d790d24284..ed05b8d66953 100644 --- a/erpnext/translations/de.csv +++ b/erpnext/translations/de.csv @@ -4480,10 +4480,23 @@ Payment Reconciliation,Zahlungsabgleich, Receivable / Payable Account,Forderungen-/Verbindlichkeiten-Konto, Bank / Cash Account,Bank / Geldkonto, From Invoice Date,Ab Rechnungsdatum, -To Invoice Date,Um Datum Rechnung, -Minimum Invoice Amount,Mindestabrechnung, +To Invoice Date,Bis Rechnungsdatum, +Invoice Limit,Max. Anzahl Rechnungen, +From Payment Date,Ab Zahlungsdatum, +To Payment Date,Bis Zahlungsdatum, +Payment Limit,Max. Anzahl Zahlungen, +Minimum Invoice Amount,Minimaler Rechnungsbetrag, Maximum Invoice Amount,Maximaler Rechnungsbetrag, -System will fetch all the entries if limit value is zero.,"Das System ruft alle Einträge ab, wenn der Grenzwert Null ist.", +Minimum Payment Amount,Minimaler Zahlungsbetrag, +Maximum Payment Amount,Maximaler Zahlungsbetrag, +Filter on Invoice,Filter auf Rechnungsnr., +Filter on Payment,Filter auf Zahlungsnr., +"If you need to reconcile particular transactions against each other, then please select accordingly. If not, all the transactions will be allocated in FIFO order.","Wenn Sie bestimmte Transaktionen gegeneinander abgleichen müssen, wählen Sie diese bitte entsprechend aus. Andernfalls werden alle Transaktionen in FIFO-Reihenfolge zugewiesen.", +System will fetch all the entries if limit value is zero.,"Das System ruft alle Einträge ab, wenn die max. Anzahl Null ist.", +This filter will be applied to Journal Entry.,Dieser Filter wird auf Buchungssätze angewendet., +Unreconciled Entries,Nicht zugeordnete Buchungen, +Allocated Entries,Zugewiesene Buchungen, +Accounting Dimensions Filter,Filetr nach Buchhaltungsdimensionen, Get Unreconciled Entries,Nicht zugeordnete Buchungen aufrufen, Unreconciled Payment Details,Nicht abgeglichene Zahlungen, Invoice/Journal Entry Details,Einzelheiten zu Rechnungs-/Journalbuchungen, From 085a4c61ac3ebef34b16f7e713d03809594fd455 Mon Sep 17 00:00:00 2001 From: barredterra <14891507+barredterra@users.noreply.github.com> Date: Wed, 18 Sep 2024 19:39:51 +0200 Subject: [PATCH 19/32] fix: shipping rule must match the company (cherry picked from commit df8f4086f6df9dcb3eed012c3b9865fef3388584) --- erpnext/public/js/utils/sales_common.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/public/js/utils/sales_common.js b/erpnext/public/js/utils/sales_common.js index 91a85aa02a54..e503fb3339c1 100644 --- a/erpnext/public/js/utils/sales_common.js +++ b/erpnext/public/js/utils/sales_common.js @@ -15,10 +15,11 @@ erpnext.sales_common = { onload() { super.onload(); this.setup_queries(); - this.frm.set_query("shipping_rule", function () { + this.frm.set_query("shipping_rule", function (doc) { return { filters: { shipping_rule_type: "Selling", + company: doc.company, }, }; }); From 99e004b61962c4463ba8b18985835295d5711b03 Mon Sep 17 00:00:00 2001 From: ljain112 Date: Tue, 17 Sep 2024 19:10:31 +0530 Subject: [PATCH 20/32] fix: item_query in pos_invoice (cherry picked from commit 7f82a06e657d71c7205189c197a46394e78fd8d0) --- .../doctype/pos_invoice/pos_invoice.js | 13 +++++++++ .../doctype/pos_invoice/pos_invoice.py | 28 +++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/erpnext/accounts/doctype/pos_invoice/pos_invoice.js b/erpnext/accounts/doctype/pos_invoice/pos_invoice.js index a6e8bfa62869..8707ee88860d 100644 --- a/erpnext/accounts/doctype/pos_invoice/pos_invoice.js +++ b/erpnext/accounts/doctype/pos_invoice/pos_invoice.js @@ -40,6 +40,19 @@ erpnext.selling.POSInvoiceController = class POSInvoiceController extends erpnex }; }); + this.frm.set_query("item_code", "items", function (doc) { + return { + query: "erpnext.accounts.doctype.pos_invoice.pos_invoice.item_query", + filters: { + has_variants: ["=", 0], + is_sales_item: ["=", 1], + disabled: ["=", 0], + is_fixed_asset: ["=", 0], + pos_profile: ["=", doc.pos_profile], + }, + }; + }); + erpnext.accounts.dimensions.setup_dimension_filters(this.frm, this.frm.doctype); } diff --git a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py index 17e777197cb0..742af7dd0fe0 100644 --- a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py +++ b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py @@ -6,6 +6,7 @@ from frappe import _, bold from frappe.query_builder.functions import IfNull, Sum from frappe.utils import cint, flt, get_link_to_form, getdate, nowdate +from frappe.utils.nestedset import get_descendants_of from erpnext.accounts.doctype.loyalty_program.loyalty_program import validate_loyalty_points from erpnext.accounts.doctype.payment_request.payment_request import make_payment_request @@ -15,6 +16,7 @@ update_multi_mode_option, ) from erpnext.accounts.party import get_due_date, get_party_account +from erpnext.controllers.queries import item_query as _item_query from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos @@ -837,3 +839,29 @@ def append_payment(payment_mode): ]: payment_mode = get_mode_of_payment_info(mode_of_payment, doc.company) append_payment(payment_mode[0]) + + +@frappe.whitelist() +@frappe.validate_and_sanitize_search_inputs +def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=False): + if pos_profile := filters.get("pos_profile")[1]: + pos_profile = frappe.get_cached_doc("POS Profile", pos_profile) + if item_groups := get_item_group(pos_profile): + filters["item_group"] = ["in", tuple(item_groups)] + + del filters["pos_profile"] + + else: + filters.pop("pos_profile", None) + + return _item_query(doctype, txt, searchfield, start, page_len, filters, as_dict) + + +def get_item_group(pos_profile): + item_groups = [] + if pos_profile.get("item_groups"): + # Get items based on the item groups defined in the POS profile + for row in pos_profile.get("item_groups"): + item_groups.extend(get_descendants_of("Item Group", row.item_group)) + + return list(set(item_groups)) From 10ecdb99fe565d5f4ebedb034f5cbad1c246a865 Mon Sep 17 00:00:00 2001 From: Kavin <78342682+kavin0411@users.noreply.github.com> Date: Fri, 20 Sep 2024 14:29:10 +0530 Subject: [PATCH 21/32] fix: update clearance date in invoice payment table (cherry picked from commit 487c2a29a6bf265d59dc3331938c48b943adfd65) --- .../doctype/bank_clearance/bank_clearance.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/bank_clearance/bank_clearance.py b/erpnext/accounts/doctype/bank_clearance/bank_clearance.py index 85713c6c9a6a..bdc2464da272 100644 --- a/erpnext/accounts/doctype/bank_clearance/bank_clearance.py +++ b/erpnext/accounts/doctype/bank_clearance/bank_clearance.py @@ -108,8 +108,17 @@ def update_clearance_date(self): if not d.clearance_date: d.clearance_date = None - payment_entry = frappe.get_doc(d.payment_document, d.payment_entry) - payment_entry.db_set("clearance_date", d.clearance_date) + if d.payment_document == "Sales Invoice": + frappe.db.set_value( + "Sales Invoice Payment", + {"parent": d.payment_entry, "account": self.get("account"), "amount": [">", 0]}, + "clearance_date", + d.clearance_date, + ) + + else: + payment_entry = frappe.get_doc(d.payment_document, d.payment_entry) + payment_entry.db_set("clearance_date", d.clearance_date) clearance_date_updated = True From 9d2cbccff2d82456a86c91f86e78e290621035f6 Mon Sep 17 00:00:00 2001 From: Kavin <78342682+kavin0411@users.noreply.github.com> Date: Fri, 20 Sep 2024 14:33:03 +0530 Subject: [PATCH 22/32] test: add test case for updating clearance date on pos invoice (cherry picked from commit ce8600520f56960dffd50bbf04e471037f7ee13c) --- .../bank_clearance/test_bank_clearance.py | 81 ++++++++++++++++++- 1 file changed, 80 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/bank_clearance/test_bank_clearance.py b/erpnext/accounts/doctype/bank_clearance/test_bank_clearance.py index d785bfbfef22..658a69a48037 100644 --- a/erpnext/accounts/doctype/bank_clearance/test_bank_clearance.py +++ b/erpnext/accounts/doctype/bank_clearance/test_bank_clearance.py @@ -6,16 +6,29 @@ import frappe from frappe.utils import add_months, getdate +from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center from erpnext.accounts.doctype.payment_entry.test_payment_entry import get_payment_entry from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice +from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice +from erpnext.stock.doctype.item.test_item import create_item +from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse from erpnext.tests.utils import if_lending_app_installed, if_lending_app_not_installed class TestBankClearance(unittest.TestCase): @classmethod def setUpClass(cls): + create_warehouse( + warehouse_name="_Test Warehouse", + properties={"parent_warehouse": "All Warehouses - _TC"}, + company="_Test Company", + ) + create_item("_Test Item") + create_cost_center(cost_center_name="_Test Cost Center", company="_Test Company") + clear_payment_entries() clear_loan_transactions() + clear_pos_sales_invoices() make_bank_account() add_transactions() @@ -83,11 +96,41 @@ def make_loan(): bank_clearance.get_payment_entries() self.assertEqual(len(bank_clearance.payment_entries), 3) + def test_update_clearance_date_on_si(self): + sales_invoice = make_pos_sales_invoice() + + date = getdate() + bank_clearance = frappe.get_doc("Bank Clearance") + bank_clearance.account = "_Test Bank Clearance - _TC" + bank_clearance.from_date = add_months(date, -1) + bank_clearance.to_date = date + bank_clearance.include_pos_transactions = 1 + bank_clearance.get_payment_entries() + + self.assertNotEqual(len(bank_clearance.payment_entries), 0) + for payment in bank_clearance.payment_entries: + if payment.payment_entry == sales_invoice.name: + payment.clearance_date = date + + bank_clearance.update_clearance_date() + + si_clearance_date = frappe.db.get_value( + "Sales Invoice Payment", + {"parent": sales_invoice.name, "account": bank_clearance.account}, + "clearance_date", + ) + + self.assertEqual(si_clearance_date, date) + def clear_payment_entries(): frappe.db.delete("Payment Entry") +def clear_pos_sales_invoices(): + frappe.db.delete("Sales Invoice", {"is_pos": 1}) + + @if_lending_app_installed def clear_loan_transactions(): for dt in [ @@ -115,9 +158,45 @@ def add_transactions(): def make_payment_entry(): - pi = make_purchase_invoice(supplier="_Test Supplier", qty=1, rate=690) + from erpnext.buying.doctype.supplier.test_supplier import create_supplier + + supplier = create_supplier(supplier_name="_Test Supplier") + pi = make_purchase_invoice( + supplier=supplier, + supplier_warehouse="_Test Warehouse - _TC", + expense_account="Cost of Goods Sold - _TC", + uom="Nos", + qty=1, + rate=690, + ) pe = get_payment_entry("Purchase Invoice", pi.name, bank_account="_Test Bank Clearance - _TC") pe.reference_no = "Conrad Oct 18" pe.reference_date = "2018-10-24" pe.insert() pe.submit() + + +def make_pos_sales_invoice(): + from erpnext.accounts.doctype.opening_invoice_creation_tool.test_opening_invoice_creation_tool import ( + make_customer, + ) + + mode_of_payment = frappe.get_doc({"doctype": "Mode of Payment", "name": "Cash"}) + + if not frappe.db.get_value("Mode of Payment Account", {"company": "_Test Company", "parent": "Cash"}): + mode_of_payment.append( + "accounts", {"company": "_Test Company", "default_account": "_Test Bank Clearance - _TC"} + ) + mode_of_payment.save() + + customer = make_customer(customer="_Test Customer") + + si = create_sales_invoice(customer=customer, item="_Test Item", is_pos=1, qty=1, rate=1000, do_not_save=1) + si.set("payments", []) + si.append( + "payments", {"mode_of_payment": "Cash", "account": "_Test Bank Clearance - _TC", "amount": 1000} + ) + si.insert() + si.submit() + + return si From 8bc76bae9cfdf40e59acaa3e8b3bbe03699125ab Mon Sep 17 00:00:00 2001 From: Kavin <78342682+kavin0411@users.noreply.github.com> Date: Fri, 20 Sep 2024 18:24:00 +0530 Subject: [PATCH 23/32] refactor: update clearance date in payment entry (cherry picked from commit c218f7527f77e24236dee41091e0a47dbb826b6d) --- erpnext/accounts/doctype/bank_clearance/bank_clearance.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/bank_clearance/bank_clearance.py b/erpnext/accounts/doctype/bank_clearance/bank_clearance.py index bdc2464da272..92abb8cea89b 100644 --- a/erpnext/accounts/doctype/bank_clearance/bank_clearance.py +++ b/erpnext/accounts/doctype/bank_clearance/bank_clearance.py @@ -117,8 +117,9 @@ def update_clearance_date(self): ) else: - payment_entry = frappe.get_doc(d.payment_document, d.payment_entry) - payment_entry.db_set("clearance_date", d.clearance_date) + frappe.db.set_value( + d.payment_document, d.payment_entry, "clearance_date", d.clearance_date + ) clearance_date_updated = True From ec27077d9cd5f3d5e832e35a32451cee7f5e3e6d Mon Sep 17 00:00:00 2001 From: Vishakh Desai Date: Mon, 16 Sep 2024 15:40:49 +0530 Subject: [PATCH 24/32] fix: set group_by condition if empty and voucher_no is set (cherry picked from commit a6b0cb6cac78a415caebaa9fbfd913f123842f55) --- erpnext/accounts/report/general_ledger/general_ledger.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/erpnext/accounts/report/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py index 2564eb0800f2..1c1d10c087b9 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.py +++ b/erpnext/accounts/report/general_ledger/general_ledger.py @@ -35,6 +35,9 @@ def execute(filters=None): if filters.get("party"): filters.party = frappe.parse_json(filters.get("party")) + if filters.get("voucher_no") and not filters.get("group_by"): + filters.group_by = "Group by Voucher (Consolidated)" + validate_filters(filters, account_details) validate_party(filters) From 176feb20ad62e4a137e5babcd363968af59b160a Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Tue, 24 Sep 2024 15:25:42 +0530 Subject: [PATCH 25/32] fix: stock dashboard (backport #43347) (#43349) fix: stock dashboard (#43347) (cherry picked from commit 9e8be8db511cdddc48cfe13218e202f1e4c31d6d) Co-authored-by: rohitwaghchaure --- .../dashboard_chart/oldest_items/oldest_items.json | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/erpnext/stock/dashboard_chart/oldest_items/oldest_items.json b/erpnext/stock/dashboard_chart/oldest_items/oldest_items.json index 9c10a5346be9..46ad308f2309 100644 --- a/erpnext/stock/dashboard_chart/oldest_items/oldest_items.json +++ b/erpnext/stock/dashboard_chart/oldest_items/oldest_items.json @@ -1,22 +1,23 @@ { "chart_name": "Oldest Items", "chart_type": "Report", - "creation": "2020-07-20 21:01:04.336845", + "creation": "2022-03-30 00:58:02.041721", "custom_options": "{\"colors\": [\"#5e64ff\"]}", "docstatus": 0, "doctype": "Dashboard Chart", - "dynamic_filters_json": "{\"company\":\"frappe.defaults.get_user_default(\\\"Company\\\")\",\"to_date\":\"frappe.datetime.nowdate()\"}", - "filters_json": "{\"range1\":30,\"range2\":60,\"range3\":90,\"show_warehouse_wise_stock\":0}", + "dynamic_filters_json": "{\"company\":\"frappe.defaults.get_user_default(\\\"Company\\\")\",\"to_date\":\"frappe.datetime.nowdate()\",\"range1\":\"30\",\"range2\":\"60\",\"range3\":\"90\"}", + "filters_json": "{\"range\":\"30, 60, 90\",\"show_warehouse_wise_stock\":0}", "idx": 0, "is_public": 1, "is_standard": 1, - "modified": "2020-07-29 14:50:26.846482", + "modified": "2024-09-23 22:37:51.392999", "modified_by": "Administrator", "module": "Stock", "name": "Oldest Items", "number_of_groups": 0, - "owner": "Administrator", + "owner": "rohitw1991@gmail.com", "report_name": "Stock Ageing", + "roles": [], "timeseries": 0, "type": "Bar", "use_report_chart": 1, From 979d801de5e2213474690a860be04db28c102d7b Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 24 Sep 2024 12:13:43 +0530 Subject: [PATCH 26/32] fix: AR / AP report to ignore 0.0 outstanding (cherry picked from commit 6e2cf79e2cf047c89367a5b446f338e65a484ba6) --- .../report/accounts_receivable/accounts_receivable.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py index 1a7638aaae46..43100c812852 100644 --- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py +++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py @@ -310,8 +310,8 @@ def build_data(self): must_consider = False if self.filters.get("for_revaluation_journals"): - if (abs(row.outstanding) >= 0.0 / 10**self.currency_precision) or ( - abs(row.outstanding_in_account_currency) >= 0.0 / 10**self.currency_precision + if (abs(row.outstanding) >= 1.0 / 10**self.currency_precision) or ( + abs(row.outstanding_in_account_currency) >= 1.0 / 10**self.currency_precision ): must_consider = True else: From 0e1884539ebfddd67c10f83f515bae23074fccf6 Mon Sep 17 00:00:00 2001 From: Khushi Rawat <142375893+khushi8112@users.noreply.github.com> Date: Mon, 23 Sep 2024 23:47:48 +0530 Subject: [PATCH 27/32] fix: added date condition --- .../asset_depreciations_and_balances.py | 53 +++++++++++-------- 1 file changed, 31 insertions(+), 22 deletions(-) diff --git a/erpnext/accounts/report/asset_depreciations_and_balances/asset_depreciations_and_balances.py b/erpnext/accounts/report/asset_depreciations_and_balances/asset_depreciations_and_balances.py index b288e8e5ac73..686aa22d6f6b 100644 --- a/erpnext/accounts/report/asset_depreciations_and_balances/asset_depreciations_and_balances.py +++ b/erpnext/accounts/report/asset_depreciations_and_balances/asset_depreciations_and_balances.py @@ -114,7 +114,11 @@ def get_asset_categories_for_grouped_by_category(filters): end), 0) as cost_of_scrapped_asset from `tabAsset` a where docstatus=1 and company=%(company)s and purchase_date <= %(to_date)s {condition} - and not exists(select name from `tabAsset Capitalization Asset Item` where asset = a.name) + and not exists( + select 1 from `tabAsset Capitalization Asset Item` acai join `tabAsset Capitalization` ac on acai.parent=ac.name + where acai.asset = a.name + and ac.posting_date between %(from_date)s AND %(to_date)s + ) group by a.asset_category """, { @@ -131,53 +135,58 @@ def get_asset_categories_for_grouped_by_category(filters): def get_asset_details_for_grouped_by_category(filters): condition = "" if filters.get("asset"): - condition += " and name = %(asset)s" + condition += " and a.name = %(asset)s" if filters.get("finance_book"): - condition += " and exists (select 1 from `tabAsset Depreciation Schedule` ads where ads.asset = `tabAsset`.name and ads.finance_book = %(finance_book)s)" + condition += " and exists (select 1 from `tabAsset Depreciation Schedule` ads where ads.asset = a.name and ads.finance_book = %(finance_book)s)" # nosemgrep return frappe.db.sql( f""" - SELECT name, - ifnull(sum(case when purchase_date < %(from_date)s then - case when ifnull(disposal_date, 0) = 0 or disposal_date >= %(from_date)s then - gross_purchase_amount + SELECT a.name, + ifnull(sum(case when a.purchase_date < %(from_date)s then + case when ifnull(a.disposal_date, 0) = 0 or a.disposal_date >= %(from_date)s then + a.gross_purchase_amount else 0 end else 0 end), 0) as cost_as_on_from_date, - ifnull(sum(case when purchase_date >= %(from_date)s then - gross_purchase_amount + ifnull(sum(case when a.purchase_date >= %(from_date)s then + a.gross_purchase_amount else 0 end), 0) as cost_of_new_purchase, - ifnull(sum(case when ifnull(disposal_date, 0) != 0 - and disposal_date >= %(from_date)s - and disposal_date <= %(to_date)s then - case when status = "Sold" then - gross_purchase_amount + ifnull(sum(case when ifnull(a.disposal_date, 0) != 0 + and a.disposal_date >= %(from_date)s + and a.disposal_date <= %(to_date)s then + case when a.status = "Sold" then + a.gross_purchase_amount else 0 end else 0 end), 0) as cost_of_sold_asset, - ifnull(sum(case when ifnull(disposal_date, 0) != 0 - and disposal_date >= %(from_date)s - and disposal_date <= %(to_date)s then - case when status = "Scrapped" then - gross_purchase_amount + ifnull(sum(case when ifnull(a.disposal_date, 0) != 0 + and a.disposal_date >= %(from_date)s + and a.disposal_date <= %(to_date)s then + case when a.status = "Scrapped" then + a.gross_purchase_amount else 0 end else 0 end), 0) as cost_of_scrapped_asset - from `tabAsset` - where docstatus=1 and company=%(company)s and purchase_date <= %(to_date)s {condition} - group by name + from `tabAsset` a + where a.docstatus=1 and a.company=%(company)s and a.purchase_date <= %(to_date)s {condition} + and not exists( + select 1 from `tabAsset Capitalization Asset Item` acai join `tabAsset Capitalization` ac on acai.parent=ac.name + where acai.asset = a.name + and ac.posting_date between %(from_date)s AND %(to_date)s + ) + group by a.name """, { "to_date": filters.to_date, From 1f423029970cb911c5a97d8b3ce92a02b151ea7e Mon Sep 17 00:00:00 2001 From: Khushi Rawat <142375893+khushi8112@users.noreply.github.com> Date: Tue, 24 Sep 2024 01:41:54 +0530 Subject: [PATCH 28/32] fix(minor): include condition to check docstatus --- .../asset_depreciations_and_balances.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/report/asset_depreciations_and_balances/asset_depreciations_and_balances.py b/erpnext/accounts/report/asset_depreciations_and_balances/asset_depreciations_and_balances.py index 686aa22d6f6b..5e399029e31f 100644 --- a/erpnext/accounts/report/asset_depreciations_and_balances/asset_depreciations_and_balances.py +++ b/erpnext/accounts/report/asset_depreciations_and_balances/asset_depreciations_and_balances.py @@ -68,7 +68,7 @@ def get_group_by_asset_category_data(filters): def get_asset_categories_for_grouped_by_category(filters): condition = "" if filters.get("asset_category"): - condition += " and asset_category = %(asset_category)s" + condition += " and a.asset_category = %(asset_category)s" if filters.get("finance_book"): condition += " and exists (select 1 from `tabAsset Depreciation Schedule` ads where ads.asset = a.name and ads.finance_book = %(finance_book)s)" @@ -113,11 +113,12 @@ def get_asset_categories_for_grouped_by_category(filters): 0 end), 0) as cost_of_scrapped_asset from `tabAsset` a - where docstatus=1 and company=%(company)s and purchase_date <= %(to_date)s {condition} + where a.docstatus=1 and a.company=%(company)s and a.purchase_date <= %(to_date)s {condition} and not exists( select 1 from `tabAsset Capitalization Asset Item` acai join `tabAsset Capitalization` ac on acai.parent=ac.name where acai.asset = a.name - and ac.posting_date between %(from_date)s AND %(to_date)s + and ac.posting_date <= %(to_date)s + and ac.docstatus=1 ) group by a.asset_category """, @@ -184,7 +185,8 @@ def get_asset_details_for_grouped_by_category(filters): and not exists( select 1 from `tabAsset Capitalization Asset Item` acai join `tabAsset Capitalization` ac on acai.parent=ac.name where acai.asset = a.name - and ac.posting_date between %(from_date)s AND %(to_date)s + and ac.posting_date <= %(to_date)s + and ac.docstatus=1 ) group by a.name """, From 4e621b09ba48bf9aed11d5a5d2bbe0553eaf3eb6 Mon Sep 17 00:00:00 2001 From: Khushi Rawat <142375893+khushi8112@users.noreply.github.com> Date: Tue, 24 Sep 2024 17:40:33 +0530 Subject: [PATCH 29/32] style: added comment --- .../asset_depreciations_and_balances.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/report/asset_depreciations_and_balances/asset_depreciations_and_balances.py b/erpnext/accounts/report/asset_depreciations_and_balances/asset_depreciations_and_balances.py index 5e399029e31f..64e6a3404646 100644 --- a/erpnext/accounts/report/asset_depreciations_and_balances/asset_depreciations_and_balances.py +++ b/erpnext/accounts/report/asset_depreciations_and_balances/asset_depreciations_and_balances.py @@ -37,7 +37,7 @@ def get_group_by_asset_category_data(filters): - flt(row.cost_of_sold_asset) - flt(row.cost_of_scrapped_asset) ) - + # Update row with corresponding asset data row.update( next( asset From cfea2de131fb5a32d3716d55a46cb1285266da2c Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Tue, 24 Sep 2024 16:20:50 +0200 Subject: [PATCH 30/32] fix(Bank Account): dashboard connections (backport #43365) (#43367) Co-authored-by: Raffael Meyer <14891507+barredterra@users.noreply.github.com> Co-authored-by: rohitwaghchaure fix(Bank Account): dashboard connections (#43365) --- .../doctype/bank_account/bank_account.json | 52 +++++++++++++++++-- .../bank_account/bank_account_dashboard.py | 20 ------- 2 files changed, 49 insertions(+), 23 deletions(-) delete mode 100644 erpnext/accounts/doctype/bank_account/bank_account_dashboard.py diff --git a/erpnext/accounts/doctype/bank_account/bank_account.json b/erpnext/accounts/doctype/bank_account/bank_account.json index 32f1c675d3b1..a5a7691eb76e 100644 --- a/erpnext/accounts/doctype/bank_account/bank_account.json +++ b/erpnext/accounts/doctype/bank_account/bank_account.json @@ -208,8 +208,54 @@ "label": "Disabled" } ], - "links": [], - "modified": "2023-09-22 21:31:34.763977", + "links": [ + { + "group": "Transactions", + "link_doctype": "Payment Request", + "link_fieldname": "bank_account" + }, + { + "group": "Transactions", + "link_doctype": "Payment Order", + "link_fieldname": "bank_account" + }, + { + "group": "Transactions", + "link_doctype": "Bank Guarantee", + "link_fieldname": "bank_account" + }, + { + "group": "Transactions", + "link_doctype": "Payroll Entry", + "link_fieldname": "bank_account" + }, + { + "group": "Transactions", + "link_doctype": "Bank Transaction", + "link_fieldname": "bank_account" + }, + { + "group": "Accounting", + "link_doctype": "Payment Entry", + "link_fieldname": "bank_account" + }, + { + "group": "Accounting", + "link_doctype": "Journal Entry", + "link_fieldname": "bank_account" + }, + { + "group": "Party", + "link_doctype": "Customer", + "link_fieldname": "default_bank_account" + }, + { + "group": "Party", + "link_doctype": "Supplier", + "link_fieldname": "default_bank_account" + } + ], + "modified": "2024-09-24 06:57:41.292970", "modified_by": "Administrator", "module": "Accounts", "name": "Bank Account", @@ -246,4 +292,4 @@ "sort_order": "DESC", "states": [], "track_changes": 1 -} \ No newline at end of file +} diff --git a/erpnext/accounts/doctype/bank_account/bank_account_dashboard.py b/erpnext/accounts/doctype/bank_account/bank_account_dashboard.py deleted file mode 100644 index 8bf8d8a5cd01..000000000000 --- a/erpnext/accounts/doctype/bank_account/bank_account_dashboard.py +++ /dev/null @@ -1,20 +0,0 @@ -from frappe import _ - - -def get_data(): - return { - "fieldname": "bank_account", - "non_standard_fieldnames": { - "Customer": "default_bank_account", - "Supplier": "default_bank_account", - }, - "transactions": [ - { - "label": _("Payments"), - "items": ["Payment Entry", "Payment Request", "Payment Order", "Payroll Entry"], - }, - {"label": _("Party"), "items": ["Customer", "Supplier"]}, - {"items": ["Bank Guarantee"]}, - {"items": ["Journal Entry"]}, - ], - } From 0722aa5a3f5c318110933fadd38303d690d0db32 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Tue, 24 Sep 2024 20:49:42 +0530 Subject: [PATCH 31/32] fix: closing amount reset to expected amount on save (backport #43358) (#43368) fix: closing amount reset to expected amount on save (#43358) (cherry picked from commit 9974b7c4ae53505e85019a29481693e492cc8b17) Co-authored-by: jabir-elat <44110258+jabir-elat@users.noreply.github.com> --- .../accounts/doctype/pos_closing_entry/pos_closing_entry.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.js b/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.js index 68a85f7ee963..c171713dc611 100644 --- a/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.js +++ b/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.js @@ -194,7 +194,9 @@ function refresh_payments(d, frm) { } if (payment) { payment.expected_amount += flt(p.amount); - payment.closing_amount = payment.expected_amount; + if (payment.closing_amount === 0) { + payment.closing_amount = payment.expected_amount; + } payment.difference = payment.closing_amount - payment.expected_amount; } else { frm.add_child("payment_reconciliation", { From 40fbb1d6ffaa75a612b64159506ed2409e2afe25 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Wed, 25 Sep 2024 00:02:24 +0530 Subject: [PATCH 32/32] fix: not able to cancel Quality Inspection (backport #43374) (#43375) fix: not able to cancel Quality Inspection (#43374) (cherry picked from commit 8c32ebee683bab44c4c94a604b33267ee77ee00c) Co-authored-by: rohitwaghchaure --- erpnext/stock/doctype/quality_inspection/quality_inspection.js | 2 +- erpnext/stock/doctype/quality_inspection/quality_inspection.py | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/quality_inspection/quality_inspection.js b/erpnext/stock/doctype/quality_inspection/quality_inspection.js index fc487514a2c7..99e25bf5eb6f 100644 --- a/erpnext/stock/doctype/quality_inspection/quality_inspection.js +++ b/erpnext/stock/doctype/quality_inspection/quality_inspection.js @@ -60,7 +60,7 @@ frappe.ui.form.on("Quality Inspection", { refresh: function (frm) { // Ignore cancellation of reference doctype on cancel all. - frm.ignore_doctypes_on_cancel_all = [frm.doc.reference_type]; + frm.ignore_doctypes_on_cancel_all = [frm.doc.reference_type, "Serial and Batch Bundle"]; }, item_code: function (frm) { diff --git a/erpnext/stock/doctype/quality_inspection/quality_inspection.py b/erpnext/stock/doctype/quality_inspection/quality_inspection.py index 60f048673fb8..5dca440adbef 100644 --- a/erpnext/stock/doctype/quality_inspection/quality_inspection.py +++ b/erpnext/stock/doctype/quality_inspection/quality_inspection.py @@ -109,6 +109,8 @@ def on_submit(self): self.update_qc_reference() def on_cancel(self): + self.ignore_linked_doctypes = "Serial and Batch Bundle" + self.update_qc_reference() def on_trash(self):