From 653cb9fc3b9c23e19d66cda12441e432a9fa2f10 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 5 Dec 2022 16:22:59 +0530 Subject: [PATCH 01/12] fix: data import mandatory account_head, charge_type (cherry picked from commit 3814db02eb0d598e324ac73fcea9fca772d0fcd7) --- erpnext/accounts/doctype/sales_invoice/sales_invoice.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json index d45d9ee1844..439a891441f 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json @@ -920,6 +920,7 @@ "fieldtype": "Table", "hide_days": 1, "hide_seconds": 1, + "label": "Sales Taxes and Charges", "oldfieldname": "other_charges", "oldfieldtype": "Table", "options": "Sales Taxes and Charges" @@ -2116,7 +2117,7 @@ "link_fieldname": "consolidated_invoice" } ], - "modified": "2022-11-17 17:17:10.883487", + "modified": "2022-12-05 16:18:14.532114", "modified_by": "Administrator", "module": "Accounts", "name": "Sales Invoice", From e5e6b5d81c949e0e8ea2e44fdfeb7d236b68e1a3 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Mon, 5 Dec 2022 18:15:13 +0530 Subject: [PATCH 02/12] fix: non empty FG batch picked while completing work order (cherry picked from commit 713330cbf69bf285b6231c0ea603d6156edfde35) --- .../doctype/work_order/test_work_order.py | 24 ++++++++++++++++++- .../stock/doctype/stock_entry/stock_entry.py | 13 +++++----- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/erpnext/manufacturing/doctype/work_order/test_work_order.py b/erpnext/manufacturing/doctype/work_order/test_work_order.py index 694dc79d4a9..36466ff6d7d 100644 --- a/erpnext/manufacturing/doctype/work_order/test_work_order.py +++ b/erpnext/manufacturing/doctype/work_order/test_work_order.py @@ -635,6 +635,10 @@ class TestWorkOrder(FrappeTestCase): bom.submit() bom_name = bom.name + ste1 = test_stock_entry.make_stock_entry( + item_code=rm1, target="_Test Warehouse - _TC", qty=32, basic_rate=5000.0 + ) + work_order = make_wo_order_test_record( item=fg_item, skip_transfer=True, planned_start_date=now(), qty=1 ) @@ -659,11 +663,29 @@ class TestWorkOrder(FrappeTestCase): work_order.insert() work_order.submit() self.assertEqual(work_order.has_batch_no, 1) - ste1 = frappe.get_doc(make_stock_entry(work_order.name, "Manufacture", 30)) + batches = frappe.get_all("Batch", filters={"reference_name": work_order.name}) + self.assertEqual(len(batches), 3) + batches = [batch.name for batch in batches] + + ste1 = frappe.get_doc(make_stock_entry(work_order.name, "Manufacture", 10)) for row in ste1.get("items"): if row.is_finished_item: self.assertEqual(row.item_code, fg_item) self.assertEqual(row.qty, 10) + self.assertTrue(row.batch_no in batches) + batches.remove(row.batch_no) + + ste1.submit() + + remaining_batches = [] + ste1 = frappe.get_doc(make_stock_entry(work_order.name, "Manufacture", 20)) + for row in ste1.get("items"): + if row.is_finished_item: + self.assertEqual(row.item_code, fg_item) + self.assertEqual(row.qty, 10) + remaining_batches.append(row.batch_no) + + self.assertEqual(sorted(remaining_batches), sorted(batches)) frappe.db.set_value("Manufacturing Settings", None, "make_serial_no_batch_from_work_order", 0) diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index 83c280f72ee..f6c53f7bca0 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -1545,6 +1545,7 @@ class StockEntry(StockController): "reference_name": self.pro_doc.name, "reference_doctype": self.pro_doc.doctype, "qty_to_produce": (">", 0), + "batch_qty": ("=", 0), } fields = ["qty_to_produce as qty", "produced_qty", "name"] @@ -2238,14 +2239,14 @@ class StockEntry(StockController): d.qty -= process_loss_dict[d.item_code][1] def set_serial_no_batch_for_finished_good(self): - args = {} + serial_nos = "" if self.pro_doc.serial_no: - self.get_serial_nos_for_fg(args) + serial_nos = self.get_serial_nos_for_fg() for row in self.items: if row.is_finished_item and row.item_code == self.pro_doc.production_item: - if args.get("serial_no"): - row.serial_no = "\n".join(args["serial_no"][0 : cint(row.qty)]) + if serial_nos: + row.serial_no = "\n".join(serial_nos[0 : cint(row.qty)]) def get_serial_nos_for_fg(self, args): fields = [ @@ -2258,14 +2259,14 @@ class StockEntry(StockController): filters = [ ["Stock Entry", "work_order", "=", self.work_order], ["Stock Entry", "purpose", "=", "Manufacture"], - ["Stock Entry", "docstatus", "=", 1], + ["Stock Entry", "docstatus", "<", 2], ["Stock Entry Detail", "item_code", "=", self.pro_doc.production_item], ] stock_entries = frappe.get_all("Stock Entry", fields=fields, filters=filters) if self.pro_doc.serial_no: - args["serial_no"] = self.get_available_serial_nos(stock_entries) + return self.get_available_serial_nos(stock_entries) def get_available_serial_nos(self, stock_entries): used_serial_nos = [] From 030765618bb6ec2b3a03f87cca54d533df65305a Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Mon, 5 Dec 2022 10:17:19 +0530 Subject: [PATCH 03/12] fix: Allow item rate udpates for non-stock invoices (cherry picked from commit ef9d126254d4df91274b983b5a7e718d38d729f1) --- .../purchase_invoice/purchase_invoice.py | 4 +- erpnext/controllers/buying_controller.py | 23 +++++----- erpnext/controllers/selling_controller.py | 45 ++++++++++--------- .../purchase_receipt/purchase_receipt.py | 4 +- 4 files changed, 41 insertions(+), 35 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index 161832216f8..df4c2770e3c 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -231,7 +231,9 @@ class PurchaseInvoice(BuyingController): ) if ( - cint(frappe.db.get_single_value("Buying Settings", "maintain_same_rate")) and not self.is_return + cint(frappe.db.get_single_value("Buying Settings", "maintain_same_rate")) + and not self.is_return + and not self.is_internal_supplier ): self.validate_rate_with_reference_doc( [ diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py index 051460474ac..2efa5457368 100644 --- a/erpnext/controllers/buying_controller.py +++ b/erpnext/controllers/buying_controller.py @@ -322,17 +322,18 @@ class BuyingController(SubcontractingController): ) if self.is_internal_transfer(): - if rate != d.rate: - d.rate = rate - frappe.msgprint( - _( - "Row {0}: Item rate has been updated as per valuation rate since its an internal stock transfer" - ).format(d.idx), - alert=1, - ) - d.discount_percentage = 0.0 - d.discount_amount = 0.0 - d.margin_rate_or_amount = 0.0 + if self.doctype == "Purchase Receipt" or self.get("update_stock"): + if rate != d.rate: + d.rate = rate + frappe.msgprint( + _( + "Row {0}: Item rate has been updated as per valuation rate since its an internal stock transfer" + ).format(d.idx), + alert=1, + ) + d.discount_percentage = 0.0 + d.discount_amount = 0.0 + d.margin_rate_or_amount = 0.0 def validate_for_subcontracting(self): if self.is_subcontracted and self.get("is_old_subcontracting_flow"): diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py index 965335b1a3f..0ebc8d4b4de 100644 --- a/erpnext/controllers/selling_controller.py +++ b/erpnext/controllers/selling_controller.py @@ -442,30 +442,31 @@ class SellingController(StockController): # For internal transfers use incoming rate as the valuation rate if self.is_internal_transfer(): - if d.doctype == "Packed Item": - incoming_rate = flt( - flt(d.incoming_rate, d.precision("incoming_rate")) * d.conversion_factor, - d.precision("incoming_rate"), - ) - if d.incoming_rate != incoming_rate: - d.incoming_rate = incoming_rate - else: - rate = flt( - flt(d.incoming_rate, d.precision("incoming_rate")) * d.conversion_factor, - d.precision("rate"), - ) - if d.rate != rate: - d.rate = rate - frappe.msgprint( - _( - "Row {0}: Item rate has been updated as per valuation rate since its an internal stock transfer" - ).format(d.idx), - alert=1, + if self.doctype == "Delivery Note" or self.get("update_stock"): + if d.doctype == "Packed Item": + incoming_rate = flt( + flt(d.incoming_rate, d.precision("incoming_rate")) * d.conversion_factor, + d.precision("incoming_rate"), ) + if d.incoming_rate != incoming_rate: + d.incoming_rate = incoming_rate + else: + rate = flt( + flt(d.incoming_rate, d.precision("incoming_rate")) * d.conversion_factor, + d.precision("rate"), + ) + if d.rate != rate: + d.rate = rate + frappe.msgprint( + _( + "Row {0}: Item rate has been updated as per valuation rate since its an internal stock transfer" + ).format(d.idx), + alert=1, + ) - d.discount_percentage = 0.0 - d.discount_amount = 0.0 - d.margin_rate_or_amount = 0.0 + d.discount_percentage = 0.0 + d.discount_amount = 0.0 + d.margin_rate_or_amount = 0.0 elif self.get("return_against"): # Get incoming rate of return entry from reference document diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index 673fcb526df..3739cb8c9dd 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -173,7 +173,9 @@ class PurchaseReceipt(BuyingController): ) if ( - cint(frappe.db.get_single_value("Buying Settings", "maintain_same_rate")) and not self.is_return + cint(frappe.db.get_single_value("Buying Settings", "maintain_same_rate")) + and not self.is_return + and not self.is_internal_supplier ): self.validate_rate_with_reference_doc( [["Purchase Order", "purchase_order", "purchase_order_item"]] From 08bca7d252e085b543dc3f49343582794ac6a02a Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Thu, 1 Dec 2022 13:38:41 +0530 Subject: [PATCH 04/12] fix: key error while filtering on date range and different currency (cherry picked from commit 9b8d6fe4119ae6cb7b913ef800e99d9c5d739518) --- erpnext/accounts/report/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/report/utils.py b/erpnext/accounts/report/utils.py index eed58367739..81fea285151 100644 --- a/erpnext/accounts/report/utils.py +++ b/erpnext/accounts/report/utils.py @@ -28,7 +28,7 @@ def get_currency(filters): filters["presentation_currency"] if filters.get("presentation_currency") else company_currency ) - report_date = filters.get("to_date") + report_date = filters.get("period_end_date") if not report_date: fiscal_year_to_date = get_from_and_to_date(filters.get("to_fiscal_year"))["to_date"] From e18d0eca3c8f917867e52ddb0837509b65ccb2b6 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 6 Dec 2022 13:42:33 +0530 Subject: [PATCH 05/12] fix: replace sql code with fields list in get_cached_value (cherry picked from commit 19db7e2989f36d3dd2f6fce1ea03e21199665b21) --- erpnext/accounts/doctype/fiscal_year/fiscal_year.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/fiscal_year/fiscal_year.py b/erpnext/accounts/doctype/fiscal_year/fiscal_year.py index 069ab5ea843..c3e83ad168f 100644 --- a/erpnext/accounts/doctype/fiscal_year/fiscal_year.py +++ b/erpnext/accounts/doctype/fiscal_year/fiscal_year.py @@ -169,5 +169,6 @@ def auto_create_fiscal_year(): def get_from_and_to_date(fiscal_year): - fields = ["year_start_date as from_date", "year_end_date as to_date"] - return frappe.db.get_value("Fiscal Year", fiscal_year, fields, as_dict=1) + fields = ["year_start_date", "year_end_date"] + cached_results = frappe.get_cached_value("Fiscal Year", fiscal_year, fields, as_dict=1) + return dict(from_date=cached_results.year_start_date, to_date=cached_results.year_end_date) From 23a0a5337e6ab1d65e32a305c4ac08f98bfa436e Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 6 Dec 2022 13:44:54 +0530 Subject: [PATCH 06/12] fix: key error on p/l and balance sheet reports on foreign currency (cherry picked from commit a6794c36062acb7963a387271e2f4b4800643a68) --- erpnext/accounts/report/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/report/utils.py b/erpnext/accounts/report/utils.py index 81fea285151..d3cd29013f2 100644 --- a/erpnext/accounts/report/utils.py +++ b/erpnext/accounts/report/utils.py @@ -28,7 +28,7 @@ def get_currency(filters): filters["presentation_currency"] if filters.get("presentation_currency") else company_currency ) - report_date = filters.get("period_end_date") + report_date = filters.get("to_date") or filters.get("period_end_date") if not report_date: fiscal_year_to_date = get_from_and_to_date(filters.get("to_fiscal_year"))["to_date"] From 82cdf49d3268ebf58540cbccdadc2d2295a03c64 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Thu, 1 Dec 2022 15:51:38 +0530 Subject: [PATCH 07/12] fix: Bundle item rates (cherry picked from commit 826f45ad603c581a7ea0c29e1274474ce124f6eb) --- erpnext/stock/doctype/packed_item/packed_item.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/packed_item/packed_item.py b/erpnext/stock/doctype/packed_item/packed_item.py index 4d05d7a345c..02f8e903bb4 100644 --- a/erpnext/stock/doctype/packed_item/packed_item.py +++ b/erpnext/stock/doctype/packed_item/packed_item.py @@ -259,7 +259,7 @@ def update_product_bundle_rate(parent_items_price, pi_row): if not rate: parent_items_price[key] = 0.0 - parent_items_price[key] += flt(pi_row.rate) + parent_items_price[key] += flt(pi_row.rate * pi_row.qty) def set_product_bundle_rate_amount(doc, parent_items_price): From 076027a68c8fd3de02ca0328bbdbea788c175a4d Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Tue, 6 Dec 2022 13:59:45 +0530 Subject: [PATCH 08/12] chore: Consider bundle qty as well (cherry picked from commit e5566b31d5b7d4c057b43b5f0fa7d8d9119c942c) --- erpnext/stock/doctype/packed_item/packed_item.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/stock/doctype/packed_item/packed_item.py b/erpnext/stock/doctype/packed_item/packed_item.py index 02f8e903bb4..d6067516660 100644 --- a/erpnext/stock/doctype/packed_item/packed_item.py +++ b/erpnext/stock/doctype/packed_item/packed_item.py @@ -48,7 +48,7 @@ def make_packing_list(doc): update_packed_item_from_cancelled_doc(item_row, bundle_item, pi_row, doc) if set_price_from_children: # create/update bundle item wise price dict - update_product_bundle_rate(parent_items_price, pi_row) + update_product_bundle_rate(parent_items_price, pi_row, item_row) if parent_items_price: set_product_bundle_rate_amount(doc, parent_items_price) # set price in bundle item @@ -247,7 +247,7 @@ def get_cancelled_doc_packed_item_details(old_packed_items): return prev_doc_packed_items_map -def update_product_bundle_rate(parent_items_price, pi_row): +def update_product_bundle_rate(parent_items_price, pi_row, item_row): """ Update the price dict of Product Bundles based on the rates of the Items in the bundle. @@ -259,7 +259,7 @@ def update_product_bundle_rate(parent_items_price, pi_row): if not rate: parent_items_price[key] = 0.0 - parent_items_price[key] += flt(pi_row.rate * pi_row.qty) + parent_items_price[key] += flt((pi_row.rate * pi_row.qty) / item_row.stock_qty) def set_product_bundle_rate_amount(doc, parent_items_price): From 98bb446e98692234f116b26f4b2551856df43848 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Tue, 6 Dec 2022 15:14:48 +0530 Subject: [PATCH 09/12] chore: Update tests (cherry picked from commit b1242bc56c3485d37fd37627a3196a754abfb442) --- erpnext/stock/doctype/packed_item/test_packed_item.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/stock/doctype/packed_item/test_packed_item.py b/erpnext/stock/doctype/packed_item/test_packed_item.py index ad7fd9a6976..ad06732bc3e 100644 --- a/erpnext/stock/doctype/packed_item/test_packed_item.py +++ b/erpnext/stock/doctype/packed_item/test_packed_item.py @@ -126,8 +126,8 @@ class TestPackedItem(FrappeTestCase): so.packed_items[1].rate = 200 so.save() - self.assertEqual(so.items[0].rate, 350) - self.assertEqual(so.items[0].amount, 700) + self.assertEqual(so.items[0].rate, 700) + self.assertEqual(so.items[0].amount, 1400) def test_newly_mapped_doc_packed_items(self): "Test impact on packed items in newly mapped DN from SO." From 5b5a85ee3bd7fc00adb7b8b9b7c0974f5c2e82c1 Mon Sep 17 00:00:00 2001 From: barredterra <14891507+barredterra@users.noreply.github.com> Date: Mon, 28 Nov 2022 22:58:31 +0100 Subject: [PATCH 10/12] fix: reload currency exchange settings (cherry picked from commit 06e094b5fccfae350b7432edb6e89a38430da931) --- erpnext/patches/v13_0/update_exchange_rate_settings.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/erpnext/patches/v13_0/update_exchange_rate_settings.py b/erpnext/patches/v13_0/update_exchange_rate_settings.py index 746195f2e13..130a7bf7df4 100644 --- a/erpnext/patches/v13_0/update_exchange_rate_settings.py +++ b/erpnext/patches/v13_0/update_exchange_rate_settings.py @@ -1,5 +1,8 @@ +import frappe + from erpnext.setup.install import setup_currency_exchange def execute(): + frappe.reload_doc("accounts", "doctype", "currency_exchange_settings") setup_currency_exchange() From 7027fdae3912351759a8ba6807215e94094c3a79 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Tue, 6 Dec 2022 16:52:45 +0530 Subject: [PATCH 11/12] feat: warehouse wise stock balance (cherry picked from commit 861aa9e08a4c95bbe26afab14c7bdd61637f80cd) --- .../warehouse_wise_stock_balance/__init__.py | 0 .../warehouse_wise_stock_balance.js | 20 +++ .../warehouse_wise_stock_balance.json | 30 ++++ .../warehouse_wise_stock_balance.py | 89 ++++++++++ erpnext/stock/workspace/stock/stock.json | 163 ++++++++++-------- 5 files changed, 226 insertions(+), 76 deletions(-) create mode 100644 erpnext/stock/report/warehouse_wise_stock_balance/__init__.py create mode 100644 erpnext/stock/report/warehouse_wise_stock_balance/warehouse_wise_stock_balance.js create mode 100644 erpnext/stock/report/warehouse_wise_stock_balance/warehouse_wise_stock_balance.json create mode 100644 erpnext/stock/report/warehouse_wise_stock_balance/warehouse_wise_stock_balance.py diff --git a/erpnext/stock/report/warehouse_wise_stock_balance/__init__.py b/erpnext/stock/report/warehouse_wise_stock_balance/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/stock/report/warehouse_wise_stock_balance/warehouse_wise_stock_balance.js b/erpnext/stock/report/warehouse_wise_stock_balance/warehouse_wise_stock_balance.js new file mode 100644 index 00000000000..58a043ec20d --- /dev/null +++ b/erpnext/stock/report/warehouse_wise_stock_balance/warehouse_wise_stock_balance.js @@ -0,0 +1,20 @@ +// Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt +/* eslint-disable */ + +frappe.query_reports["Warehouse Wise Stock Balance"] = { + "filters": [ + { + "fieldname":"company", + "label": __("Company"), + "fieldtype": "Link", + "options": "Company", + "reqd": 1, + "default": frappe.defaults.get_user_default("Company") + } + ], + "initial_depth": 3, + "tree": true, + "parent_field": "parent_warehouse", + "name_field": "warehouse" +}; diff --git a/erpnext/stock/report/warehouse_wise_stock_balance/warehouse_wise_stock_balance.json b/erpnext/stock/report/warehouse_wise_stock_balance/warehouse_wise_stock_balance.json new file mode 100644 index 00000000000..4f7ec65de39 --- /dev/null +++ b/erpnext/stock/report/warehouse_wise_stock_balance/warehouse_wise_stock_balance.json @@ -0,0 +1,30 @@ +{ + "add_total_row": 0, + "columns": [], + "creation": "2022-12-06 14:15:31.924345", + "disable_prepared_report": 0, + "disabled": 0, + "docstatus": 0, + "doctype": "Report", + "filters": [], + "idx": 0, + "is_standard": "Yes", + "json": "{}", + "modified": "2022-12-06 14:16:55.969214", + "modified_by": "Administrator", + "module": "Stock", + "name": "Warehouse Wise Stock Balance", + "owner": "Administrator", + "prepared_report": 0, + "ref_doctype": "Stock Ledger Entry", + "report_name": "Warehouse Wise Stock Balance", + "report_type": "Script Report", + "roles": [ + { + "role": "Stock User" + }, + { + "role": "Accounts Manager" + } + ] +} \ No newline at end of file diff --git a/erpnext/stock/report/warehouse_wise_stock_balance/warehouse_wise_stock_balance.py b/erpnext/stock/report/warehouse_wise_stock_balance/warehouse_wise_stock_balance.py new file mode 100644 index 00000000000..81700099fa4 --- /dev/null +++ b/erpnext/stock/report/warehouse_wise_stock_balance/warehouse_wise_stock_balance.py @@ -0,0 +1,89 @@ +# Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +from typing import Any, Dict, List, Optional, TypedDict + +import frappe +from frappe import _ +from frappe.query_builder.functions import Sum + + +class StockBalanceFilter(TypedDict): + company: Optional[str] + warehouse: Optional[str] + + +SLEntry = Dict[str, Any] + + +def execute(filters=None): + columns, data = [], [] + columns = get_columns() + data = get_data(filters) + + return columns, data + + +def get_warehouse_wise_balance(filters: StockBalanceFilter) -> List[SLEntry]: + sle = frappe.qb.DocType("Stock Ledger Entry") + + query = ( + frappe.qb.from_(sle) + .select(sle.warehouse, Sum(sle.stock_value_difference).as_("stock_balance")) + .where((sle.docstatus < 2) & (sle.is_cancelled == 0)) + .groupby(sle.warehouse) + ) + + if filters.get("company"): + query = query.where(sle.company == filters.get("company")) + + data = query.run(as_list=True) + return frappe._dict(data) if data else frappe._dict() + + +def get_warehouses(report_filters: StockBalanceFilter): + return frappe.get_all( + "Warehouse", + fields=["name", "parent_warehouse", "is_group"], + filters={"company": report_filters.company, "disabled": 0}, + order_by="lft", + ) + + +def get_data(filters: StockBalanceFilter): + warehouse_balance = get_warehouse_wise_balance(filters) + warehouses = get_warehouses(filters) + + for warehouse in warehouses: + warehouse["stock_balance"] = warehouse_balance.get(warehouse.name, 0) + + update_indent(warehouses) + + return warehouses + + +def update_indent(warehouses): + for warehouse in warehouses: + + def add_indent(warehouse, indent): + warehouse.indent = indent + for child in warehouses: + if child.parent_warehouse == warehouse.name: + warehouse.stock_balance += child.stock_balance + add_indent(child, indent + 1) + + if warehouse.is_group: + add_indent(warehouse, warehouse.indent or 0) + + +def get_columns(): + return [ + { + "label": _("Warehouse"), + "fieldname": "name", + "fieldtype": "Link", + "options": "Warehouse", + "width": 200, + }, + {"label": _("Stock Balance"), "fieldname": "stock_balance", "fieldtype": "Float", "width": 150}, + ] diff --git a/erpnext/stock/workspace/stock/stock.json b/erpnext/stock/workspace/stock/stock.json index ed33067e733..de5e6de8f13 100644 --- a/erpnext/stock/workspace/stock/stock.json +++ b/erpnext/stock/workspace/stock/stock.json @@ -5,7 +5,7 @@ "label": "Warehouse wise Stock Value" } ], - "content": "[{\"type\":\"onboarding\",\"data\":{\"onboarding_name\":\"Stock\",\"col\":12}},{\"type\":\"chart\",\"data\":{\"chart_name\":\"Warehouse wise Stock Value\",\"col\":12}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"Quick Access\",\"col\":12}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Item\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Material Request\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Stock Entry\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Purchase Receipt\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Delivery Note\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Stock Ledger\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Stock Balance\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Dashboard\",\"col\":3}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"Masters & Reports\",\"col\":12}},{\"type\":\"card\",\"data\":{\"card_name\":\"Items and Pricing\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Stock Transactions\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Stock Reports\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Settings\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Serial No and Batch\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Tools\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Key Reports\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Other Reports\",\"col\":4}}]", + "content": "[{\"type\":\"onboarding\",\"data\":{\"onboarding_name\":\"Stock\",\"col\":12}},{\"type\":\"chart\",\"data\":{\"chart_name\":\"Warehouse wise Stock Value\",\"col\":12}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"Quick Access\",\"col\":12}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Item\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Material Request\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Stock Entry\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Purchase Receipt\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Delivery Note\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Stock Ledger\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Stock Balance\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Dashboard\",\"col\":3}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"Masters & Reports\",\"col\":12}},{\"type\":\"card\",\"data\":{\"card_name\":\"Items and Pricing\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Stock Transactions\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Stock Reports\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Settings\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Serial No and Batch\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Tools\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Key Reports\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Other Reports\",\"col\":4}}]", "creation": "2020-03-02 15:43:10.096528", "docstatus": 0, "doctype": "Workspace", @@ -207,80 +207,6 @@ "onboard": 0, "type": "Link" }, - { - "hidden": 0, - "is_query_report": 0, - "label": "Stock Reports", - "link_count": 0, - "onboard": 0, - "type": "Card Break" - }, - { - "dependencies": "Item", - "hidden": 0, - "is_query_report": 1, - "label": "Stock Ledger", - "link_count": 0, - "link_to": "Stock Ledger", - "link_type": "Report", - "onboard": 1, - "type": "Link" - }, - { - "dependencies": "Item", - "hidden": 0, - "is_query_report": 1, - "label": "Stock Balance", - "link_count": 0, - "link_to": "Stock Balance", - "link_type": "Report", - "onboard": 1, - "type": "Link" - }, - { - "dependencies": "Item", - "hidden": 0, - "is_query_report": 1, - "label": "Stock Projected Qty", - "link_count": 0, - "link_to": "Stock Projected Qty", - "link_type": "Report", - "onboard": 1, - "type": "Link" - }, - { - "dependencies": "Item", - "hidden": 0, - "is_query_report": 0, - "label": "Stock Summary", - "link_count": 0, - "link_to": "stock-balance", - "link_type": "Page", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "Item", - "hidden": 0, - "is_query_report": 1, - "label": "Stock Ageing", - "link_count": 0, - "link_to": "Stock Ageing", - "link_type": "Report", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "Item", - "hidden": 0, - "is_query_report": 1, - "label": "Item Price Stock", - "link_count": 0, - "link_to": "Item Price Stock", - "link_type": "Report", - "onboard": 0, - "type": "Link" - }, { "hidden": 0, "is_query_report": 0, @@ -705,15 +631,100 @@ "link_type": "Report", "onboard": 0, "type": "Link" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Stock Reports", + "link_count": 7, + "onboard": 0, + "type": "Card Break" + }, + { + "dependencies": "Item", + "hidden": 0, + "is_query_report": 1, + "label": "Stock Ledger", + "link_count": 0, + "link_to": "Stock Ledger", + "link_type": "Report", + "onboard": 1, + "type": "Link" + }, + { + "dependencies": "Item", + "hidden": 0, + "is_query_report": 1, + "label": "Stock Balance", + "link_count": 0, + "link_to": "Stock Balance", + "link_type": "Report", + "onboard": 1, + "type": "Link" + }, + { + "dependencies": "Item", + "hidden": 0, + "is_query_report": 1, + "label": "Stock Projected Qty", + "link_count": 0, + "link_to": "Stock Projected Qty", + "link_type": "Report", + "onboard": 1, + "type": "Link" + }, + { + "dependencies": "Item", + "hidden": 0, + "is_query_report": 0, + "label": "Stock Summary", + "link_count": 0, + "link_to": "stock-balance", + "link_type": "Page", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "Item", + "hidden": 0, + "is_query_report": 1, + "label": "Stock Ageing", + "link_count": 0, + "link_to": "Stock Ageing", + "link_type": "Report", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "Item", + "hidden": 0, + "is_query_report": 1, + "label": "Item Price Stock", + "link_count": 0, + "link_to": "Item Price Stock", + "link_type": "Report", + "onboard": 0, + "type": "Link" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Warehouse Wise Stock Balance", + "link_count": 0, + "link_to": "Warehouse Wise Stock Balance", + "link_type": "Report", + "onboard": 0, + "type": "Link" } ], - "modified": "2022-01-13 17:47:38.339931", + "modified": "2022-12-06 17:03:56.397272", "modified_by": "Administrator", "module": "Stock", "name": "Stock", "owner": "Administrator", "parent_page": "", "public": 1, + "quick_lists": [], "restrict_to_domain": "", "roles": [], "sequence_id": 24.0, From a657db66b4057ce37d8a5fbb56f6ba9757e4425c Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Mon, 5 Dec 2022 22:47:05 +0530 Subject: [PATCH 12/12] fix: order status in `Production Planning Report` (cherry picked from commit 632c08f7e0b0c6a932457afdfa484f7668e9a9e5) --- .../production_planning_report.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/erpnext/manufacturing/report/production_planning_report/production_planning_report.py b/erpnext/manufacturing/report/production_planning_report/production_planning_report.py index 16c25ce7e6d..109d9ab656b 100644 --- a/erpnext/manufacturing/report/production_planning_report/production_planning_report.py +++ b/erpnext/manufacturing/report/production_planning_report/production_planning_report.py @@ -49,7 +49,7 @@ class ProductionPlanReport(object): parent.bom_no, parent.fg_warehouse.as_("warehouse"), ) - .where(parent.status.notin(["Completed", "Stopped"])) + .where(parent.status.notin(["Completed", "Stopped", "Closed"])) ) if order_by == "Planned Start Date": @@ -79,10 +79,11 @@ class ProductionPlanReport(object): query = query.where(child.parent.isin(self.filters.docnames)) if doctype == "Sales Order": - query = query.select( - child.delivery_date, - parent.base_grand_total, - ).where((child.stock_qty > child.produced_qty) & (parent.per_delivered < 100.0)) + query = query.select(child.delivery_date, parent.base_grand_total,).where( + (child.stock_qty > child.produced_qty) + & (parent.per_delivered < 100.0) + & (parent.status.notin(["Completed", "Closed"])) + ) if order_by == "Delivery Date": query = query.orderby(child.delivery_date, order=Order.asc) @@ -91,7 +92,9 @@ class ProductionPlanReport(object): elif doctype == "Material Request": query = query.select(child.schedule_date,).where( - (parent.per_ordered < 100) & (parent.material_request_type == "Manufacture") + (parent.per_ordered < 100) + & (parent.material_request_type == "Manufacture") + & (parent.status != "Stopped") ) if order_by == "Required Date":