From 6ba8725940c731048445839c8d274c033ab08ffd Mon Sep 17 00:00:00 2001 From: Frappe PR Bot Date: Tue, 3 Feb 2026 17:18:56 +0000 Subject: [PATCH 01/11] chore(release): Bumped to Version 15.96.0 # [15.96.0](https://github.com/frappe/erpnext/compare/v15.95.2...v15.96.0) (2026-02-03) ### Bug Fixes * add docstatus condition to get_sales_invoice_item function ([#51517](https://github.com/frappe/erpnext/issues/51517)) ([afc4c85](https://github.com/frappe/erpnext/commit/afc4c856f80506d528a7db182f54b46a0b879f39)) * add missing param ([a61ad15](https://github.com/frappe/erpnext/commit/a61ad1599866cc54c723f7b8b566ddb3738c73c4)) * add precision to rejected batch no qty calculation ([d5570f8](https://github.com/frappe/erpnext/commit/d5570f83d28028d3b04d2bbd8420c3813b3bbac2)) * backport Switzerland VAT rates update to version-15 ([#52244](https://github.com/frappe/erpnext/issues/52244)) ([f5481dc](https://github.com/frappe/erpnext/commit/f5481dc7d563e6300014c4e5924158a9a7bde3a8)) * **bank_account:** `is_company_account` related validations (backport [#51887](https://github.com/frappe/erpnext/issues/51887)) ([#51921](https://github.com/frappe/erpnext/issues/51921)) ([7226066](https://github.com/frappe/erpnext/commit/7226066772642e572cf08c05469fe98b08e46f26)) * **barcode:** failing request when item has both batch and serial ([19e0d75](https://github.com/frappe/erpnext/commit/19e0d75c225e92becbe55bc4b09fea6d9b8c9219)) * correct exchange gain loss in ppr ([e42f8ff](https://github.com/frappe/erpnext/commit/e42f8ffd5d4e6cfd214af30c5c964d25ba497817)) * duplicate account number (Indonesia COA) (backport [#52080](https://github.com/frappe/erpnext/issues/52080)) ([#52316](https://github.com/frappe/erpnext/issues/52316)) ([ac1f29d](https://github.com/frappe/erpnext/commit/ac1f29d5cb71c279e955cc4e31680c193767fdf8)) * hide close button on WO if WO is completed ([bd96868](https://github.com/frappe/erpnext/commit/bd96868736a4cb4f7b4d7b17b0c70f3832cb420d)) * imports ([528a482](https://github.com/frappe/erpnext/commit/528a4822405989574797b6721ee06ddb06270c1b)) * include credit notes in project gross margin calculation ([d9d48da](https://github.com/frappe/erpnext/commit/d9d48da50566511ae5a67aef64208b67a841074e)) * journal auditing voucher print date to use posting_date ([6413ce4](https://github.com/frappe/erpnext/commit/6413ce467f1708428f8179352589565e345b76b2)) * **mode of payment:** use valid syntax (backport [#51542](https://github.com/frappe/erpnext/issues/51542)) ([#52134](https://github.com/frappe/erpnext/issues/52134)) ([22869b6](https://github.com/frappe/erpnext/commit/22869b6f9dc5b98e86b9e6442212946ab1e5257e)) * negative stock for purchase return ([c30d76a](https://github.com/frappe/erpnext/commit/c30d76ae686982fa60a2f6d5ffa5b4b3e7b3ebc5)) * populate contact fields when creating quotation from customer ([78f8922](https://github.com/frappe/erpnext/commit/78f8922a9c7d4f9f82eb7976088c5785d38d8a6f)) * production plan not considering planning datetime when creating WO ([7b6c7c3](https://github.com/frappe/erpnext/commit/7b6c7c3e2740013d2b60f10469ed1b1175783290)) * **profit and loss statement:** exclude non period columns ([32c5861](https://github.com/frappe/erpnext/commit/32c5861919301b297326916ef9b9a1af079564d9)) * remove unneccessary check ([6a68155](https://github.com/frappe/erpnext/commit/6a681557a9558d8c1ba8e323db9dea17c4c2b2f6)) * reset incoming rate in selling controller if there are changes in item ([c6937c8](https://github.com/frappe/erpnext/commit/c6937c8375bbb1d417d492884b4a5e840157212a)) * revert to old orm ([7e01ae9](https://github.com/frappe/erpnext/commit/7e01ae9e4aef20c2d87490a884b66f1301199192)) * **RFQ:** render email templates for preview and sending ([07c5622](https://github.com/frappe/erpnext/commit/07c56221a5d40a1c092d778cb163a1d227903495)) * **stock:** add stock recon opening stock condition ([0cbb7f8](https://github.com/frappe/erpnext/commit/0cbb7f8714f8051e5e4f9c9d4638b8b051b4670c)) * **stock:** fetch batch wise valuation rate in get_items ([f1ba825](https://github.com/frappe/erpnext/commit/f1ba8258185709142e43adf65f9d60225b94a291)) * **stock:** ignore packing slip while cancelling the sales invoice ([e6083a5](https://github.com/frappe/erpnext/commit/e6083a57de2b64390e56ca4ee449f3565272cd8c)) * **stock:** include subcontracting order qty while calculating the bin qty ([ba17fdd](https://github.com/frappe/erpnext/commit/ba17fdd07221177c9f94023304a0c070377b26b6)) * **stock:** remove is_return condition on pos batch qty calculation ([a638dec](https://github.com/frappe/erpnext/commit/a638dece6b79ef26fe8486dfa1e3baf0afcd13b7)) * **stock:** set incoming_rate with lcv rate for internal purchase ([41c592a](https://github.com/frappe/erpnext/commit/41c592a1a8668ddf8ab7847857e7d981561679c6)) * **subcontracting:** include item bom in supplied items grouping key ([3b12d60](https://github.com/frappe/erpnext/commit/3b12d60877e5a26fa75b78c421dba6b3773f3856)) * test cases ([2c74491](https://github.com/frappe/erpnext/commit/2c74491eb61133d401a2ec8566b527d1fd933dde)) * validate over ordering of quotation ([0e60750](https://github.com/frappe/erpnext/commit/0e60750bd848aa7c5550900c2055ea04d7799611)) * validation when more than one FG items in repack stock entry ([fec3a8b](https://github.com/frappe/erpnext/commit/fec3a8b5115af95142bc25bf666ec4c30e462b61)) * zero valuation rate if returning from different warehouse ([28929df](https://github.com/frappe/erpnext/commit/28929df0e8f85e12f4e896b377a373cbada53357)) ### Features * **delivery-note:** add status indicator when document is partially billed ([e5e3b8a](https://github.com/frappe/erpnext/commit/e5e3b8a6ae7dbd89493a7721ca79c01d6a2f2b26)) * filter to display trial balance report without group account (backport [#48486](https://github.com/frappe/erpnext/issues/48486)) ([#52146](https://github.com/frappe/erpnext/issues/52146)) ([f48b4cd](https://github.com/frappe/erpnext/commit/f48b4cda50b29b65dfe661de263105bf8a87eb22)) --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 7450d8ee1cd..129a7ceeb7f 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -4,7 +4,7 @@ import inspect import frappe from frappe.utils.user import is_website_user -__version__ = "15.95.2" +__version__ = "15.96.0" def get_default_company(user=None): From 3d525addbecbdd99d1b32d9cce2400208848e54a Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Thu, 5 Feb 2026 14:53:17 +0530 Subject: [PATCH 02/11] fix: stock balance report issue (cherry picked from commit bda7220b701fe35abc8704a69f250b0fac19da63) --- erpnext/stock/report/stock_balance/stock_balance.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/erpnext/stock/report/stock_balance/stock_balance.py b/erpnext/stock/report/stock_balance/stock_balance.py index 913a31df1a7..5ce641eb210 100644 --- a/erpnext/stock/report/stock_balance/stock_balance.py +++ b/erpnext/stock/report/stock_balance/stock_balance.py @@ -198,10 +198,8 @@ class StockBalanceReport: for field in self.inventory_dimensions: qty_dict[field] = entry.get(field) - if ( - entry.voucher_type == "Stock Reconciliation" - and frappe.get_cached_value(entry.voucher_type, entry.voucher_no, "purpose") != "Opening Stock" - and (not entry.batch_no or entry.serial_no) + if entry.voucher_type == "Stock Reconciliation" and ( + not entry.batch_no and not entry.serial_no and not entry.serial_and_batch_bundle ): qty_diff = flt(entry.qty_after_transaction) - flt(qty_dict.bal_qty) else: From 9c2b4f611d642c4fd65eaad77bc98d611eed8e93 Mon Sep 17 00:00:00 2001 From: Frappe PR Bot Date: Thu, 5 Feb 2026 10:53:47 +0000 Subject: [PATCH 03/11] chore(release): Bumped to Version 15.96.1 ## [15.96.1](https://github.com/frappe/erpnext/compare/v15.96.0...v15.96.1) (2026-02-05) ### Bug Fixes * stock balance report issue ([3d525ad](https://github.com/frappe/erpnext/commit/3d525addbecbdd99d1b32d9cce2400208848e54a)) --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 129a7ceeb7f..862c1758fb2 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -4,7 +4,7 @@ import inspect import frappe from frappe.utils.user import is_website_user -__version__ = "15.96.0" +__version__ = "15.96.1" def get_default_company(user=None): From b340d7c6bb9595b466290d1f8d918f3c69fa477f Mon Sep 17 00:00:00 2001 From: Frappe PR Bot Date: Wed, 11 Feb 2026 04:58:18 +0000 Subject: [PATCH 04/11] chore(release): Bumped to Version 15.97.0 # [15.97.0](https://github.com/frappe/erpnext/compare/v15.96.1...v15.97.0) (2026-02-11) ### Bug Fixes * Added a missing option to the currency field (backport [#52528](https://github.com/frappe/erpnext/issues/52528)) ([#52586](https://github.com/frappe/erpnext/issues/52586)) ([a6f5b88](https://github.com/frappe/erpnext/commit/a6f5b88f9b275c2122dc1c23cee3b86a7f3118b4)) * **buying:** add supplier group link filters in field level ([436cb8d](https://github.com/frappe/erpnext/commit/436cb8dbfc2dca2be6abe7021b1a7bff21b447a7)) * email campaign timeout issue (backport [#51994](https://github.com/frappe/erpnext/issues/51994)) ([#52555](https://github.com/frappe/erpnext/issues/52555)) ([6c9681b](https://github.com/frappe/erpnext/commit/6c9681ba4cdbb50edfe66ce0451a19c221adb532)) * enabling skip delivery option for order type maintenance ([a8f05ca](https://github.com/frappe/erpnext/commit/a8f05cadea5b744d1f687345ac2623e301c9921d)) * **gross profit report:** translate column Sales Invoice ([4e910d8](https://github.com/frappe/erpnext/commit/4e910d8a69427e991d564cf6805befbe9310b11c)) * **gross-profit:** handle item group filters ([7cd9de2](https://github.com/frappe/erpnext/commit/7cd9de211f10fcca4f13dfbda0bfc7d668ae5d4c)) * **gross-profit:** handle returns outside sale period ([303dac2](https://github.com/frappe/erpnext/commit/303dac262cd023e70fbed0d4aaf8ae780789de16)) * handle gross profit and percentage for return invoices ([bde19ab](https://github.com/frappe/erpnext/commit/bde19ab0101aaa9d81f8cc271e4b9ded995b1674)) * **manufacturing:** fix chart period keys ([99f3a7e](https://github.com/frappe/erpnext/commit/99f3a7e4cf1c9996a0afccccd9f0d7daf64ce245)) * **manufacturing:** handle None value for actual_end_date ([f965b35](https://github.com/frappe/erpnext/commit/f965b352c8817ce685dfb64672127020181e5dcd)) * **map_current_doc:** prevent mutation of query args in get_query (backport [#52202](https://github.com/frappe/erpnext/issues/52202)) ([#52583](https://github.com/frappe/erpnext/issues/52583)) ([9519773](https://github.com/frappe/erpnext/commit/9519773c5c64014ceca4662fdb667ccbda110dee)) * merge taxes in purchase receipt when get items from multiple purchase invoices ([#51422](https://github.com/frappe/erpnext/issues/51422)) ([68338ab](https://github.com/frappe/erpnext/commit/68338abe07b52479a4235fd4bf3a81c92bba5db6)) * **quotation:** ignore zero ordered_qty ([ad92c02](https://github.com/frappe/erpnext/commit/ad92c021f73449702f9d8ea2c27c0ab88aa51f10)) * rate comparison in stock reco ([cacca81](https://github.com/frappe/erpnext/commit/cacca812ed96076d6b55ccfb54f84534c69169ed)) * remove incorrect validation from email digest throwing spurious error (backport [#51827](https://github.com/frappe/erpnext/issues/51827)) ([#52582](https://github.com/frappe/erpnext/issues/52582)) ([b034f3d](https://github.com/frappe/erpnext/commit/b034f3d3db8947bf5e9f89a3bb625b5759a44581)) * resolve conflicts ([36e2cf4](https://github.com/frappe/erpnext/commit/36e2cf49f359cb59bb52e5ebdaf0327cf446c7b5)) * return None instead of 0 if valuation rate is falsy ([195f020](https://github.com/frappe/erpnext/commit/195f02063630b8163fe3eba8b5cf72b8ebd4d2e8)) * stock balance report issue ([bda7220](https://github.com/frappe/erpnext/commit/bda7220b701fe35abc8704a69f250b0fac19da63)) * **stock:** add is group filter for warehouse fields ([5b7ee0a](https://github.com/frappe/erpnext/commit/5b7ee0af661131cd4a3959b498fbe59924e568bd)) * **stock:** ignore pos reserved batches for stock levels ([635a421](https://github.com/frappe/erpnext/commit/635a4218078d9353a251bee7917d606fca857aba)) * **stock:** inward stock for pick list test record ([5a42ff0](https://github.com/frappe/erpnext/commit/5a42ff0c3cd901069278d82682f378ce6142b3fb)) * **stock:** set source warehouse for issue type ([19dca36](https://github.com/frappe/erpnext/commit/19dca36dece3baa4fd916e846d68f74779138884)) * **stock:** update target field attribute ([9cfd704](https://github.com/frappe/erpnext/commit/9cfd704eef992bcdea2ad902aae1e541b78cdc86)) * validate asset movement transaction date (backport [#52340](https://github.com/frappe/erpnext/issues/52340)) ([#52560](https://github.com/frappe/erpnext/issues/52560)) ([eea8cb5](https://github.com/frappe/erpnext/commit/eea8cb58853c6baae6cbddf75319496d30305352)) ### Features * allow negative stock for the batch item ([4c094c3](https://github.com/frappe/erpnext/commit/4c094c3d8614d7d49cbdbfad3d9b97317fda39df)) --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 862c1758fb2..39e633a98c6 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -4,7 +4,7 @@ import inspect import frappe from frappe.utils.user import is_website_user -__version__ = "15.96.1" +__version__ = "15.97.0" def get_default_company(user=None): From a66854d16d4ca936bddec37b9fd384d0b719ae8a Mon Sep 17 00:00:00 2001 From: Frappe PR Bot Date: Tue, 17 Feb 2026 14:12:38 +0000 Subject: [PATCH 05/11] chore(release): Bumped to Version 15.98.0 # [15.98.0](https://github.com/frappe/erpnext/compare/v15.97.0...v15.98.0) (2026-02-17) ### Bug Fixes * **accounts-controller:** handle empty items list ([13239a9](https://github.com/frappe/erpnext/commit/13239a9deecd312b8fb50192b9e14be3eecfa6cc)) * **accounts:** correct base grand total and rounded total mismatch ([#51739](https://github.com/frappe/erpnext/issues/51739)) ([8bdbb24](https://github.com/frappe/erpnext/commit/8bdbb24d73deddd87cc46b9b18a0107959b3526b)) * add base_tax_withholding_net_total to tax withholding report ([ed42d54](https://github.com/frappe/erpnext/commit/ed42d5498912966a32e8a1999d062c85c4288d1d)) * allow rename for market segment doctype ([0a41987](https://github.com/frappe/erpnext/commit/0a4198718b77f89923349a788b026381880f2412)) * allow sequence id edit in BOM if routing is not set ([c425944](https://github.com/frappe/erpnext/commit/c425944bdff1e207f7fe8991ee347a923d46ab0b)) * better validation for negative batch ([85d18fa](https://github.com/frappe/erpnext/commit/85d18fa7a4c167fa1ce740544fec20da19193709)) * cancel SABB if SLE cancelled from LCV ([f2a77d1](https://github.com/frappe/erpnext/commit/f2a77d178dcea70771e1bb385e08effd1cc3f88d)) * consider sle for negative stock validation ([ca79f64](https://github.com/frappe/erpnext/commit/ca79f6478a4c95c82753fb0bc76d776b4dfe8fa0)) * do not allow plant floor company and warehouse to be updated ([d6333c1](https://github.com/frappe/erpnext/commit/d6333c15621dc5d6912767a63325348f74caac0f)) * **manufacturing:** add sales order fields in subassembly child table ([0576752](https://github.com/frappe/erpnext/commit/0576752d3b59ae6fd16a97ce46c414a9a436594b)) * **manufacturing:** set sales order references in subassembly child table ([53e18a9](https://github.com/frappe/erpnext/commit/53e18a9beb551d8c025f2964eb1560e2707878d8)) * Payment Terms auto-fetched in Sales Invoice even when automatically_fetch_payment_terms is disabled ([78a3701](https://github.com/frappe/erpnext/commit/78a3701f4c19a5a322a00758654d19fa7b89d511)) * **pos_invoice:** add correct depends on condition (backport [#52689](https://github.com/frappe/erpnext/issues/52689)) ([#52693](https://github.com/frappe/erpnext/issues/52693)) ([4fe9689](https://github.com/frappe/erpnext/commit/4fe968961afbff5825f6e8e78e91559d92f91a2f)) * **postgres:** validate against period closing using MAX(period_end_date) ([#51554](https://github.com/frappe/erpnext/issues/51554)) ([9ec3031](https://github.com/frappe/erpnext/commit/9ec30319e4232f7dffd221003cfa39e7395fe978)) * production plan status ([97a6610](https://github.com/frappe/erpnext/commit/97a6610c0c8b349a6d10e79cb9386d2d67e2c75e)) * recalculate tax withholding during Purchase Order child update ([273029d](https://github.com/frappe/erpnext/commit/273029d0f0367b58fd9f7bcc49fdfcc2b78dad4d)) * set base_tax_withholding_net_total for jv in tds report ([68099a9](https://github.com/frappe/erpnext/commit/68099a9b5c5be97036d42b11c7cd6e97b16fa69f)) * standalone credit/debit notes should not fetch any serial or batch by default ([79c3bc9](https://github.com/frappe/erpnext/commit/79c3bc9bcdb405d20649a493d7aa8e59296c4507)) * total weight does not update when updating items ([e12871b](https://github.com/frappe/erpnext/commit/e12871b4083060036497063a3c661dd33c302c23)) ### Features * Negative Batch report ([6313636](https://github.com/frappe/erpnext/commit/631363632b53281f37863978b609cba5c426488d)) * show formatted currency symbol on ledger preview ([383648f](https://github.com/frappe/erpnext/commit/383648fb592223d1cc0776e10c65e682a18ceb61)) --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 39e633a98c6..531cf75d3a8 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -4,7 +4,7 @@ import inspect import frappe from frappe.utils.user import is_website_user -__version__ = "15.97.0" +__version__ = "15.98.0" def get_default_company(user=None): From f06e20d993622af519505488c6df55ff8fe458ac Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 16 Feb 2026 13:19:10 +0530 Subject: [PATCH 06/11] fix: better permissions on make payment request (cherry picked from commit f36962fc5842361872caccc13ec56567a5c1e203) --- erpnext/accounts/doctype/payment_request/payment_request.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/payment_request/payment_request.py b/erpnext/accounts/doctype/payment_request/payment_request.py index 752085e5f99..86e93e1d783 100644 --- a/erpnext/accounts/doctype/payment_request/payment_request.py +++ b/erpnext/accounts/doctype/payment_request/payment_request.py @@ -548,6 +548,9 @@ def make_payment_request(**args): if args.dn and not isinstance(args.dn, str): frappe.throw(_("Invalid parameter. 'dn' should be of type str")) + frappe.has_permission("Payment Request", "create", throw=True) + frappe.has_permission(args.dt, "read", args.dn, throw=True) + ref_doc = args.ref_doc or frappe.get_doc(args.dt, args.dn) if not args.get("company"): args.company = ref_doc.company @@ -822,7 +825,7 @@ def get_print_format_list(ref_doctype): return {"print_format": print_format_list} -@frappe.whitelist(allow_guest=True) +@frappe.whitelist() def resend_payment_email(docname): return frappe.get_doc("Payment Request", docname).send_email() From 2888b68334a08d4fc8886e3f6afff1eac23c119b Mon Sep 17 00:00:00 2001 From: Frappe PR Bot Date: Thu, 19 Feb 2026 05:00:53 +0000 Subject: [PATCH 07/11] chore(release): Bumped to Version 15.98.1 ## [15.98.1](https://github.com/frappe/erpnext/compare/v15.98.0...v15.98.1) (2026-02-19) ### Bug Fixes * better permissions on make payment request ([f06e20d](https://github.com/frappe/erpnext/commit/f06e20d993622af519505488c6df55ff8fe458ac)) --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 531cf75d3a8..f8eb123c2aa 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -4,7 +4,7 @@ import inspect import frappe from frappe.utils.user import is_website_user -__version__ = "15.98.0" +__version__ = "15.98.1" def get_default_company(user=None): From 7ad770a83ad7947d97281f96fb8a47f71dca17df Mon Sep 17 00:00:00 2001 From: Frappe PR Bot Date: Wed, 25 Feb 2026 06:29:35 +0000 Subject: [PATCH 08/11] chore(release): Bumped to Version 15.99.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # [15.99.0](https://github.com/frappe/erpnext/compare/v15.98.1...v15.99.0) (2026-02-25) ### Bug Fixes * **`fiscal_year_company`:** made `company` field mandatory ([2fffc94](https://github.com/frappe/erpnext/commit/2fffc9448b8d38c50d238de6d14a0f8c6eca6fc8)) * **`fiscal_year`:** `Fiscal Year` auto-generation and notification ([397f39e](https://github.com/frappe/erpnext/commit/397f39e27108294c44174f165dfa4ec9e3bef81e)) * `update_stock` behaviour on selling invoices ([82bcb62](https://github.com/frappe/erpnext/commit/82bcb62b215b41d0188f5e3fc9a434ee5dd8b1eb)) * Add handling for Sales Invoice Item quantity field ([41c7890](https://github.com/frappe/erpnext/commit/41c7890a6d0ca32410e24a3a6739a13f51e409d7)) * add purchase invoice as well ([2fc3e30](https://github.com/frappe/erpnext/commit/2fc3e30f9fba5e10425c9487469d41db65bbf931)) * avoid duplicate taxes and charges rows in payment entry (backport [#52178](https://github.com/frappe/erpnext/issues/52178)) ([#52318](https://github.com/frappe/erpnext/issues/52318)) ([946c355](https://github.com/frappe/erpnext/commit/946c3554b1df67e50ecc2929ffdd86891093b776)) * better permissions on make payment request ([ce7101f](https://github.com/frappe/erpnext/commit/ce7101f5556eecfab982d40aa2a54fa80d8f6da8)) * bug with comparison regarding `None` values and empty string ([852c200](https://github.com/frappe/erpnext/commit/852c200ee053fc2ab2208c0866afe31808e07932)) * check gl account of an associated bank account in bank transaction ([6b286ae](https://github.com/frappe/erpnext/commit/6b286ae03d91998d0bd7986f6824990cb9291792)) * enfore permission on make_payment_request ([4602919](https://github.com/frappe/erpnext/commit/460291990aa570acf7aa2b113cbe68ddb929a6bc)) * get employee email with priority if preferred is not set ([943e2c0](https://github.com/frappe/erpnext/commit/943e2c00bc92ae5c509c36d25988ca46d842b4dc)) * ignore permissions instead of saving parent ([bce77b6](https://github.com/frappe/erpnext/commit/bce77b6117f418f3cae08bbcdc22f977694de8e8)) * inconsistent label name between parent and child ([1bf608f](https://github.com/frappe/erpnext/commit/1bf608f8358b93a81e857f2c0be1e4032d53bf17)) * **manufacturing:** remove delete query of job card & batch and serial no ([#52840](https://github.com/frappe/erpnext/issues/52840)) ([e30b2f1](https://github.com/frappe/erpnext/commit/e30b2f1d04f5e8346cf12c845914c06dc9c701e5)) * **manufacturing:** set pick list purpose while creating it from work order ([33d48c5](https://github.com/frappe/erpnext/commit/33d48c55750324ff1da83414955d8e2f52361b3f)) * **manufacturing:** update status for work order before calculating planned qty ([b3bcfd5](https://github.com/frappe/erpnext/commit/b3bcfd5a6496dabaa64d1394a107cceae4e1192b)) * permission issue for quotation item during update item ([5a3c027](https://github.com/frappe/erpnext/commit/5a3c02743238a975bbd978d2a60f6b60cba0fd35)) * prevent precision errors in discount distribution with inclusive tax ([61ac180](https://github.com/frappe/erpnext/commit/61ac18069bd0ca9159960d9c8fd79063d1935b47)) * **Purchase Receipt:** copy project from first row when adding items ([fd48fb4](https://github.com/frappe/erpnext/commit/fd48fb49b9d03c83c3c481a1a073dde63265869f)) * remove supplier invoice date/posting date validation ([dcf4ac6](https://github.com/frappe/erpnext/commit/dcf4ac66bb3833a67847bb6c8280ab04ee7cffa2)) * reservation based on field should be read only in SRE ([c3626d6](https://github.com/frappe/erpnext/commit/c3626d67ca7ad6c0649ab2415aa7f9379099c58a)) * restore missing `has_permission` import ([0ba965a](https://github.com/frappe/erpnext/commit/0ba965aae615aec7f77f3d3c28755e398a0c72db)) * **sales-order:** update quotation status while cancelling sales order ([#52822](https://github.com/frappe/erpnext/issues/52822)) ([2420122](https://github.com/frappe/erpnext/commit/2420122f0e89f5344f70b136c6e972c6f3651ee6)) * **sales-order:** update quotation status while cancelling sales order (backport [#52822](https://github.com/frappe/erpnext/issues/52822)) ([#52918](https://github.com/frappe/erpnext/issues/52918)) ([3ae5de7](https://github.com/frappe/erpnext/commit/3ae5de7b11f40a876f5723b2d82363df7b9f8872)) * sensible insufficient stock message in pick list ([3bafa36](https://github.com/frappe/erpnext/commit/3bafa360b266379d8f7f34764c80c0bea7ca07c5)) * setup fails to set abbr to departments ([c432506](https://github.com/frappe/erpnext/commit/c4325069126752b596e508b7f072bf5f6244a365)) * skip empty dimension values in exchange gain loss ([09ba980](https://github.com/frappe/erpnext/commit/09ba9808de9d7fb719dba136c20707554cc53d27)) * typo ([3893900](https://github.com/frappe/erpnext/commit/38939005caa265b407939fb54f484d07e399a986)) * unable to submit subcontracting order if created from material request ([0422117](https://github.com/frappe/erpnext/commit/042211700387ff4e2f352e632ae25ad907579e7c)) * update items fetches wrong item code ([97a4a5f](https://github.com/frappe/erpnext/commit/97a4a5f1cc801d5372ace9b9cb0eae86950a6c7d)) * **work_order:** update returned qty ([bb1a655](https://github.com/frappe/erpnext/commit/bb1a655efb4c619702043e59b3e992571c212f51)) ### Features * **Journal Entry Account:** add Bank Transaction as Reference Type (backport [#52760](https://github.com/frappe/erpnext/issues/52760)) ([#52815](https://github.com/frappe/erpnext/issues/52815)) ([7032197](https://github.com/frappe/erpnext/commit/7032197f97657d06c8a4a32ba8a401b83eb103ec)) * retrieve employee basic contact information ([4b2ac62](https://github.com/frappe/erpnext/commit/4b2ac626c5cd0abb7bf1ca0aca7916497a1b98d6)) * retrieve employee contact details ([caa03ef](https://github.com/frappe/erpnext/commit/caa03efbe11b17e55b269276ca8ce07e419f9ec6)) * update item button addition for quotation (backport [#50976](https://github.com/frappe/erpnext/issues/50976)) ([#52810](https://github.com/frappe/erpnext/issues/52810)) ([800e384](https://github.com/frappe/erpnext/commit/800e38453b662a18e5473ad058c291fb347722b0)) * update item button addition for quotation (backport [#50976](https://github.com/frappe/erpnext/issues/50976)) ([#52810](https://github.com/frappe/erpnext/issues/52810)) ([e2a1a7a](https://github.com/frappe/erpnext/commit/e2a1a7a36d8c057f09b029c180135d37237a42b8)) ### Reverts * Revert "feat: update item button addition for quotation (backport [#50976](https://github.com/frappe/erpnext/issues/50976)) ([#5](https://github.com/frappe/erpnext/issues/5)…" ([656b1bc](https://github.com/frappe/erpnext/commit/656b1bcede274002e54eb2ff034845bc1787d160)) --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index f8eb123c2aa..df14a255c1e 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -4,7 +4,7 @@ import inspect import frappe from frappe.utils.user import is_website_user -__version__ = "15.98.1" +__version__ = "15.99.0" def get_default_company(user=None): From bba0a6d9508f7ee2d18f65b85e103ef686eb401f Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Fri, 27 Feb 2026 12:00:16 +0530 Subject: [PATCH 09/11] fix: old stock reco entries causing issue in the stock balance report (cherry picked from commit 0874cbc268b6e33072a18c220de43e317308e732) # Conflicts: # erpnext/stock/report/stock_balance/stock_balance.py (cherry picked from commit b7124670491f1f5a7cdeb2dd2becf231fa6c6ea6) --- .../report/stock_balance/stock_balance.py | 201 ++++++++++++++++++ .../stock_ledger_invariant_check.js | 2 +- 2 files changed, 202 insertions(+), 1 deletion(-) diff --git a/erpnext/stock/report/stock_balance/stock_balance.py b/erpnext/stock/report/stock_balance/stock_balance.py index 5ce641eb210..29d6f3e8a21 100644 --- a/erpnext/stock/report/stock_balance/stock_balance.py +++ b/erpnext/stock/report/stock_balance/stock_balance.py @@ -7,8 +7,12 @@ from typing import Any, TypedDict import frappe from frappe import _ +<<<<<<< HEAD from frappe.query_builder import Order from frappe.query_builder.functions import Coalesce +======= +from frappe.query_builder.functions import Coalesce, Count +>>>>>>> 0874cbc268 (fix: old stock reco entries causing issue in the stock balance report) from frappe.utils import add_days, cint, date_diff, flt, getdate from frappe.utils.nestedset import get_descendants_of @@ -318,6 +322,7 @@ class StockBalanceReport: sle.serial_no, sle.serial_and_batch_bundle, sle.has_serial_no, + sle.voucher_detail_no, item_table.item_group, item_table.stock_uom, item_table.item_name, @@ -337,6 +342,202 @@ class StockBalanceReport: self.sle_query = query +<<<<<<< HEAD +======= + def prepare_item_warehouse_map_for_current_period(self): + self.opening_vouchers = self.get_opening_vouchers() + + if self.filters.get("show_stock_ageing_data"): + self.sle_entries = self.sle_query.run(as_dict=True) + + self.prepare_stock_reco_voucher_wise_count() + + # HACK: This is required to avoid causing db query in flt + _system_settings = frappe.get_cached_doc("System Settings") + with frappe.db.unbuffered_cursor(): + if not self.filters.get("show_stock_ageing_data"): + self.sle_entries = self.sle_query.run(as_dict=True, as_iterator=True) + + for entry in self.sle_entries: + group_by_key = self.get_group_by_key(entry) + if group_by_key not in self.item_warehouse_map: + self.initialize_data(group_by_key, entry) + + self.prepare_item_warehouse_map(entry, group_by_key) + + self.item_warehouse_map = filter_items_with_no_transactions( + self.item_warehouse_map, self.float_precision, self.inventory_dimensions + ) + + def prepare_stock_reco_voucher_wise_count(self): + self.stock_reco_voucher_wise_count = frappe._dict() + + doctype = frappe.qb.DocType("Stock Ledger Entry") + item = frappe.qb.DocType("Item") + + query = ( + frappe.qb.from_(doctype) + .inner_join(item) + .on(doctype.item_code == item.name) + .select(doctype.voucher_detail_no, Count(doctype.name).as_("count")) + .where( + (doctype.voucher_type == "Stock Reconciliation") + & (doctype.docstatus < 2) + & (doctype.is_cancelled == 0) + & (item.has_serial_no == 1) + ) + .groupby(doctype.voucher_detail_no) + ) + + data = query.run(as_list=True) + if data: + self.stock_reco_voucher_wise_count = frappe._dict(data) + + def prepare_new_data(self): + if self.filters.get("show_stock_ageing_data"): + self.filters["show_warehouse_wise_stock"] = True + item_wise_fifo_queue = FIFOSlots(self.filters).generate() + + _func = itemgetter(1) + + del self.sle_entries + + sre_details = self.get_sre_reserved_qty_details() + + variant_values = {} + if self.filters.get("show_variant_attributes"): + variant_values = self.get_variant_values_for() + + for _key, report_data in self.item_warehouse_map.items(): + if variant_data := variant_values.get(report_data.item_code): + report_data.update(variant_data) + + if self.filters.get("show_stock_ageing_data"): + opening_fifo_queue = self.get_opening_fifo_queue(report_data) or [] + + fifo_queue = [] + if fifo_queue := item_wise_fifo_queue.get((report_data.item_code, report_data.warehouse)): + fifo_queue = fifo_queue.get("fifo_queue") + + if fifo_queue: + opening_fifo_queue.extend(fifo_queue) + + stock_ageing_data = {"average_age": 0, "earliest_age": 0, "latest_age": 0} + + if opening_fifo_queue: + fifo_queue = sorted(filter(_func, opening_fifo_queue), key=_func) + if not fifo_queue: + continue + + to_date = self.to_date + stock_ageing_data["average_age"] = get_average_age(fifo_queue, to_date) + stock_ageing_data["earliest_age"] = date_diff(to_date, fifo_queue[0][1]) + stock_ageing_data["latest_age"] = date_diff(to_date, fifo_queue[-1][1]) + stock_ageing_data["fifo_queue"] = fifo_queue + + report_data.update(stock_ageing_data) + + report_data.update( + {"reserved_stock": sre_details.get((report_data.item_code, report_data.warehouse), 0.0)} + ) + + if ( + not self.filters.get("include_zero_stock_items") + and report_data + and report_data.bal_qty == 0 + and report_data.bal_val == 0 + ): + continue + + self.data.append(report_data) + + def get_sre_reserved_qty_details(self) -> dict: + from erpnext.stock.doctype.stock_reservation_entry.stock_reservation_entry import ( + get_sre_reserved_qty_for_items_and_warehouses as get_reserved_qty_details, + ) + + item_code_list, warehouse_list = [], [] + for d in self.item_warehouse_map: + item_code_list.append(d[0]) + warehouse_list.append(d[1]) + + return get_reserved_qty_details(item_code_list, warehouse_list) + + def prepare_item_warehouse_map(self, entry, group_by_key): + qty_dict = self.item_warehouse_map[group_by_key] + for field in self.inventory_dimensions: + qty_dict[field] = entry.get(field) + + if entry.voucher_type == "Stock Reconciliation" and ( + not entry.batch_no or entry.serial_no or entry.serial_and_batch_bundle + ): + if entry.serial_no and self.stock_reco_voucher_wise_count.get(entry.voucher_detail_no, 0) == 1: + qty_dict.bal_qty = 0.0 + qty_diff = flt(entry.actual_qty) + else: + qty_diff = flt(entry.qty_after_transaction) - flt(qty_dict.bal_qty) + else: + qty_diff = flt(entry.actual_qty) + + value_diff = flt(entry.stock_value_difference) + + if entry.posting_date < self.from_date or entry.voucher_no in self.opening_vouchers.get( + entry.voucher_type, [] + ): + qty_dict.opening_qty += qty_diff + qty_dict.opening_val += value_diff + + elif entry.posting_date >= self.from_date and entry.posting_date <= self.to_date: + if flt(qty_diff, self.float_precision) >= 0: + qty_dict.in_qty += qty_diff + else: + qty_dict.out_qty += abs(qty_diff) + + if flt(value_diff, self.float_precision) >= 0: + qty_dict.in_val += value_diff + else: + qty_dict.out_val += abs(value_diff) + + qty_dict.val_rate = entry.valuation_rate + qty_dict.bal_qty += qty_diff + qty_dict.bal_val += value_diff + + def initialize_data(self, group_by_key, entry): + self.item_warehouse_map[group_by_key] = frappe._dict( + { + "item_code": entry.item_code, + "warehouse": entry.warehouse, + "item_group": entry.item_group, + "company": entry.company, + "currency": self.company_currency, + "stock_uom": entry.stock_uom, + "item_name": entry.item_name, + "opening_qty": 0.0, + "opening_val": 0.0, + "opening_fifo_queue": [], + "in_qty": 0.0, + "in_val": 0.0, + "out_qty": 0.0, + "out_val": 0.0, + "bal_qty": 0.0, + "bal_val": 0.0, + "val_rate": 0.0, + } + ) + + def get_group_by_key(self, row) -> tuple: + group_by_key = [row.item_code, row.warehouse] + + for fieldname in self.inventory_dimensions: + if not row.get(fieldname): + continue + + if self.filters.get(fieldname) or self.filters.get("show_dimension_wise_stock"): + group_by_key.append(row.get(fieldname)) + + return tuple(group_by_key) + +>>>>>>> 0874cbc268 (fix: old stock reco entries causing issue in the stock balance report) def apply_inventory_dimensions_filters(self, query, sle) -> str: inventory_dimension_fields = self.get_inventory_dimension_fields() if inventory_dimension_fields: diff --git a/erpnext/stock/report/stock_ledger_invariant_check/stock_ledger_invariant_check.js b/erpnext/stock/report/stock_ledger_invariant_check/stock_ledger_invariant_check.js index df65654e36b..1f405cda78f 100644 --- a/erpnext/stock/report/stock_ledger_invariant_check/stock_ledger_invariant_check.js +++ b/erpnext/stock/report/stock_ledger_invariant_check/stock_ledger_invariant_check.js @@ -21,7 +21,7 @@ frappe.query_reports["Stock Ledger Invariant Check"] = { options: "Item", get_query: function () { return { - filters: { is_stock_item: 1, has_serial_no: 0 }, + filters: { is_stock_item: 1 }, }; }, }, From 435c852b549820a89b6a0851940384ebf2e0b377 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Fri, 27 Feb 2026 15:46:52 +0530 Subject: [PATCH 10/11] chore: fix conflicts Added a method to prepare stock reconciliation voucher-wise count and updated logic for handling stock reconciliation entries. (cherry picked from commit cc6fbde4639237c632dee5c19c95b83b88c1a393) --- .../report/stock_balance/stock_balance.py | 234 +++--------------- 1 file changed, 32 insertions(+), 202 deletions(-) diff --git a/erpnext/stock/report/stock_balance/stock_balance.py b/erpnext/stock/report/stock_balance/stock_balance.py index 29d6f3e8a21..ccc5ba62b01 100644 --- a/erpnext/stock/report/stock_balance/stock_balance.py +++ b/erpnext/stock/report/stock_balance/stock_balance.py @@ -7,12 +7,8 @@ from typing import Any, TypedDict import frappe from frappe import _ -<<<<<<< HEAD from frappe.query_builder import Order -from frappe.query_builder.functions import Coalesce -======= from frappe.query_builder.functions import Coalesce, Count ->>>>>>> 0874cbc268 (fix: old stock reco entries causing issue in the stock balance report) from frappe.utils import add_days, cint, date_diff, flt, getdate from frappe.utils.nestedset import get_descendants_of @@ -159,6 +155,8 @@ class StockBalanceReport: if self.filters.get("show_stock_ageing_data"): self.sle_entries = self.sle_query.run(as_dict=True) + self.prepare_stock_reco_voucher_wise_count() + # HACK: This is required to avoid causing db query in flt _system_settings = frappe.get_cached_doc("System Settings") with frappe.db.unbuffered_cursor(): @@ -185,6 +183,30 @@ class StockBalanceReport: return item_warehouse_map + def prepare_stock_reco_voucher_wise_count(self): + self.stock_reco_voucher_wise_count = frappe._dict() + + doctype = frappe.qb.DocType("Stock Ledger Entry") + item = frappe.qb.DocType("Item") + + query = ( + frappe.qb.from_(doctype) + .inner_join(item) + .on(doctype.item_code == item.name) + .select(doctype.voucher_detail_no, Count(doctype.name).as_("count")) + .where( + (doctype.voucher_type == "Stock Reconciliation") + & (doctype.docstatus < 2) + & (doctype.is_cancelled == 0) + & (item.has_serial_no == 1) + ) + .groupby(doctype.voucher_detail_no) + ) + + data = query.run(as_list=True) + if data: + self.stock_reco_voucher_wise_count = frappe._dict(data) + def get_sre_reserved_qty_details(self) -> dict: from erpnext.stock.doctype.stock_reservation_entry.stock_reservation_entry import ( get_sre_reserved_qty_for_items_and_warehouses as get_reserved_qty_details, @@ -203,9 +225,13 @@ class StockBalanceReport: qty_dict[field] = entry.get(field) if entry.voucher_type == "Stock Reconciliation" and ( - not entry.batch_no and not entry.serial_no and not entry.serial_and_batch_bundle + not entry.batch_no or entry.serial_no or entry.serial_and_batch_bundle ): - qty_diff = flt(entry.qty_after_transaction) - flt(qty_dict.bal_qty) + if entry.serial_no and self.stock_reco_voucher_wise_count.get(entry.voucher_detail_no, 0) == 1: + qty_dict.bal_qty = 0.0 + qty_diff = flt(entry.actual_qty) + else: + qty_diff = flt(entry.qty_after_transaction) - flt(qty_dict.bal_qty) else: qty_diff = flt(entry.actual_qty) @@ -342,202 +368,6 @@ class StockBalanceReport: self.sle_query = query -<<<<<<< HEAD -======= - def prepare_item_warehouse_map_for_current_period(self): - self.opening_vouchers = self.get_opening_vouchers() - - if self.filters.get("show_stock_ageing_data"): - self.sle_entries = self.sle_query.run(as_dict=True) - - self.prepare_stock_reco_voucher_wise_count() - - # HACK: This is required to avoid causing db query in flt - _system_settings = frappe.get_cached_doc("System Settings") - with frappe.db.unbuffered_cursor(): - if not self.filters.get("show_stock_ageing_data"): - self.sle_entries = self.sle_query.run(as_dict=True, as_iterator=True) - - for entry in self.sle_entries: - group_by_key = self.get_group_by_key(entry) - if group_by_key not in self.item_warehouse_map: - self.initialize_data(group_by_key, entry) - - self.prepare_item_warehouse_map(entry, group_by_key) - - self.item_warehouse_map = filter_items_with_no_transactions( - self.item_warehouse_map, self.float_precision, self.inventory_dimensions - ) - - def prepare_stock_reco_voucher_wise_count(self): - self.stock_reco_voucher_wise_count = frappe._dict() - - doctype = frappe.qb.DocType("Stock Ledger Entry") - item = frappe.qb.DocType("Item") - - query = ( - frappe.qb.from_(doctype) - .inner_join(item) - .on(doctype.item_code == item.name) - .select(doctype.voucher_detail_no, Count(doctype.name).as_("count")) - .where( - (doctype.voucher_type == "Stock Reconciliation") - & (doctype.docstatus < 2) - & (doctype.is_cancelled == 0) - & (item.has_serial_no == 1) - ) - .groupby(doctype.voucher_detail_no) - ) - - data = query.run(as_list=True) - if data: - self.stock_reco_voucher_wise_count = frappe._dict(data) - - def prepare_new_data(self): - if self.filters.get("show_stock_ageing_data"): - self.filters["show_warehouse_wise_stock"] = True - item_wise_fifo_queue = FIFOSlots(self.filters).generate() - - _func = itemgetter(1) - - del self.sle_entries - - sre_details = self.get_sre_reserved_qty_details() - - variant_values = {} - if self.filters.get("show_variant_attributes"): - variant_values = self.get_variant_values_for() - - for _key, report_data in self.item_warehouse_map.items(): - if variant_data := variant_values.get(report_data.item_code): - report_data.update(variant_data) - - if self.filters.get("show_stock_ageing_data"): - opening_fifo_queue = self.get_opening_fifo_queue(report_data) or [] - - fifo_queue = [] - if fifo_queue := item_wise_fifo_queue.get((report_data.item_code, report_data.warehouse)): - fifo_queue = fifo_queue.get("fifo_queue") - - if fifo_queue: - opening_fifo_queue.extend(fifo_queue) - - stock_ageing_data = {"average_age": 0, "earliest_age": 0, "latest_age": 0} - - if opening_fifo_queue: - fifo_queue = sorted(filter(_func, opening_fifo_queue), key=_func) - if not fifo_queue: - continue - - to_date = self.to_date - stock_ageing_data["average_age"] = get_average_age(fifo_queue, to_date) - stock_ageing_data["earliest_age"] = date_diff(to_date, fifo_queue[0][1]) - stock_ageing_data["latest_age"] = date_diff(to_date, fifo_queue[-1][1]) - stock_ageing_data["fifo_queue"] = fifo_queue - - report_data.update(stock_ageing_data) - - report_data.update( - {"reserved_stock": sre_details.get((report_data.item_code, report_data.warehouse), 0.0)} - ) - - if ( - not self.filters.get("include_zero_stock_items") - and report_data - and report_data.bal_qty == 0 - and report_data.bal_val == 0 - ): - continue - - self.data.append(report_data) - - def get_sre_reserved_qty_details(self) -> dict: - from erpnext.stock.doctype.stock_reservation_entry.stock_reservation_entry import ( - get_sre_reserved_qty_for_items_and_warehouses as get_reserved_qty_details, - ) - - item_code_list, warehouse_list = [], [] - for d in self.item_warehouse_map: - item_code_list.append(d[0]) - warehouse_list.append(d[1]) - - return get_reserved_qty_details(item_code_list, warehouse_list) - - def prepare_item_warehouse_map(self, entry, group_by_key): - qty_dict = self.item_warehouse_map[group_by_key] - for field in self.inventory_dimensions: - qty_dict[field] = entry.get(field) - - if entry.voucher_type == "Stock Reconciliation" and ( - not entry.batch_no or entry.serial_no or entry.serial_and_batch_bundle - ): - if entry.serial_no and self.stock_reco_voucher_wise_count.get(entry.voucher_detail_no, 0) == 1: - qty_dict.bal_qty = 0.0 - qty_diff = flt(entry.actual_qty) - else: - qty_diff = flt(entry.qty_after_transaction) - flt(qty_dict.bal_qty) - else: - qty_diff = flt(entry.actual_qty) - - value_diff = flt(entry.stock_value_difference) - - if entry.posting_date < self.from_date or entry.voucher_no in self.opening_vouchers.get( - entry.voucher_type, [] - ): - qty_dict.opening_qty += qty_diff - qty_dict.opening_val += value_diff - - elif entry.posting_date >= self.from_date and entry.posting_date <= self.to_date: - if flt(qty_diff, self.float_precision) >= 0: - qty_dict.in_qty += qty_diff - else: - qty_dict.out_qty += abs(qty_diff) - - if flt(value_diff, self.float_precision) >= 0: - qty_dict.in_val += value_diff - else: - qty_dict.out_val += abs(value_diff) - - qty_dict.val_rate = entry.valuation_rate - qty_dict.bal_qty += qty_diff - qty_dict.bal_val += value_diff - - def initialize_data(self, group_by_key, entry): - self.item_warehouse_map[group_by_key] = frappe._dict( - { - "item_code": entry.item_code, - "warehouse": entry.warehouse, - "item_group": entry.item_group, - "company": entry.company, - "currency": self.company_currency, - "stock_uom": entry.stock_uom, - "item_name": entry.item_name, - "opening_qty": 0.0, - "opening_val": 0.0, - "opening_fifo_queue": [], - "in_qty": 0.0, - "in_val": 0.0, - "out_qty": 0.0, - "out_val": 0.0, - "bal_qty": 0.0, - "bal_val": 0.0, - "val_rate": 0.0, - } - ) - - def get_group_by_key(self, row) -> tuple: - group_by_key = [row.item_code, row.warehouse] - - for fieldname in self.inventory_dimensions: - if not row.get(fieldname): - continue - - if self.filters.get(fieldname) or self.filters.get("show_dimension_wise_stock"): - group_by_key.append(row.get(fieldname)) - - return tuple(group_by_key) - ->>>>>>> 0874cbc268 (fix: old stock reco entries causing issue in the stock balance report) def apply_inventory_dimensions_filters(self, query, sle) -> str: inventory_dimension_fields = self.get_inventory_dimension_fields() if inventory_dimension_fields: From b2a8af5ba66a775e9a1887ae03235d68062c7e63 Mon Sep 17 00:00:00 2001 From: Frappe PR Bot Date: Fri, 27 Feb 2026 10:50:36 +0000 Subject: [PATCH 11/11] chore(release): Bumped to Version 15.99.1 ## [15.99.1](https://github.com/frappe/erpnext/compare/v15.99.0...v15.99.1) (2026-02-27) ### Bug Fixes * old stock reco entries causing issue in the stock balance report ([bba0a6d](https://github.com/frappe/erpnext/commit/bba0a6d9508f7ee2d18f65b85e103ef686eb401f)) --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index df14a255c1e..467aa3a3c59 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -4,7 +4,7 @@ import inspect import frappe from frappe.utils.user import is_website_user -__version__ = "15.99.0" +__version__ = "15.99.1" def get_default_company(user=None):