From 5f376009d04d641b0076e392144902a5bd78581c Mon Sep 17 00:00:00 2001 From: Frappe PR Bot Date: Thu, 9 May 2024 05:31:55 +0000 Subject: [PATCH 01/36] chore(release): Bumped to Version 15.23.0 # [15.23.0](https://github.com/frappe/erpnext/compare/v15.22.2...v15.23.0) (2024-05-09) ### Bug Fixes * Add PO reference ([c417b0c](https://github.com/frappe/erpnext/commit/c417b0c15a269b147c3efef560c838a37f8a2601)) * correct ordered qty on SO when removing PO item - v15 ([#41342](https://github.com/frappe/erpnext/issues/41342)) ([5c1043f](https://github.com/frappe/erpnext/commit/5c1043fe88d31a6c0621d00ad6ac914605ec88c4)) * Cost center not getting saved in PSOA ([fbbc0af](https://github.com/frappe/erpnext/commit/fbbc0af7bcb6f12d5c3249ff670ebe09fb81626e)) * Do not deduct TCS for opening invoices ([1999b7a](https://github.com/frappe/erpnext/commit/1999b7a6c5cdff5432644d8f63069e7b62887fb7)) * filter validation for batch-wise balance history report (backport [#41356](https://github.com/frappe/erpnext/issues/41356)) ([#41361](https://github.com/frappe/erpnext/issues/41361)) ([913cea0](https://github.com/frappe/erpnext/commit/913cea001815a66dd994673056e9968691d969a5)) * future subscripition updates ([b27a55e](https://github.com/frappe/erpnext/commit/b27a55e802899c4fc6d3508c19614f0e3d3d5366)) * GL Entries against orders as an advance ([e49a401](https://github.com/frappe/erpnext/commit/e49a401c23e64c46d34cdc935339ca504ed07f06)) * incorrect qty picked in the pick list (backport [#41378](https://github.com/frappe/erpnext/issues/41378)) ([#41381](https://github.com/frappe/erpnext/issues/41381)) ([a293ec0](https://github.com/frappe/erpnext/commit/a293ec0db31b5c05c58ce29910df132f74327ecb)) * incorrect query for Purchase Invoice rate in GP ([20daae4](https://github.com/frappe/erpnext/commit/20daae4de975be6db46679eb675c0e956fae77fb)) * **Item:** allow UOM conversion for non-stock items (backport [#41267](https://github.com/frappe/erpnext/issues/41267)) ([#41346](https://github.com/frappe/erpnext/issues/41346)) ([cd3ca1e](https://github.com/frappe/erpnext/commit/cd3ca1ee253c2124a2f4fe234248348f4dadbb17)) * Merge debit and credit in transaction currency while merging gle with similar head ([9a58823](https://github.com/frappe/erpnext/commit/9a58823867dff30491c2bf4b1fa4d921955b4b1c)) * missing Item Name on Save for Quotation created from Item (backport [#41233](https://github.com/frappe/erpnext/issues/41233)) ([#41304](https://github.com/frappe/erpnext/issues/41304)) ([6491577](https://github.com/frappe/erpnext/commit/649157750101028127b801e6138839d357c49bec)) * Patch to fix the incorrect debit and credit in transaction currency ([f7e165b](https://github.com/frappe/erpnext/commit/f7e165b5ffd029973bd4cb54d1f852d22dda96df)) * Patch to remove cancelled asset capitalization from asset ([a755540](https://github.com/frappe/erpnext/commit/a755540708ef024d28c8c5967554d5d19292653b)) * pick list with multiple batch issue (backport [#41335](https://github.com/frappe/erpnext/issues/41335)) ([#41338](https://github.com/frappe/erpnext/issues/41338)) ([1b1dfa8](https://github.com/frappe/erpnext/commit/1b1dfa8893c23691fbfea1754af78cb39266e9a8)) * pricing rule rounding ([b93828c](https://github.com/frappe/erpnext/commit/b93828cd337be9c6b71903f1a9cfc54fec956b9f)) * Purchase Invoice gain loss gl entry for periodic inventory ([0513481](https://github.com/frappe/erpnext/commit/0513481ec8bcc86ba0f11818f0e1591b12b38553)) * resolved conflict ([5039f45](https://github.com/frappe/erpnext/commit/5039f45be461f0467f6c50a0b770fc35d24896ae)) * resolved conflict ([81afdcf](https://github.com/frappe/erpnext/commit/81afdcf745a69c335710a0630173810bd517fc19)) * search for item price in stock UOM (backport [#41075](https://github.com/frappe/erpnext/issues/41075)) ([#41313](https://github.com/frappe/erpnext/issues/41313)) ([112f96b](https://github.com/frappe/erpnext/commit/112f96bae0d7734e2db56aa510bf6bf3bd8248fd)) * update project URLs (backport [#41331](https://github.com/frappe/erpnext/issues/41331)) ([#41332](https://github.com/frappe/erpnext/issues/41332)) ([bb619a6](https://github.com/frappe/erpnext/commit/bb619a64fe0e5583f3394f67a742ca1ea703ad4d)) ### Features * **Item Price:** make UOM mandatory (backport [#40588](https://github.com/frappe/erpnext/issues/40588)) ([#41312](https://github.com/frappe/erpnext/issues/41312)) ([cab0e30](https://github.com/frappe/erpnext/commit/cab0e30cebc5c7a2c9f6a264a7bd554d5b89e58f)) ### Performance Improvements * index on item code for the Pick List Item doctype (backport [#41357](https://github.com/frappe/erpnext/issues/41357)) ([#41364](https://github.com/frappe/erpnext/issues/41364)) ([bba738f](https://github.com/frappe/erpnext/commit/bba738f5f4f63432068ce7f19ce553b2e7563208)) --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 1ad327da5ee..77eeaf1b7ca 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -3,7 +3,7 @@ import inspect import frappe -__version__ = "15.22.2" +__version__ = "15.23.0" def get_default_company(user=None): From aa2b64476e1267b6e0859c8185ef7e356d720e05 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Mon, 13 May 2024 16:53:35 +0530 Subject: [PATCH 02/36] fix: valuation issue for batch (backport #41425) (backport #41430) (#41434) fix: valuation issue for batch (backport #41425) (#41430) fix: valuation issue for batch (#41425) (cherry picked from commit 065163146c6137e235c1da1409537d12563a140f) Co-authored-by: rohitwaghchaure (cherry picked from commit f55a131dea68986c3f3a29336fc5748184d6e054) Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- .../serial_and_batch_bundle.py | 14 +++++++++++++- .../test_serial_and_batch_bundle.py | 2 ++ erpnext/stock/serial_batch_bundle.py | 4 ++-- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py index 91951834bf9..67f946eb7c8 100644 --- a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py +++ b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py @@ -1149,7 +1149,18 @@ def make_batch_nos(item_code, batch_nos): continue batch_nos_details.append( - (batch_no, batch_no, now(), now(), user, user, item.item_code, item.item_name, item.description) + ( + batch_no, + batch_no, + now(), + now(), + user, + user, + item.item_code, + item.item_name, + item.description, + 1, + ) ) fields = [ @@ -1162,6 +1173,7 @@ def make_batch_nos(item_code, batch_nos): "item", "item_name", "description", + "use_batchwise_valuation", ] frappe.db.bulk_insert("Batch", fields=fields, values=set(batch_nos_details)) diff --git a/erpnext/stock/doctype/serial_and_batch_bundle/test_serial_and_batch_bundle.py b/erpnext/stock/doctype/serial_and_batch_bundle/test_serial_and_batch_bundle.py index 5f75b40411c..c313917bd4c 100644 --- a/erpnext/stock/doctype/serial_and_batch_bundle/test_serial_and_batch_bundle.py +++ b/erpnext/stock/doctype/serial_and_batch_bundle/test_serial_and_batch_bundle.py @@ -498,6 +498,8 @@ class TestSerialandBatchBundle(FrappeTestCase): make_batch_nos(item_code, batch_nos) self.assertTrue(frappe.db.exists("Batch", batch_id)) + use_batchwise_valuation = frappe.db.get_value("Batch", batch_id, "use_batchwise_valuation") + self.assertEqual(use_batchwise_valuation, 1) batch_id = "TEST-BATTCCH-VAL-00001" batch_nos = [{"batch_no": batch_id, "qty": 1}] diff --git a/erpnext/stock/serial_batch_bundle.py b/erpnext/stock/serial_batch_bundle.py index 72945e9abc3..573d7280ca1 100644 --- a/erpnext/stock/serial_batch_bundle.py +++ b/erpnext/stock/serial_batch_bundle.py @@ -553,7 +553,7 @@ class BatchNoValuation(DeprecatedBatchNoValuation): self.set_stock_value_difference() def get_batch_no_ledgers(self) -> list[dict]: - if not self.batchwise_valuation_batches: + if not self.batches: return [] parent = frappe.qb.DocType("Serial and Batch Bundle") @@ -575,7 +575,7 @@ class BatchNoValuation(DeprecatedBatchNoValuation): Sum(child.qty).as_("qty"), ) .where( - (child.batch_no.isin(self.batchwise_valuation_batches)) + (child.batch_no.isin(self.batches)) & (parent.warehouse == self.sle.warehouse) & (parent.item_code == self.sle.item_code) & (parent.docstatus == 1) From 1b2c2515bc60524705e116f107dd75245b1575cb Mon Sep 17 00:00:00 2001 From: Frappe PR Bot Date: Mon, 13 May 2024 11:24:52 +0000 Subject: [PATCH 03/36] chore(release): Bumped to Version 15.23.1 ## [15.23.1](https://github.com/frappe/erpnext/compare/v15.23.0...v15.23.1) (2024-05-13) ### Bug Fixes * valuation issue for batch (backport [#41425](https://github.com/frappe/erpnext/issues/41425)) (backport [#41430](https://github.com/frappe/erpnext/issues/41430)) ([#41434](https://github.com/frappe/erpnext/issues/41434)) ([aa2b644](https://github.com/frappe/erpnext/commit/aa2b64476e1267b6e0859c8185ef7e356d720e05)) --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 77eeaf1b7ca..c5331681dff 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -3,7 +3,7 @@ import inspect import frappe -__version__ = "15.23.0" +__version__ = "15.23.1" def get_default_company(user=None): From 7b8b58f8ca25d7950498114d47e39695e6f01010 Mon Sep 17 00:00:00 2001 From: Frappe PR Bot Date: Wed, 15 May 2024 05:12:37 +0000 Subject: [PATCH 04/36] chore(release): Bumped to Version 15.23.2 ## [15.23.2](https://github.com/frappe/erpnext/compare/v15.23.1...v15.23.2) (2024-05-15) ### Bug Fixes * 'Bill for Rejected Quantity in Purchase Invoice' feature not working (backport [#41437](https://github.com/frappe/erpnext/issues/41437)) ([#41445](https://github.com/frappe/erpnext/issues/41445)) ([b8db903](https://github.com/frappe/erpnext/commit/b8db9033204da35b0e214d86d81f31f42a0c3586)) * address filter and quotation to for prospect ([37741b5](https://github.com/frappe/erpnext/commit/37741b5b45a83525cdcef51ef7566fcb5098a1ce)) * address filter and quotation to for prospect ([394b1f4](https://github.com/frappe/erpnext/commit/394b1f499d1aa6ee78045ef0f87b460005f4b0c2)) * address filter and quotation to for prospect ([cdbb515](https://github.com/frappe/erpnext/commit/cdbb51537905d16de7929725e6cc8e50bc0845a5)) * Asset cancelation issue ([e18be9b](https://github.com/frappe/erpnext/commit/e18be9b21e7905ab4c8eb3d3be94ea3010b821c5)) * consistent use of "Address & Contact" (backport [#41386](https://github.com/frappe/erpnext/issues/41386)) ([#41388](https://github.com/frappe/erpnext/issues/41388)) ([b6f82a6](https://github.com/frappe/erpnext/commit/b6f82a656f5a5399a71da0cbc0beade7a5ebad5f)) * daily prorata based depreciation bug in wdv method ([c335c2c](https://github.com/frappe/erpnext/commit/c335c2c85a26ee9c4c0b306c4cf07ae18c936cb0)) * data getting override in delivery trip (backport [#41431](https://github.com/frappe/erpnext/issues/41431)) ([#41433](https://github.com/frappe/erpnext/issues/41433)) ([15d2881](https://github.com/frappe/erpnext/commit/15d2881bc891a23c591d4db1defb7f1f2b211249)) * Duplicate party name column in AR/AP report ([55edbec](https://github.com/frappe/erpnext/commit/55edbec6fa508ce9e8e8efc9e672fdcfe71affae)) * incorrect total days calculation ([01b25b5](https://github.com/frappe/erpnext/commit/01b25b5821753a2111c7e82a2a4f26801447a423)) * **minor:** removed extra parameter ([ce2c6c3](https://github.com/frappe/erpnext/commit/ce2c6c31651536d735bcda0b3729012d905fd058)) * pro rata based depreciation with opening accumulated depreciation ([72f3fb2](https://github.com/frappe/erpnext/commit/72f3fb2a2ca84ff3ddb2fc25f20394cd6dfebeae)) * PSOA ageing ([6590d78](https://github.com/frappe/erpnext/commit/6590d782989de2f2c7f4689045147397a6b01bf6)) * removed same named function ([955ce9b](https://github.com/frappe/erpnext/commit/955ce9b670caf55d5b1c31e10c54f62bfb8d1dd6)) * removed unrelated code modification ([0aca1e8](https://github.com/frappe/erpnext/commit/0aca1e8e05dead191ee323df7f0615e6e12457f4)) * resolved conflict ([520e1e9](https://github.com/frappe/erpnext/commit/520e1e9c8f5771b5209e4d2fc5b8a7bd774ff06a)) * resolved conflict ([3a72f4b](https://github.com/frappe/erpnext/commit/3a72f4bd309602358457406652433d11e0995f2c)) * resolved conflict ([8cca74d](https://github.com/frappe/erpnext/commit/8cca74d5ef720788512108e0a2610db42935c6a9)) * Unknown column 'tabBatch.batch_no' in 'where clause' (backport [#41418](https://github.com/frappe/erpnext/issues/41418)) ([#41444](https://github.com/frappe/erpnext/issues/41444)) ([d988c7b](https://github.com/frappe/erpnext/commit/d988c7bd0698e2e300681384bcff847dd7d072bc)) * update description of Supplier Invoice Number ([a7533ff](https://github.com/frappe/erpnext/commit/a7533ff7f6a51dd41c299d05eefdb9e3e592140d)) * valuation issue for batch (backport [#41425](https://github.com/frappe/erpnext/issues/41425)) ([#41430](https://github.com/frappe/erpnext/issues/41430)) ([f55a131](https://github.com/frappe/erpnext/commit/f55a131dea68986c3f3a29336fc5748184d6e054)) * **wip:** daily depreciation bug ([1016ec2](https://github.com/frappe/erpnext/commit/1016ec2a148859c2016ee4e7af36e96e5f89bae8)) * **wip:** depreciation calculation after asset value adjustment ([3eff9c9](https://github.com/frappe/erpnext/commit/3eff9c97794a8caedb3862fc2fbeb499c2620684)) * zero valuation rate for batched item (backport [#41446](https://github.com/frappe/erpnext/issues/41446)) ([#41447](https://github.com/frappe/erpnext/issues/41447)) ([5c3a096](https://github.com/frappe/erpnext/commit/5c3a0965bc1de4886a05329154f32902938d6926)) --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index c5331681dff..a1f9b11f512 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -3,7 +3,7 @@ import inspect import frappe -__version__ = "15.23.1" +__version__ = "15.23.2" def get_default_company(user=None): From 66684e7e2386bd54727ceed877e5d5d881e02896 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Wed, 15 May 2024 18:55:40 +0530 Subject: [PATCH 05/36] fix: not able to submit landed cost voucher (backport #41481) (backport #41486) (#41487) fix: not able to submit landed cost voucher (backport #41481) (#41486) fix: not able to submit landed cost voucher (#41481) (cherry picked from commit 81a9521f04df8786b07d780cbbc838bbd08bfb6a) Co-authored-by: rohitwaghchaure (cherry picked from commit a070ad786d636fca77f99da798d9b272d70d2131) Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- erpnext/controllers/stock_controller.py | 1 + .../test_landed_cost_voucher.py | 122 ++++++++++++++++++ .../serial_and_batch_bundle.py | 3 + erpnext/stock/serial_batch_bundle.py | 3 + 4 files changed, 129 insertions(+) diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py index 49252bd5b54..63a8c842c9a 100644 --- a/erpnext/controllers/stock_controller.py +++ b/erpnext/controllers/stock_controller.py @@ -205,6 +205,7 @@ class StockController(AccountsController): "company": self.company, "is_rejected": 1 if row.get("rejected_warehouse") else 0, "use_serial_batch_fields": row.use_serial_batch_fields, + "via_landed_cost_voucher": via_landed_cost_voucher, "do_not_submit": True if not via_landed_cost_voucher else False, } diff --git a/erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py b/erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py index 13b7f97b7c4..39f9ecb915d 100644 --- a/erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py +++ b/erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py @@ -946,6 +946,128 @@ class TestLandedCostVoucher(FrappeTestCase): frappe.db.get_value("Serial and Batch Bundle", row.serial_and_batch_bundle, "avg_rate"), ) + def test_do_not_validate_against_landed_cost_voucher_for_serial_for_legacy_pr(self): + from erpnext.stock.doctype.item.test_item import make_item + from erpnext.stock.doctype.serial_and_batch_bundle.serial_and_batch_bundle import get_auto_batch_nos + + frappe.flags.ignore_serial_batch_bundle_validation = True + frappe.flags.use_serial_and_batch_fields = True + sn_item = "Test Don't Validate Against LCV For Serial NO for Legacy PR" + sn_item_doc = make_item( + sn_item, + { + "has_serial_no": 1, + "serial_no_series": "SN-ALCVTDVLCVSNO-.####", + "is_stock_item": 1, + }, + ) + + serial_nos = [ + "SN-ALCVTDVLCVSNO-0001", + "SN-ALCVTDVLCVSNO-0002", + "SN-ALCVTDVLCVSNO-0003", + "SN-ALCVTDVLCVSNO-0004", + "SN-ALCVTDVLCVSNO-0005", + ] + + for sn in serial_nos: + if not frappe.db.exists("Serial No", sn): + sn_doc = frappe.get_doc( + { + "doctype": "Serial No", + "item_code": sn_item, + "serial_no": sn, + } + ) + sn_doc.insert() + + warehouse = "_Test Warehouse - _TC" + company = frappe.db.get_value("Warehouse", warehouse, "company") + + pr = make_purchase_receipt( + company=company, + warehouse=warehouse, + item_code=sn_item, + qty=5, + rate=100, + uom=sn_item_doc.stock_uom, + stock_uom=sn_item_doc.stock_uom, + ) + + pr.reload() + + for sn in serial_nos: + sn_doc = frappe.get_doc("Serial No", sn) + sn_doc.db_set( + { + "warehouse": warehouse, + "status": "Active", + } + ) + + for row in pr.items: + if row.item_code == sn_item: + row.db_set("serial_no", ", ".join(serial_nos)) + + stock_ledger_entries = frappe.get_all("Stock Ledger Entry", filters={"voucher_no": pr.name}) + for sle in stock_ledger_entries: + doc = frappe.get_doc("Stock Ledger Entry", sle.name) + if doc.item_code == sn_item: + doc.db_set("serial_no", ", ".join(serial_nos)) + + dn = create_delivery_note( + company=company, + warehouse=warehouse, + item_code=sn_item, + qty=5, + rate=100, + uom=sn_item_doc.stock_uom, + stock_uom=sn_item_doc.stock_uom, + ) + + stock_ledger_entries = frappe.get_all("Stock Ledger Entry", filters={"voucher_no": dn.name}) + for sle in stock_ledger_entries: + doc = frappe.get_doc("Stock Ledger Entry", sle.name) + if doc.item_code == sn_item: + doc.db_set("serial_no", ", ".join(serial_nos)) + + frappe.flags.ignore_serial_batch_bundle_validation = False + frappe.flags.use_serial_and_batch_fields = False + + lcv = make_landed_cost_voucher( + company=pr.company, + receipt_document_type="Purchase Receipt", + receipt_document=pr.name, + charges=20, + distribute_charges_based_on="Qty", + do_not_save=True, + ) + + lcv.get_items_from_purchase_receipts() + lcv.save() + lcv.submit() + + pr.reload() + + for row in pr.items: + self.assertEqual(row.valuation_rate, 104) + self.assertTrue(row.serial_and_batch_bundle) + self.assertEqual( + row.valuation_rate, + frappe.db.get_value("Serial and Batch Bundle", row.serial_and_batch_bundle, "avg_rate"), + ) + + lcv.cancel() + pr.reload() + + for row in pr.items: + self.assertEqual(row.valuation_rate, 100) + self.assertTrue(row.serial_and_batch_bundle) + self.assertEqual( + row.valuation_rate, + frappe.db.get_value("Serial and Batch Bundle", row.serial_and_batch_bundle, "avg_rate"), + ) + def make_landed_cost_voucher(**args): args = frappe._dict(args) diff --git a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py index a1a8a85e745..4c9fc881986 100644 --- a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py +++ b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py @@ -428,6 +428,9 @@ class SerialandBatchBundle(Document): self.throw_error_message(f"The {self.voucher_type} # {self.voucher_no} should be submit first.") def check_future_entries_exists(self): + if self.flags and self.flags.via_landed_cost_voucher: + return + if not self.has_serial_no: return diff --git a/erpnext/stock/serial_batch_bundle.py b/erpnext/stock/serial_batch_bundle.py index 573d7280ca1..21a96c41cb4 100644 --- a/erpnext/stock/serial_batch_bundle.py +++ b/erpnext/stock/serial_batch_bundle.py @@ -840,6 +840,9 @@ class SerialBatchCreation: self.set_auto_serial_batch_entries_for_inward() self.add_serial_nos_for_batch_item() + if hasattr(self, "via_landed_cost_voucher") and self.via_landed_cost_voucher: + doc.flags.via_landed_cost_voucher = self.via_landed_cost_voucher + self.set_serial_batch_entries(doc) if not doc.get("entries"): return frappe._dict({}) From c1f7d5a2d1b4c8ffec4509dacb40d19ce1c87162 Mon Sep 17 00:00:00 2001 From: Frappe PR Bot Date: Wed, 15 May 2024 13:27:07 +0000 Subject: [PATCH 06/36] chore(release): Bumped to Version 15.23.3 ## [15.23.3](https://github.com/frappe/erpnext/compare/v15.23.2...v15.23.3) (2024-05-15) ### Bug Fixes * not able to submit landed cost voucher (backport [#41481](https://github.com/frappe/erpnext/issues/41481)) (backport [#41486](https://github.com/frappe/erpnext/issues/41486)) ([#41487](https://github.com/frappe/erpnext/issues/41487)) ([66684e7](https://github.com/frappe/erpnext/commit/66684e7e2386bd54727ceed877e5d5d881e02896)) --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index a1f9b11f512..ca66978e7bb 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -3,7 +3,7 @@ import inspect import frappe -__version__ = "15.23.2" +__version__ = "15.23.3" def get_default_company(user=None): From 68faf575db6690f92164e8ca6223366830e94e3a Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Mon, 13 May 2024 15:39:22 +0530 Subject: [PATCH 07/36] feat: Config to enable immutable ledger (cherry picked from commit d56f52b0ba3665d829e971df1f7ea42770e9f89e) # Conflicts: # erpnext/accounts/doctype/accounts_settings/accounts_settings.json # erpnext/accounts/general_ledger.py (cherry picked from commit 32c935bc30b0dc93b6416e7717012ce25be3e174) # Conflicts: # erpnext/accounts/doctype/accounts_settings/accounts_settings.json --- .../accounts_settings/accounts_settings.js | 19 +++++++++++++++ .../accounts_settings/accounts_settings.json | 16 +++++++++++++ .../accounts_settings/accounts_settings.py | 1 + erpnext/accounts/general_ledger.py | 23 +++++++++++++++++-- 4 files changed, 57 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/accounts_settings/accounts_settings.js b/erpnext/accounts/doctype/accounts_settings/accounts_settings.js index 5b9a52e8f8b..4f59085db0a 100644 --- a/erpnext/accounts/doctype/accounts_settings/accounts_settings.js +++ b/erpnext/accounts/doctype/accounts_settings/accounts_settings.js @@ -3,4 +3,23 @@ frappe.ui.form.on("Accounts Settings", { refresh: function (frm) {}, + enable_immutable_ledger: function (frm) { + if (!frm.doc.enable_immutable_ledger) { + return; + } + + let msg = __("Enabling this will change the way how cancelled transactions are handled."); + msg += " "; + msg += __("Please enable only if the understand the effects of enabling this."); + msg += "
"; + msg += "Do you still want to enable immutable ledger?"; + + frappe.confirm( + msg, + () => {}, + () => { + frm.set_value("enable_immutable_ledger", 0); + } + ); + }, }); diff --git a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json index 305ee72edcc..e7f5b5a9d98 100644 --- a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json +++ b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json @@ -12,6 +12,7 @@ "unlink_advance_payment_on_cancelation_of_order", "column_break_13", "delete_linked_ledger_entries", + "enable_immutable_ledger", "invoicing_features_section", "check_supplier_invoice_uniqueness", "automatically_fetch_payment_terms", @@ -454,6 +455,13 @@ "fieldname": "remarks_section", "fieldtype": "Section Break", "label": "Remarks Column Length" + }, + { + "default": "0", + "description": "On enabling this cancellation entries will be posted on the actual cancellation date and reports will consider cancelled entries as well", + "fieldname": "enable_immutable_ledger", + "fieldtype": "Check", + "label": "Enable Immutable Ledger" } ], "icon": "icon-cog", @@ -461,7 +469,15 @@ "index_web_pages_for_search": 1, "issingle": 1, "links": [], +<<<<<<< HEAD "modified": "2024-03-15 12:11:36.085158", +======= +<<<<<<< HEAD + "modified": "2024-01-30 14:04:26.553554", +======= + "modified": "2024-05-11 23:19:44.673975", +>>>>>>> d56f52b0ba (feat: Config to enable immutable ledger) +>>>>>>> 32c935bc30 (feat: Config to enable immutable ledger) "modified_by": "Administrator", "module": "Accounts", "name": "Accounts Settings", diff --git a/erpnext/accounts/doctype/accounts_settings/accounts_settings.py b/erpnext/accounts/doctype/accounts_settings/accounts_settings.py index 07d1a65265b..34f0f24047b 100644 --- a/erpnext/accounts/doctype/accounts_settings/accounts_settings.py +++ b/erpnext/accounts/doctype/accounts_settings/accounts_settings.py @@ -39,6 +39,7 @@ class AccountsSettings(Document): determine_address_tax_category_from: DF.Literal["Billing Address", "Shipping Address"] enable_common_party_accounting: DF.Check enable_fuzzy_matching: DF.Check + enable_immutable_ledger: DF.Check enable_party_matching: DF.Check frozen_accounts_modifier: DF.Link | None general_ledger_remarks_length: DF.Int diff --git a/erpnext/accounts/general_ledger.py b/erpnext/accounts/general_ledger.py index 0ff9e973e59..8b99226ba27 100644 --- a/erpnext/accounts/general_ledger.py +++ b/erpnext/accounts/general_ledger.py @@ -7,7 +7,12 @@ import copy import frappe from frappe import _ from frappe.model.meta import get_field_precision +<<<<<<< HEAD from frappe.utils import cint, cstr, flt, formatdate, getdate, now +======= +from frappe.utils import cint, flt, formatdate, getdate, now +from frappe.utils.dashboard import cache_source +>>>>>>> d56f52b0ba (feat: Config to enable immutable ledger) import erpnext from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( @@ -577,6 +582,8 @@ def make_reverse_gl_entries( and make reverse gl entries by swapping debit and credit """ + immutable_ledger_enabled = is_immutable_ledger_enabled() + if not gl_entries: gl_entry = frappe.qb.DocType("GL Entry") gl_entries = ( @@ -608,7 +615,6 @@ def make_reverse_gl_entries( for x in gl_entries: query = ( frappe.qb.update(gle) - .set(gle.is_cancelled, True) .set(gle.modified, now()) .set(gle.modified_by, frappe.session.user) .where( @@ -623,9 +629,14 @@ def make_reverse_gl_entries( & (gle.voucher_detail_no == x.voucher_detail_no) ) ) + + if not immutable_ledger_enabled: + query = query.set(gle.is_cancelled, True) + query.run() else: - set_as_cancel(gl_entries[0]["voucher_type"], gl_entries[0]["voucher_no"]) + if not immutable_ledger_enabled: + set_as_cancel(gl_entries[0]["voucher_type"], gl_entries[0]["voucher_no"]) for entry in gl_entries: new_gle = copy.deepcopy(entry) @@ -644,6 +655,10 @@ def make_reverse_gl_entries( new_gle["remarks"] = "On cancellation of " + new_gle["voucher_no"] new_gle["is_cancelled"] = 1 + if immutable_ledger_enabled: + new_gle["is_cancelled"] = 0 + new_gle["posting_date"] = frappe.form_dict.get("posting_date") or getdate() + if new_gle["debit"] or new_gle["credit"]: make_entry(new_gle, adv_adj, "Yes") @@ -736,3 +751,7 @@ def validate_allowed_dimensions(gl_entry, dimension_filter_map): ), InvalidAccountDimensionError, ) + + +def is_immutable_ledger_enabled(): + return frappe.db.get_single_value("Accounts Settings", "enable_immutable_ledger") From f09a6d76a7050a85080755293313dfc2fc943723 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Thu, 16 May 2024 20:27:50 +0530 Subject: [PATCH 08/36] chore: Resolve conflicts (cherry picked from commit 983c55eca1ef34b5e2e84bc8f95976a6d9cadf8e) --- erpnext/accounts/general_ledger.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/erpnext/accounts/general_ledger.py b/erpnext/accounts/general_ledger.py index 8b99226ba27..3f01dee888d 100644 --- a/erpnext/accounts/general_ledger.py +++ b/erpnext/accounts/general_ledger.py @@ -7,12 +7,7 @@ import copy import frappe from frappe import _ from frappe.model.meta import get_field_precision -<<<<<<< HEAD from frappe.utils import cint, cstr, flt, formatdate, getdate, now -======= -from frappe.utils import cint, flt, formatdate, getdate, now -from frappe.utils.dashboard import cache_source ->>>>>>> d56f52b0ba (feat: Config to enable immutable ledger) import erpnext from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( From ce60b77fa59d2cc3c284d861f330e1d6b45ce39e Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Thu, 16 May 2024 20:59:47 +0530 Subject: [PATCH 09/36] chore: Resolve conflicts (cherry picked from commit 9315607ee730da03cc591526a98bd1c18f3fedb8) # Conflicts: # erpnext/accounts/doctype/accounts_settings/accounts_settings.json --- .../accounts/doctype/accounts_settings/accounts_settings.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json index e7f5b5a9d98..663a9e990d1 100644 --- a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json +++ b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json @@ -469,6 +469,7 @@ "index_web_pages_for_search": 1, "issingle": 1, "links": [], +<<<<<<< HEAD <<<<<<< HEAD "modified": "2024-03-15 12:11:36.085158", ======= @@ -478,6 +479,9 @@ "modified": "2024-05-11 23:19:44.673975", >>>>>>> d56f52b0ba (feat: Config to enable immutable ledger) >>>>>>> 32c935bc30 (feat: Config to enable immutable ledger) +======= + "modified": "2024-05-11 23:19:44.673975", +>>>>>>> 9315607ee7 (chore: Resolve conflicts) "modified_by": "Administrator", "module": "Accounts", "name": "Accounts Settings", From 7cbe03174f8f53e254a7be275f1a805a011e3f58 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Fri, 17 May 2024 10:37:32 +0530 Subject: [PATCH 10/36] chore: resolve conflicts --- .../doctype/accounts_settings/accounts_settings.json | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json index 663a9e990d1..7bf3826e781 100644 --- a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json +++ b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json @@ -469,19 +469,7 @@ "index_web_pages_for_search": 1, "issingle": 1, "links": [], -<<<<<<< HEAD -<<<<<<< HEAD - "modified": "2024-03-15 12:11:36.085158", -======= -<<<<<<< HEAD - "modified": "2024-01-30 14:04:26.553554", -======= "modified": "2024-05-11 23:19:44.673975", ->>>>>>> d56f52b0ba (feat: Config to enable immutable ledger) ->>>>>>> 32c935bc30 (feat: Config to enable immutable ledger) -======= - "modified": "2024-05-11 23:19:44.673975", ->>>>>>> 9315607ee7 (chore: Resolve conflicts) "modified_by": "Administrator", "module": "Accounts", "name": "Accounts Settings", From 9b7bda958b7498a91501061a2f5b35ef6b958962 Mon Sep 17 00:00:00 2001 From: Frappe PR Bot Date: Fri, 17 May 2024 05:27:58 +0000 Subject: [PATCH 11/36] chore(release): Bumped to Version 15.24.0 # [15.24.0](https://github.com/frappe/erpnext/compare/v15.23.3...v15.24.0) (2024-05-17) ### Features * Config to enable immutable ledger ([68faf57](https://github.com/frappe/erpnext/commit/68faf575db6690f92164e8ca6223366830e94e3a)) --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index ca66978e7bb..73d34d5e0fe 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -3,7 +3,7 @@ import inspect import frappe -__version__ = "15.23.3" +__version__ = "15.24.0" def get_default_company(user=None): From 4ddd6e685b8739b62a16574f84ad69a9ef723233 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Mon, 20 May 2024 15:51:42 +0530 Subject: [PATCH 12/36] fix: valuation rate for legacy serial nos (backport #41543) (backport #41545) (#41546) fix: valuation rate for legacy serial nos (backport #41543) (#41545) fix: valuation rate for legacy serial nos (#41543) fix: valuation rate for serial nos (cherry picked from commit 214b38f7c88cd31b0caa42f3122355fb19d1d044) Co-authored-by: rohitwaghchaure (cherry picked from commit f121b33e291915f3a445de75380cefacb82041de) Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- erpnext/stock/deprecated_serial_batch.py | 19 +-- .../delivery_note/test_delivery_note.py | 126 ++++++++++++++++++ erpnext/stock/serial_batch_bundle.py | 4 +- 3 files changed, 139 insertions(+), 10 deletions(-) diff --git a/erpnext/stock/deprecated_serial_batch.py b/erpnext/stock/deprecated_serial_batch.py index 81daa924b75..5b826455d4c 100644 --- a/erpnext/stock/deprecated_serial_batch.py +++ b/erpnext/stock/deprecated_serial_batch.py @@ -17,15 +17,11 @@ class DeprecatedSerialNoValuation: if not serial_nos: return - actual_qty = flt(self.sle.actual_qty) - stock_value_change = 0 - if actual_qty < 0: - if not self.sle.is_cancelled: - outgoing_value = self.get_incoming_value_for_serial_nos(serial_nos) - stock_value_change = -1 * outgoing_value + if not self.sle.is_cancelled: + stock_value_change = self.get_incoming_value_for_serial_nos(serial_nos) - self.stock_value_change += stock_value_change + self.stock_value_change += flt(stock_value_change) def get_filterd_serial_nos(self): serial_nos = [] @@ -141,7 +137,14 @@ class DeprecatedBatchNoValuation: if not self.non_batchwise_balance_qty: continue - self.batch_avg_rate[batch_no] = self.non_batchwise_balance_value / self.non_batchwise_balance_qty + if self.non_batchwise_balance_value == 0: + self.batch_avg_rate[batch_no] = 0.0 + self.stock_value_differece[batch_no] = 0.0 + else: + self.batch_avg_rate[batch_no] = ( + self.non_batchwise_balance_value / self.non_batchwise_balance_qty + ) + self.stock_value_differece[batch_no] = self.non_batchwise_balance_value stock_value_change = self.batch_avg_rate[batch_no] * ledger.qty self.stock_value_change += stock_value_change diff --git a/erpnext/stock/doctype/delivery_note/test_delivery_note.py b/erpnext/stock/doctype/delivery_note/test_delivery_note.py index 791a9730b50..192d828d843 100644 --- a/erpnext/stock/doctype/delivery_note/test_delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/test_delivery_note.py @@ -1697,6 +1697,132 @@ class TestDeliveryNote(FrappeTestCase): if row.serial_no: self.assertEqual(row.serial_no, serial_no) + def test_delivery_note_legacy_serial_no_valuation(self): + from erpnext.stock.doctype.delivery_note.delivery_note import make_sales_return + from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos + + frappe.flags.ignore_serial_batch_bundle_validation = True + sn_item = "Old Serial NO Item Valuation Test - 2" + make_item( + sn_item, + { + "has_serial_no": 1, + "serial_no_series": "SN-SOVOSN-.####", + "is_stock_item": 1, + }, + ) + + serial_nos = [ + "SN-SOVOSN-1234", + "SN-SOVOSN-2234", + ] + + for sn in serial_nos: + if not frappe.db.exists("Serial No", sn): + sn_doc = frappe.get_doc( + { + "doctype": "Serial No", + "item_code": sn_item, + "serial_no": sn, + } + ) + sn_doc.insert() + + warehouse = "_Test Warehouse - _TC" + company = frappe.db.get_value("Warehouse", warehouse, "company") + se_doc = make_stock_entry( + item_code=sn_item, + company=company, + target="_Test Warehouse - _TC", + qty=2, + basic_rate=150, + do_not_submit=1, + use_serial_batch_fields=0, + ) + se_doc.submit() + + se_doc.items[0].db_set("serial_no", "\n".join(serial_nos)) + + sle_data = frappe.get_all( + "Stock Ledger Entry", + filters={"voucher_no": se_doc.name, "voucher_type": "Stock Entry"}, + )[0] + + sle_doc = frappe.get_doc("Stock Ledger Entry", sle_data.name) + self.assertFalse(sle_doc.serial_no) + sle_doc.db_set("serial_no", "\n".join(serial_nos)) + sle_doc.reload() + self.assertTrue(sle_doc.serial_no) + self.assertFalse(sle_doc.is_cancelled) + + for sn in serial_nos: + sn_doc = frappe.get_doc("Serial No", sn) + sn_doc.db_set( + { + "status": "Active", + "warehouse": warehouse, + } + ) + + self.assertEqual(sorted(get_serial_nos(se_doc.items[0].serial_no)), sorted(serial_nos)) + frappe.flags.ignore_serial_batch_bundle_validation = False + + se_doc = make_stock_entry( + item_code=sn_item, + company=company, + target="_Test Warehouse - _TC", + qty=2, + basic_rate=200, + ) + + serial_nos.extend(get_serial_nos_from_bundle(se_doc.items[0].serial_and_batch_bundle)) + + dn = create_delivery_note( + item_code=sn_item, + qty=3, + rate=500, + warehouse=warehouse, + company=company, + expense_account="Cost of Goods Sold - _TC", + cost_center="Main - _TC", + use_serial_batch_fields=1, + serial_no="\n".join(serial_nos[0:3]), + ) + + dn.reload() + + sle_data = frappe.get_all( + "Stock Ledger Entry", + filters={"voucher_no": dn.name, "voucher_type": "Delivery Note"}, + fields=["stock_value_difference", "actual_qty"], + )[0] + + self.assertEqual(sle_data.actual_qty, 3 * -1) + self.assertEqual(sle_data.stock_value_difference, 500.0 * -1) + + dn = create_delivery_note( + item_code=sn_item, + qty=1, + rate=500, + warehouse=warehouse, + company=company, + expense_account="Cost of Goods Sold - _TC", + cost_center="Main - _TC", + use_serial_batch_fields=1, + serial_no=serial_nos[-1], + ) + + dn.reload() + + sle_data = frappe.get_all( + "Stock Ledger Entry", + filters={"voucher_no": dn.name, "voucher_type": "Delivery Note"}, + fields=["stock_value_difference", "actual_qty"], + )[0] + + self.assertEqual(sle_data.actual_qty, 1 * -1) + self.assertEqual(sle_data.stock_value_difference, 200.0 * -1) + def create_delivery_note(**args): dn = frappe.new_doc("Delivery Note") diff --git a/erpnext/stock/serial_batch_bundle.py b/erpnext/stock/serial_batch_bundle.py index 21a96c41cb4..50a7707d4a9 100644 --- a/erpnext/stock/serial_batch_bundle.py +++ b/erpnext/stock/serial_batch_bundle.py @@ -553,7 +553,7 @@ class BatchNoValuation(DeprecatedBatchNoValuation): self.set_stock_value_difference() def get_batch_no_ledgers(self) -> list[dict]: - if not self.batches: + if not self.batchwise_valuation_batches: return [] parent = frappe.qb.DocType("Serial and Batch Bundle") @@ -575,7 +575,7 @@ class BatchNoValuation(DeprecatedBatchNoValuation): Sum(child.qty).as_("qty"), ) .where( - (child.batch_no.isin(self.batches)) + (child.batch_no.isin(self.batchwise_valuation_batches)) & (parent.warehouse == self.sle.warehouse) & (parent.item_code == self.sle.item_code) & (parent.docstatus == 1) From b1d345ba0b57d527f892c3e669396339935b7a91 Mon Sep 17 00:00:00 2001 From: Frappe PR Bot Date: Mon, 20 May 2024 10:22:57 +0000 Subject: [PATCH 13/36] chore(release): Bumped to Version 15.24.1 ## [15.24.1](https://github.com/frappe/erpnext/compare/v15.24.0...v15.24.1) (2024-05-20) ### Bug Fixes * valuation rate for legacy serial nos (backport [#41543](https://github.com/frappe/erpnext/issues/41543)) (backport [#41545](https://github.com/frappe/erpnext/issues/41545)) ([#41546](https://github.com/frappe/erpnext/issues/41546)) ([4ddd6e6](https://github.com/frappe/erpnext/commit/4ddd6e685b8739b62a16574f84ad69a9ef723233)) --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 73d34d5e0fe..4c3bc621038 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -3,7 +3,7 @@ import inspect import frappe -__version__ = "15.24.0" +__version__ = "15.24.1" def get_default_company(user=None): From a3fdfba46f3452505e921f9211b8f178913fbbc7 Mon Sep 17 00:00:00 2001 From: Frappe PR Bot Date: Wed, 22 May 2024 08:49:10 +0000 Subject: [PATCH 14/36] chore(release): Bumped to Version 15.25.0 # [15.25.0](https://github.com/frappe/erpnext/compare/v15.24.1...v15.25.0) (2024-05-22) ### Bug Fixes * added validation message for low gross purchase amount (backport [#41502](https://github.com/frappe/erpnext/issues/41502)) ([#41553](https://github.com/frappe/erpnext/issues/41553)) ([89ba7a2](https://github.com/frappe/erpnext/commit/89ba7a22fba54dbd51d674f7727a2ba441d02c5c)) * Auto reconcile only after selecting bank account (backport [#41489](https://github.com/frappe/erpnext/issues/41489)) ([#41554](https://github.com/frappe/erpnext/issues/41554)) ([33eb251](https://github.com/frappe/erpnext/commit/33eb251727fce9a04422233d693bcfa07ee9a122)) * bold total in exponential smoothing forecasting (backport [#41393](https://github.com/frappe/erpnext/issues/41393)) ([#41404](https://github.com/frappe/erpnext/issues/41404)) ([8101b51](https://github.com/frappe/erpnext/commit/8101b51899514c202d79b30f7ce46949ebd63778)) * BOM creator validation for parent row no (backport [#41413](https://github.com/frappe/erpnext/issues/41413)) ([#41558](https://github.com/frappe/erpnext/issues/41558)) ([953de99](https://github.com/frappe/erpnext/commit/953de995bcd2bcb502fd461d0fb3977a63350272)) * convert invoice_portion value from str to float (backport [#41485](https://github.com/frappe/erpnext/issues/41485)) ([#41555](https://github.com/frappe/erpnext/issues/41555)) ([0a36139](https://github.com/frappe/erpnext/commit/0a36139ef4fc55543b00ec7fdaac494c4fc59402)) * correct report name in inner button (backport [#41568](https://github.com/frappe/erpnext/issues/41568)) ([#41572](https://github.com/frappe/erpnext/issues/41572)) ([4ccc426](https://github.com/frappe/erpnext/commit/4ccc426fec6ef619dc058197b5881b3c0f2d8b4b)) * create custom field for accounting dimensions only if the field not exists already ([#41557](https://github.com/frappe/erpnext/issues/41557)) ([68fa55c](https://github.com/frappe/erpnext/commit/68fa55ca024f1b8d691ab2d861544a8026827b0e)) * Deadlock on submitting Sales Invoice (backport [#41417](https://github.com/frappe/erpnext/issues/41417)) ([#41562](https://github.com/frappe/erpnext/issues/41562)) ([49db19d](https://github.com/frappe/erpnext/commit/49db19d57af9484b3449a44678829d25ce876a97)) * Demo data clearing ([46ec61f](https://github.com/frappe/erpnext/commit/46ec61f0c923ed2800cd2642e4d935080a030ee8)) * Filters in trend reports ([52d5d7a](https://github.com/frappe/erpnext/commit/52d5d7a4d3fdc475c1db4eb445f40d40e7bed9ec)) * job card time logs overlap issue (backport [#41567](https://github.com/frappe/erpnext/issues/41567)) ([#41571](https://github.com/frappe/erpnext/issues/41571)) ([6554f19](https://github.com/frappe/erpnext/commit/6554f192fbe90033a71fa323462633c5130e1b46)) * minor Dr and Cr between Purchase Receipt and Purchase Invoice ([3872cdc](https://github.com/frappe/erpnext/commit/3872cdc54a2f1567ef2104da963a4c573fbe7e36)) * not able to delete line items in the subcontracting receipt (backport [#41569](https://github.com/frappe/erpnext/issues/41569)) ([#41570](https://github.com/frappe/erpnext/issues/41570)) ([26c3235](https://github.com/frappe/erpnext/commit/26c3235bf9e6972d04a082fcfcc172ef6b552460)) * not able to submit landed cost voucher (backport [#41481](https://github.com/frappe/erpnext/issues/41481)) ([#41486](https://github.com/frappe/erpnext/issues/41486)) ([a070ad7](https://github.com/frappe/erpnext/commit/a070ad786d636fca77f99da798d9b272d70d2131)) * possible sql error on General Ledger ([e0a0cb7](https://github.com/frappe/erpnext/commit/e0a0cb7b258cdbd83be99264bbc3416190e80a1d)) * print format bold for field "total" ([e36880d](https://github.com/frappe/erpnext/commit/e36880da2d181ae441cd17fdb86e8b6fe2a2be45)) * priority not working for multiple pricing rules (backport [#41516](https://github.com/frappe/erpnext/issues/41516)) ([#41525](https://github.com/frappe/erpnext/issues/41525)) ([5fd68f9](https://github.com/frappe/erpnext/commit/5fd68f9fcb0f2e5ee3579652841cc4d5335a933d)) * Show acheived amount and variance for parent item groups (backport [#41495](https://github.com/frappe/erpnext/issues/41495)) ([#41551](https://github.com/frappe/erpnext/issues/41551)) ([5e0bff3](https://github.com/frappe/erpnext/commit/5e0bff3a60561fe15b0a9f2dc054411a12f3c315)) * stock levels for batch (backport [#41494](https://github.com/frappe/erpnext/issues/41494)) ([#41501](https://github.com/frappe/erpnext/issues/41501)) ([938888c](https://github.com/frappe/erpnext/commit/938888cddd8dd343b8658f7e2cc71b367f59fd28)) * timeout error while submitting purchase invoice (backport [#41520](https://github.com/frappe/erpnext/issues/41520)) ([#41522](https://github.com/frappe/erpnext/issues/41522)) ([fcd9f89](https://github.com/frappe/erpnext/commit/fcd9f89deec07e2188959dcc3118700b68cd6b37)) * typerror on hide_fields ([8ae9da5](https://github.com/frappe/erpnext/commit/8ae9da5484543ddb2357bbe500ff5fba4d2a443d)) * Unable to add items in POS Invoice ([a90186f](https://github.com/frappe/erpnext/commit/a90186f9aec48d5b8d2adf388f91d6e8b6b85a69)) * validate reorder group warehouse (backport [#41478](https://github.com/frappe/erpnext/issues/41478)) ([#41480](https://github.com/frappe/erpnext/issues/41480)) ([a1ce514](https://github.com/frappe/erpnext/commit/a1ce514cf3e2abaed3ccc76b4885cb6a3ca1b28e)) * valuation rate for legacy serial nos (backport [#41543](https://github.com/frappe/erpnext/issues/41543)) ([#41545](https://github.com/frappe/erpnext/issues/41545)) ([f121b33](https://github.com/frappe/erpnext/commit/f121b33e291915f3a445de75380cefacb82041de)) ### Features * Config to enable immutable ledger ([32c935b](https://github.com/frappe/erpnext/commit/32c935bc30b0dc93b6416e7717012ce25be3e174)) * enter serial range in Serial/Batch Selector (backport [#41530](https://github.com/frappe/erpnext/issues/41530)) ([#41534](https://github.com/frappe/erpnext/issues/41534)) ([7225347](https://github.com/frappe/erpnext/commit/722534738774576bf39c8f1d6ebe8d964f1f5e1d)) --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 4c3bc621038..e7adbd4e9e4 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -3,7 +3,7 @@ import inspect import frappe -__version__ = "15.24.1" +__version__ = "15.25.0" def get_default_company(user=None): From 56d83d44be2717ca6330e24d81005f050a83a1de Mon Sep 17 00:00:00 2001 From: Frappe PR Bot Date: Wed, 29 May 2024 07:54:16 +0000 Subject: [PATCH 15/36] chore(release): Bumped to Version 15.26.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # [15.26.0](https://github.com/frappe/erpnext/compare/v15.25.0...v15.26.0) (2024-05-29) ### Bug Fixes * add in some indices to speed up Purchase Order deletion ([3ed3b21](https://github.com/frappe/erpnext/commit/3ed3b214c881c0e5dd10eda8ae76364cf706630b)) * cost center filter according to the company in project ([193b844](https://github.com/frappe/erpnext/commit/193b844bf1ad0b514953b5ea59cf81cfaf46ffa3)) * cost center filter according to the company in project ([e6aaab3](https://github.com/frappe/erpnext/commit/e6aaab38b06f326b2133e7404d4d6deef1c777a5)) * cost center filter according to the company in project ([563e15e](https://github.com/frappe/erpnext/commit/563e15e1c8ece1071f71e8c9fb495ec0b410d580)) * multiple issues related to serial and batch bundle (backport [#41662](https://github.com/frappe/erpnext/issues/41662)) ([#41668](https://github.com/frappe/erpnext/issues/41668)) ([dc0bb22](https://github.com/frappe/erpnext/commit/dc0bb220ed2d7a7e0bb2db8d284480d051b9e221)) * not allow template item in product bundle item ([8fb3294](https://github.com/frappe/erpnext/commit/8fb329467458eb7317c7e5c31721ad351158e26b)) * not allow template item in product bundle item ([b64f5a4](https://github.com/frappe/erpnext/commit/b64f5a4e542f94c7b066532c665daf2437a5d76b)) * not allow template item in product bundle item - v15/v14 ([9864377](https://github.com/frappe/erpnext/commit/9864377b47800b86f4a0a63c1e0e6f3f35e170a8)) * opening stock not showing in the stock ledger report for the bat… (backport [#41584](https://github.com/frappe/erpnext/issues/41584)) ([#41590](https://github.com/frappe/erpnext/issues/41590)) ([162ec7d](https://github.com/frappe/erpnext/commit/162ec7d6e88fdab528e6c850ee5c3cccae7f1474)) * SCR batch qty issue (backport [#41595](https://github.com/frappe/erpnext/issues/41595)) ([#41599](https://github.com/frappe/erpnext/issues/41599)) ([17ea958](https://github.com/frappe/erpnext/commit/17ea95817051714a1cfc49d854047ca4c39fba55)) * set expense account as Assets RBNB only if it is booked in linked PR (backport [#41368](https://github.com/frappe/erpnext/issues/41368)) ([#41673](https://github.com/frappe/erpnext/issues/41673)) ([0a0970e](https://github.com/frappe/erpnext/commit/0a0970e0e7b4662e093189b692748b16cd1e7588)) * Unable to 'Get Suppliers' using tags in Request for Quotation (backport [#41626](https://github.com/frappe/erpnext/issues/41626)) ([#41627](https://github.com/frappe/erpnext/issues/41627)) ([ca855e8](https://github.com/frappe/erpnext/commit/ca855e8ab81214e6d05e53db023d53554fb5e62c)) ### Features * Add Party details to Serial No Ledger Report ([#41656](https://github.com/frappe/erpnext/issues/41656)) ([7462de6](https://github.com/frappe/erpnext/commit/7462de66ce099391bbb11f0c566c92136d9539c1)) ### Performance Improvements * sales order UI render (backport [#41591](https://github.com/frappe/erpnext/issues/41591)) ([#41592](https://github.com/frappe/erpnext/issues/41592)) ([09d112a](https://github.com/frappe/erpnext/commit/09d112a0616db7d998eb319dc9114a96fdba9a7f)) --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index e7adbd4e9e4..279827a6f6e 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -3,7 +3,7 @@ import inspect import frappe -__version__ = "15.25.0" +__version__ = "15.26.0" def get_default_company(user=None): From 64835b99eca0619835f876cf1e1c7ca15bfde4f9 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Thu, 30 May 2024 19:26:02 +0530 Subject: [PATCH 16/36] fix: batch selection issue (backport #41692) (backport #41693) (#41694) fix: batch selection issue (backport #41692) (#41693) fix: batch selection issue (#41692) (cherry picked from commit 968120d0eba08b0bf8fd807be2bcb93d64817c8f) Co-authored-by: rohitwaghchaure (cherry picked from commit 24775db97e3c58ae213d7bd0cdd1f902599ef351) Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- erpnext/controllers/queries.py | 2 ++ erpnext/public/js/controllers/transaction.js | 3 +++ erpnext/stock/doctype/stock_entry/stock_entry.js | 4 +++- .../doctype/stock_settings/stock_settings.js | 16 ++++++++++++++++ 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py index 854682bec66..c57b2f3ddd6 100644 --- a/erpnext/controllers/queries.py +++ b/erpnext/controllers/queries.py @@ -422,6 +422,7 @@ def get_batches_from_stock_ledger_entries(searchfields, txt, filters, start=0, p & (stock_ledger_entry.batch_no.isnotnull()) ) .groupby(stock_ledger_entry.batch_no, stock_ledger_entry.warehouse) + .having(Sum(stock_ledger_entry.actual_qty) > 0) .offset(start) .limit(page_len) ) @@ -472,6 +473,7 @@ def get_batches_from_serial_and_batch_bundle(searchfields, txt, filters, start=0 & (stock_ledger_entry.serial_and_batch_bundle.isnotnull()) ) .groupby(bundle.batch_no, bundle.warehouse) + .having(Sum(bundle.qty) > 0) .offset(start) .limit(page_len) ) diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index b421aeebfb3..937b19d9abb 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -2295,6 +2295,9 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe if (doc.is_return) { filters["is_return"] = 1; + if (["Sales Invoice", "Delivery Note"].includes(doc.doctype)) { + filters["is_inward"] = 1; + } } if (item.warehouse) filters["warehouse"] = item.warehouse; diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js index 4e00de0d7ce..c54876713c3 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.js +++ b/erpnext/stock/doctype/stock_entry/stock_entry.js @@ -111,7 +111,9 @@ frappe.ui.form.on("Stock Entry", { // or a pre-existing batch if (frm.doc.purpose != "Material Receipt") { filters["warehouse"] = item.s_warehouse || item.t_warehouse; - } else { + } + + if (!item.s_warehouse && item.t_warehouse) { filters["is_inward"] = 1; } diff --git a/erpnext/stock/doctype/stock_settings/stock_settings.js b/erpnext/stock/doctype/stock_settings/stock_settings.js index 1972b193732..0443f3f1ece 100644 --- a/erpnext/stock/doctype/stock_settings/stock_settings.js +++ b/erpnext/stock/doctype/stock_settings/stock_settings.js @@ -14,6 +14,22 @@ frappe.ui.form.on("Stock Settings", { frm.set_query("default_warehouse", filters); frm.set_query("sample_retention_warehouse", filters); }, + + use_serial_batch_fields(frm) { + if (frm.doc.use_serial_batch_fields && !frm.doc.disable_serial_no_and_batch_selector) { + frm.set_value("disable_serial_no_and_batch_selector", 1); + } + }, + + disable_serial_no_and_batch_selector(frm) { + if (!frm.doc.disable_serial_no_and_batch_selector && frm.doc.use_serial_batch_fields) { + frm.set_value("disable_serial_no_and_batch_selector", 1); + frappe.msgprint( + __("Serial No and Batch Selector cannot be use when Use Serial / Batch Fields is enabled.") + ); + } + }, + allow_negative_stock: function (frm) { if (!frm.doc.allow_negative_stock) { return; From 55121a22a5346666cfe9c0fc69f50417d8187059 Mon Sep 17 00:00:00 2001 From: Frappe PR Bot Date: Thu, 30 May 2024 13:57:20 +0000 Subject: [PATCH 17/36] chore(release): Bumped to Version 15.26.1 ## [15.26.1](https://github.com/frappe/erpnext/compare/v15.26.0...v15.26.1) (2024-05-30) ### Bug Fixes * batch selection issue (backport [#41692](https://github.com/frappe/erpnext/issues/41692)) (backport [#41693](https://github.com/frappe/erpnext/issues/41693)) ([#41694](https://github.com/frappe/erpnext/issues/41694)) ([64835b9](https://github.com/frappe/erpnext/commit/64835b99eca0619835f876cf1e1c7ca15bfde4f9)) --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 279827a6f6e..9d6a51bb102 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -3,7 +3,7 @@ import inspect import frappe -__version__ = "15.26.0" +__version__ = "15.26.1" def get_default_company(user=None): From dcdaa02173ffcba329e37f7c61ea22104d3a30d9 Mon Sep 17 00:00:00 2001 From: Frappe PR Bot Date: Wed, 5 Jun 2024 01:20:36 +0000 Subject: [PATCH 18/36] chore(release): Bumped to Version 15.27.0 # [15.27.0](https://github.com/frappe/erpnext/compare/v15.26.1...v15.27.0) (2024-06-05) ### Bug Fixes * Auditor permissions (backport [#41659](https://github.com/frappe/erpnext/issues/41659)) ([#41661](https://github.com/frappe/erpnext/issues/41661)) ([27f3981](https://github.com/frappe/erpnext/commit/27f3981269710ee2d1a6ab0662132b08e01bf2bf)) * bank account no fieldname mismatch (backport [#41778](https://github.com/frappe/erpnext/issues/41778)) ([#41783](https://github.com/frappe/erpnext/issues/41783)) ([b94a6f2](https://github.com/frappe/erpnext/commit/b94a6f2d5cec1432ad29c5728ff90364646ed065)) * batch selection issue (backport [#41692](https://github.com/frappe/erpnext/issues/41692)) ([#41693](https://github.com/frappe/erpnext/issues/41693)) ([24775db](https://github.com/frappe/erpnext/commit/24775db97e3c58ae213d7bd0cdd1f902599ef351)) * **Company:** Allow Equity type account in unrealised exchange gain/loss account (backport [#41740](https://github.com/frappe/erpnext/issues/41740)) ([#41747](https://github.com/frappe/erpnext/issues/41747)) ([460ee5d](https://github.com/frappe/erpnext/commit/460ee5d542d619d5f6c96cf44a65d84bd538cc90)) * condition filter for transaction pricing rule ([e493b11](https://github.com/frappe/erpnext/commit/e493b11ae3cc40a4e03666dba166d45f25f631a7)) * convert percentage from str to float (backport [#41766](https://github.com/frappe/erpnext/issues/41766)) ([#41776](https://github.com/frappe/erpnext/issues/41776)) ([cd0852f](https://github.com/frappe/erpnext/commit/cd0852f05d71a0d10b171bd68258e7d35021702d)) * Copy depreciation schedule on asset split only if it exists (backport [#41775](https://github.com/frappe/erpnext/issues/41775)) ([#41784](https://github.com/frappe/erpnext/issues/41784)) ([03bf480](https://github.com/frappe/erpnext/commit/03bf48032e13af7452ff123c428493b0c1ae95d7)) * filtered out data having none values in date field (backport [#41457](https://github.com/frappe/erpnext/issues/41457)) ([#41765](https://github.com/frappe/erpnext/issues/41765)) ([97b1b7f](https://github.com/frappe/erpnext/commit/97b1b7f8423d9c485c68a1b1cb60da17d8e84dfc)) * Filters in account balance report ([0b9d89b](https://github.com/frappe/erpnext/commit/0b9d89b966cd7fdd78ac3f57ee63ec18cc1c74f2)) * French chart of account the 4191 code must be of type Income Account ([797b718](https://github.com/frappe/erpnext/commit/797b718e5a3e487a1d2c5cb810e5855ea0645c0c)) * get assets received but not billed account only if any asset item is received (backport [#41734](https://github.com/frappe/erpnext/issues/41734)) ([#41735](https://github.com/frappe/erpnext/issues/41735)) ([638c944](https://github.com/frappe/erpnext/commit/638c94451e987dee6a8097f70fa95d32150ed5fe)) * Ignore disabling default currency field while creating new company (backport [#41699](https://github.com/frappe/erpnext/issues/41699)) ([#41761](https://github.com/frappe/erpnext/issues/41761)) ([dc922ab](https://github.com/frappe/erpnext/commit/dc922abfbe30c3087cc2599c11eddf4248c351d5)) * incorrect accumulated depr amount in asset depr ledger (backport [#41654](https://github.com/frappe/erpnext/issues/41654)) ([#41763](https://github.com/frappe/erpnext/issues/41763)) ([a93cd02](https://github.com/frappe/erpnext/commit/a93cd02d546250de6e64903d56e741c5efb69bd9)) * incorrect batch selection while sales return (backport [#41768](https://github.com/frappe/erpnext/issues/41768)) ([#41772](https://github.com/frappe/erpnext/issues/41772)) ([95c0dc9](https://github.com/frappe/erpnext/commit/95c0dc9b388d659abebe80c045af926a139a7f9a)) * key error for stock ledger report (backport [#41700](https://github.com/frappe/erpnext/issues/41700)) ([#41703](https://github.com/frappe/erpnext/issues/41703)) ([b22d714](https://github.com/frappe/erpnext/commit/b22d71410327fb504fc758778d9332ff16cb9dcf)) * link opportunity in prospect after creating opportunity from prospect (backport [#41769](https://github.com/frappe/erpnext/issues/41769)) ([#41777](https://github.com/frappe/erpnext/issues/41777)) ([d30aee5](https://github.com/frappe/erpnext/commit/d30aee5dd618c8ab5b898b49f11e71d0d3176af7)) * local var referenced before assignment (backport [#41780](https://github.com/frappe/erpnext/issues/41780)) ([#41782](https://github.com/frappe/erpnext/issues/41782)) ([3777cae](https://github.com/frappe/erpnext/commit/3777cae8600280a436b8741cb94947dcc6334813)) * **minor:** corrected wrong filter condition (backport [#41755](https://github.com/frappe/erpnext/issues/41755)) ([#41762](https://github.com/frappe/erpnext/issues/41762)) ([a67fa68](https://github.com/frappe/erpnext/commit/a67fa6863ee051465ed81371d330e7ec10ba6737)) * payment term when creating PO from SO (backport [#41376](https://github.com/frappe/erpnext/issues/41376)) ([#41744](https://github.com/frappe/erpnext/issues/41744)) ([806ff5b](https://github.com/frappe/erpnext/commit/806ff5bc19597eb0a408b313c6f52a4064c52d11)) * Select both account number and company in the account form (backport [#41731](https://github.com/frappe/erpnext/issues/41731)) ([#41737](https://github.com/frappe/erpnext/issues/41737)) ([c5d72cd](https://github.com/frappe/erpnext/commit/c5d72cd9345a68868bfa9eefbf7362868d98cb04)) * show material to supplier button (backport [#41686](https://github.com/frappe/erpnext/issues/41686)) ([#41688](https://github.com/frappe/erpnext/issues/41688)) ([1a24914](https://github.com/frappe/erpnext/commit/1a24914aedc7f5ed2caa9416f846679b4d204180)) * **stock settings:** Allowed any number in stock frozen upto days field (backport [#41736](https://github.com/frappe/erpnext/issues/41736)) ([#41749](https://github.com/frappe/erpnext/issues/41749)) ([278682f](https://github.com/frappe/erpnext/commit/278682f4df3176b12e8b45d93b5b54dbd2552da8)) * test for pricing rule transaction with cond ([0823de8](https://github.com/frappe/erpnext/commit/0823de86ad22069901c525173feca6ccbda21b56)) * Transaction currency value in Journal Entry (backport [#41717](https://github.com/frappe/erpnext/issues/41717)) ([#41720](https://github.com/frappe/erpnext/issues/41720)) ([77f58ca](https://github.com/frappe/erpnext/commit/77f58caa934924b5dd94441d84aef5b2144e93a5)) * TypeError: 'float' object is not iterable (backport [#41758](https://github.com/frappe/erpnext/issues/41758)) ([#41764](https://github.com/frappe/erpnext/issues/41764)) ([12addb7](https://github.com/frappe/erpnext/commit/12addb7565459406102e09f9cfb804288777edd2)) * Use full name instead of abbreviation ([#41759](https://github.com/frappe/erpnext/issues/41759)) ([5448d5d](https://github.com/frappe/erpnext/commit/5448d5d1cb2daa454931204da5110990d2e2b516)) * work order created message pops up if no items are selected (backport [#41677](https://github.com/frappe/erpnext/issues/41677)) ([#41682](https://github.com/frappe/erpnext/issues/41682)) ([4e9faf6](https://github.com/frappe/erpnext/commit/4e9faf6ad6beca3ac38b95af28c192bf5e612f34)) ### Features * optional to reconcile all serial nos / batches in stock reconciliation (backport [#41696](https://github.com/frappe/erpnext/issues/41696)) ([#41713](https://github.com/frappe/erpnext/issues/41713)) ([38249f4](https://github.com/frappe/erpnext/commit/38249f41708a5c955192c817d380eec38419d144)) --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 9d6a51bb102..fca29051bb5 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -3,7 +3,7 @@ import inspect import frappe -__version__ = "15.26.1" +__version__ = "15.27.0" def get_default_company(user=None): From edd4e674d32a9728b4bda3248b6b618613605643 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Thu, 6 Jun 2024 17:22:27 +0530 Subject: [PATCH 19/36] fix: Add posting date to key for consolidated view (cherry picked from commit 2c164b47a13bc458b10df95f0aa3f2425bef1bfb) (cherry picked from commit 94720851c6b819f3466dbae45a566f2d1830e2e3) --- erpnext/accounts/report/general_ledger/general_ledger.py | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/accounts/report/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py index 2946cfa0e82..44fad110baa 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.py +++ b/erpnext/accounts/report/general_ledger/general_ledger.py @@ -482,6 +482,7 @@ def get_accountwise_gle(filters, accounting_dimensions, gl_entries, gle_map): elif group_by_voucher_consolidated: keylist = [ + gle.get("posting_date"), gle.get("voucher_type"), gle.get("voucher_no"), gle.get("account"), From df4307fef8a9bdfb893100d98dee65d949ef8643 Mon Sep 17 00:00:00 2001 From: Frappe PR Bot Date: Thu, 6 Jun 2024 12:20:49 +0000 Subject: [PATCH 20/36] chore(release): Bumped to Version 15.27.1 ## [15.27.1](https://github.com/frappe/erpnext/compare/v15.27.0...v15.27.1) (2024-06-06) ### Bug Fixes * Add posting date to key for consolidated view ([edd4e67](https://github.com/frappe/erpnext/commit/edd4e674d32a9728b4bda3248b6b618613605643)) --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index fca29051bb5..22be77c9b4a 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -3,7 +3,7 @@ import inspect import frappe -__version__ = "15.27.0" +__version__ = "15.27.1" def get_default_company(user=None): From 9a629f860c6acd0d51aaf39e9fc0cfe1c0f27d98 Mon Sep 17 00:00:00 2001 From: Poorvi Date: Fri, 10 May 2024 11:47:57 +0530 Subject: [PATCH 21/36] fix: fixing Item-wise sales register (cherry picked from commit c90185f5331e2271afb5ddc22340d3704f5bbcd3) (cherry picked from commit f36db7ebaf0c1e3c0de716f2733961be4f5b632e) --- .../accounts/report/purchase_register/purchase_register.py | 6 ++++-- erpnext/accounts/report/sales_register/sales_register.py | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/report/purchase_register/purchase_register.py b/erpnext/accounts/report/purchase_register/purchase_register.py index 504c74babcb..7631506f506 100644 --- a/erpnext/accounts/report/purchase_register/purchase_register.py +++ b/erpnext/accounts/report/purchase_register/purchase_register.py @@ -376,8 +376,10 @@ def get_account_columns(invoice_list, include_payments): def get_invoices(filters, additional_query_columns): pi = frappe.qb.DocType("Purchase Invoice") + pii = frappe.qb.DocType("Purchase Invoice Item") query = ( frappe.qb.from_(pi) + .left_join(pii).on(pi.name == pii.parent) .select( ConstantColumn("Purchase Invoice").as_("doctype"), pi.name, @@ -386,7 +388,7 @@ def get_invoices(filters, additional_query_columns): pi.supplier, pi.supplier_name, pi.tax_id, - pi.bill_no, + pi.bill_no, pi.bill_date, pi.remarks, pi.base_net_total, @@ -395,7 +397,7 @@ def get_invoices(filters, additional_query_columns): pi.outstanding_amount, pi.mode_of_payment, ) - .where(pi.docstatus == 1) + .where((pi.docstatus == 1) & pii.item_code.isnotnull()) .orderby(pi.posting_date, pi.name, order=Order.desc) ) diff --git a/erpnext/accounts/report/sales_register/sales_register.py b/erpnext/accounts/report/sales_register/sales_register.py index f27569531b1..832845ffe2e 100644 --- a/erpnext/accounts/report/sales_register/sales_register.py +++ b/erpnext/accounts/report/sales_register/sales_register.py @@ -414,9 +414,11 @@ def get_account_columns(invoice_list, include_payments): def get_invoices(filters, additional_query_columns): si = frappe.qb.DocType("Sales Invoice") + sii = frappe.qb.DocType("Sales Invoice Item") query = ( frappe.qb.from_(si) - .select( + .left_join(sii).on(si.name == sii.parent) + .select( ConstantColumn("Sales Invoice").as_("doctype"), si.name, si.posting_date, @@ -437,7 +439,7 @@ def get_invoices(filters, additional_query_columns): si.represents_company, si.company, ) - .where(si.docstatus == 1) + .where((si.docstatus == 1) & sii.item_code.isnotnull()) .orderby(si.posting_date, si.name, order=Order.desc) ) From 3e0123ba7bf54bd94fd7693ed33b8e94a7625be8 Mon Sep 17 00:00:00 2001 From: Poorvi-R-Bhat Date: Mon, 13 May 2024 09:35:10 +0530 Subject: [PATCH 22/36] fix: Item-wise Sales and Purchase register with no item codes #41373 (cherry picked from commit 1b45ecfcae5ed9587c5d03e14afaf6d39d3fa84f) # Conflicts: # erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py # erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py (cherry picked from commit 96405e8e4957c672b7a4aa5f7e9ead081a6e143d) --- .../item_wise_purchase_register.py | 36 +++++++++++++++- .../item_wise_sales_register.py | 43 +++++++++++++++++++ .../purchase_register/purchase_register.py | 4 +- .../report/sales_register/sales_register.py | 6 +-- 4 files changed, 81 insertions(+), 8 deletions(-) diff --git a/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py b/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py index ebdea0602d1..02fb873c572 100644 --- a/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py +++ b/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py @@ -311,8 +311,8 @@ def get_conditions(filters): return conditions - def get_items(filters, additional_query_columns): +<<<<<<< HEAD conditions = get_conditions(filters) if additional_query_columns: additional_query_columns = "," + ",".join(additional_query_columns) @@ -339,6 +339,40 @@ def get_items(filters, additional_query_columns): filters, as_dict=1, ) +======= + pi = frappe.qb.DocType('Purchase Invoice') + pii = frappe.qb.DocType('Purchase Invoice Item') + Item = frappe.qb.DocType('Item') + query = (frappe.qb.from_(pi) + .join(pii).on(pi.name == pii.parent) + .left_join(Item).on(pii.item_code == Item.name) + .select( + pii.name.as_('pii_name'), pii.parent, + pi.posting_date, pi.credit_to, pi.company, + pi.supplier, pi.remarks, pi.base_net_total, + pi.unrealized_profit_loss_account, + pii.item_code, pii.description, pii.item_group, + pii.item_name.as_('pi_item_name'), pii.item_group.as_('pi_item_group'), + Item.item_name.as_('i_item_name'), Item.item_group.as_('i_item_group'), + pii.project, pii.purchase_order, + pii.purchase_receipt, pii.po_detail, + pii.expense_account, pii.stock_qty, + pii.stock_uom, pii.base_net_amount, + pi.supplier_name, pi.mode_of_payment + ) + .where(pi.docstatus == 1)) + + if additional_query_columns: + query = query.select(*additional_query_columns) + + if filters.get("supplier"): + query = query.where(pi.supplier == filters['supplier']) + if filters.get("company"): + query = query.where(pi.company == filters['company']) + + return query.run(as_dict=True) + +>>>>>>> 1b45ecfcae (fix: Item-wise Sales and Purchase register with no item codes #41373) def get_aii_accounts(): diff --git a/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py b/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py index c7819731930..fd538b7bfa6 100644 --- a/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py +++ b/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py @@ -388,6 +388,7 @@ def get_group_by_conditions(filters, doctype): return "ORDER BY `tab{}`.{}".format(doctype, frappe.scrub(filters.get("group_by"))) +<<<<<<< HEAD def get_items(filters, additional_query_columns, additional_conditions=None): conditions = get_conditions(filters, additional_conditions) if additional_query_columns: @@ -420,6 +421,48 @@ def get_items(filters, additional_query_columns, additional_conditions=None): filters, as_dict=1, ) # nosec +======= +def get_items(filters, additional_query_columns,additional_conditions=None): + si = frappe.qb.DocType('Sales Invoice') + sii = frappe.qb.DocType('Sales Invoice Item') + Item = frappe.qb.DocType('Item') + + query = ( + frappe.qb.from_(si) + .join(sii).on(si.name == sii.parent) + .left_join(Item).on(sii.item_code == Item.name) + .select( + sii.name, sii.parent, + si.posting_date, si.debit_to, + si.unrealized_profit_loss_account, + si.is_internal_customer, + si.customer, si.remarks, + si.territory, si.company, si.base_net_total, + sii.project, + sii.item_code, sii.description, + sii.item_name, sii.item_group, + sii.item_name.as_('si_item_name'), sii.item_group.as_('si_item_group'), + Item.item_name.as_('i_item_name'), Item.item_group.as_('i_item_group'), + sii.sales_order, sii.delivery_note, + sii.income_account, sii.cost_center, + sii.enable_deferred_revenue, sii.deferred_revenue_account, + sii.stock_qty, sii.stock_uom, + sii.base_net_rate, sii.base_net_amount, + si.customer_name, si.customer_group, sii.so_detail, + si.update_stock, sii.uom, sii.qty + ) + .where(si.docstatus == 1) + ) + if filters.get("customer"): + query = query.where(si.customer == filters['customer']) + + if filters.get("customer_group"): + query = query.where(si.customer_group == filters['customer_group']) + + return query.run(as_dict=True) + + +>>>>>>> 1b45ecfcae (fix: Item-wise Sales and Purchase register with no item codes #41373) def get_delivery_notes_against_sales_order(item_list): diff --git a/erpnext/accounts/report/purchase_register/purchase_register.py b/erpnext/accounts/report/purchase_register/purchase_register.py index 7631506f506..25caa9e03fb 100644 --- a/erpnext/accounts/report/purchase_register/purchase_register.py +++ b/erpnext/accounts/report/purchase_register/purchase_register.py @@ -376,10 +376,8 @@ def get_account_columns(invoice_list, include_payments): def get_invoices(filters, additional_query_columns): pi = frappe.qb.DocType("Purchase Invoice") - pii = frappe.qb.DocType("Purchase Invoice Item") query = ( frappe.qb.from_(pi) - .left_join(pii).on(pi.name == pii.parent) .select( ConstantColumn("Purchase Invoice").as_("doctype"), pi.name, @@ -397,7 +395,7 @@ def get_invoices(filters, additional_query_columns): pi.outstanding_amount, pi.mode_of_payment, ) - .where((pi.docstatus == 1) & pii.item_code.isnotnull()) + .where((pi.docstatus == 1)) .orderby(pi.posting_date, pi.name, order=Order.desc) ) diff --git a/erpnext/accounts/report/sales_register/sales_register.py b/erpnext/accounts/report/sales_register/sales_register.py index 832845ffe2e..dc557433f7d 100644 --- a/erpnext/accounts/report/sales_register/sales_register.py +++ b/erpnext/accounts/report/sales_register/sales_register.py @@ -414,11 +414,9 @@ def get_account_columns(invoice_list, include_payments): def get_invoices(filters, additional_query_columns): si = frappe.qb.DocType("Sales Invoice") - sii = frappe.qb.DocType("Sales Invoice Item") query = ( frappe.qb.from_(si) - .left_join(sii).on(si.name == sii.parent) - .select( + .select( ConstantColumn("Sales Invoice").as_("doctype"), si.name, si.posting_date, @@ -439,7 +437,7 @@ def get_invoices(filters, additional_query_columns): si.represents_company, si.company, ) - .where((si.docstatus == 1) & sii.item_code.isnotnull()) + .where((si.docstatus == 1)) .orderby(si.posting_date, si.name, order=Order.desc) ) From 50ef81a997425d35208c25ccfa0137c2f9be34ec Mon Sep 17 00:00:00 2001 From: Poorvi-R-Bhat Date: Wed, 22 May 2024 12:26:02 +0530 Subject: [PATCH 23/36] fix: fixing Item-wise sales register and purchase register #41373 (cherry picked from commit 76073ae228d9f3ebe67eae562e2e48bd54ace252) # Conflicts: # erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py (cherry picked from commit a4b28ba354873a8bb5253a5902970fc780aa9441) --- .../item_wise_purchase_register.py | 62 ++++++++++++++++--- 1 file changed, 54 insertions(+), 8 deletions(-) diff --git a/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py b/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py index 02fb873c572..bc2f24b8076 100644 --- a/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py +++ b/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py @@ -311,7 +311,9 @@ def get_conditions(filters): return conditions + def get_items(filters, additional_query_columns): +<<<<<<< HEAD <<<<<<< HEAD conditions = get_conditions(filters) if additional_query_columns: @@ -361,18 +363,62 @@ def get_items(filters, additional_query_columns): pi.supplier_name, pi.mode_of_payment ) .where(pi.docstatus == 1)) +======= + pi = frappe.qb.DocType("Purchase Invoice") + pii = frappe.qb.DocType("Purchase Invoice Item") + Item = frappe.qb.DocType("Item") + query = ( + frappe.qb.from_(pi) + .join(pii) + .on(pi.name == pii.parent) + # added left join + .left_join(Item) + .on(pii.item_code == Item.name) + .select( + pii.name.as_("pii_name"), + pii.parent, + pi.posting_date, + pi.credit_to, + pi.company, + pi.supplier, + pi.remarks, + pi.base_net_total, + pi.unrealized_profit_loss_account, + pii.item_code, + pii.description, + pii.item_group, + pii.item_name.as_("pi_item_name"), + pii.item_group.as_("pi_item_group"), + Item.item_name.as_("i_item_name"), + Item.item_group.as_("i_item_group"), + pii.project, + pii.purchase_order, + pii.purchase_receipt, + pii.po_detail, + pii.expense_account, + pii.stock_qty, + pii.stock_uom, + pii.base_net_amount, + pi.supplier_name, + pi.mode_of_payment, + ) + .where(pi.docstatus == 1) + ) +>>>>>>> 76073ae228 (fix: fixing Item-wise sales register and purchase register #41373) - if additional_query_columns: - query = query.select(*additional_query_columns) + if additional_query_columns: + query = query.select(*additional_query_columns) - if filters.get("supplier"): - query = query.where(pi.supplier == filters['supplier']) - if filters.get("company"): - query = query.where(pi.company == filters['company']) - - return query.run(as_dict=True) + if filters.get("supplier"): + query = query.where(pi.supplier == filters["supplier"]) + if filters.get("company"): + query = query.where(pi.company == filters["company"]) +<<<<<<< HEAD >>>>>>> 1b45ecfcae (fix: Item-wise Sales and Purchase register with no item codes #41373) +======= + return query.run(as_dict=True) +>>>>>>> 76073ae228 (fix: fixing Item-wise sales register and purchase register #41373) def get_aii_accounts(): From d75d64eb258c3d398e721cea9d7fc5e6725694e4 Mon Sep 17 00:00:00 2001 From: Poorvi-R-Bhat Date: Wed, 22 May 2024 12:39:22 +0530 Subject: [PATCH 24/36] fix: fixing Item-wise sales register #41373 (cherry picked from commit eafa88b8e9da824d89e5673504c0de3422b54b6b) # Conflicts: # erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py (cherry picked from commit 5e0fa1b75ec1437516aa190550ccf8fbfab67a6e) --- .../item_wise_purchase_register.py | 1 - .../item_wise_sales_register.py | 66 +++++++++++++++++-- .../purchase_register/purchase_register.py | 6 +- .../report/sales_register/sales_register.py | 4 +- 4 files changed, 67 insertions(+), 10 deletions(-) diff --git a/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py b/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py index bc2f24b8076..086026efb53 100644 --- a/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py +++ b/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py @@ -371,7 +371,6 @@ def get_items(filters, additional_query_columns): frappe.qb.from_(pi) .join(pii) .on(pi.name == pii.parent) - # added left join .left_join(Item) .on(pii.item_code == Item.name) .select( diff --git a/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py b/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py index fd538b7bfa6..102d9d6a0af 100644 --- a/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py +++ b/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py @@ -388,6 +388,7 @@ def get_group_by_conditions(filters, doctype): return "ORDER BY `tab{}`.{}".format(doctype, frappe.scrub(filters.get("group_by"))) +<<<<<<< HEAD <<<<<<< HEAD def get_items(filters, additional_query_columns, additional_conditions=None): conditions = get_conditions(filters, additional_conditions) @@ -455,14 +456,71 @@ def get_items(filters, additional_query_columns,additional_conditions=None): ) if filters.get("customer"): query = query.where(si.customer == filters['customer']) +======= +def get_items(filters, additional_query_columns, additional_conditions=None): + si = frappe.qb.DocType("Sales Invoice") + sii = frappe.qb.DocType("Sales Invoice Item") + Item = frappe.qb.DocType("Item") +>>>>>>> eafa88b8e9 (fix: fixing Item-wise sales register #41373) - if filters.get("customer_group"): - query = query.where(si.customer_group == filters['customer_group']) - - return query.run(as_dict=True) + query = ( + frappe.qb.from_(si) + .join(sii) + .on(si.name == sii.parent) + # added left join + .left_join(Item) + .on(sii.item_code == Item.name) + .select( + sii.name, + sii.parent, + si.posting_date, + si.debit_to, + si.unrealized_profit_loss_account, + si.is_internal_customer, + si.customer, + si.remarks, + si.territory, + si.company, + si.base_net_total, + sii.project, + sii.item_code, + sii.description, + sii.item_name, + sii.item_group, + sii.item_name.as_("si_item_name"), + sii.item_group.as_("si_item_group"), + Item.item_name.as_("i_item_name"), + Item.item_group.as_("i_item_group"), + sii.sales_order, + sii.delivery_note, + sii.income_account, + sii.cost_center, + sii.enable_deferred_revenue, + sii.deferred_revenue_account, + sii.stock_qty, + sii.stock_uom, + sii.base_net_rate, + sii.base_net_amount, + si.customer_name, + si.customer_group, + sii.so_detail, + si.update_stock, + sii.uom, + sii.qty, + ) + .where(si.docstatus == 1) + ) + if filters.get("customer"): + query = query.where(si.customer == filters["customer"]) + if filters.get("customer_group"): + query = query.where(si.customer_group == filters["customer_group"]) +<<<<<<< HEAD >>>>>>> 1b45ecfcae (fix: Item-wise Sales and Purchase register with no item codes #41373) +======= + return query.run(as_dict=True) +>>>>>>> eafa88b8e9 (fix: fixing Item-wise sales register #41373) def get_delivery_notes_against_sales_order(item_list): diff --git a/erpnext/accounts/report/purchase_register/purchase_register.py b/erpnext/accounts/report/purchase_register/purchase_register.py index 25caa9e03fb..1e24d96115d 100644 --- a/erpnext/accounts/report/purchase_register/purchase_register.py +++ b/erpnext/accounts/report/purchase_register/purchase_register.py @@ -377,7 +377,7 @@ def get_account_columns(invoice_list, include_payments): def get_invoices(filters, additional_query_columns): pi = frappe.qb.DocType("Purchase Invoice") query = ( - frappe.qb.from_(pi) + frappe.qb.from_(pi) # qb .select( ConstantColumn("Purchase Invoice").as_("doctype"), pi.name, @@ -386,7 +386,7 @@ def get_invoices(filters, additional_query_columns): pi.supplier, pi.supplier_name, pi.tax_id, - pi.bill_no, + pi.bill_no, pi.bill_date, pi.remarks, pi.base_net_total, @@ -395,7 +395,7 @@ def get_invoices(filters, additional_query_columns): pi.outstanding_amount, pi.mode_of_payment, ) - .where((pi.docstatus == 1)) + .where(pi.docstatus == 1) .orderby(pi.posting_date, pi.name, order=Order.desc) ) diff --git a/erpnext/accounts/report/sales_register/sales_register.py b/erpnext/accounts/report/sales_register/sales_register.py index dc557433f7d..f8b94d353f9 100644 --- a/erpnext/accounts/report/sales_register/sales_register.py +++ b/erpnext/accounts/report/sales_register/sales_register.py @@ -415,7 +415,7 @@ def get_account_columns(invoice_list, include_payments): def get_invoices(filters, additional_query_columns): si = frappe.qb.DocType("Sales Invoice") query = ( - frappe.qb.from_(si) + frappe.qb.from_(si) # qb .select( ConstantColumn("Sales Invoice").as_("doctype"), si.name, @@ -437,7 +437,7 @@ def get_invoices(filters, additional_query_columns): si.represents_company, si.company, ) - .where((si.docstatus == 1)) + .where(si.docstatus == 1) .orderby(si.posting_date, si.name, order=Order.desc) ) From 7ca848c2db77615f867c161450c613ee02004aab Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Sun, 2 Jun 2024 20:17:24 +0530 Subject: [PATCH 25/36] chore: update condition queries in qb (cherry picked from commit d2af36e1eb2ba395b3bf35f933f40b6906852fa0) # Conflicts: # erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py # erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py (cherry picked from commit 209af58f8318c58c3e8bad840aedd21ba8fa0c3c) --- .../item_wise_purchase_register.py | 42 +++--- .../item_wise_sales_register.js | 6 + .../item_wise_sales_register.py | 126 ++++++++++-------- .../purchase_register/purchase_register.py | 2 +- .../report/sales_register/sales_register.py | 2 +- 5 files changed, 105 insertions(+), 73 deletions(-) diff --git a/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py b/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py index 086026efb53..dc4999a3b4e 100644 --- a/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py +++ b/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py @@ -5,14 +5,15 @@ import frappe from frappe import _ from frappe.utils import flt +from pypika import Order import erpnext from erpnext.accounts.report.item_wise_sales_register.item_wise_sales_register import ( add_sub_total_row, add_total_row, + apply_group_by_conditions, get_grand_total, get_group_by_and_display_fields, - get_group_by_conditions, get_tax_accounts, ) from erpnext.accounts.report.utils import get_query_columns, get_values_for_columns @@ -287,29 +288,27 @@ def get_columns(additional_table_columns, filters): return columns -def get_conditions(filters): - conditions = "" +def apply_conditions(query, pi, pii, filters): + for opts in ("company", "supplier", "item_code", "mode_of_payment"): + if filters.get(opts): + query = query.where(pi[opts] == filters[opts]) - for opts in ( - ("company", " and `tabPurchase Invoice`.company=%(company)s"), - ("supplier", " and `tabPurchase Invoice`.supplier = %(supplier)s"), - ("item_code", " and `tabPurchase Invoice Item`.item_code = %(item_code)s"), - ("from_date", " and `tabPurchase Invoice`.posting_date>=%(from_date)s"), - ("to_date", " and `tabPurchase Invoice`.posting_date<=%(to_date)s"), - ("mode_of_payment", " and ifnull(mode_of_payment, '') = %(mode_of_payment)s"), - ("item_group", " and ifnull(`tabPurchase Invoice Item`.item_group, '') = %(item_group)s"), - ): - if filters.get(opts[0]): - conditions += opts[1] + if filters.get("from_date"): + query = query.where(pi.posting_date >= filters.get("from_date")) + + if filters.get("to_date"): + query = query.where(pi.posting_date <= filters.get("to_date")) + + if filters.get("item_group"): + query = query.where(pii.item_group == filters.get("item_group")) if not filters.get("group_by"): - conditions += ( - "ORDER BY `tabPurchase Invoice`.posting_date desc, `tabPurchase Invoice Item`.item_code desc" - ) + query = query.orderby(pi.posting_date, order=Order.desc) + query = query.orderby(pii.item_group, order=Order.desc) else: - conditions += get_group_by_conditions(filters, "Purchase Invoice") + query = apply_group_by_conditions(filters, "Purchase Invoice") - return conditions + return query def get_items(filters, additional_query_columns): @@ -413,9 +412,14 @@ def get_items(filters, additional_query_columns): if filters.get("company"): query = query.where(pi.company == filters["company"]) +<<<<<<< HEAD <<<<<<< HEAD >>>>>>> 1b45ecfcae (fix: Item-wise Sales and Purchase register with no item codes #41373) ======= +======= + query = apply_conditions(query, pi, pii, filters) + +>>>>>>> d2af36e1eb (chore: update condition queries in qb) return query.run(as_dict=True) >>>>>>> 76073ae228 (fix: fixing Item-wise sales register and purchase register #41373) diff --git a/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.js b/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.js index 7ed2ebd89ab..1f155de63a0 100644 --- a/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.js +++ b/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.js @@ -41,6 +41,12 @@ frappe.query_reports["Item-wise Sales Register"] = { label: __("Warehouse"), fieldtype: "Link", options: "Warehouse", + get_query: function () { + const company = frappe.query_report.get_filter_value("company"); + return { + filters: { company: company }, + }; + }, }, { fieldname: "brand", diff --git a/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py b/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py index 102d9d6a0af..192cbc0e0cc 100644 --- a/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py +++ b/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py @@ -7,6 +7,7 @@ from frappe import _ from frappe.model.meta import get_field_precision from frappe.utils import cstr, flt from frappe.utils.xlsxutils import handle_html +from pypika import Order from erpnext.accounts.report.sales_register.sales_register import get_mode_of_payments from erpnext.accounts.report.utils import get_query_columns, get_values_for_columns @@ -333,59 +334,69 @@ def get_columns(additional_table_columns, filters): return columns -def get_conditions(filters, additional_conditions=None): - conditions = "" +def apply_conditions(query, si, sii, filters, additional_conditions=None): + for opts in ("company", "customer", "item_code"): + if filters.get(opts): + query = query.where(si[opts] == filters[opts]) - for opts in ( - ("company", " and `tabSales Invoice`.company=%(company)s"), - ("customer", " and `tabSales Invoice`.customer = %(customer)s"), - ("item_code", " and `tabSales Invoice Item`.item_code = %(item_code)s"), - ("from_date", " and `tabSales Invoice`.posting_date>=%(from_date)s"), - ("to_date", " and `tabSales Invoice`.posting_date<=%(to_date)s"), - ): - if filters.get(opts[0]): - conditions += opts[1] + if filters.get("from_date"): + query = query.where(si.posting_date >= filters.get("from_date")) - if additional_conditions: - conditions += additional_conditions + if filters.get("to_date"): + query = query.where(si.posting_date <= filters.get("to_date")) if filters.get("mode_of_payment"): - conditions += """ and exists(select name from `tabSales Invoice Payment` - where parent=`tabSales Invoice`.name - and ifnull(`tabSales Invoice Payment`.mode_of_payment, '') = %(mode_of_payment)s)""" + sales_invoice = frappe.db.get_all( + "Sales Invoice Payment", {"mode_of_payment": filters.get("mode_of_payment")}, pluck="parent" + ) + query = query.where(si.name.isin(sales_invoice)) if filters.get("warehouse"): if frappe.db.get_value("Warehouse", filters.get("warehouse"), "is_group"): lft, rgt = frappe.db.get_all( "Warehouse", filters={"name": filters.get("warehouse")}, fields=["lft", "rgt"], as_list=True )[0] - conditions += f"and ifnull(`tabSales Invoice Item`.warehouse, '') in (select name from `tabWarehouse` where lft > {lft} and rgt < {rgt}) " + warehouses = frappe.db.get_all("Warehouse", {"lft": (">", lft), "rgt": ("<", rgt)}, pluck="name") + query = query.where(sii.warehouse.isin(warehouses)) else: - conditions += """and ifnull(`tabSales Invoice Item`.warehouse, '') = %(warehouse)s""" + query = query.where(sii.warehouse == filters.get("warehouse")) if filters.get("brand"): - conditions += """and ifnull(`tabSales Invoice Item`.brand, '') = %(brand)s""" + query = query.where(sii.brand == filters.get("brand")) if filters.get("item_group"): - conditions += """and ifnull(`tabSales Invoice Item`.item_group, '') = %(item_group)s""" + query = query.where(sii.item_group == filters.get("item_group")) +<<<<<<< HEAD +======= + if filters.get("income_account"): + query = query.where( + (sii.income_account == filters.get("income_account")) + | (sii.deferred_revenue_account == filters.get("income_account")) + | (si.unrealized_profit_loss_account == filters.get("income_account")) + ) + +>>>>>>> d2af36e1eb (chore: update condition queries in qb) if not filters.get("group_by"): - conditions += "ORDER BY `tabSales Invoice`.posting_date desc, `tabSales Invoice Item`.item_group desc" + query = query.orderby(si.posting_date, order=Order.desc) + query = query.orderby(sii.item_group, order=Order.desc) else: - conditions += get_group_by_conditions(filters, "Sales Invoice") + query = apply_group_by_conditions(query, si, sii, filters) - return conditions + return query -def get_group_by_conditions(filters, doctype): +def apply_group_by_conditions(query, si, ii, filters): if filters.get("group_by") == "Invoice": - return f"ORDER BY `tab{doctype} Item`.parent desc" + query = query.orderby(ii.parent, order=Order.desc) elif filters.get("group_by") == "Item": - return f"ORDER BY `tab{doctype} Item`.`item_code`" + query = query.orderby(ii.item_code) elif filters.get("group_by") == "Item Group": - return "ORDER BY `tab{} Item`.{}".format(doctype, frappe.scrub(filters.get("group_by"))) + query = query.orderby(ii.item_group) elif filters.get("group_by") in ("Customer", "Customer Group", "Territory", "Supplier"): - return "ORDER BY `tab{}`.{}".format(doctype, frappe.scrub(filters.get("group_by"))) + query = query.orderby(si[frappe.scrub(filters.get("group_by"))]) + + return query <<<<<<< HEAD @@ -460,16 +471,19 @@ def get_items(filters, additional_query_columns,additional_conditions=None): def get_items(filters, additional_query_columns, additional_conditions=None): si = frappe.qb.DocType("Sales Invoice") sii = frappe.qb.DocType("Sales Invoice Item") +<<<<<<< HEAD Item = frappe.qb.DocType("Item") >>>>>>> eafa88b8e9 (fix: fixing Item-wise sales register #41373) +======= + item = frappe.qb.DocType("Item") +>>>>>>> d2af36e1eb (chore: update condition queries in qb) query = ( frappe.qb.from_(si) .join(sii) .on(si.name == sii.parent) - # added left join - .left_join(Item) - .on(sii.item_code == Item.name) + .left_join(item) + .on(sii.item_code == item.name) .select( sii.name, sii.parent, @@ -489,8 +503,8 @@ def get_items(filters, additional_query_columns, additional_conditions=None): sii.item_group, sii.item_name.as_("si_item_name"), sii.item_group.as_("si_item_group"), - Item.item_name.as_("i_item_name"), - Item.item_group.as_("i_item_group"), + item.item_name.as_("i_item_name"), + item.item_group.as_("i_item_group"), sii.sales_order, sii.delivery_note, sii.income_account, @@ -510,15 +524,24 @@ def get_items(filters, additional_query_columns, additional_conditions=None): ) .where(si.docstatus == 1) ) + + if additional_query_columns: + query = query.select(*additional_query_columns) + if filters.get("customer"): query = query.where(si.customer == filters["customer"]) if filters.get("customer_group"): query = query.where(si.customer_group == filters["customer_group"]) +<<<<<<< HEAD <<<<<<< HEAD >>>>>>> 1b45ecfcae (fix: Item-wise Sales and Purchase register with no item codes #41373) ======= +======= + query = apply_conditions(query, si, sii, filters, additional_conditions) + +>>>>>>> d2af36e1eb (chore: update condition queries in qb) return query.run(as_dict=True) >>>>>>> eafa88b8e9 (fix: fixing Item-wise sales register #41373) @@ -528,16 +551,14 @@ def get_delivery_notes_against_sales_order(item_list): so_item_rows = list(set([d.so_detail for d in item_list])) if so_item_rows: - delivery_notes = frappe.db.sql( - """ - select parent, so_detail - from `tabDelivery Note Item` - where docstatus=1 and so_detail in (%s) - group by so_detail, parent - """ - % (", ".join(["%s"] * len(so_item_rows))), - tuple(so_item_rows), - as_dict=1, + dn_item = frappe.qb.DocType("Delivery Note Item") + delivery_notes = ( + frappe.qb.from_(dn_item) + .select(dn_item.parent, dn_item.so_detail) + .where(dn_item.docstatus == 1) + .where(dn_item.so_detail.isin(so_item_rows)) + .groupby(dn_item.so_detail, dn_item.parent) + .run(as_dict=True) ) for dn in delivery_notes: @@ -547,15 +568,16 @@ def get_delivery_notes_against_sales_order(item_list): def get_grand_total(filters, doctype): - return frappe.db.sql( - f""" SELECT - SUM(`tab{doctype}`.base_grand_total) - FROM `tab{doctype}` - WHERE `tab{doctype}`.docstatus = 1 - and posting_date between %s and %s - """, - (filters.get("from_date"), filters.get("to_date")), - )[0][0] # nosec + return flt( + frappe.db.get_value( + doctype, + { + "docstatus": 1, + "posting_date": ("between", [filters.get("from_date"), filters.get("to_date")]), + }, + "sum(base_grand_total)", + ) + ) def get_tax_accounts( diff --git a/erpnext/accounts/report/purchase_register/purchase_register.py b/erpnext/accounts/report/purchase_register/purchase_register.py index 1e24d96115d..504c74babcb 100644 --- a/erpnext/accounts/report/purchase_register/purchase_register.py +++ b/erpnext/accounts/report/purchase_register/purchase_register.py @@ -377,7 +377,7 @@ def get_account_columns(invoice_list, include_payments): def get_invoices(filters, additional_query_columns): pi = frappe.qb.DocType("Purchase Invoice") query = ( - frappe.qb.from_(pi) # qb + frappe.qb.from_(pi) .select( ConstantColumn("Purchase Invoice").as_("doctype"), pi.name, diff --git a/erpnext/accounts/report/sales_register/sales_register.py b/erpnext/accounts/report/sales_register/sales_register.py index f8b94d353f9..f27569531b1 100644 --- a/erpnext/accounts/report/sales_register/sales_register.py +++ b/erpnext/accounts/report/sales_register/sales_register.py @@ -415,7 +415,7 @@ def get_account_columns(invoice_list, include_payments): def get_invoices(filters, additional_query_columns): si = frappe.qb.DocType("Sales Invoice") query = ( - frappe.qb.from_(si) # qb + frappe.qb.from_(si) .select( ConstantColumn("Sales Invoice").as_("doctype"), si.name, From 45c16f615c6c94c69f4c633cc4a5faef333e1b2c Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Fri, 7 Jun 2024 18:48:16 +0530 Subject: [PATCH 26/36] fix: Add additional condition application (cherry picked from commit 8ec364df6fe07817fd6c69c6e9db31af08d1a455) # Conflicts: # erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py (cherry picked from commit 1fca6ea5e70da34cdce637bf2a4b1beb94bc3507) --- .../item_wise_purchase_register.py | 20 +++++++++++++++---- .../item_wise_sales_register.py | 12 +++++++++-- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py b/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py index dc4999a3b4e..bafd83db37a 100644 --- a/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py +++ b/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py @@ -30,7 +30,7 @@ def _execute(filters=None, additional_table_columns=None): company_currency = erpnext.get_company_currency(filters.company) - item_list = get_items(filters, get_query_columns(additional_table_columns)) + item_list = get_items(filters, additional_table_columns) aii_account_map = get_aii_accounts() if item_list: itemised_tax, tax_columns = get_tax_accounts( @@ -311,6 +311,7 @@ def apply_conditions(query, pi, pii, filters): return query +<<<<<<< HEAD def get_items(filters, additional_query_columns): <<<<<<< HEAD <<<<<<< HEAD @@ -363,6 +364,9 @@ def get_items(filters, additional_query_columns): ) .where(pi.docstatus == 1)) ======= +======= +def get_items(filters, additional_table_columns): +>>>>>>> 8ec364df6f (fix: Add additional condition application) pi = frappe.qb.DocType("Purchase Invoice") pii = frappe.qb.DocType("Purchase Invoice Item") Item = frappe.qb.DocType("Item") @@ -404,19 +408,27 @@ def get_items(filters, additional_query_columns): ) >>>>>>> 76073ae228 (fix: fixing Item-wise sales register and purchase register #41373) - if additional_query_columns: - query = query.select(*additional_query_columns) - if filters.get("supplier"): query = query.where(pi.supplier == filters["supplier"]) if filters.get("company"): query = query.where(pi.company == filters["company"]) +<<<<<<< HEAD <<<<<<< HEAD <<<<<<< HEAD >>>>>>> 1b45ecfcae (fix: Item-wise Sales and Purchase register with no item codes #41373) ======= ======= +======= + if additional_table_columns: + for column in additional_table_columns: + if column.get("_doctype"): + table = frappe.qb.DocType(column.get("_doctype")) + query = query.select(table[column.get("fieldname")]) + else: + query = query.select(pi[column.get("fieldname")]) + +>>>>>>> 8ec364df6f (fix: Add additional condition application) query = apply_conditions(query, pi, pii, filters) >>>>>>> d2af36e1eb (chore: update condition queries in qb) diff --git a/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py b/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py index 192cbc0e0cc..5a989a929ab 100644 --- a/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py +++ b/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py @@ -27,7 +27,7 @@ def _execute(filters=None, additional_table_columns=None, additional_conditions= company_currency = frappe.get_cached_value("Company", filters.get("company"), "default_currency") - item_list = get_items(filters, get_query_columns(additional_table_columns), additional_conditions) + item_list = get_items(filters, additional_table_columns, additional_conditions) if item_list: itemised_tax, tax_columns = get_tax_accounts(item_list, columns, company_currency) @@ -383,6 +383,9 @@ def apply_conditions(query, si, sii, filters, additional_conditions=None): else: query = apply_group_by_conditions(query, si, sii, filters) + for key, value in (additional_conditions or {}).items(): + query = query.where(si[key] == value) + return query @@ -526,7 +529,12 @@ def get_items(filters, additional_query_columns, additional_conditions=None): ) if additional_query_columns: - query = query.select(*additional_query_columns) + for column in additional_query_columns: + if column.get("_doctype"): + table = frappe.qb.DocType(column.get("_doctype")) + query = query.select(table[column.get("fieldname")]) + else: + query = query.select(si[column.get("fieldname")]) if filters.get("customer"): query = query.where(si.customer == filters["customer"]) From 14c98fe6f0e1b9dbe04522ed6c61cf34656dea4e Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Sun, 9 Jun 2024 20:02:39 +0530 Subject: [PATCH 27/36] chore: resolve conflicts (cherry picked from commit c29db5afcda6d283c32676c437f525e7aaba5ef6) --- .../item_wise_purchase_register.py | 66 ------------- .../item_wise_sales_register.py | 97 ++----------------- 2 files changed, 10 insertions(+), 153 deletions(-) diff --git a/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py b/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py index bafd83db37a..80c246cad55 100644 --- a/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py +++ b/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py @@ -311,62 +311,7 @@ def apply_conditions(query, pi, pii, filters): return query -<<<<<<< HEAD -def get_items(filters, additional_query_columns): -<<<<<<< HEAD -<<<<<<< HEAD - conditions = get_conditions(filters) - if additional_query_columns: - additional_query_columns = "," + ",".join(additional_query_columns) - return frappe.db.sql( - f""" - select - `tabPurchase Invoice Item`.`name`, `tabPurchase Invoice Item`.`parent`, - `tabPurchase Invoice`.posting_date, `tabPurchase Invoice`.credit_to, `tabPurchase Invoice`.company, - `tabPurchase Invoice`.supplier, `tabPurchase Invoice`.remarks, `tabPurchase Invoice`.base_net_total, - `tabPurchase Invoice`.unrealized_profit_loss_account, - `tabPurchase Invoice Item`.`item_code`, `tabPurchase Invoice Item`.description, - `tabPurchase Invoice Item`.`item_name` as pi_item_name, `tabPurchase Invoice Item`.`item_group` as pi_item_group, - `tabItem`.`item_name` as i_item_name, `tabItem`.`item_group` as i_item_group, - `tabPurchase Invoice Item`.`project`, `tabPurchase Invoice Item`.`purchase_order`, - `tabPurchase Invoice Item`.`purchase_receipt`, `tabPurchase Invoice Item`.`po_detail`, - `tabPurchase Invoice Item`.`expense_account`, `tabPurchase Invoice Item`.`stock_qty`, - `tabPurchase Invoice Item`.`stock_uom`, `tabPurchase Invoice Item`.`base_net_amount`, - `tabPurchase Invoice`.`supplier_name`, `tabPurchase Invoice`.`mode_of_payment` {additional_query_columns} - from `tabPurchase Invoice`, `tabPurchase Invoice Item`, `tabItem` - where `tabPurchase Invoice`.name = `tabPurchase Invoice Item`.`parent` and - `tabItem`.name = `tabPurchase Invoice Item`.`item_code` and - `tabPurchase Invoice`.docstatus = 1 {conditions} - """, - filters, - as_dict=1, - ) -======= - pi = frappe.qb.DocType('Purchase Invoice') - pii = frappe.qb.DocType('Purchase Invoice Item') - Item = frappe.qb.DocType('Item') - query = (frappe.qb.from_(pi) - .join(pii).on(pi.name == pii.parent) - .left_join(Item).on(pii.item_code == Item.name) - .select( - pii.name.as_('pii_name'), pii.parent, - pi.posting_date, pi.credit_to, pi.company, - pi.supplier, pi.remarks, pi.base_net_total, - pi.unrealized_profit_loss_account, - pii.item_code, pii.description, pii.item_group, - pii.item_name.as_('pi_item_name'), pii.item_group.as_('pi_item_group'), - Item.item_name.as_('i_item_name'), Item.item_group.as_('i_item_group'), - pii.project, pii.purchase_order, - pii.purchase_receipt, pii.po_detail, - pii.expense_account, pii.stock_qty, - pii.stock_uom, pii.base_net_amount, - pi.supplier_name, pi.mode_of_payment - ) - .where(pi.docstatus == 1)) -======= -======= def get_items(filters, additional_table_columns): ->>>>>>> 8ec364df6f (fix: Add additional condition application) pi = frappe.qb.DocType("Purchase Invoice") pii = frappe.qb.DocType("Purchase Invoice Item") Item = frappe.qb.DocType("Item") @@ -406,20 +351,12 @@ def get_items(filters, additional_table_columns): ) .where(pi.docstatus == 1) ) ->>>>>>> 76073ae228 (fix: fixing Item-wise sales register and purchase register #41373) if filters.get("supplier"): query = query.where(pi.supplier == filters["supplier"]) if filters.get("company"): query = query.where(pi.company == filters["company"]) -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD ->>>>>>> 1b45ecfcae (fix: Item-wise Sales and Purchase register with no item codes #41373) -======= -======= -======= if additional_table_columns: for column in additional_table_columns: if column.get("_doctype"): @@ -428,12 +365,9 @@ def get_items(filters, additional_table_columns): else: query = query.select(pi[column.get("fieldname")]) ->>>>>>> 8ec364df6f (fix: Add additional condition application) query = apply_conditions(query, pi, pii, filters) ->>>>>>> d2af36e1eb (chore: update condition queries in qb) return query.run(as_dict=True) ->>>>>>> 76073ae228 (fix: fixing Item-wise sales register and purchase register #41373) def get_aii_accounts(): diff --git a/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py b/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py index 5a989a929ab..cd50b118715 100644 --- a/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py +++ b/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py @@ -84,9 +84,7 @@ def _execute(filters=None, additional_table_columns=None, additional_conditions= "company": d.company, "sales_order": d.sales_order, "delivery_note": d.delivery_note, - "income_account": d.unrealized_profit_loss_account - if d.is_internal_customer == 1 - else d.income_account, + "income_account": get_income_account(d), "cost_center": d.cost_center, "stock_qty": d.stock_qty, "stock_uom": d.stock_uom, @@ -151,6 +149,15 @@ def _execute(filters=None, additional_table_columns=None, additional_conditions= return columns, data, None, None, None, skip_total_row +def get_income_account(row): + if row.enable_deferred_revenue: + return row.deferred_revenue_account + elif row.is_internal_customer == 1: + return row.unrealized_profit_loss_account + else: + return row.income_account + + def get_columns(additional_table_columns, filters): columns = [] @@ -367,8 +374,6 @@ def apply_conditions(query, si, sii, filters, additional_conditions=None): if filters.get("item_group"): query = query.where(sii.item_group == filters.get("item_group")) -<<<<<<< HEAD -======= if filters.get("income_account"): query = query.where( (sii.income_account == filters.get("income_account")) @@ -376,7 +381,6 @@ def apply_conditions(query, si, sii, filters, additional_conditions=None): | (si.unrealized_profit_loss_account == filters.get("income_account")) ) ->>>>>>> d2af36e1eb (chore: update condition queries in qb) if not filters.get("group_by"): query = query.orderby(si.posting_date, order=Order.desc) query = query.orderby(sii.item_group, order=Order.desc) @@ -402,84 +406,10 @@ def apply_group_by_conditions(query, si, ii, filters): return query -<<<<<<< HEAD -<<<<<<< HEAD -def get_items(filters, additional_query_columns, additional_conditions=None): - conditions = get_conditions(filters, additional_conditions) - if additional_query_columns: - additional_query_columns = "," + ",".join(additional_query_columns) - return frappe.db.sql( - """ - select - `tabSales Invoice Item`.name, `tabSales Invoice Item`.parent, - `tabSales Invoice`.posting_date, `tabSales Invoice`.debit_to, - `tabSales Invoice`.unrealized_profit_loss_account, - `tabSales Invoice`.is_internal_customer, - `tabSales Invoice`.customer, `tabSales Invoice`.remarks, - `tabSales Invoice`.territory, `tabSales Invoice`.company, `tabSales Invoice`.base_net_total, - `tabSales Invoice Item`.project, - `tabSales Invoice Item`.item_code, `tabSales Invoice Item`.description, - `tabSales Invoice Item`.`item_name`, `tabSales Invoice Item`.`item_group`, - `tabSales Invoice Item`.`item_name` as si_item_name, `tabSales Invoice Item`.`item_group` as si_item_group, - `tabItem`.`item_name` as i_item_name, `tabItem`.`item_group` as i_item_group, - `tabSales Invoice Item`.sales_order, `tabSales Invoice Item`.delivery_note, - `tabSales Invoice Item`.income_account, `tabSales Invoice Item`.cost_center, - `tabSales Invoice Item`.stock_qty, `tabSales Invoice Item`.stock_uom, - `tabSales Invoice Item`.base_net_rate, `tabSales Invoice Item`.base_net_amount, - `tabSales Invoice`.customer_name, `tabSales Invoice`.customer_group, `tabSales Invoice Item`.so_detail, - `tabSales Invoice`.update_stock, `tabSales Invoice Item`.uom, `tabSales Invoice Item`.qty {} - from `tabSales Invoice`, `tabSales Invoice Item`, `tabItem` - where `tabSales Invoice`.name = `tabSales Invoice Item`.parent and - `tabItem`.name = `tabSales Invoice Item`.`item_code` and - `tabSales Invoice`.docstatus = 1 {} - """.format(additional_query_columns, conditions), - filters, - as_dict=1, - ) # nosec -======= -def get_items(filters, additional_query_columns,additional_conditions=None): - si = frappe.qb.DocType('Sales Invoice') - sii = frappe.qb.DocType('Sales Invoice Item') - Item = frappe.qb.DocType('Item') - - query = ( - frappe.qb.from_(si) - .join(sii).on(si.name == sii.parent) - .left_join(Item).on(sii.item_code == Item.name) - .select( - sii.name, sii.parent, - si.posting_date, si.debit_to, - si.unrealized_profit_loss_account, - si.is_internal_customer, - si.customer, si.remarks, - si.territory, si.company, si.base_net_total, - sii.project, - sii.item_code, sii.description, - sii.item_name, sii.item_group, - sii.item_name.as_('si_item_name'), sii.item_group.as_('si_item_group'), - Item.item_name.as_('i_item_name'), Item.item_group.as_('i_item_group'), - sii.sales_order, sii.delivery_note, - sii.income_account, sii.cost_center, - sii.enable_deferred_revenue, sii.deferred_revenue_account, - sii.stock_qty, sii.stock_uom, - sii.base_net_rate, sii.base_net_amount, - si.customer_name, si.customer_group, sii.so_detail, - si.update_stock, sii.uom, sii.qty - ) - .where(si.docstatus == 1) - ) - if filters.get("customer"): - query = query.where(si.customer == filters['customer']) -======= def get_items(filters, additional_query_columns, additional_conditions=None): si = frappe.qb.DocType("Sales Invoice") sii = frappe.qb.DocType("Sales Invoice Item") -<<<<<<< HEAD - Item = frappe.qb.DocType("Item") ->>>>>>> eafa88b8e9 (fix: fixing Item-wise sales register #41373) -======= item = frappe.qb.DocType("Item") ->>>>>>> d2af36e1eb (chore: update condition queries in qb) query = ( frappe.qb.from_(si) @@ -542,16 +472,9 @@ def get_items(filters, additional_query_columns, additional_conditions=None): if filters.get("customer_group"): query = query.where(si.customer_group == filters["customer_group"]) -<<<<<<< HEAD -<<<<<<< HEAD ->>>>>>> 1b45ecfcae (fix: Item-wise Sales and Purchase register with no item codes #41373) -======= -======= query = apply_conditions(query, si, sii, filters, additional_conditions) ->>>>>>> d2af36e1eb (chore: update condition queries in qb) return query.run(as_dict=True) ->>>>>>> eafa88b8e9 (fix: fixing Item-wise sales register #41373) def get_delivery_notes_against_sales_order(item_list): From f2909e9784ec677b0ea116cb9cb2acc60db30da8 Mon Sep 17 00:00:00 2001 From: Frappe PR Bot Date: Mon, 10 Jun 2024 04:54:40 +0000 Subject: [PATCH 28/36] chore(release): Bumped to Version 15.27.2 ## [15.27.2](https://github.com/frappe/erpnext/compare/v15.27.1...v15.27.2) (2024-06-10) ### Bug Fixes * Add additional condition application ([45c16f6](https://github.com/frappe/erpnext/commit/45c16f615c6c94c69f4c633cc4a5faef333e1b2c)) * fixing Item-wise sales register ([9a629f8](https://github.com/frappe/erpnext/commit/9a629f860c6acd0d51aaf39e9fc0cfe1c0f27d98)) * fixing Item-wise sales register [#41373](https://github.com/frappe/erpnext/issues/41373) ([d75d64e](https://github.com/frappe/erpnext/commit/d75d64eb258c3d398e721cea9d7fc5e6725694e4)) * fixing Item-wise sales register and purchase register [#41373](https://github.com/frappe/erpnext/issues/41373) ([50ef81a](https://github.com/frappe/erpnext/commit/50ef81a997425d35208c25ccfa0137c2f9be34ec)) * Item-wise Sales and Purchase register with no item codes [#41373](https://github.com/frappe/erpnext/issues/41373) ([3e0123b](https://github.com/frappe/erpnext/commit/3e0123ba7bf54bd94fd7693ed33b8e94a7625be8)) --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 22be77c9b4a..f758814da21 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -3,7 +3,7 @@ import inspect import frappe -__version__ = "15.27.1" +__version__ = "15.27.2" def get_default_company(user=None): From 439ef109f305020a5b60f852e4c2d24581ac06be Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Tue, 11 Jun 2024 14:47:08 +0530 Subject: [PATCH 29/36] fix: Add timestamp to key for immutable views (cherry picked from commit 6bded59f1c5e7f5f63703ccf8fa03cd3dae935e9) (cherry picked from commit 9e9bc8b59c35bbf4fbb5548c0341296f858e06c9) --- erpnext/accounts/report/general_ledger/general_ledger.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/erpnext/accounts/report/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py index 44fad110baa..e884deb2a17 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.py +++ b/erpnext/accounts/report/general_ledger/general_ledger.py @@ -421,6 +421,8 @@ def get_accountwise_gle(filters, accounting_dimensions, gl_entries, gle_map): if filters.get("show_net_values_in_party_account"): account_type_map = get_account_type_map(filters.get("company")) + immutable_ledger = frappe.db.get_single_value("Accounts Settings", "enable_immutable_ledger") + def update_value_in_dict(data, key, gle): data[key].debit += gle.debit data[key].credit += gle.credit @@ -489,6 +491,10 @@ def get_accountwise_gle(filters, accounting_dimensions, gl_entries, gle_map): gle.get("party_type"), gle.get("party"), ] + + if immutable_ledger: + keylist.append(gle.get("creation")) + if filters.get("include_dimensions"): for dim in accounting_dimensions: keylist.append(gle.get(dim)) From 6157119bcf25b8ddfdf0b6384f43cd11c24e0af9 Mon Sep 17 00:00:00 2001 From: Frappe PR Bot Date: Tue, 11 Jun 2024 09:50:57 +0000 Subject: [PATCH 30/36] chore(release): Bumped to Version 15.27.3 ## [15.27.3](https://github.com/frappe/erpnext/compare/v15.27.2...v15.27.3) (2024-06-11) ### Bug Fixes * Add timestamp to key for immutable views ([439ef10](https://github.com/frappe/erpnext/commit/439ef109f305020a5b60f852e4c2d24581ac06be)) --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index f758814da21..2a58be190d1 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -3,7 +3,7 @@ import inspect import frappe -__version__ = "15.27.2" +__version__ = "15.27.3" def get_default_company(user=None): From 4d2d38cd9dc22b91d0c23d39bafd05b240fa5cb7 Mon Sep 17 00:00:00 2001 From: Frappe PR Bot Date: Tue, 11 Jun 2024 13:18:31 +0000 Subject: [PATCH 31/36] chore(release): Bumped to Version 15.27.4 ## [15.27.4](https://github.com/frappe/erpnext/compare/v15.27.3...v15.27.4) (2024-06-11) ### Bug Fixes * Add additional condition application ([1fca6ea](https://github.com/frappe/erpnext/commit/1fca6ea5e70da34cdce637bf2a4b1beb94bc3507)) * Add posting date to key for consolidated view ([9472085](https://github.com/frappe/erpnext/commit/94720851c6b819f3466dbae45a566f2d1830e2e3)) * Add timestamp to key for immutable views ([9e9bc8b](https://github.com/frappe/erpnext/commit/9e9bc8b59c35bbf4fbb5548c0341296f858e06c9)) * asset depreciations and balances report correction (backport [#41824](https://github.com/frappe/erpnext/issues/41824)) ([#41851](https://github.com/frappe/erpnext/issues/41851)) ([28b7fad](https://github.com/frappe/erpnext/commit/28b7fad579bfca19f3b0be0331a38215f01521bc)) * calculate totals and taxes ([5544309](https://github.com/frappe/erpnext/commit/5544309048e905592355dc1f206c31db40126e41)) * Do no apply pricing rule on qty change for mapped docs ([822bc58](https://github.com/frappe/erpnext/commit/822bc581f3965f85f0080cfc0b2426520538fccb)) * do not fetch items with no active BOM in PP (backport [#41833](https://github.com/frappe/erpnext/issues/41833)) ([#41835](https://github.com/frappe/erpnext/issues/41835)) ([30c0b2b](https://github.com/frappe/erpnext/commit/30c0b2bb546c1c78bd5db29311a78d71a02efdf1)) * enable no_copy for timesheet in sales invoice ([f1ad0f6](https://github.com/frappe/erpnext/commit/f1ad0f6f269c7eeb9668798f0e6815a620c38a95)) * fixing Item-wise sales register ([f36db7e](https://github.com/frappe/erpnext/commit/f36db7ebaf0c1e3c0de716f2733961be4f5b632e)) * fixing Item-wise sales register [#41373](https://github.com/frappe/erpnext/issues/41373) ([5e0fa1b](https://github.com/frappe/erpnext/commit/5e0fa1b75ec1437516aa190550ccf8fbfab67a6e)) * fixing Item-wise sales register and purchase register [#41373](https://github.com/frappe/erpnext/issues/41373) ([a4b28ba](https://github.com/frappe/erpnext/commit/a4b28ba354873a8bb5253a5902970fc780aa9441)) * Item-wise Sales and Purchase register with no item codes [#41373](https://github.com/frappe/erpnext/issues/41373) ([96405e8](https://github.com/frappe/erpnext/commit/96405e8e4957c672b7a4aa5f7e9ead081a6e143d)) * stock_value_change for legacy serial nos (backport [#41825](https://github.com/frappe/erpnext/issues/41825)) ([#41826](https://github.com/frappe/erpnext/issues/41826)) ([a7971cf](https://github.com/frappe/erpnext/commit/a7971cf8443dac71347369fb38ab2edf0ed8dc27)) * terms and conditions for material request (backport [#41834](https://github.com/frappe/erpnext/issues/41834)) ([#41837](https://github.com/frappe/erpnext/issues/41837)) ([1ead667](https://github.com/frappe/erpnext/commit/1ead66721d92a25e8037da2198a80031c69049d4)) * typo in method - holiday list (backport [#41811](https://github.com/frappe/erpnext/issues/41811)) ([#41812](https://github.com/frappe/erpnext/issues/41812)) ([4d3e883](https://github.com/frappe/erpnext/commit/4d3e88313013af0e3741a0b108c49f6680fc95a5)) * valuation rate for backdated legacy serial/batches (backport [#41788](https://github.com/frappe/erpnext/issues/41788)) ([#41821](https://github.com/frappe/erpnext/issues/41821)) ([8d31243](https://github.com/frappe/erpnext/commit/8d31243a42a37b4dd0947d4d506815e8d999a009)) * valuation rate for serial and batch bundle for current bundle (backport [#41850](https://github.com/frappe/erpnext/issues/41850)) ([#41860](https://github.com/frappe/erpnext/issues/41860)) ([3e4c568](https://github.com/frappe/erpnext/commit/3e4c568ddccfde0dd1a03a2e90dfeedf38521ae3)) * **Vehicle:** allow doc renaming and add test (backport [#41729](https://github.com/frappe/erpnext/issues/41729)) ([#41785](https://github.com/frappe/erpnext/issues/41785)) ([4d37739](https://github.com/frappe/erpnext/commit/4d37739dd3ede937e93e8328fa6a147462efc241)) --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 2a58be190d1..b3e5b4b6880 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -3,7 +3,7 @@ import inspect import frappe -__version__ = "15.27.3" +__version__ = "15.27.4" def get_default_company(user=None): From 2c9b3908dd61ae51e9c455dc0b4b03fd69ea15c0 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Wed, 12 Jun 2024 12:12:58 +0530 Subject: [PATCH 32/36] fix: batch qty in the dropdown field (cherry picked from commit eb426c69fe85e27e79cadb4da7ff90b298a111de) (cherry picked from commit 67d1709ef8e477d39c4d95e6bfb00128e570faa1) --- erpnext/controllers/queries.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py index c57b2f3ddd6..a07a00dd03e 100644 --- a/erpnext/controllers/queries.py +++ b/erpnext/controllers/queries.py @@ -352,6 +352,7 @@ def get_batch_no(doctype, txt, searchfield, start, page_len, filters): doctype = "Batch" meta = frappe.get_meta(doctype, cached=True) searchfields = meta.get_search_fields() + page_len = 30 batches = get_batches_from_stock_ledger_entries(searchfields, txt, filters, start, page_len) batches.extend(get_batches_from_serial_and_batch_bundle(searchfields, txt, filters, start, page_len)) @@ -422,7 +423,7 @@ def get_batches_from_stock_ledger_entries(searchfields, txt, filters, start=0, p & (stock_ledger_entry.batch_no.isnotnull()) ) .groupby(stock_ledger_entry.batch_no, stock_ledger_entry.warehouse) - .having(Sum(stock_ledger_entry.actual_qty) > 0) + .having(Sum(stock_ledger_entry.actual_qty) != 0) .offset(start) .limit(page_len) ) @@ -473,7 +474,7 @@ def get_batches_from_serial_and_batch_bundle(searchfields, txt, filters, start=0 & (stock_ledger_entry.serial_and_batch_bundle.isnotnull()) ) .groupby(bundle.batch_no, bundle.warehouse) - .having(Sum(bundle.qty) > 0) + .having(Sum(bundle.qty) != 0) .offset(start) .limit(page_len) ) From 00b7c49b4b0b831141d830d5f06e42fea283e0b1 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Wed, 12 Jun 2024 14:33:25 +0530 Subject: [PATCH 33/36] fix: return from accepted and rejected warehouse at a same time not working (cherry picked from commit 17731f09ef614537cf5dc07ad0cce6b8f918bb59) (cherry picked from commit 6c57971abc12fd08ca3986f10c8b78d089cbb3c4) --- .../controllers/sales_and_purchase_return.py | 18 ++++++- erpnext/controllers/stock_controller.py | 9 +++- .../purchase_receipt/test_purchase_receipt.py | 49 +++++++++++++++++++ 3 files changed, 73 insertions(+), 3 deletions(-) diff --git a/erpnext/controllers/sales_and_purchase_return.py b/erpnext/controllers/sales_and_purchase_return.py index 96af12f2340..3414b5b2520 100644 --- a/erpnext/controllers/sales_and_purchase_return.py +++ b/erpnext/controllers/sales_and_purchase_return.py @@ -936,6 +936,7 @@ def get_serial_and_batch_bundle(field, doctype, reference_ids, is_rejected=False if is_rejected: fields.extend(["rejected_serial_and_batch_bundle", "return_qty_from_rejected_warehouse"]) + del filters["rejected_serial_and_batch_bundle"] data = frappe.get_all( doctype, fields=fields, @@ -943,6 +944,9 @@ def get_serial_and_batch_bundle(field, doctype, reference_ids, is_rejected=False ) for d in data: + if not d.get("serial_and_batch_bundle") and not d.get("rejected_serial_and_batch_bundle"): + continue + if is_rejected: if d.get("return_qty_from_rejected_warehouse"): _bundle_ids.append(d.get("serial_and_batch_bundle")) @@ -1027,7 +1031,7 @@ def get_available_batch_qty(parent_doc, batch_no, warehouse): ) -def make_serial_batch_bundle_for_return(data, child_doc, parent_doc, warehouse_field=None): +def make_serial_batch_bundle_for_return(data, child_doc, parent_doc, warehouse_field=None, qty_field=None): from erpnext.stock.serial_batch_bundle import SerialBatchCreation type_of_transaction = "Outward" @@ -1037,11 +1041,21 @@ def make_serial_batch_bundle_for_return(data, child_doc, parent_doc, warehouse_f if not warehouse_field: warehouse_field = "warehouse" + if not qty_field: + qty_field = "qty" + warehouse = child_doc.get(warehouse_field) if parent_doc.get("is_internal_customer"): warehouse = child_doc.get("target_warehouse") type_of_transaction = "Outward" + if not child_doc.get(qty_field): + frappe.throw( + _("For the {0}, the quantity is required to make the return entry").format( + frappe.bold(child_doc.item_code) + ) + ) + cls_obj = SerialBatchCreation( { "type_of_transaction": type_of_transaction, @@ -1054,7 +1068,7 @@ def make_serial_batch_bundle_for_return(data, child_doc, parent_doc, warehouse_f "voucher_type": parent_doc.doctype, "voucher_no": parent_doc.name, "voucher_detail_no": child_doc.name, - "qty": child_doc.qty, + "qty": child_doc.get(qty_field), "company": parent_doc.company, "do_not_submit": True, } diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py index cad9178366e..4f579fd500e 100644 --- a/erpnext/controllers/stock_controller.py +++ b/erpnext/controllers/stock_controller.py @@ -255,10 +255,17 @@ class StockController(AccountsController): qty_field = "qty" warehouse_field = "warehouse" + if not data.get("qty"): + frappe.throw( + _("For the {0}, no stock is available for the return in the warehouse {1}.").format( + frappe.bold(row.item_code), row.get(warehouse_field) + ) + ) + data = filter_serial_batches( self, data, row, warehouse_field=warehouse_field, qty_field=qty_field ) - bundle = make_serial_batch_bundle_for_return(data, row, self, warehouse_field) + bundle = make_serial_batch_bundle_for_return(data, row, self, warehouse_field, qty_field) if row.get("return_qty_from_rejected_warehouse"): row.db_set( { diff --git a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py index edfe8152169..88e9c94c2b1 100644 --- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py @@ -2864,6 +2864,55 @@ class TestPurchaseReceipt(FrappeTestCase): for row in sabb_doc.entries: self.assertEqual(row.incoming_rate, 0) + def test_purchase_return_from_accepted_and_rejected_warehouse(self): + from erpnext.stock.doctype.purchase_receipt.purchase_receipt import ( + make_purchase_return, + ) + + item = make_item( + "_Test PR Item With Return From Accepted and Rejected WH", + { + "is_purchase_item": 1, + "is_stock_item": 1, + "has_batch_no": 1, + "create_new_batch": 1, + "batch_number_series": "SD-TZVRFORBATCH.#####", + "valuation_rate": 200, + }, + ) + + pr = make_purchase_receipt( + qty=10, + rejected_qty=5, + rate=100, + item_code=item.name, + ) + + pr.reload() + self.assertTrue(pr.items[0].serial_and_batch_bundle) + self.assertTrue(pr.items[0].rejected_serial_and_batch_bundle) + + return_pr = make_purchase_return(pr.name) + return_pr.submit() + + return_pr.reload() + self.assertTrue(return_pr.items[0].serial_and_batch_bundle) + self.assertTrue(return_pr.items[0].rejected_serial_and_batch_bundle) + + self.assertEqual( + return_pr.items[0].qty, + frappe.db.get_value( + "Serial and Batch Bundle", return_pr.items[0].serial_and_batch_bundle, "total_qty" + ), + ) + + self.assertEqual( + return_pr.items[0].rejected_qty, + frappe.db.get_value( + "Serial and Batch Bundle", return_pr.items[0].rejected_serial_and_batch_bundle, "total_qty" + ), + ) + def prepare_data_for_internal_transfer(): from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_internal_supplier From a89b4f49fe9870065fee39a154b3a17e2d249f55 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 10 Jun 2024 17:14:27 +0530 Subject: [PATCH 34/36] fix: use invoice outstanding on Dunning (#41817) (cherry picked from commit cf0a29b05f9e120a7a1e648da50164a15c6b5b4e) --- erpnext/accounts/doctype/sales_invoice/sales_invoice.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 68da9ea1657..cb0803db932 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -2678,6 +2678,10 @@ def create_dunning(source_name, target_doc=None, ignore_permissions=False): target.closing_text = letter_text.get("closing_text") target.language = letter_text.get("language") + # update outstanding + if source.payment_schedule and len(source.payment_schedule) == 1: + target.overdue_payments[0].outstanding = source.get("outstanding_amount") + target.validate() return get_mapped_doc( From b34191e81f486a8ee1f04842490a61a9d99172a8 Mon Sep 17 00:00:00 2001 From: Frappe PR Bot Date: Wed, 12 Jun 2024 11:32:40 +0000 Subject: [PATCH 35/36] chore(release): Bumped to Version 15.27.5 ## [15.27.5](https://github.com/frappe/erpnext/compare/v15.27.4...v15.27.5) (2024-06-12) ### Bug Fixes * use invoice outstanding on Dunning ([#41817](https://github.com/frappe/erpnext/issues/41817)) ([a89b4f4](https://github.com/frappe/erpnext/commit/a89b4f49fe9870065fee39a154b3a17e2d249f55)) --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index b3e5b4b6880..a84e8dcc6b3 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -3,7 +3,7 @@ import inspect import frappe -__version__ = "15.27.4" +__version__ = "15.27.5" def get_default_company(user=None): From 9ccfbe1bf54c0353f4ee7fa9ee5bd859dc2d5b55 Mon Sep 17 00:00:00 2001 From: Frappe PR Bot Date: Wed, 12 Jun 2024 11:54:13 +0000 Subject: [PATCH 36/36] chore(release): Bumped to Version 15.27.6 ## [15.27.6](https://github.com/frappe/erpnext/compare/v15.27.5...v15.27.6) (2024-06-12) ### Bug Fixes * batch qty in the dropdown field ([2c9b390](https://github.com/frappe/erpnext/commit/2c9b3908dd61ae51e9c455dc0b4b03fd69ea15c0)) * return from accepted and rejected warehouse at a same time not working ([00b7c49](https://github.com/frappe/erpnext/commit/00b7c49b4b0b831141d830d5f06e42fea283e0b1)) --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index a84e8dcc6b3..61ed40e7e23 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -3,7 +3,7 @@ import inspect import frappe -__version__ = "15.27.5" +__version__ = "15.27.6" def get_default_company(user=None):