From d9f15e96b55b674de3e3aba96c1307fa49257760 Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Sun, 10 Sep 2023 17:18:42 +0200 Subject: [PATCH 01/22] refactor(region): Splitting of France Regional logic from ERPNext --- erpnext/patches/v14_0/france_depreciation_warning.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 erpnext/patches/v14_0/france_depreciation_warning.py diff --git a/erpnext/patches/v14_0/france_depreciation_warning.py b/erpnext/patches/v14_0/france_depreciation_warning.py new file mode 100644 index 00000000000..8d8719f8623 --- /dev/null +++ b/erpnext/patches/v14_0/france_depreciation_warning.py @@ -0,0 +1,12 @@ +import click +import frappe + + +def execute(): + if "erpnext_france" in frappe.get_installed_apps(): + return + click.secho( + "Feature for Feature Region will be remove in version-15 and moved to a separate app\n" + "Please install the app to continue using the regionnal France features: git@github.com:scopen-coop/erpnext_france.git", + fg="yellow", + ) From fb7ca8fca2a5a24b73435ee22b261e53d1a2c174 Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Sun, 10 Sep 2023 17:19:35 +0200 Subject: [PATCH 02/22] refactor(region): Splitting of France Regional logic from ERPNext --- erpnext/patches/v14_0/france_depreciation_warning.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/patches/v14_0/france_depreciation_warning.py b/erpnext/patches/v14_0/france_depreciation_warning.py index 8d8719f8623..45ec07e7737 100644 --- a/erpnext/patches/v14_0/france_depreciation_warning.py +++ b/erpnext/patches/v14_0/france_depreciation_warning.py @@ -7,6 +7,6 @@ def execute(): return click.secho( "Feature for Feature Region will be remove in version-15 and moved to a separate app\n" - "Please install the app to continue using the regionnal France features: git@github.com:scopen-coop/erpnext_france.git", + "Please install the app to continue using the regionnal France features: https://github.com/scopen-coop/erpnext_france.git", fg="yellow", ) From 7de3d08ce39e4722495c49756579ea9461a92935 Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Sun, 10 Sep 2023 17:23:35 +0200 Subject: [PATCH 03/22] refactor(region): Splitting of France Regional logic from ERPNext --- erpnext/patches/v14_0/france_depreciation_warning.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/patches/v14_0/france_depreciation_warning.py b/erpnext/patches/v14_0/france_depreciation_warning.py index 45ec07e7737..27acfd94703 100644 --- a/erpnext/patches/v14_0/france_depreciation_warning.py +++ b/erpnext/patches/v14_0/france_depreciation_warning.py @@ -6,7 +6,7 @@ def execute(): if "erpnext_france" in frappe.get_installed_apps(): return click.secho( - "Feature for Feature Region will be remove in version-15 and moved to a separate app\n" + "Feature for Region France will be remove in version-15 and moved to a separate app\n" "Please install the app to continue using the regionnal France features: https://github.com/scopen-coop/erpnext_france.git", fg="yellow", ) From 5c0a232e0fc4c6cb67fbdb4b76747fbd0878b109 Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Sun, 10 Sep 2023 17:24:01 +0200 Subject: [PATCH 04/22] refactor(region): Splitting of France Regional logic from ERPNext --- erpnext/patches/v14_0/france_depreciation_warning.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/patches/v14_0/france_depreciation_warning.py b/erpnext/patches/v14_0/france_depreciation_warning.py index 27acfd94703..5efbc5bd7fb 100644 --- a/erpnext/patches/v14_0/france_depreciation_warning.py +++ b/erpnext/patches/v14_0/france_depreciation_warning.py @@ -6,7 +6,7 @@ def execute(): if "erpnext_france" in frappe.get_installed_apps(): return click.secho( - "Feature for Region France will be remove in version-15 and moved to a separate app\n" + "Feature for region France will be remove in version-15 and moved to a separate app\n" "Please install the app to continue using the regionnal France features: https://github.com/scopen-coop/erpnext_france.git", fg="yellow", ) From 8236814270f2a74bb5ae46ea7d3818c2ddc7619b Mon Sep 17 00:00:00 2001 From: Raffael Meyer <14891507+barredterra@users.noreply.github.com> Date: Tue, 19 Sep 2023 16:27:43 +0200 Subject: [PATCH 05/22] fix: german translation of Sales and Purchase Invoice (#37122) * fix: german translation of Purchase Invoice * fix: german translation of Sales Invoice (cherry picked from commit 84a9000db2f92e81dec825be1df42672305aec5d) # Conflicts: # erpnext/translations/de.csv --- erpnext/translations/de.csv | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/erpnext/translations/de.csv b/erpnext/translations/de.csv index 42d313f4db1..6dae398e334 100644 --- a/erpnext/translations/de.csv +++ b/erpnext/translations/de.csv @@ -1312,7 +1312,7 @@ Invalid GSTIN! A GSTIN must have 15 characters.,Ungültige GSTIN! Eine GSTIN mus Invalid GSTIN! First 2 digits of GSTIN should match with State number {0}.,Ungültige GSTIN! Die ersten beiden Ziffern von GSTIN sollten mit der Statusnummer {0} übereinstimmen., Invalid GSTIN! The input you've entered doesn't match the format of GSTIN.,Ungültige GSTIN! Die von Ihnen eingegebene Eingabe stimmt nicht mit dem Format von GSTIN überein., Invalid Posting Time,Ungültige Buchungszeit, -Invalid Purchase Invoice,Ungültige Einkaufsrechnung, +Invalid Purchase Invoice,Ungültige Eingangsrechnung, Invalid attribute {0} {1},Ungültiges Attribut {0} {1}, Invalid quantity specified for item {0}. Quantity should be greater than 0.,Ungültzige Anzahl für Artikel {0} angegeben. Anzahl sollte größer als 0 sein., Invalid reference {0} {1},Ungültige Referenz {0} {1}, @@ -1969,8 +1969,12 @@ Please check Multi Currency option to allow accounts with other currency,"Bitte Please click on 'Generate Schedule',"Bitte auf ""Zeitplan generieren"" klicken", Please click on 'Generate Schedule' to fetch Serial No added for Item {0},"Bitte auf ""Zeitplan generieren"" klicken, um die Seriennummer für Artikel {0} abzurufen", Please click on 'Generate Schedule' to get schedule,"Bitte auf ""Zeitplan generieren"" klicken, um den Zeitplan zu erhalten", +<<<<<<< HEAD Please confirm once you have completed your training,"Bitte bestätigen Sie, sobald Sie Ihre Ausbildung abgeschlossen haben", Please create purchase receipt or purchase invoice for the item {0},Bitte erstellen Sie eine Kaufquittung oder eine Kaufrechnung für den Artikel {0}, +======= +Please create purchase receipt or purchase invoice for the item {0},Bitte erstellen Sie eine Kaufquittung oder eine Eingangsrechnungen für den Artikel {0}, +>>>>>>> 84a9000db2 (fix: german translation of Sales and Purchase Invoice (#37122)) Please define grade for Threshold 0%,Bitte definieren Sie Grade for Threshold 0%, Please enable Applicable on Booking Actual Expenses,Bitte aktivieren Sie Anwendbar bei der Buchung von tatsächlichen Ausgaben, Please enable Applicable on Purchase Order and Applicable on Booking Actual Expenses,Bitte aktivieren Sie Anwendbar bei Bestellung und Anwendbar bei Buchung von tatsächlichen Ausgaben, @@ -4937,7 +4941,7 @@ POS Customer Group,POS Kundengruppe, POS Field,POS-Feld, POS Item Group,POS Artikelgruppe, Company Address,Anschrift des Unternehmens, -Update Stock,Lagerbestand aktualisieren, +Update Stock,Lagerbestand aktualisieren, Ignore Pricing Rule,Preisregel ignorieren, Applicable for Users,Anwendbar für Benutzer, Sales Invoice Payment,Ausgangsrechnung-Zahlungen, @@ -5134,7 +5138,6 @@ ACC-SINV-.YYYY.-,ACC-SINV-.JJJJ.-, Include Payment (POS),(POS) Zahlung einschließen, Offline POS Name,Offline-Verkaufsstellen-Name, Is Return (Credit Note),ist Rücklieferung (Gutschrift), -Return Against Sales Invoice,Zurück zur Kundenrechnung, Update Billed Amount in Sales Order,Aktualisierung des Rechnungsbetrags im Auftrag, Customer PO Details,Auftragsdetails, Customer's Purchase Order,Bestellung des Kunden, @@ -7673,8 +7676,8 @@ Default Company Bank Account,Standard-Bankkonto des Unternehmens, From Lead,Aus Lead, Account Manager,Kundenberater, Accounts Manager,Buchhalter, -Allow Sales Invoice Creation Without Sales Order,Ermöglichen Sie die Erstellung von Kundenrechnungen ohne Auftrag, -Allow Sales Invoice Creation Without Delivery Note,Ermöglichen Sie die Erstellung einer Ausgangsrechnung ohne Lieferschein, +Allow Sales Invoice Creation Without Sales Order,Ermöglichen Sie die Erstellung von Ausgangsrechnungen ohne Auftrag, +Allow Sales Invoice Creation Without Delivery Note,Ermöglichen Sie die Erstellung von Ausgangsrechnungen ohne Lieferschein, Default Price List,Standardpreisliste, Primary Address and Contact,Hauptadresse und -kontakt, "Select, to make the customer searchable with these fields","Wählen Sie, um den Kunden mit diesen Feldern durchsuchbar zu machen", @@ -9598,8 +9601,8 @@ This role is allowed to submit transactions that exceed credit limits,"Diese Rol Show Inclusive Tax in Print,Inklusive Steuern im Druck anzeigen, Only select this if you have set up the Cash Flow Mapper documents,"Wählen Sie diese Option nur, wenn Sie die Cash Flow Mapper-Dokumente eingerichtet haben", Payment Channel,Zahlungskanal, -Is Purchase Order Required for Purchase Invoice & Receipt Creation?,Ist für die Erstellung von Kaufrechnungen und Quittungen eine Bestellung erforderlich?, -Is Purchase Receipt Required for Purchase Invoice Creation?,Ist für die Erstellung der Kaufrechnung ein Kaufbeleg erforderlich?, +Is Purchase Order Required for Purchase Invoice & Receipt Creation?,Ist für die Erstellung von Eingangsrechnungen und Quittungen eine Bestellung erforderlich?, +Is Purchase Receipt Required for Purchase Invoice Creation?,Ist für die Erstellung der Eingangsrechnungen ein Kaufbeleg erforderlich?, Maintain Same Rate Throughout the Purchase Cycle,Behalten Sie den gleichen Preis während des gesamten Kaufzyklus bei, Allow Item To Be Added Multiple Times in a Transaction,"Zulassen, dass ein Element in einer Transaktion mehrmals hinzugefügt wird", Suppliers,Lieferanten, @@ -9657,8 +9660,8 @@ Purchase Order already created for all Sales Order items,Bestellung bereits für Select Items,Gegenstände auswählen, Against Default Supplier,Gegen Standardlieferanten, Auto close Opportunity after the no. of days mentioned above,Gelegenheit zum automatischen Schließen nach der Nr. der oben genannten Tage, -Is Sales Order Required for Sales Invoice & Delivery Note Creation?,Ist ein Auftrag für die Erstellung von Kundenrechnungen und Lieferscheinen erforderlich?, -Is Delivery Note Required for Sales Invoice Creation?,Ist für die Erstellung der Ausgangsrechnung ein Lieferschein erforderlich?, +Is Sales Order Required for Sales Invoice & Delivery Note Creation?,Ist ein Auftrag für die Erstellung von Ausgangsrechnungen und Lieferscheinen erforderlich?, +Is Delivery Note Required for Sales Invoice Creation?,Ist ein Lieferschein für die Erstellung von Ausgangsrechnungen erforderlich?, How often should Project and Company be updated based on Sales Transactions?,Wie oft sollten Projekt und Unternehmen basierend auf Verkaufstransaktionen aktualisiert werden?, Allow User to Edit Price List Rate in Transactions,Benutzer darf Preisliste in Transaktionen bearbeiten, Allow Item to Be Added Multiple Times in a Transaction,"Zulassen, dass ein Element in einer Transaktion mehrmals hinzugefügt wird", @@ -9804,7 +9807,7 @@ or it is not the default inventory account,oder es ist nicht das Standard-Invent Expense Head Changed,Ausgabenkopf geändert, because expense is booked against this account in Purchase Receipt {},weil die Kosten für dieses Konto im Kaufbeleg {} gebucht werden, as no Purchase Receipt is created against Item {}. ,da für Artikel {} kein Kaufbeleg erstellt wird., -This is done to handle accounting for cases when Purchase Receipt is created after Purchase Invoice,"Dies erfolgt zur Abrechnung von Fällen, in denen der Kaufbeleg nach der Kaufrechnung erstellt wird", +This is done to handle accounting for cases when Purchase Receipt is created after Purchase Invoice,"Dies erfolgt zur Abrechnung von Fällen, in denen der Kaufbeleg nach der Eingangsrechnung erstellt wird", Purchase Order Required for item {},Bestellung erforderlich für Artikel {}, To submit the invoice without purchase order please set {} ,"Um die Rechnung ohne Bestellung einzureichen, setzen Sie bitte {}", as {} in {},wie in {}, From 56657b6122c056a8ba091b41fd1b6e94447f34da Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Wed, 20 Sep 2023 18:06:30 +0530 Subject: [PATCH 06/22] fix: allow to select parent warehouse in the website item (backport #37047) (#37173) fix: allow to select parent warehouse in the website item (#37047) (cherry picked from commit e6199dc80227023d70c7b7dabb7b0239345f9be5) Co-authored-by: rohitwaghchaure --- .../doctype/website_item/test_website_item.py | 6 +-- .../doctype/website_item/website_item.js | 6 --- .../doctype/website_item/website_item.json | 4 +- .../e_commerce/product_data_engine/query.py | 10 ++--- erpnext/e_commerce/shopping_cart/cart.py | 14 ++++++- erpnext/e_commerce/variant_selector/utils.py | 19 +++++---- erpnext/stock/get_item_details.py | 3 ++ .../generators/item/item_add_to_cart.html | 2 +- erpnext/templates/pages/wishlist.py | 16 ++++++-- erpnext/utilities/product.py | 39 ++++++++++++------- 10 files changed, 75 insertions(+), 44 deletions(-) diff --git a/erpnext/e_commerce/doctype/website_item/test_website_item.py b/erpnext/e_commerce/doctype/website_item/test_website_item.py index 019a5f9ee4f..8eebfdb83af 100644 --- a/erpnext/e_commerce/doctype/website_item/test_website_item.py +++ b/erpnext/e_commerce/doctype/website_item/test_website_item.py @@ -312,7 +312,7 @@ class TestWebsiteItem(unittest.TestCase): # check if stock details are fetched and item not in stock with warehouse set data = get_product_info_for_website(item_code, skip_quotation_creation=True) self.assertFalse(bool(data.product_info["in_stock"])) - self.assertEqual(data.product_info["stock_qty"][0][0], 0) + self.assertEqual(data.product_info["stock_qty"], 0) # disable show stock availability setup_e_commerce_settings({"show_stock_availability": 0}) @@ -355,7 +355,7 @@ class TestWebsiteItem(unittest.TestCase): # check if stock details are fetched and item is in stock with warehouse set data = get_product_info_for_website(item_code, skip_quotation_creation=True) self.assertTrue(bool(data.product_info["in_stock"])) - self.assertEqual(data.product_info["stock_qty"][0][0], 2) + self.assertEqual(data.product_info["stock_qty"], 2) # unset warehouse frappe.db.set_value("Website Item", {"item_code": item_code}, "website_warehouse", "") @@ -364,7 +364,7 @@ class TestWebsiteItem(unittest.TestCase): # (even though it has stock in some warehouse) data = get_product_info_for_website(item_code, skip_quotation_creation=True) self.assertFalse(bool(data.product_info["in_stock"])) - self.assertFalse(bool(data.product_info["stock_qty"])) + self.assertFalse(data.product_info["stock_qty"]) # disable show stock availability setup_e_commerce_settings({"show_stock_availability": 0}) diff --git a/erpnext/e_commerce/doctype/website_item/website_item.js b/erpnext/e_commerce/doctype/website_item/website_item.js index 7b7193e833a..b6595cce8a9 100644 --- a/erpnext/e_commerce/doctype/website_item/website_item.js +++ b/erpnext/e_commerce/doctype/website_item/website_item.js @@ -5,12 +5,6 @@ frappe.ui.form.on('Website Item', { onload: (frm) => { // should never check Private frm.fields_dict["website_image"].df.is_private = 0; - - frm.set_query("website_warehouse", () => { - return { - filters: {"is_group": 0} - }; - }); }, refresh: (frm) => { diff --git a/erpnext/e_commerce/doctype/website_item/website_item.json b/erpnext/e_commerce/doctype/website_item/website_item.json index 6556eabf4ab..6f551a0b42d 100644 --- a/erpnext/e_commerce/doctype/website_item/website_item.json +++ b/erpnext/e_commerce/doctype/website_item/website_item.json @@ -135,7 +135,7 @@ "fieldtype": "Column Break" }, { - "description": "Show Stock availability based on this warehouse.", + "description": "Show Stock availability based on this warehouse. If the parent warehouse is selected, then the system will display the consolidated available quantity of all child warehouses.", "fieldname": "website_warehouse", "fieldtype": "Link", "ignore_user_permissions": 1, @@ -348,7 +348,7 @@ "index_web_pages_for_search": 1, "links": [], "make_attachments_public": 1, - "modified": "2022-09-30 04:01:52.090732", + "modified": "2023-09-12 14:19:22.822689", "modified_by": "Administrator", "module": "E-commerce", "name": "Website Item", diff --git a/erpnext/e_commerce/product_data_engine/query.py b/erpnext/e_commerce/product_data_engine/query.py index e6a595a0344..975f87608a6 100644 --- a/erpnext/e_commerce/product_data_engine/query.py +++ b/erpnext/e_commerce/product_data_engine/query.py @@ -259,6 +259,10 @@ class ProductQuery: ) def get_stock_availability(self, item): + from erpnext.templates.pages.wishlist import ( + get_stock_availability as get_stock_availability_from_template, + ) + """Modify item object and add stock details.""" item.in_stock = False warehouse = item.get("website_warehouse") @@ -274,11 +278,7 @@ class ProductQuery: else: item.in_stock = True elif warehouse: - # stock item and has warehouse - actual_qty = frappe.db.get_value( - "Bin", {"item_code": item.item_code, "warehouse": item.get("website_warehouse")}, "actual_qty" - ) - item.in_stock = bool(flt(actual_qty)) + item.in_stock = get_stock_availability_from_template(item.item_code, warehouse) def get_cart_items(self): customer = get_customer(silent=True) diff --git a/erpnext/e_commerce/shopping_cart/cart.py b/erpnext/e_commerce/shopping_cart/cart.py index 57746a234bc..030b439ae4b 100644 --- a/erpnext/e_commerce/shopping_cart/cart.py +++ b/erpnext/e_commerce/shopping_cart/cart.py @@ -111,8 +111,8 @@ def place_order(): item_stock = get_web_item_qty_in_stock(item.item_code, "website_warehouse") if not cint(item_stock.in_stock): throw(_("{0} Not in Stock").format(item.item_code)) - if item.qty > item_stock.stock_qty[0][0]: - throw(_("Only {0} in Stock for item {1}").format(item_stock.stock_qty[0][0], item.item_code)) + if item.qty > item_stock.stock_qty: + throw(_("Only {0} in Stock for item {1}").format(item_stock.stock_qty, item.item_code)) sales_order.flags.ignore_permissions = True sales_order.insert() @@ -150,6 +150,10 @@ def update_cart(item_code, qty, additional_notes=None, with_items=False): empty_card = True else: + warehouse = frappe.get_cached_value( + "Website Item", {"item_code": item_code}, "website_warehouse" + ) + quotation_items = quotation.get("items", {"item_code": item_code}) if not quotation_items: quotation.append( @@ -159,11 +163,13 @@ def update_cart(item_code, qty, additional_notes=None, with_items=False): "item_code": item_code, "qty": qty, "additional_notes": additional_notes, + "warehouse": warehouse, }, ) else: quotation_items[0].qty = qty quotation_items[0].additional_notes = additional_notes + quotation_items[0].warehouse = warehouse apply_cart_settings(quotation=quotation) @@ -322,6 +328,10 @@ def decorate_quotation_doc(doc): fields = fields[2:] d.update(frappe.db.get_value("Website Item", {"item_code": item_code}, fields, as_dict=True)) + website_warehouse = frappe.get_cached_value( + "Website Item", {"item_code": item_code}, "website_warehouse" + ) + d.warehouse = website_warehouse return doc diff --git a/erpnext/e_commerce/variant_selector/utils.py b/erpnext/e_commerce/variant_selector/utils.py index 4466c457436..88356f5e909 100644 --- a/erpnext/e_commerce/variant_selector/utils.py +++ b/erpnext/e_commerce/variant_selector/utils.py @@ -104,6 +104,8 @@ def get_attributes_and_values(item_code): @frappe.whitelist(allow_guest=True) def get_next_attribute_and_values(item_code, selected_attributes): + from erpnext.stock.doctype.warehouse.warehouse import get_child_warehouses + """Find the count of Items that match the selected attributes. Also, find the attribute values that are not applicable for further searching. If less than equal to 10 items are found, return item_codes of those items. @@ -168,7 +170,7 @@ def get_next_attribute_and_values(item_code, selected_attributes): product_info = None product_id = "" - website_warehouse = "" + warehouse = "" if exact_match or filtered_items: if exact_match and len(exact_match) == 1: product_id = exact_match[0] @@ -176,16 +178,19 @@ def get_next_attribute_and_values(item_code, selected_attributes): product_id = list(filtered_items)[0] if product_id: - website_warehouse = frappe.get_cached_value( + warehouse = frappe.get_cached_value( "Website Item", {"item_code": product_id}, "website_warehouse" ) available_qty = 0.0 - if website_warehouse: - available_qty = flt( - frappe.db.get_value( - "Bin", {"item_code": product_id, "warehouse": website_warehouse}, "actual_qty" - ) + if warehouse and frappe.get_cached_value("Warehouse", warehouse, "is_group") == 1: + warehouses = get_child_warehouses(warehouse) + else: + warehouses = [warehouse] if warehouse else [] + + for warehouse in warehouses: + available_qty += flt( + frappe.db.get_value("Bin", {"item_code": product_id, "warehouse": warehouse}, "actual_qty") ) return { diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py index f7eb859f830..13f484b1c85 100644 --- a/erpnext/stock/get_item_details.py +++ b/erpnext/stock/get_item_details.py @@ -1392,6 +1392,9 @@ def get_default_bom(item_code=None): @frappe.whitelist() def get_valuation_rate(item_code, company, warehouse=None): + if frappe.get_cached_value("Warehouse", warehouse, "is_group"): + return {"valuation_rate": 0.0} + item = get_item_defaults(item_code, company) item_group = get_item_group_defaults(item_code, company) brand = get_brand_defaults(item_code, company) diff --git a/erpnext/templates/generators/item/item_add_to_cart.html b/erpnext/templates/generators/item/item_add_to_cart.html index 1381dfe3b74..9bd3f7514c9 100644 --- a/erpnext/templates/generators/item/item_add_to_cart.html +++ b/erpnext/templates/generators/item/item_add_to_cart.html @@ -49,7 +49,7 @@ {{ _('In stock') }} {% if product_info.show_stock_qty and product_info.stock_qty %} - ({{ product_info.stock_qty[0][0] }}) + ({{ product_info.stock_qty }}) {% endif %} {% endif %} diff --git a/erpnext/templates/pages/wishlist.py b/erpnext/templates/pages/wishlist.py index d70f27c9d9d..17607e45f91 100644 --- a/erpnext/templates/pages/wishlist.py +++ b/erpnext/templates/pages/wishlist.py @@ -25,9 +25,19 @@ def get_context(context): def get_stock_availability(item_code, warehouse): - stock_qty = frappe.utils.flt( - frappe.db.get_value("Bin", {"item_code": item_code, "warehouse": warehouse}, "actual_qty") - ) + from erpnext.stock.doctype.warehouse.warehouse import get_child_warehouses + + if warehouse and frappe.get_cached_value("Warehouse", warehouse, "is_group") == 1: + warehouses = get_child_warehouses(warehouse) + else: + warehouses = [warehouse] if warehouse else [] + + stock_qty = 0.0 + for warehouse in warehouses: + stock_qty += frappe.utils.flt( + frappe.db.get_value("Bin", {"item_code": item_code, "warehouse": warehouse}, "actual_qty") + ) + return bool(stock_qty) diff --git a/erpnext/utilities/product.py b/erpnext/utilities/product.py index afe9654e8ea..e967f7061bb 100644 --- a/erpnext/utilities/product.py +++ b/erpnext/utilities/product.py @@ -6,6 +6,7 @@ from frappe.utils import cint, flt, fmt_money, getdate, nowdate from erpnext.accounts.doctype.pricing_rule.pricing_rule import get_pricing_rule_for_item from erpnext.stock.doctype.batch.batch import get_batch_qty +from erpnext.stock.doctype.warehouse.warehouse import get_child_warehouses def get_web_item_qty_in_stock(item_code, item_warehouse_field, warehouse=None): @@ -22,23 +23,31 @@ def get_web_item_qty_in_stock(item_code, item_warehouse_field, warehouse=None): "Website Item", {"item_code": template_item_code}, item_warehouse_field ) - if warehouse: - stock_qty = frappe.db.sql( - """ - select GREATEST(S.actual_qty - S.reserved_qty - S.reserved_qty_for_production - S.reserved_qty_for_sub_contract, 0) / IFNULL(C.conversion_factor, 1) - from tabBin S - inner join `tabItem` I on S.item_code = I.Item_code - left join `tabUOM Conversion Detail` C on I.sales_uom = C.uom and C.parent = I.Item_code - where S.item_code=%s and S.warehouse=%s""", - (item_code, warehouse), - ) + if warehouse and frappe.get_cached_value("Warehouse", warehouse, "is_group") == 1: + warehouses = get_child_warehouses(warehouse) + else: + warehouses = [warehouse] if warehouse else [] - if stock_qty: - stock_qty = adjust_qty_for_expired_items(item_code, stock_qty, warehouse) - in_stock = stock_qty[0][0] > 0 and 1 or 0 + total_stock = 0.0 + if warehouses: + for warehouse in warehouses: + stock_qty = frappe.db.sql( + """ + select GREATEST(S.actual_qty - S.reserved_qty - S.reserved_qty_for_production - S.reserved_qty_for_sub_contract, 0) / IFNULL(C.conversion_factor, 1) + from tabBin S + inner join `tabItem` I on S.item_code = I.Item_code + left join `tabUOM Conversion Detail` C on I.sales_uom = C.uom and C.parent = I.Item_code + where S.item_code=%s and S.warehouse=%s""", + (item_code, warehouse), + ) + + if stock_qty: + total_stock += adjust_qty_for_expired_items(item_code, stock_qty, warehouse) + + in_stock = total_stock > 0 and 1 or 0 return frappe._dict( - {"in_stock": in_stock, "stock_qty": stock_qty, "is_stock_item": is_stock_item} + {"in_stock": in_stock, "stock_qty": total_stock, "is_stock_item": is_stock_item} ) @@ -56,7 +65,7 @@ def adjust_qty_for_expired_items(item_code, stock_qty, warehouse): if not stock_qty[0][0]: break - return stock_qty + return stock_qty[0][0] if stock_qty else 0 def get_expired_batches(batches): From 03e52d385969504564b5079c2551b34dd373292f Mon Sep 17 00:00:00 2001 From: Raffael Meyer <14891507+barredterra@users.noreply.github.com> Date: Wed, 20 Sep 2023 14:38:42 +0200 Subject: [PATCH 07/22] chore: resolve conflicts --- erpnext/translations/de.csv | 4 ---- 1 file changed, 4 deletions(-) diff --git a/erpnext/translations/de.csv b/erpnext/translations/de.csv index 6dae398e334..dcba85b4d20 100644 --- a/erpnext/translations/de.csv +++ b/erpnext/translations/de.csv @@ -1969,12 +1969,8 @@ Please check Multi Currency option to allow accounts with other currency,"Bitte Please click on 'Generate Schedule',"Bitte auf ""Zeitplan generieren"" klicken", Please click on 'Generate Schedule' to fetch Serial No added for Item {0},"Bitte auf ""Zeitplan generieren"" klicken, um die Seriennummer für Artikel {0} abzurufen", Please click on 'Generate Schedule' to get schedule,"Bitte auf ""Zeitplan generieren"" klicken, um den Zeitplan zu erhalten", -<<<<<<< HEAD Please confirm once you have completed your training,"Bitte bestätigen Sie, sobald Sie Ihre Ausbildung abgeschlossen haben", -Please create purchase receipt or purchase invoice for the item {0},Bitte erstellen Sie eine Kaufquittung oder eine Kaufrechnung für den Artikel {0}, -======= Please create purchase receipt or purchase invoice for the item {0},Bitte erstellen Sie eine Kaufquittung oder eine Eingangsrechnungen für den Artikel {0}, ->>>>>>> 84a9000db2 (fix: german translation of Sales and Purchase Invoice (#37122)) Please define grade for Threshold 0%,Bitte definieren Sie Grade for Threshold 0%, Please enable Applicable on Booking Actual Expenses,Bitte aktivieren Sie Anwendbar bei der Buchung von tatsächlichen Ausgaben, Please enable Applicable on Purchase Order and Applicable on Booking Actual Expenses,Bitte aktivieren Sie Anwendbar bei Bestellung und Anwendbar bei Buchung von tatsächlichen Ausgaben, From f2bcfb5f977927cad9f4288b667bbce4d231c6c8 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Wed, 20 Sep 2023 19:21:54 +0530 Subject: [PATCH 08/22] fix: labels for `Stock Ledger Invariant Check` report (backport #37150) (#37176) fix: labels for `Stock Ledger Invariant Check` report (#37150) refactor: `Stock Ledger Invariant Check` report (cherry picked from commit f0859ecc60a8a08f547bf124f222ef5cd3282502) Co-authored-by: s-aga-r --- .../stock_ledger_invariant_check.js | 4 ++-- .../stock_ledger_invariant_check.py | 22 +++++++++---------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/erpnext/stock/report/stock_ledger_invariant_check/stock_ledger_invariant_check.js b/erpnext/stock/report/stock_ledger_invariant_check/stock_ledger_invariant_check.js index 74849058c3c..94e0b2dce3b 100644 --- a/erpnext/stock/report/stock_ledger_invariant_check/stock_ledger_invariant_check.js +++ b/erpnext/stock/report/stock_ledger_invariant_check/stock_ledger_invariant_check.js @@ -2,7 +2,7 @@ // For license information, please see license.txt /* eslint-disable */ -const DIFFERNCE_FIELD_NAMES = [ +const DIFFERENCE_FIELD_NAMES = [ 'difference_in_qty', 'fifo_qty_diff', 'fifo_value_diff', @@ -37,7 +37,7 @@ frappe.query_reports['Stock Ledger Invariant Check'] = { formatter (value, row, column, data, default_formatter) { value = default_formatter(value, row, column, data); - if (DIFFERNCE_FIELD_NAMES.includes(column.fieldname) && Math.abs(data[column.fieldname]) > 0.001) { + if (DIFFERENCE_FIELD_NAMES.includes(column.fieldname) && Math.abs(data[column.fieldname]) > 0.001) { value = '' + value + ''; } return value; diff --git a/erpnext/stock/report/stock_ledger_invariant_check/stock_ledger_invariant_check.py b/erpnext/stock/report/stock_ledger_invariant_check/stock_ledger_invariant_check.py index e11c9bb7891..ca15afe444d 100644 --- a/erpnext/stock/report/stock_ledger_invariant_check/stock_ledger_invariant_check.py +++ b/erpnext/stock/report/stock_ledger_invariant_check/stock_ledger_invariant_check.py @@ -186,7 +186,7 @@ def get_columns(): { "fieldname": "fifo_queue_qty", "fieldtype": "Float", - "label": _("(C) Total qty in queue"), + "label": _("(C) Total Qty in Queue"), }, { "fieldname": "fifo_qty_diff", @@ -211,52 +211,52 @@ def get_columns(): { "fieldname": "stock_value_difference", "fieldtype": "Float", - "label": _("(F) Stock Value Difference"), + "label": _("(F) Change in Stock Value"), }, { "fieldname": "stock_value_from_diff", "fieldtype": "Float", - "label": _("Balance Stock Value using (F)"), + "label": _("(G) Sum of Change in Stock Value"), }, { "fieldname": "diff_value_diff", "fieldtype": "Float", - "label": _("K - D"), + "label": _("G - D"), }, { "fieldname": "fifo_stock_diff", "fieldtype": "Float", - "label": _("(G) Stock Value difference (FIFO queue)"), + "label": _("(H) Change in Stock Value (FIFO Queue)"), }, { "fieldname": "fifo_difference_diff", "fieldtype": "Float", - "label": _("F - G"), + "label": _("H - F"), }, { "fieldname": "valuation_rate", "fieldtype": "Float", - "label": _("(H) Valuation Rate"), + "label": _("(I) Valuation Rate"), }, { "fieldname": "fifo_valuation_rate", "fieldtype": "Float", - "label": _("(I) Valuation Rate as per FIFO"), + "label": _("(J) Valuation Rate as per FIFO"), }, { "fieldname": "fifo_valuation_diff", "fieldtype": "Float", - "label": _("H - I"), + "label": _("I - J"), }, { "fieldname": "balance_value_by_qty", "fieldtype": "Float", - "label": _("(J) Valuation = Value (D) ÷ Qty (A)"), + "label": _("(K) Valuation = Value (D) ÷ Qty (A)"), }, { "fieldname": "valuation_diff", "fieldtype": "Float", - "label": _("H - J"), + "label": _("I - K"), }, ] From 02fc67c83c94b6277e4e6dafd22381ed04da0ad6 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Thu, 21 Sep 2023 07:49:02 +0000 Subject: [PATCH 09/22] feat: `Stock Ledger Variance` report (backport #37165) (#37183) feat: `Stock Ledger Variance` report (#37165) * feat: `Stock Ledger Variance` report * refactor: `get_data()` (cherry picked from commit acda72d6165aa395fedebf9522aa0adf45c25fa2) Co-authored-by: s-aga-r --- .../report/stock_ledger_variance/__init__.py | 0 .../stock_ledger_variance.js | 101 +++++++ .../stock_ledger_variance.json | 22 ++ .../stock_ledger_variance.py | 279 ++++++++++++++++++ 4 files changed, 402 insertions(+) create mode 100644 erpnext/stock/report/stock_ledger_variance/__init__.py create mode 100644 erpnext/stock/report/stock_ledger_variance/stock_ledger_variance.js create mode 100644 erpnext/stock/report/stock_ledger_variance/stock_ledger_variance.json create mode 100644 erpnext/stock/report/stock_ledger_variance/stock_ledger_variance.py diff --git a/erpnext/stock/report/stock_ledger_variance/__init__.py b/erpnext/stock/report/stock_ledger_variance/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/stock/report/stock_ledger_variance/stock_ledger_variance.js b/erpnext/stock/report/stock_ledger_variance/stock_ledger_variance.js new file mode 100644 index 00000000000..b1e4a74571e --- /dev/null +++ b/erpnext/stock/report/stock_ledger_variance/stock_ledger_variance.js @@ -0,0 +1,101 @@ +// Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt + +const DIFFERENCE_FIELD_NAMES = [ + "difference_in_qty", + "fifo_qty_diff", + "fifo_value_diff", + "fifo_valuation_diff", + "valuation_diff", + "fifo_difference_diff", + "diff_value_diff" +]; + +frappe.query_reports["Stock Ledger Variance"] = { + "filters": [ + { + "fieldname": "item_code", + "fieldtype": "Link", + "label": "Item", + "options": "Item", + get_query: function() { + return { + filters: {is_stock_item: 1, has_serial_no: 0} + } + } + }, + { + "fieldname": "warehouse", + "fieldtype": "Link", + "label": "Warehouse", + "options": "Warehouse", + get_query: function() { + return { + filters: {is_group: 0, disabled: 0} + } + } + }, + { + "fieldname": "difference_in", + "fieldtype": "Select", + "label": "Difference In", + "options": [ + "", + "Qty", + "Value", + "Valuation", + ], + }, + { + "fieldname": "include_disabled", + "fieldtype": "Check", + "label": "Include Disabled", + } + ], + + formatter (value, row, column, data, default_formatter) { + value = default_formatter(value, row, column, data); + + if (DIFFERENCE_FIELD_NAMES.includes(column.fieldname) && Math.abs(data[column.fieldname]) > 0.001) { + value = "" + value + ""; + } + + return value; + }, + + get_datatable_options(options) { + return Object.assign(options, { + checkboxColumn: true, + }); + }, + + onload(report) { + report.page.add_inner_button(__('Create Reposting Entries'), () => { + let message = ` +
+

+ Reposting Entries will change the value of + accounts Stock In Hand, and Stock Expenses + in the Trial Balance report and will also change + the Balance Value in the Stock Balance report. +

+

Are you sure you want to create Reposting Entries?

+
`; + let indexes = frappe.query_report.datatable.rowmanager.getCheckedRows(); + let selected_rows = indexes.map(i => frappe.query_report.data[i]); + + if (!selected_rows.length) { + frappe.throw(__("Please select rows to create Reposting Entries")); + } + + frappe.confirm(__(message), () => { + frappe.call({ + method: 'erpnext.stock.report.stock_ledger_invariant_check.stock_ledger_invariant_check.create_reposting_entries', + args: { + rows: selected_rows, + } + }); + }); + }); + }, +}; diff --git a/erpnext/stock/report/stock_ledger_variance/stock_ledger_variance.json b/erpnext/stock/report/stock_ledger_variance/stock_ledger_variance.json new file mode 100644 index 00000000000..f36ed1b9ca6 --- /dev/null +++ b/erpnext/stock/report/stock_ledger_variance/stock_ledger_variance.json @@ -0,0 +1,22 @@ +{ + "add_total_row": 0, + "columns": [], + "creation": "2023-09-20 10:44:19.414449", + "disabled": 0, + "docstatus": 0, + "doctype": "Report", + "filters": [], + "idx": 0, + "is_standard": "Yes", + "letterhead": null, + "modified": "2023-09-20 10:44:19.414449", + "modified_by": "Administrator", + "module": "Stock", + "name": "Stock Ledger Variance", + "owner": "Administrator", + "prepared_report": 0, + "ref_doctype": "Stock Ledger Entry", + "report_name": "Stock Ledger Variance", + "report_type": "Script Report", + "roles": [] +} \ No newline at end of file diff --git a/erpnext/stock/report/stock_ledger_variance/stock_ledger_variance.py b/erpnext/stock/report/stock_ledger_variance/stock_ledger_variance.py new file mode 100644 index 00000000000..732f108ac41 --- /dev/null +++ b/erpnext/stock/report/stock_ledger_variance/stock_ledger_variance.py @@ -0,0 +1,279 @@ +# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +import frappe +from frappe import _ +from frappe.utils import cint, flt + +from erpnext.stock.report.stock_ledger_invariant_check.stock_ledger_invariant_check import ( + get_data as stock_ledger_invariant_check, +) + + +def execute(filters=None): + columns, data = [], [] + + filters = frappe._dict(filters or {}) + columns = get_columns() + data = get_data(filters) + + return columns, data + + +def get_columns(): + return [ + { + "fieldname": "name", + "fieldtype": "Link", + "label": _("Stock Ledger Entry"), + "options": "Stock Ledger Entry", + }, + { + "fieldname": "posting_date", + "fieldtype": "Data", + "label": _("Posting Date"), + }, + { + "fieldname": "posting_time", + "fieldtype": "Data", + "label": _("Posting Time"), + }, + { + "fieldname": "creation", + "fieldtype": "Data", + "label": _("Creation"), + }, + { + "fieldname": "item_code", + "fieldtype": "Link", + "label": _("Item"), + "options": "Item", + }, + { + "fieldname": "warehouse", + "fieldtype": "Link", + "label": _("Warehouse"), + "options": "Warehouse", + }, + { + "fieldname": "voucher_type", + "fieldtype": "Link", + "label": _("Voucher Type"), + "options": "DocType", + }, + { + "fieldname": "voucher_no", + "fieldtype": "Dynamic Link", + "label": _("Voucher No"), + "options": "voucher_type", + }, + { + "fieldname": "batch_no", + "fieldtype": "Link", + "label": _("Batch"), + "options": "Batch", + }, + { + "fieldname": "use_batchwise_valuation", + "fieldtype": "Check", + "label": _("Batchwise Valuation"), + }, + { + "fieldname": "actual_qty", + "fieldtype": "Float", + "label": _("Qty Change"), + }, + { + "fieldname": "incoming_rate", + "fieldtype": "Float", + "label": _("Incoming Rate"), + }, + { + "fieldname": "consumption_rate", + "fieldtype": "Float", + "label": _("Consumption Rate"), + }, + { + "fieldname": "qty_after_transaction", + "fieldtype": "Float", + "label": _("(A) Qty After Transaction"), + }, + { + "fieldname": "expected_qty_after_transaction", + "fieldtype": "Float", + "label": _("(B) Expected Qty After Transaction"), + }, + { + "fieldname": "difference_in_qty", + "fieldtype": "Float", + "label": _("A - B"), + }, + { + "fieldname": "stock_queue", + "fieldtype": "Data", + "label": _("FIFO/LIFO Queue"), + }, + { + "fieldname": "fifo_queue_qty", + "fieldtype": "Float", + "label": _("(C) Total Qty in Queue"), + }, + { + "fieldname": "fifo_qty_diff", + "fieldtype": "Float", + "label": _("A - C"), + }, + { + "fieldname": "stock_value", + "fieldtype": "Float", + "label": _("(D) Balance Stock Value"), + }, + { + "fieldname": "fifo_stock_value", + "fieldtype": "Float", + "label": _("(E) Balance Stock Value in Queue"), + }, + { + "fieldname": "fifo_value_diff", + "fieldtype": "Float", + "label": _("D - E"), + }, + { + "fieldname": "stock_value_difference", + "fieldtype": "Float", + "label": _("(F) Change in Stock Value"), + }, + { + "fieldname": "stock_value_from_diff", + "fieldtype": "Float", + "label": _("(G) Sum of Change in Stock Value"), + }, + { + "fieldname": "diff_value_diff", + "fieldtype": "Float", + "label": _("G - D"), + }, + { + "fieldname": "fifo_stock_diff", + "fieldtype": "Float", + "label": _("(H) Change in Stock Value (FIFO Queue)"), + }, + { + "fieldname": "fifo_difference_diff", + "fieldtype": "Float", + "label": _("H - F"), + }, + { + "fieldname": "valuation_rate", + "fieldtype": "Float", + "label": _("(I) Valuation Rate"), + }, + { + "fieldname": "fifo_valuation_rate", + "fieldtype": "Float", + "label": _("(J) Valuation Rate as per FIFO"), + }, + { + "fieldname": "fifo_valuation_diff", + "fieldtype": "Float", + "label": _("I - J"), + }, + { + "fieldname": "balance_value_by_qty", + "fieldtype": "Float", + "label": _("(K) Valuation = Value (D) ÷ Qty (A)"), + }, + { + "fieldname": "valuation_diff", + "fieldtype": "Float", + "label": _("I - K"), + }, + ] + + +def get_data(filters=None): + filters = frappe._dict(filters or {}) + item_warehouse_map = get_item_warehouse_combinations(filters) + + data = [] + if item_warehouse_map: + precision = cint(frappe.db.get_single_value("System Settings", "float_precision")) + + for item_warehouse in item_warehouse_map: + report_data = stock_ledger_invariant_check(item_warehouse) + + if not report_data: + continue + + for row in report_data: + if has_difference(row, precision, filters.difference_in): + data.append(add_item_warehouse_details(row, item_warehouse)) + break + + return data + + +def get_item_warehouse_combinations(filters: dict = None) -> dict: + filters = frappe._dict(filters or {}) + + bin = frappe.qb.DocType("Bin") + item = frappe.qb.DocType("Item") + warehouse = frappe.qb.DocType("Warehouse") + + query = ( + frappe.qb.from_(bin) + .inner_join(item) + .on(bin.item_code == item.name) + .inner_join(warehouse) + .on(bin.warehouse == warehouse.name) + .select( + bin.item_code, + bin.warehouse, + ) + .where((item.is_stock_item == 1) & (item.has_serial_no == 0) & (warehouse.is_group == 0)) + ) + + if filters.item_code: + query = query.where(item.name == filters.item_code) + if filters.warehouse: + query = query.where(warehouse.name == filters.warehouse) + if not filters.include_disabled: + query = query.where((item.disabled == 0) & (warehouse.disabled == 0)) + + return query.run(as_dict=1) + + +def has_difference(row, precision, difference_in): + has_qty_difference = flt(row.difference_in_qty, precision) or flt(row.fifo_qty_diff, precision) + has_value_difference = ( + flt(row.diff_value_diff, precision) + or flt(row.fifo_value_diff, precision) + or flt(row.fifo_difference_diff, precision) + ) + has_valuation_difference = flt(row.valuation_diff, precision) or flt( + row.fifo_valuation_diff, precision + ) + + if difference_in == "Qty" and has_qty_difference: + return True + elif difference_in == "Value" and has_value_difference: + return True + elif difference_in == "Valuation" and has_valuation_difference: + return True + elif difference_in not in ["Qty", "Value", "Valuation"] and ( + has_qty_difference or has_value_difference or has_valuation_difference + ): + return True + + return False + + +def add_item_warehouse_details(row, item_warehouse): + row.update( + { + "item_code": item_warehouse.item_code, + "warehouse": item_warehouse.warehouse, + } + ) + + return row From 1181dcf521b6d5bc6f96a217f6991e0d5cb138d3 Mon Sep 17 00:00:00 2001 From: marination Date: Wed, 13 Sep 2023 14:24:56 +0530 Subject: [PATCH 10/22] fix: Update `advance_paid` in SO/PO after unlinking from advance entry (cherry picked from commit 426350eee6efdfeddf300bbeccd7674f0a6d7b9b) --- erpnext/accounts/utils.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py index 8f0ef869ad3..971932e415a 100644 --- a/erpnext/accounts/utils.py +++ b/erpnext/accounts/utils.py @@ -560,6 +560,10 @@ def update_reference_in_journal_entry(d, journal_entry, do_not_save=False): """ jv_detail = journal_entry.get("accounts", {"name": d["voucher_detail_no"]})[0] + # Update Advance Paid in SO/PO since they might be getting unlinked + if jv_detail.get("reference_type") in ("Sales Order", "Purchase Order"): + frappe.get_doc(jv_detail.reference_type, jv_detail.reference_name).set_total_advance_paid() + if flt(d["unadjusted_amount"]) - flt(d["allocated_amount"]) != 0: # adjust the unreconciled balance amount_in_account_currency = flt(d["unadjusted_amount"]) - flt(d["allocated_amount"]) @@ -625,6 +629,13 @@ def update_reference_in_payment_entry( if d.voucher_detail_no: existing_row = payment_entry.get("references", {"name": d["voucher_detail_no"]})[0] + + # Update Advance Paid in SO/PO since they are getting unlinked + if existing_row.get("reference_doctype") in ("Sales Order", "Purchase Order"): + frappe.get_doc( + existing_row.reference_doctype, existing_row.reference_name + ).set_total_advance_paid() + original_row = existing_row.as_dict().copy() existing_row.update(reference_details) From 591c720e5165019672faacb9369c9da8087dfbbe Mon Sep 17 00:00:00 2001 From: marination Date: Wed, 13 Sep 2023 19:09:03 +0530 Subject: [PATCH 11/22] test: Impact on SO of advance PE submit and unlinking/replacement by SI (cherry picked from commit 8a4954d713a31a60581414be38ca90c1fad3c794) --- .../sales_invoice/test_sales_invoice.py | 32 ++++++++++++++++--- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 378be113e7c..e0a7ff002bb 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -1801,6 +1801,10 @@ class TestSalesInvoice(unittest.TestCase): ) def test_outstanding_amount_after_advance_payment_entry_cancellation(self): + """Test impact of advance PE submission/cancellation on SI and SO.""" + from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order + + sales_order = make_sales_order(item_code="138-CMS Shoe", qty=1, price_list_rate=500) pe = frappe.get_doc( { "doctype": "Payment Entry", @@ -1820,10 +1824,25 @@ class TestSalesInvoice(unittest.TestCase): "paid_to": "_Test Cash - _TC", } ) + pe.append( + "references", + { + "reference_doctype": "Sales Order", + "reference_name": sales_order.name, + "total_amount": sales_order.grand_total, + "outstanding_amount": sales_order.grand_total, + "allocated_amount": 300, + }, + ) pe.insert() pe.submit() + sales_order.reload() + self.assertEqual(sales_order.advance_paid, 300) + si = frappe.copy_doc(test_records[0]) + si.items[0].sales_order = sales_order.name + si.items[0].so_detail = sales_order.get("items")[0].name si.is_pos = 0 si.append( "advances", @@ -1831,6 +1850,7 @@ class TestSalesInvoice(unittest.TestCase): "doctype": "Sales Invoice Advance", "reference_type": "Payment Entry", "reference_name": pe.name, + "reference_row": pe.references[0].name, "advance_amount": 300, "allocated_amount": 300, "remarks": pe.remarks, @@ -1839,7 +1859,13 @@ class TestSalesInvoice(unittest.TestCase): si.insert() si.submit() - si.load_from_db() + si.reload() + pe.reload() + sales_order.reload() + + # Check if SO is unlinked/replaced by SI in PE & if SO advance paid is 0 + self.assertEqual(pe.references[0].reference_name, si.name) + self.assertEqual(sales_order.advance_paid, 0.0) # check outstanding after advance allocation self.assertEqual( @@ -1847,11 +1873,9 @@ class TestSalesInvoice(unittest.TestCase): flt(si.rounded_total - si.total_advance, si.precision("outstanding_amount")), ) - # added to avoid Document has been modified exception - pe = frappe.get_doc("Payment Entry", pe.name) pe.cancel() + si.reload() - si.load_from_db() # check outstanding after advance cancellation self.assertEqual( flt(si.outstanding_amount), From 9d5fce9091c2e0bd9f32ebf4735f4fefb69aab3b Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Fri, 22 Sep 2023 12:21:57 +0530 Subject: [PATCH 12/22] refactor: ignore PLE's on PCV cancellation (cherry picked from commit 301092dad1020634986dfa744a279b2a793ff30f) --- .../doctype/period_closing_voucher/period_closing_voucher.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.py b/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.py index af1c06643a1..d984d86af25 100644 --- a/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.py +++ b/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.py @@ -33,7 +33,7 @@ class PeriodClosingVoucher(AccountsController): def on_cancel(self): self.validate_future_closing_vouchers() self.db_set("gle_processing_status", "In Progress") - self.ignore_linked_doctypes = ("GL Entry", "Stock Ledger Entry") + self.ignore_linked_doctypes = ("GL Entry", "Stock Ledger Entry", "Payment Ledger Entry") gle_count = frappe.db.count( "GL Entry", {"voucher_type": "Period Closing Voucher", "voucher_no": self.name, "is_cancelled": 0}, From b4bc44db4a8d459de02ee80b0516f20913897b95 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Sat, 23 Sep 2023 17:50:45 +0530 Subject: [PATCH 13/22] fix: apply gl report filters (cherry picked from commit 5346c67b020fe2ae1bdf01399aa7bf6e57dedaeb) --- .../process_statement_of_accounts.py | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py index e1f32952205..c622d308995 100644 --- a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py +++ b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py @@ -64,6 +64,7 @@ def get_report_pdf(doc, consolidated=True): filters = get_common_filters(doc) if doc.report == "General Ledger": + filters.update(get_gl_filters(doc, entry, tax_id, presentation_currency)) col, res = get_soa(filters) for x in [0, -2, -1]: res[x]["account"] = res[x]["account"].replace("'", "") From 57c82c18008ace3b95ccf984be06bb60ec51fe66 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Sat, 23 Sep 2023 14:34:11 +0530 Subject: [PATCH 14/22] feat: Toggle net values in Trial Balance report (cherry picked from commit 06a45897def2595916c93e4b15ded624011adecb) --- .../accounts/report/trial_balance/trial_balance.js | 6 ++++++ .../accounts/report/trial_balance/trial_balance.py | 11 +++++++---- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/report/trial_balance/trial_balance.js b/erpnext/accounts/report/trial_balance/trial_balance.js index e45c3adcb6d..6e233c802f0 100644 --- a/erpnext/accounts/report/trial_balance/trial_balance.js +++ b/erpnext/accounts/report/trial_balance/trial_balance.js @@ -99,6 +99,12 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() { "label": __("Include Default Book Entries"), "fieldtype": "Check", "default": 1 + }, + { + "fieldname": "show_net_values", + "label": __("Show net values in opening and closing columns"), + "fieldtype": "Check", + "default": 1 } ], "formatter": erpnext.financial_statements.formatter, diff --git a/erpnext/accounts/report/trial_balance/trial_balance.py b/erpnext/accounts/report/trial_balance/trial_balance.py index 376571f0346..2a8aa0c202f 100644 --- a/erpnext/accounts/report/trial_balance/trial_balance.py +++ b/erpnext/accounts/report/trial_balance/trial_balance.py @@ -120,7 +120,9 @@ def get_data(filters): ignore_opening_entries=True, ) - calculate_values(accounts, gl_entries_by_account, opening_balances) + calculate_values( + accounts, gl_entries_by_account, opening_balances, filters.get("show_net_values") + ) accumulate_values_into_parents(accounts, accounts_by_name) data = prepare_data(accounts, filters, parent_children_map, company_currency) @@ -310,7 +312,7 @@ def get_opening_balance( return gle -def calculate_values(accounts, gl_entries_by_account, opening_balances): +def calculate_values(accounts, gl_entries_by_account, opening_balances, show_net_values): init = { "opening_debit": 0.0, "opening_credit": 0.0, @@ -335,7 +337,8 @@ def calculate_values(accounts, gl_entries_by_account, opening_balances): d["closing_debit"] = d["opening_debit"] + d["debit"] d["closing_credit"] = d["opening_credit"] + d["credit"] - prepare_opening_closing(d) + if show_net_values: + prepare_opening_closing(d) def calculate_total_row(accounts, company_currency): @@ -375,7 +378,7 @@ def prepare_data(accounts, filters, parent_children_map, company_currency): for d in accounts: # Prepare opening closing for group account - if parent_children_map.get(d.account): + if parent_children_map.get(d.account) and filters.get("show_net_values"): prepare_opening_closing(d) has_value = False From e0da8d261f7b0f73f898bc80f51788843cae6051 Mon Sep 17 00:00:00 2001 From: milanpethani Date: Wed, 20 Sep 2023 11:58:46 +0530 Subject: [PATCH 15/22] fix: set customer currency in pos_invoice if exists if currency exists in the profile and customer currency doesn't exists still it will update currency to None, so update customer currency only if exists (cherry picked from commit 041d52e82880610a99903ecf4c459e98bd1fff76) --- erpnext/accounts/doctype/pos_invoice/pos_invoice.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py index 7c013b6abef..d3058e44509 100644 --- a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py +++ b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py @@ -518,7 +518,7 @@ class POSInvoice(SalesInvoice): selling_price_list = ( customer_price_list or customer_group_price_list or profile.get("selling_price_list") ) - if customer_currency != profile.get("currency"): + if customer_currency and customer_currency != profile.get("currency"): self.set("currency", customer_currency) else: From 25f800d3f5cfd4a3c4d58b455b54d47a782d0d76 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Sun, 24 Sep 2023 22:24:56 +0530 Subject: [PATCH 16/22] fix(Material Request): consider project for item details (backport #37215) (#37221) fix(Material Request): consider project for item details (#37215) fix(Material Request): project in item details (cherry picked from commit 7c4ebe27334b188c9fce225103a1e9ce9b64f40e) Co-authored-by: Raffael Meyer <14891507+barredterra@users.noreply.github.com> --- erpnext/stock/doctype/material_request/material_request.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/material_request/material_request.js b/erpnext/stock/doctype/material_request/material_request.js index b096b024f44..2632501b718 100644 --- a/erpnext/stock/doctype/material_request/material_request.js +++ b/erpnext/stock/doctype/material_request/material_request.js @@ -218,7 +218,8 @@ frappe.ui.form.on('Material Request', { plc_conversion_rate: 1, rate: item.rate, uom: item.uom, - conversion_factor: item.conversion_factor + conversion_factor: item.conversion_factor, + project: item.project, }, overwrite_warehouse: overwrite_warehouse }, From c9ba777e3cf71dd2b30bc3a5a9d22ede0cebe12a Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Mon, 25 Sep 2023 10:24:32 +0200 Subject: [PATCH 17/22] refactor(region): Splitting of France Regional logic from ERPNext --- erpnext/patches.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 19f8dab9a17..37e70967388 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -269,6 +269,7 @@ erpnext.patches.v13_0.show_hr_payroll_deprecation_warning erpnext.patches.v13_0.reset_corrupt_defaults erpnext.patches.v13_0.create_accounting_dimensions_for_asset_repair erpnext.patches.v14_0.update_reference_due_date_in_journal_entry +erpnext.patches.v14_0.france_depreciation_warning [post_model_sync] execute:frappe.delete_doc_if_exists('Workspace', 'ERPNext Integrations Settings') @@ -333,7 +334,7 @@ erpnext.patches.v14_0.update_company_in_ldc erpnext.patches.v14_0.set_packed_qty_in_draft_delivery_notes erpnext.patches.v14_0.cleanup_workspaces erpnext.patches.v14_0.enable_allow_existing_serial_no -erpnext.patches.v14_0.set_report_in_process_SOA +erpnext.patches.v14_0.set_report_in_process_SOA erpnext.patches.v14_0.create_accounting_dimensions_for_closing_balance erpnext.patches.v14_0.update_closing_balances #15-07-2023 execute:frappe.defaults.clear_default("fiscal_year") From 279f21d1e54208790a6fdcf4c828fdef3a74468d Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Tue, 26 Sep 2023 13:32:05 +0530 Subject: [PATCH 18/22] fix: incorrect `Parent Task` getting set for 2nd to nth child Task (backport #37230) (#37240) fix: incorrect `Parent Task` getting set for 2nd to nth child Task (#37230) (cherry picked from commit 73fc97495040fe574cef94930e06aaa7b4e87b7b) Co-authored-by: s-aga-r --- erpnext/projects/doctype/project/project.py | 29 ++++++++------------- 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/erpnext/projects/doctype/project/project.py b/erpnext/projects/doctype/project/project.py index 082ba915207..5c351faae1a 100644 --- a/erpnext/projects/doctype/project/project.py +++ b/erpnext/projects/doctype/project/project.py @@ -67,6 +67,7 @@ class Project(Document): tmp_task_details.append(template_task_details) task = self.create_task_from_template(template_task_details) project_tasks.append(task) + self.dependency_mapping(tmp_task_details, project_tasks) def create_task_from_template(self, task_details): @@ -105,36 +106,28 @@ class Project(Document): def dependency_mapping(self, template_tasks, project_tasks): for project_task in project_tasks: - if project_task.get("template_task"): - template_task = frappe.get_doc("Task", project_task.template_task) - else: - template_task = list(filter(lambda x: x.subject == project_task.subject, template_tasks))[0] - template_task = frappe.get_doc("Task", template_task.name) + template_task = frappe.get_doc("Task", project_task.template_task) self.check_depends_on_value(template_task, project_task, project_tasks) self.check_for_parent_tasks(template_task, project_task, project_tasks) def check_depends_on_value(self, template_task, project_task, project_tasks): if template_task.get("depends_on") and not project_task.get("depends_on"): + project_template_map = {pt.template_task: pt for pt in project_tasks} + for child_task in template_task.get("depends_on"): - child_task_subject = frappe.db.get_value("Task", child_task.task, "subject") - corresponding_project_task = list( - filter(lambda x: x.subject == child_task_subject, project_tasks) - ) - if len(corresponding_project_task): + if project_template_map and project_template_map.get(child_task.task): project_task.reload() # reload, as it might have been updated in the previous iteration - project_task.append("depends_on", {"task": corresponding_project_task[0].name}) + project_task.append("depends_on", {"task": project_template_map.get(child_task.task).name}) project_task.save() def check_for_parent_tasks(self, template_task, project_task, project_tasks): if template_task.get("parent_task") and not project_task.get("parent_task"): - parent_task_subject = frappe.db.get_value("Task", template_task.get("parent_task"), "subject") - corresponding_project_task = list( - filter(lambda x: x.subject == parent_task_subject, project_tasks) - ) - if len(corresponding_project_task): - project_task.parent_task = corresponding_project_task[0].name - project_task.save() + for pt in project_tasks: + if pt.template_task == template_task.parent_task: + project_task.parent_task = pt.name + project_task.save() + break def is_row_updated(self, row, existing_task_data, fields): if self.get("__islocal") or not existing_task_data: From 70e2093941dba32ae06d4af123e9daa2441c8e71 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Tue, 26 Sep 2023 16:34:19 +0530 Subject: [PATCH 19/22] fix: validate duplicate serial no on submit in DN (#37243) --- erpnext/stock/doctype/delivery_note/delivery_note.py | 4 +++- erpnext/stock/doctype/delivery_note/test_delivery_note.py | 8 ++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py index ba6e247d2e4..115827a60cb 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/delivery_note.py @@ -138,7 +138,9 @@ class DeliveryNote(SellingController): self.validate_uom_is_integer("stock_uom", "stock_qty") self.validate_uom_is_integer("uom", "qty") self.validate_with_previous_doc() - self.validate_duplicate_serial_nos() + + if self.get("_action") == "submit": + self.validate_duplicate_serial_nos() from erpnext.stock.doctype.packed_item.packed_item import make_packing_list diff --git a/erpnext/stock/doctype/delivery_note/test_delivery_note.py b/erpnext/stock/doctype/delivery_note/test_delivery_note.py index 2acfd84d944..093e16c1cf8 100644 --- a/erpnext/stock/doctype/delivery_note/test_delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/test_delivery_note.py @@ -1234,14 +1234,10 @@ class TestDeliveryNote(FrappeTestCase): ) dn.items[0].serial_no = "\n".join(serial_nos[:2]) dn.append("items", dn.items[0].as_dict()) + dn.save() # Test - 1: ValidationError should be raised - self.assertRaises(frappe.ValidationError, dn.save) - - # Step - 4: Submit Delivery Note with unique Serial Nos - dn.items[1].serial_no = "\n".join(serial_nos[2:]) - dn.save() - dn.submit() + self.assertRaises(frappe.ValidationError, dn.submit) def tearDown(self): frappe.db.rollback() From 78ab2013e59bb6a95d10164328ad3f7c815497b5 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Tue, 26 Sep 2023 16:46:19 +0530 Subject: [PATCH 20/22] fix: serial number decimal issue (#37242) --- erpnext/controllers/subcontracting_controller.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/controllers/subcontracting_controller.py b/erpnext/controllers/subcontracting_controller.py index b01b76d1ec9..6faddd2a8be 100644 --- a/erpnext/controllers/subcontracting_controller.py +++ b/erpnext/controllers/subcontracting_controller.py @@ -655,7 +655,7 @@ class SubcontractingController(StockController): { "item_code": item.rm_item_code, "warehouse": self.supplier_warehouse, - "actual_qty": -1 * flt(item.consumed_qty), + "actual_qty": -1 * flt(item.consumed_qty, item.precision("consumed_qty")), "dependant_sle_voucher_detail_no": item.reference_name, }, ) From 0a0d5b3e6612be1b6e1c9febd4a86a772a02511d Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Tue, 26 Sep 2023 17:55:33 +0530 Subject: [PATCH 21/22] fix: reserved qty for production plan (#37251) --- .../production_plan/test_production_plan.py | 53 +++++++++++++++++++ .../doctype/work_order/work_order.py | 15 +++--- 2 files changed, 61 insertions(+), 7 deletions(-) diff --git a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py index 78080645050..9ea746cbd8b 100644 --- a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py +++ b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py @@ -1039,6 +1039,59 @@ class TestProductionPlan(FrappeTestCase): self.assertEqual(after_qty, before_qty) + def test_resered_qty_for_production_plan_for_work_order(self): + from erpnext.stock.utils import get_or_make_bin + + bin_name = get_or_make_bin("Raw Material Item 1", "_Test Warehouse - _TC") + before_qty = flt(frappe.db.get_value("Bin", bin_name, "reserved_qty_for_production_plan")) + + pln = create_production_plan(item_code="Test Production Item 1") + + bin_name = get_or_make_bin("Raw Material Item 1", "_Test Warehouse - _TC") + after_qty = flt(frappe.db.get_value("Bin", bin_name, "reserved_qty_for_production_plan")) + + self.assertEqual(after_qty - before_qty, 1) + + pln.make_work_order() + + work_orders = [] + for row in frappe.get_all("Work Order", filters={"production_plan": pln.name}, fields=["name"]): + wo_doc = frappe.get_doc("Work Order", row.name) + wo_doc.source_warehouse = "_Test Warehouse - _TC" + wo_doc.wip_warehouse = "_Test Warehouse 1 - _TC" + wo_doc.fg_warehouse = "_Test Warehouse - _TC" + for d in wo_doc.required_items: + d.source_warehouse = "_Test Warehouse - _TC" + make_stock_entry( + item_code=d.item_code, + qty=d.required_qty, + rate=100, + target="_Test Warehouse - _TC", + ) + + wo_doc.submit() + work_orders.append(wo_doc) + + bin_name = get_or_make_bin("Raw Material Item 1", "_Test Warehouse - _TC") + after_qty = flt(frappe.db.get_value("Bin", bin_name, "reserved_qty_for_production_plan")) + + self.assertEqual(after_qty, before_qty) + + rm_work_order = None + for wo_doc in work_orders: + for d in wo_doc.required_items: + if d.item_code == "Raw Material Item 1": + rm_work_order = wo_doc + break + + if rm_work_order: + s = frappe.get_doc(make_se_from_wo(rm_work_order.name, "Material Transfer for Manufacture", 1)) + s.submit() + bin_name = get_or_make_bin("Raw Material Item 1", "_Test Warehouse - _TC") + after_qty = flt(frappe.db.get_value("Bin", bin_name, "reserved_qty_for_production_plan")) + + self.assertEqual(after_qty, before_qty) + def test_resered_qty_for_production_plan_for_material_requests_with_multi_UOM(self): from erpnext.stock.utils import get_or_make_bin diff --git a/erpnext/manufacturing/doctype/work_order/work_order.py b/erpnext/manufacturing/doctype/work_order/work_order.py index c4b6846376f..070aaf00459 100644 --- a/erpnext/manufacturing/doctype/work_order/work_order.py +++ b/erpnext/manufacturing/doctype/work_order/work_order.py @@ -1497,16 +1497,17 @@ def get_reserved_qty_for_production( wo = frappe.qb.DocType("Work Order") wo_item = frappe.qb.DocType("Work Order Item") + if check_production_plan: + qty_field = wo_item.required_qty + else: + qty_field = Case() + qty_field = qty_field.when(wo.skip_transfer == 0, wo_item.required_qty - wo_item.transferred_qty) + qty_field = qty_field.else_(wo_item.required_qty - wo_item.consumed_qty) + query = ( frappe.qb.from_(wo) .from_(wo_item) - .select( - Sum( - Case() - .when(wo.skip_transfer == 0, wo_item.required_qty - wo_item.transferred_qty) - .else_(wo_item.required_qty - wo_item.consumed_qty) - ) - ) + .select(Sum(qty_field)) .where( (wo_item.item_code == item_code) & (wo_item.parent == wo.name) From 1dc58b36603ffbd11a5467f62b36d9148a831534 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Wed, 27 Sep 2023 10:22:27 +0530 Subject: [PATCH 22/22] fix: AP & AR summary filters to match AR (backport #37248) (#37261) * fix: set AR filters after rename (cherry picked from commit 832d7e7d7bdf8569c4ae0d35d929f7a0a440954f) * fix: change filters for AR summary (cherry picked from commit 7d96044d8eb74ad1cb78548183350b7512cc091b) * fix: set new AP summary filters (cherry picked from commit 76a5d94f37054a8c24f84fecf7d55fd9b0d01e81) --------- Co-authored-by: Gursheen Anand --- .../process_statement_of_accounts.py | 3 ++- .../accounts_payable/accounts_payable.js | 3 --- .../accounts_payable_summary.js | 23 +++++++++++++++--- .../accounts_receivable.js | 2 -- .../accounts_receivable_summary.js | 24 ++++++++++++++++--- 5 files changed, 43 insertions(+), 12 deletions(-) diff --git a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py index c622d308995..5055c345917 100644 --- a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py +++ b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py @@ -143,7 +143,8 @@ def get_gl_filters(doc, entry, tax_id, presentation_currency): def get_ar_filters(doc, entry): return { "report_date": doc.posting_date if doc.posting_date else None, - "customer": entry.customer, + "party_type": "Customer", + "party": entry.customer, "customer_name": entry.customer_name if entry.customer_name else None, "payment_terms_template": doc.payment_terms_template if doc.payment_terms_template else None, "sales_partner": doc.sales_partner if doc.sales_partner else None, diff --git a/erpnext/accounts/report/accounts_payable/accounts_payable.js b/erpnext/accounts/report/accounts_payable/accounts_payable.js index 27a85701edd..484ff7fa2b3 100644 --- a/erpnext/accounts/report/accounts_payable/accounts_payable.js +++ b/erpnext/accounts/report/accounts_payable/accounts_payable.js @@ -108,11 +108,8 @@ frappe.query_reports["Accounts Payable"] = { }, on_change: () => { frappe.query_report.set_filter_value('party', ""); - let party_type = frappe.query_report.get_filter_value('party_type'); frappe.query_report.toggle_filter_display('supplier_group', frappe.query_report.get_filter_value('party_type') !== "Supplier"); - } - }, { "fieldname":"party", diff --git a/erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js b/erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js index ea200720dff..8a1725c0485 100644 --- a/erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js +++ b/erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js @@ -72,10 +72,27 @@ frappe.query_reports["Accounts Payable Summary"] = { } }, { - "fieldname":"supplier", - "label": __("Supplier"), + "fieldname": "party_type", + "label": __("Party Type"), "fieldtype": "Link", - "options": "Supplier" + "options": "Party Type", + get_query: () => { + return { + filters: { + 'account_type': 'Payable' + } + }; + }, + on_change: () => { + frappe.query_report.set_filter_value('party', ""); + frappe.query_report.toggle_filter_display('supplier_group', frappe.query_report.get_filter_value('party_type') !== "Supplier"); + } + }, + { + "fieldname":"party", + "label": __("Party"), + "fieldtype": "Dynamic Link", + "options": "party_type", }, { "fieldname":"payment_terms_template", diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.js b/erpnext/accounts/report/accounts_receivable/accounts_receivable.js index bb00d616dbc..67a14e7880a 100644 --- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.js +++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.js @@ -52,9 +52,7 @@ frappe.query_reports["Accounts Receivable"] = { }, on_change: () => { frappe.query_report.set_filter_value('party', ""); - let party_type = frappe.query_report.get_filter_value('party_type'); frappe.query_report.toggle_filter_display('customer_group', frappe.query_report.get_filter_value('party_type') !== "Customer"); - } }, { diff --git a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js index 715cd6476e8..a78fbeb0308 100644 --- a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js +++ b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js @@ -72,10 +72,28 @@ frappe.query_reports["Accounts Receivable Summary"] = { } }, { - "fieldname":"customer", - "label": __("Customer"), + "fieldname": "party_type", + "label": __("Party Type"), "fieldtype": "Link", - "options": "Customer" + "options": "Party Type", + "Default": "Customer", + get_query: () => { + return { + filters: { + 'account_type': 'Receivable' + } + }; + }, + on_change: () => { + frappe.query_report.set_filter_value('party', ""); + frappe.query_report.toggle_filter_display('customer_group', frappe.query_report.get_filter_value('party_type') !== "Customer"); + } + }, + { + "fieldname":"party", + "label": __("Party"), + "fieldtype": "Dynamic Link", + "options": "party_type", }, { "fieldname":"customer_group",