From 0b565026a4d179ee6eca5a1a9f47d7df87ab9f72 Mon Sep 17 00:00:00 2001 From: Frappe PR Bot Date: Wed, 7 Jan 2026 05:01:14 +0000 Subject: [PATCH 01/13] chore(release): Bumped to Version 15.94.0 # [15.94.0](https://github.com/frappe/erpnext/compare/v15.93.2...v15.94.0) (2026-01-07) ### Bug Fixes * add company filters to project ([d6511b0](https://github.com/frappe/erpnext/commit/d6511b00451e713d85b99e195ad9afb9b35ab962)) * **journal entry:** use submission_queue to perform submit and cancel actions for rows over 100 ([1d58e9b](https://github.com/frappe/erpnext/commit/1d58e9b91a9d135919c76413881f0ffa6a7cf201)) * not able to submit backdated stock reco ([4b60979](https://github.com/frappe/erpnext/commit/4b6097914abfe5f602723dd83faeb1f0082f7e15)) * precision issue causing reservation error ([2d49cc9](https://github.com/frappe/erpnext/commit/2d49cc9ab28e49afbdb1e12a432d539a7c40427f)) * resolve conflict ([dbd2964](https://github.com/frappe/erpnext/commit/dbd2964139de1f66d39d40447c4ababf0e3a216d)) * SABB not cancelled on cancel of Stock Reco ([eebd885](https://github.com/frappe/erpnext/commit/eebd88529fe3f639f7437cb0f1c52cf736982b76)) * **stock:** prevent excess stock reservation ([4d31012](https://github.com/frappe/erpnext/commit/4d31012df23b359d84c434fe0b618d616d063986)) * **stock:** remove item image to avoid setting the image of previous item ([6f1cfdb](https://github.com/frappe/erpnext/commit/6f1cfdb1de987303c153a41cc4b26517258f1e54)) * **trial balance party:** add check for parties with zero credit and debit ([a0566c9](https://github.com/frappe/erpnext/commit/a0566c9e98b6c6e75ad9202bc882536f7b53d31f)) * update filters on period closing voucher ([728a8b0](https://github.com/frappe/erpnext/commit/728a8b0b7dfcfe04f67d4e0e542a0cd01af00f05)) ### Features * add default-age-range in accounts settings (backport [#51458](https://github.com/frappe/erpnext/issues/51458)) ([#51531](https://github.com/frappe/erpnext/issues/51531)) ([582db48](https://github.com/frappe/erpnext/commit/582db48ca521ad958ddb21b28ab383f624498971)) * allow data import for asset repair doctype ([dc10ef4](https://github.com/frappe/erpnext/commit/dc10ef4287d90028f9a4d2ea74b91af32e51d4de)) --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index b9dfd4326d3..a0e7a435210 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.93.2" +__version__ = "15.94.0" def get_default_company(user=None): From 69259c9933f6104cd2df3f1ad081d7d113d6c6dc Mon Sep 17 00:00:00 2001 From: kavin-114 Date: Wed, 7 Jan 2026 01:00:29 +0530 Subject: [PATCH 02/13] fix: remove posting date & time on SRE batch validation (cherry picked from commit d3f2da0d594434e7d6a18654898a5a23a1e3fbf6) --- erpnext/stock/stock_ledger.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py index d00d092e795..0040aec77dc 100644 --- a/erpnext/stock/stock_ledger.py +++ b/erpnext/stock/stock_ledger.py @@ -2337,8 +2337,6 @@ def validate_reserved_batch_nos(kwargs): { "item_code": kwargs.item_code, "warehouse": kwargs.warehouse, - "posting_date": kwargs.posting_date, - "posting_time": kwargs.posting_time, "ignore_voucher_nos": kwargs.ignore_voucher_nos, "ignore_reserved_stock": True, } From c805c7fac460af0b97cebc9aadd857b85df6adca Mon Sep 17 00:00:00 2001 From: Frappe PR Bot Date: Thu, 8 Jan 2026 08:16:29 +0000 Subject: [PATCH 03/13] chore(release): Bumped to Version 15.94.1 ## [15.94.1](https://github.com/frappe/erpnext/compare/v15.94.0...v15.94.1) (2026-01-08) ### Bug Fixes * remove posting date & time on SRE batch validation ([69259c9](https://github.com/frappe/erpnext/commit/69259c9933f6104cd2df3f1ad081d7d113d6c6dc)) --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index a0e7a435210..2c4eae39a31 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.94.0" +__version__ = "15.94.1" def get_default_company(user=None): From ddca3b580028a418b360ad0d6b1cc54ef9b86cdd Mon Sep 17 00:00:00 2001 From: Frappe PR Bot Date: Tue, 13 Jan 2026 15:02:59 +0000 Subject: [PATCH 04/13] chore(release): Bumped to Version 15.94.2 ## [15.94.2](https://github.com/frappe/erpnext/compare/v15.94.1...v15.94.2) (2026-01-13) ### Bug Fixes * **accounting-dimension:** System-generated round-off GL entries fail to set the accounting dimension ([#51167](https://github.com/frappe/erpnext/issues/51167)) ([1179514](https://github.com/frappe/erpnext/commit/1179514118a07465867e06ed336f7e885eab6c66)) * **accounts:** correct sales order item deletion message for MR and PO linkage ([4c53af0](https://github.com/frappe/erpnext/commit/4c53af049464b7458a971e3f1231359255f9aaf4)) * allow all users of supplier to create purchase invoices ([8f1509d](https://github.com/frappe/erpnext/commit/8f1509dca18a949c415da23f5db908a62cd2a80d)) * **asset value adjustment:** skip cancelling revaluation journal entry if already cancelled ([dae6adf](https://github.com/frappe/erpnext/commit/dae6adfe13a07061ee89a772fa5e04903ea0d63c)) * **asset:** properly reset purchase reference and item fields ([ea0b768](https://github.com/frappe/erpnext/commit/ea0b76831f8c202f88234d792ebef0876b5ebedc)) * **asset:** remove references for composite and existing asset ([c7f79d1](https://github.com/frappe/erpnext/commit/c7f79d16e94ab7fd0ad3888962ca077fd43881ab)) * change float types in payment entry reference table to currency ([d17deba](https://github.com/frappe/erpnext/commit/d17debabf70fd307cb334d3f18f2951f446e6a26)) * closed WO becomes open when RM is returned ([7db6ae8](https://github.com/frappe/erpnext/commit/7db6ae8bda7a6ad88206083f9139028824e3e4e0)) * correct uom reflecting in sales order when fetching from barcode ([3cc41cf](https://github.com/frappe/erpnext/commit/3cc41cf643aca0bfacdf6dc3b302432ddabea5b5)) * don't duplicate default income account to Item ([#50413](https://github.com/frappe/erpnext/issues/50413)) ([1cb22f9](https://github.com/frappe/erpnext/commit/1cb22f9d057612e4e592494e472c4d962236d828)), closes [#48231](https://github.com/frappe/erpnext/issues/48231) * ignore permissions when cancelling revaluation journal entry ([129457b](https://github.com/frappe/erpnext/commit/129457b2ce1766566a94b00faad2849cdf064d67)) * incoming rate calculation ([01af6c8](https://github.com/frappe/erpnext/commit/01af6c876262bf03077503ad7c12e23b9def9fca)) * **minor:** hide target_qty field from the capitalization ([ed05b4c](https://github.com/frappe/erpnext/commit/ed05b4cc5cd026f2100ba7249b6007a913992dda)) * move validation to before_cancel ([11d23e1](https://github.com/frappe/erpnext/commit/11d23e1a4a3ada7549640aabba04a9a838d6db3d)) * negative stock issue for higher precision ([1bbeecf](https://github.com/frappe/erpnext/commit/1bbeecff12ee22efccf0c1e8583d52aecd78bbb7)) * **payment reconciliation:** handle adhoc payment returns ([#51311](https://github.com/frappe/erpnext/issues/51311)) ([159d1d6](https://github.com/frappe/erpnext/commit/159d1d61b5bc58e8c180e1e48590c1841adcdf94)) * pick list qty does not reset when pick list is cancelled ([f9be364](https://github.com/frappe/erpnext/commit/f9be364bd1fca6bfb5af362aa17b9a5e9a9c6ae9)) * prevent manual cancellation of the linked Revaluation Journal Entry ([07de3f4](https://github.com/frappe/erpnext/commit/07de3f43915f40644e3e32862899c45bbbd2b819)) * remove posting date & time on SRE batch validation ([d3f2da0](https://github.com/frappe/erpnext/commit/d3f2da0d594434e7d6a18654898a5a23a1e3fbf6)) * **stock:** enable allow on submit for tracking status field ([9d5a493](https://github.com/frappe/erpnext/commit/9d5a493609ed6c4e2741b393b2bdede64b1d06f6)) ### Performance Improvements * SABB taking time to save the record ([ee9debe](https://github.com/frappe/erpnext/commit/ee9debe581432dbaec3c83e780a6e61c0360e89a)) --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 2c4eae39a31..f4534705fd5 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.94.1" +__version__ = "15.94.2" def get_default_company(user=None): From 9819ed112bdb4d1a8030a8a4155e64661e1cbdc2 Mon Sep 17 00:00:00 2001 From: diptanilsaha Date: Wed, 14 Jan 2026 01:34:20 +0530 Subject: [PATCH 05/13] fix(transaction.js): use flt instead of cint for plc_conversion_rate (cherry picked from commit 8b445e04e57ecfb25a22e767c455c3cabe173cb6) # Conflicts: # erpnext/public/js/controllers/transaction.js (cherry picked from commit f618bf212ff468a89b236b170e52c0ef5ccbebb6) --- erpnext/public/js/controllers/transaction.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index 7abdbe75fd5..c8fdad3f6ba 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -1332,9 +1332,18 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe plc_conversion_rate() { if(this.frm.doc.price_list_currency === this.get_company_currency()) { this.frm.set_value("plc_conversion_rate", 1.0); +<<<<<<< HEAD } else if(this.frm.doc.price_list_currency === this.frm.doc.currency && this.frm.doc.plc_conversion_rate && cint(this.frm.doc.plc_conversion_rate) != 1 && cint(this.frm.doc.plc_conversion_rate) != cint(this.frm.doc.conversion_rate)) { +======= + } else if ( + this.frm.doc.price_list_currency === this.frm.doc.currency && + this.frm.doc.plc_conversion_rate && + flt(this.frm.doc.plc_conversion_rate) != 1 && + flt(this.frm.doc.plc_conversion_rate) != flt(this.frm.doc.conversion_rate) + ) { +>>>>>>> 8b445e04e5 (fix(transaction.js): use flt instead of cint for plc_conversion_rate) this.frm.set_value("conversion_rate", this.frm.doc.plc_conversion_rate); } From 14d197d9eb780a8feaa8c72752a0d060059310c5 Mon Sep 17 00:00:00 2001 From: Diptanil Saha Date: Wed, 14 Jan 2026 15:54:10 +0530 Subject: [PATCH 06/13] chore: resolve conflict (cherry picked from commit d5982cab030f1b6c3c6f28354aa068ead64d9fb7) --- erpnext/public/js/controllers/transaction.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index c8fdad3f6ba..898e8347292 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -1332,18 +1332,12 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe plc_conversion_rate() { if(this.frm.doc.price_list_currency === this.get_company_currency()) { this.frm.set_value("plc_conversion_rate", 1.0); -<<<<<<< HEAD - } else if(this.frm.doc.price_list_currency === this.frm.doc.currency - && this.frm.doc.plc_conversion_rate && cint(this.frm.doc.plc_conversion_rate) != 1 && - cint(this.frm.doc.plc_conversion_rate) != cint(this.frm.doc.conversion_rate)) { -======= } else if ( this.frm.doc.price_list_currency === this.frm.doc.currency && this.frm.doc.plc_conversion_rate && flt(this.frm.doc.plc_conversion_rate) != 1 && flt(this.frm.doc.plc_conversion_rate) != flt(this.frm.doc.conversion_rate) ) { ->>>>>>> 8b445e04e5 (fix(transaction.js): use flt instead of cint for plc_conversion_rate) this.frm.set_value("conversion_rate", this.frm.doc.plc_conversion_rate); } From d82ab066bd67c6a4584f72c3bb8848da41496378 Mon Sep 17 00:00:00 2001 From: Frappe PR Bot Date: Wed, 14 Jan 2026 12:17:05 +0000 Subject: [PATCH 07/13] chore(release): Bumped to Version 15.94.3 ## [15.94.3](https://github.com/frappe/erpnext/compare/v15.94.2...v15.94.3) (2026-01-14) ### Bug Fixes * **transaction.js:** use flt instead of cint for plc_conversion_rate ([9819ed1](https://github.com/frappe/erpnext/commit/9819ed112bdb4d1a8030a8a4155e64661e1cbdc2)) --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index f4534705fd5..5b076e38dc6 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.94.2" +__version__ = "15.94.3" def get_default_company(user=None): From 1e16e751ee43f9cc676a1711eb094d10c73eba40 Mon Sep 17 00:00:00 2001 From: Frappe PR Bot Date: Tue, 20 Jan 2026 16:40:54 +0000 Subject: [PATCH 08/13] chore(release): Bumped to Version 15.95.0 # [15.95.0](https://github.com/frappe/erpnext/compare/v15.94.3...v15.95.0) (2026-01-20) ### Bug Fixes * **accounts_controller:** make return message translatable ([8f6095d](https://github.com/frappe/erpnext/commit/8f6095d05f1d1d8f162e227ff4bdcd106601a09c)) * **accounts:** add missing accounting dimensions in advance taxes and charges ([1d5f406](https://github.com/frappe/erpnext/commit/1d5f406930c9783d27d0bff29c86a590c6a37cf9)) * add other charges in total ([3ef4fa5](https://github.com/frappe/erpnext/commit/3ef4fa51dcdede9d0dce0444a76106b18e971b52)) * allow disassemble stock entry without work order (backport [#51761](https://github.com/frappe/erpnext/issues/51761)) ([#51835](https://github.com/frappe/erpnext/issues/51835)) ([be20698](https://github.com/frappe/erpnext/commit/be2069883ed743286f5cc559f9e474d45d0f1696)) * calculate net profit amount from root node accounts ([e9573b0](https://github.com/frappe/erpnext/commit/e9573b0b933bee4721cd12838f548f75b6701a64)) * common_party_path ([#51826](https://github.com/frappe/erpnext/issues/51826)) ([6225217](https://github.com/frappe/erpnext/commit/62252170dd14528b9d140d480696a923fc856ad4)) * docs_path ([b3df300](https://github.com/frappe/erpnext/commit/b3df300ea5a936f6ecc7bb213970d8c64e5bc336)) * **manufacturing:** consider process loss qty while validating the work order ([4418fb4](https://github.com/frappe/erpnext/commit/4418fb48a9f30e660b878d62389cc7ea21ccec8c)) * **pos:** reapply set warehouse during cart update ([75b4a0a](https://github.com/frappe/erpnext/commit/75b4a0a89ce218d7afdb376b760dfa26bbb4043d)) * **postgres:** compute current month sales without DATE_FORMAT ([fbf4305](https://github.com/frappe/erpnext/commit/fbf4305028da9168b64756872a431eba3924e9c7)) * **postgres:** fix v15 migration failures on Postgres ([#51481](https://github.com/frappe/erpnext/issues/51481)) ([eef26fe](https://github.com/frappe/erpnext/commit/eef26fea9adc2aa561f39ce88279cf342be17a5d)) * prevent UOM from updating incorrectly while scanning barcode ([d196956](https://github.com/frappe/erpnext/commit/d1969563071af34f44845897d73ab1d05cf00807)) * **process statement of accounts:** allow renaming ([8b2778b](https://github.com/frappe/erpnext/commit/8b2778b29f711f47414c3501372e1a158cb38576)) * **process statement of accounts:** naming of reports ([054468a](https://github.com/frappe/erpnext/commit/054468a5eff3d583827661992aeddc23091bfa0c)) * RFQ does not fetch html response ([90e8090](https://github.com/frappe/erpnext/commit/90e8090dccf396ad72b5b219ca786ab592c4548e)) * **sales analytics:** add curve filter ([c2995f6](https://github.com/frappe/erpnext/commit/c2995f6800f6bdcd462590e2908837a7c590afb3)) * Show non-SLE vouchers with GL entries in Stock vs Account Value Comparison report ([6219d7d](https://github.com/frappe/erpnext/commit/6219d7d9a59ea57af02d14e55424fca64b255f53)) * **stock entry:** calculate transferred quantity using transfer_qty (backport [#51656](https://github.com/frappe/erpnext/issues/51656)) ([#51675](https://github.com/frappe/erpnext/issues/51675)) ([1da781f](https://github.com/frappe/erpnext/commit/1da781f2aedd9d7fa1a33b82f90203ae9f4f5c0c)) * **stock:** resolve quantity issue when adding items via barcode scan ([c508ef5](https://github.com/frappe/erpnext/commit/c508ef5b82bd2b38db0a09128ec007ee913ccc13)) * **transaction.js:** use flt instead of cint for plc_conversion_rate ([f618bf2](https://github.com/frappe/erpnext/commit/f618bf212ff468a89b236b170e52c0ef5ccbebb6)) * valuation rate for non batchwise valuation ([3008c7a](https://github.com/frappe/erpnext/commit/3008c7ad82eec6d7ef157421f5cf39660b851cc0)) ### Features * add new 2025 Charts of Accounts for France ([6af6fe8](https://github.com/frappe/erpnext/commit/6af6fe82046c83788c1a1c7434204506f91023d8)) * **process statement of accounts:** added more frequency options for auto email ([546ab05](https://github.com/frappe/erpnext/commit/546ab05eb5ff596a36231314ff51b148a175b2ab)) * remove old French chart of accounts with code as nex 2025 is provided ([e568ab2](https://github.com/frappe/erpnext/commit/e568ab2255cd60fa16d616d5e1d214ffdb6a1a2c)) ### Performance Improvements * prevent duplicate reposting for the same item ([eff9595](https://github.com/frappe/erpnext/commit/eff9595e342facbbca804f8b4da56d28628b3b07)) --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 5b076e38dc6..8bd5d6c2a0e 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.94.3" +__version__ = "15.95.0" def get_default_company(user=None): From b268de460967f3eb2de2d1f28cc464ae9c2fd3e3 Mon Sep 17 00:00:00 2001 From: Frappe PR Bot Date: Wed, 28 Jan 2026 04:14:22 +0000 Subject: [PATCH 09/13] chore(release): Bumped to Version 15.95.1 ## [15.95.1](https://github.com/frappe/erpnext/compare/v15.95.0...v15.95.1) (2026-01-28) ### Bug Fixes * allow creation of DN in SI for items not having DN reference ([184fa88](https://github.com/frappe/erpnext/commit/184fa889c33b13b184132dea6d35e0621e7124ff)) * **asset capitalization:** update asset values using db_set ([74bf61e](https://github.com/frappe/erpnext/commit/74bf61e0c152507b954ff8e07326d6dbcd771cdb)) * autofill warehouse for packed items ([0a87fa5](https://github.com/frappe/erpnext/commit/0a87fa53489ef01b984b8d517f56aa8cd9404c8e)) * Bin reserved qty for production for extra material transfer ([b5d8477](https://github.com/frappe/erpnext/commit/b5d84773545362715f61dbe17930a977fa81ee43)) * check the payment ledger entry has the dimension ([#51823](https://github.com/frappe/erpnext/issues/51823)) ([468ec80](https://github.com/frappe/erpnext/commit/468ec805f101283124797063865644f113a7c718)) * Ensure paid_amount is always numeric before calling allocate_amount_to_references (backport [#50935](https://github.com/frappe/erpnext/issues/50935)) ([#52035](https://github.com/frappe/erpnext/issues/52035)) ([9fce694](https://github.com/frappe/erpnext/commit/9fce694936f38ba62399aba9ba28517462c0731f)) * handle parent level project change ([7146c03](https://github.com/frappe/erpnext/commit/7146c0385cdf13322c80ff8daf112dfc4856d295)) * handle undefined bank_transaction_mapping in quick entry ([d4195d3](https://github.com/frappe/erpnext/commit/d4195d31bf49e889b43bb82d1af266057e4cc607)) * job cards should not be deleted on close of WO ([8d06ee3](https://github.com/frappe/erpnext/commit/8d06ee3966271fbfec499a4409c00a73f8fca0e4)) * **journal-entry:** prevent submit failure due to double background queuing (backport [#52083](https://github.com/frappe/erpnext/issues/52083)) ([#52086](https://github.com/frappe/erpnext/issues/52086)) ([72a9b58](https://github.com/frappe/erpnext/commit/72a9b58b14c310da75e7632ae71c987945edd66f)) * negative stock for purchae return ([f9fd0ff](https://github.com/frappe/erpnext/commit/f9fd0ffbae96f2191cdfffe72681f00dbb29966b)) * **payment entry:** update currency symbol (backport [#51956](https://github.com/frappe/erpnext/issues/51956)) ([#52093](https://github.com/frappe/erpnext/issues/52093)) ([934b549](https://github.com/frappe/erpnext/commit/934b5494f012b05e245c4a35816119322edcfec0)) * **project:** add missing counter to project update naming series ([f61305a](https://github.com/frappe/erpnext/commit/f61305aa4560f585fc572bb42a2a8f093bca3ad1)) * rejected qty in PR doesn't consider conversion factor ([83352b5](https://github.com/frappe/erpnext/commit/83352b5a34ac5a127f2b6ff289b282a9746dcb42)) * **sales order:** set project at item level from parent ([a09b73e](https://github.com/frappe/erpnext/commit/a09b73e65d98253f1a6f370504cb6408bed87496)) * **shipment:** user contact validation to use full name ([90dc22a](https://github.com/frappe/erpnext/commit/90dc22a57d51c54b4b2c1ccd7a0c33276cef3fc5)) * show message if image is removed from item description ([0c89cd5](https://github.com/frappe/erpnext/commit/0c89cd55248a7d9bab6750375fb6ae7c9a4e339c)) * **stock:** use purchase UOM in Supplier Quotation items ([dadd4b1](https://github.com/frappe/erpnext/commit/dadd4b1f95937811472a51334718fbafa1755c66)) * strip whitespace in customer_name ([853faca](https://github.com/frappe/erpnext/commit/853facad96410205b2ebf9b26e68c9085e2e6395)) * swedish_address_template ([5e61922](https://github.com/frappe/erpnext/commit/5e6192249e5dc20c322f00f9d26e4353f5239d71)) * UOM of item not fetching in BOM ([14de520](https://github.com/frappe/erpnext/commit/14de520ebb9307004faa34199f80ba756fa2e360)) * update country_wise_tax.json for Algerian Taxes (backport [#51878](https://github.com/frappe/erpnext/issues/51878)) ([#52037](https://github.com/frappe/erpnext/issues/52037)) ([d89ac99](https://github.com/frappe/erpnext/commit/d89ac99e761816e62668c342152dce35ee4dca17)) * validation to check at-least one raw material for manufacture entry ([650f874](https://github.com/frappe/erpnext/commit/650f874fbdd7cc949c6e2088ed91df8249119e91)) --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 8bd5d6c2a0e..317d8b4b6b3 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.0" +__version__ = "15.95.1" def get_default_company(user=None): From 65ed4e5cf611b412f4c6fed723c6d33bb45b955f Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Thu, 29 Jan 2026 14:30:22 +0530 Subject: [PATCH 10/13] Merge pull request #52140 from frappe/mergify/bp/version-15-hotfix/pr-52007 Fix: Set Zero Rate for Standalone Credit Note with Expired Batch (backport #52007) (cherry picked from commit ad8c8cb0e81b322fbbeb837d5765444629cd70ee) --- .../sales_invoice/test_sales_invoice.py | 60 +++++++++++++++++++ .../controllers/sales_and_purchase_return.py | 39 +++++++++++- erpnext/controllers/selling_controller.py | 21 ++++++- .../selling_settings/selling_settings.json | 12 +++- .../selling_settings/selling_settings.py | 1 + 5 files changed, 127 insertions(+), 6 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index bd8af98b16f..f9b6ab4f07c 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -4775,6 +4775,66 @@ class TestSalesInvoice(FrappeTestCase): self.assertEqual(q[0][0], 1) + @change_settings("Selling Settings", {"set_zero_rate_for_expired_batch": True}) + def test_zero_valuation_for_standalone_credit_note_with_expired_batch(self): + item_code = "_Test Item for Expiry Batch Zero Valuation" + make_item_for_si( + item_code, + { + "is_stock_item": 1, + "has_batch_no": 1, + "has_expiry_date": 1, + "shelf_life_in_days": 2, + "create_new_batch": 1, + "batch_number_series": "TBATCH-EBZV.####", + }, + ) + + se = make_stock_entry( + item_code=item_code, + qty=10, + target="_Test Warehouse - _TC", + rate=100, + ) + + # fetch batch no from bundle + batch_no = get_batch_from_bundle(se.items[0].serial_and_batch_bundle) + + si = create_sales_invoice( + posting_date=add_days(nowdate(), 3), + item=item_code, + qty=-10, + rate=100, + is_return=1, + update_stock=1, + use_serial_batch_fields=1, + do_not_save=1, + do_not_submit=1, + ) + + si.items[0].batch_no = batch_no + si.save() + si.submit() + + si.reload() + # check zero incoming rate in voucher + self.assertEqual(si.items[0].incoming_rate, 0.0) + + # chekc zero incoming rate in stock ledger + stock_ledger_entry = frappe.db.get_value( + "Stock Ledger Entry", + { + "voucher_type": "Sales Invoice", + "voucher_no": si.name, + "item_code": item_code, + "warehouse": "_Test Warehouse - _TC", + }, + ["incoming_rate", "valuation_rate"], + as_dict=True, + ) + + self.assertEqual(stock_ledger_entry.incoming_rate, 0.0) + def make_item_for_si(item_code, properties=None): from erpnext.stock.doctype.item.test_item import make_item diff --git a/erpnext/controllers/sales_and_purchase_return.py b/erpnext/controllers/sales_and_purchase_return.py index c774c3de341..d3d5cb808f3 100644 --- a/erpnext/controllers/sales_and_purchase_return.py +++ b/erpnext/controllers/sales_and_purchase_return.py @@ -11,7 +11,7 @@ from frappe.utils import cint, flt, format_datetime, get_datetime import erpnext from erpnext.stock.serial_batch_bundle import get_batches_from_bundle from erpnext.stock.serial_batch_bundle import get_serial_nos as get_serial_nos_from_bundle -from erpnext.stock.utils import get_incoming_rate, get_valuation_method +from erpnext.stock.utils import get_incoming_rate, get_valuation_method, getdate class StockOverReturnError(frappe.ValidationError): @@ -683,6 +683,29 @@ def get_rate_for_return( else: select_field = "abs(stock_value_difference / actual_qty)" + item_details = frappe.get_cached_value("Item", item_code, ["has_batch_no", "has_expiry_date"], as_dict=1) + set_zero_rate_for_expired_batch = frappe.db.get_single_value( + "Selling Settings", "set_zero_rate_for_expired_batch" + ) + + if ( + set_zero_rate_for_expired_batch + and item_details.has_batch_no + and item_details.has_expiry_date + and not return_against + and voucher_type in ["Sales Invoice", "Delivery Note"] + ): + # set incoming_rate zero explicitly for standalone credit note with expired batch + batch_no = frappe.db.get_value(f"{voucher_type} Item", voucher_detail_no, "batch_no") + if batch_no and is_batch_expired(batch_no, sle.get("posting_date")): + frappe.db.set_value( + voucher_type + " Item", + voucher_detail_no, + "incoming_rate", + 0, + ) + return 0 + rate = flt(frappe.db.get_value("Stock Ledger Entry", filters, select_field)) if not (rate and return_against) and voucher_type in ["Sales Invoice", "Delivery Note"]: rate = frappe.db.get_value(f"{voucher_type} Item", voucher_detail_no, "incoming_rate") @@ -1152,3 +1175,17 @@ def get_available_serial_nos(serial_nos, warehouse): def get_payment_data(invoice): payment = frappe.db.get_all("Sales Invoice Payment", {"parent": invoice}, ["mode_of_payment", "amount"]) return payment + + +def is_batch_expired(batch_no, posting_date): + """ + To check whether the batch is expired or not based on the posting date. + """ + expiry_date = frappe.db.get_value("Batch", batch_no, "expiry_date") + if not expiry_date: + return + + if getdate(posting_date) > getdate(expiry_date): + return True + + return False diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py index 3667a7a7e76..5c2dc7491c2 100644 --- a/erpnext/controllers/selling_controller.py +++ b/erpnext/controllers/selling_controller.py @@ -8,7 +8,7 @@ from frappe.utils import cint, flt, get_link_to_form, nowtime from erpnext.accounts.party import render_address from erpnext.controllers.accounts_controller import get_taxes_and_charges -from erpnext.controllers.sales_and_purchase_return import get_rate_for_return +from erpnext.controllers.sales_and_purchase_return import get_rate_for_return, is_batch_expired from erpnext.controllers.stock_controller import StockController from erpnext.stock.doctype.item.item import set_item_default from erpnext.stock.get_item_details import get_bin_details, get_conversion_factor @@ -521,16 +521,31 @@ class SellingController(StockController): allow_at_arms_length_price = frappe.get_cached_value( "Stock Settings", None, "allow_internal_transfer_at_arms_length_price" ) + set_zero_rate_for_expired_batch = frappe.db.get_single_value( + "Selling Settings", "set_zero_rate_for_expired_batch" + ) + items = self.get("items") + (self.get("packed_items") or []) for d in items: if not frappe.get_cached_value("Item", d.item_code, "is_stock_item"): continue item_details = frappe.get_cached_value( - "Item", d.item_code, ["has_serial_no", "has_batch_no"], as_dict=1 + "Item", d.item_code, ["has_serial_no", "has_batch_no", "has_expiry_date"], as_dict=1 ) - if not self.get("return_against") or ( + if ( + set_zero_rate_for_expired_batch + and item_details.has_batch_no + and item_details.has_expiry_date + and self.get("is_return") + and not self.get("return_against") + and is_batch_expired(d.batch_no, self.get("posting_date")) + ): + # set incoming rate as zero for stand-lone credit note with expired batch + d.incoming_rate = 0 + + elif not self.get("return_against") or ( get_valuation_method(d.item_code) == "Moving Average" and self.get("is_return") and not item_details.has_serial_no diff --git a/erpnext/selling/doctype/selling_settings/selling_settings.json b/erpnext/selling/doctype/selling_settings/selling_settings.json index d2f8945eb29..5bef5bc55a2 100644 --- a/erpnext/selling/doctype/selling_settings/selling_settings.json +++ b/erpnext/selling/doctype/selling_settings/selling_settings.json @@ -35,7 +35,8 @@ "hide_tax_id", "enable_discount_accounting", "allow_zero_qty_in_quotation", - "allow_zero_qty_in_sales_order" + "allow_zero_qty_in_sales_order", + "set_zero_rate_for_expired_batch" ], "fields": [ { @@ -224,6 +225,13 @@ "fieldname": "fallback_to_default_price_list", "fieldtype": "Check", "label": "Use Prices from Default Price List as Fallback" + }, + { + "default": "0", + "description": "If enabled, system will set incoming rate as zero for stand-alone credit notes with expired batch item.", + "fieldname": "set_zero_rate_for_expired_batch", + "fieldtype": "Check", + "label": "Set Incoming Rate as Zero for Expired Batch" } ], "grid_page_length": 50, @@ -232,7 +240,7 @@ "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2026-01-21 17:28:37.027837", + "modified": "2026-01-24 00:04:33.105916", "modified_by": "Administrator", "module": "Selling", "name": "Selling Settings", diff --git a/erpnext/selling/doctype/selling_settings/selling_settings.py b/erpnext/selling/doctype/selling_settings/selling_settings.py index f15fdc7041d..cad8385ab73 100644 --- a/erpnext/selling/doctype/selling_settings/selling_settings.py +++ b/erpnext/selling/doctype/selling_settings/selling_settings.py @@ -41,6 +41,7 @@ class SellingSettings(Document): role_to_override_stop_action: DF.Link | None sales_update_frequency: DF.Literal["Monthly", "Each Transaction", "Daily"] selling_price_list: DF.Link | None + set_zero_rate_for_expired_batch: DF.Check so_required: DF.Literal["No", "Yes"] territory: DF.Link | None validate_selling_price: DF.Check From 6ea4f1a03d82680117f4041ae14ad030f0e02a98 Mon Sep 17 00:00:00 2001 From: kavin-114 Date: Thu, 29 Jan 2026 00:20:23 +0530 Subject: [PATCH 11/13] fix(stock): set incoming_rate with lcv rate for internal purchase (cherry picked from commit f0dccc3cd7c797a62bbbba4894857dbbe9a60981) (cherry picked from commit 41c592a1a8668ddf8ab7847857e7d981561679c6) --- erpnext/stock/stock_ledger.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py index 55e30258044..be351b195e2 100644 --- a/erpnext/stock/stock_ledger.py +++ b/erpnext/stock/stock_ledger.py @@ -2377,6 +2377,7 @@ def get_incoming_rate_for_inter_company_transfer(sle) -> float: For inter company transfer, incoming rate is the average of the outgoing rate """ rate = 0.0 + lcv_rate = 0.0 field = "delivery_note_item" if sle.voucher_type == "Purchase Receipt" else "sales_invoice_item" @@ -2391,7 +2392,15 @@ def get_incoming_rate_for_inter_company_transfer(sle) -> float: "incoming_rate", ) - return rate + # add lcv amount in incoming_rate + lcv_amount = frappe.db.get_value( + f"{sle.voucher_type} Item", sle.voucher_detail_no, "landed_cost_voucher_amount" + ) + + if lcv_amount: + lcv_rate = flt(lcv_amount / abs(sle.actual_qty)) + + return rate + lcv_rate def is_internal_transfer(sle): From 419df361a7c8feec83f586d3ef84836196c36646 Mon Sep 17 00:00:00 2001 From: kavin-114 Date: Thu, 29 Jan 2026 00:21:02 +0530 Subject: [PATCH 12/13] test: add unit test to check internal purchase with lcv (cherry picked from commit dd4fd89ef84126332552a202a69abe4fa5aad1e3) (cherry picked from commit 3ccd1b4a6cd9370f621d13d5dd80df3022d1cb98) --- .../purchase_receipt/test_purchase_receipt.py | 78 +++++++++++++++++++ erpnext/stock/stock_ledger.py | 1 - 2 files changed, 78 insertions(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py index ee7b327adca..341c38bdcf1 100644 --- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py @@ -4716,6 +4716,84 @@ class TestPurchaseReceipt(FrappeTestCase): return_pr = make_return_doc("Purchase Receipt", pr.name) self.assertRaises(frappe.ValidationError, return_pr.submit) + def test_internal_purchase_receipt_incoming_rate_with_lcv(self): + """ + To test inter branch transaction incoming rate calculation with lcv after item reposting + """ + from erpnext.stock.doctype.delivery_note.delivery_note import make_inter_company_purchase_receipt + from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note + + prepare_data_for_internal_transfer() + customer = "_Test Internal Customer 2" + company = "_Test Company with perpetual inventory" + item_doc = create_item("_Test Internal PR LCV Item") + lcv_expense_account = "Expenses Included In Valuation - TCP1" + + from_warehouse = create_warehouse("_Test Internal From Warehouse LCV", company=company) + to_warehouse = create_warehouse("_Test Internal To Warehouse LCV", company=company) + + # inward qty for internal transactions + make_purchase_receipt( + item_code=item_doc.item_code, + qty=5, + rate=100, + company="_Test Company with perpetual inventory", + warehouse=from_warehouse, + ) + + idn = create_delivery_note( + item_code=item_doc.name, + company=company, + customer=customer, + cost_center="Main - TCP1", + expense_account="Cost of Goods Sold - TCP1", + qty=5, + rate=100, + warehouse=from_warehouse, + target_warehouse=to_warehouse, + ) + self.assertEqual(idn.items[0].rate, 100) + + ipr = make_inter_company_purchase_receipt(idn.name) + ipr.items[0].warehouse = from_warehouse + self.assertEqual(ipr.items[0].rate, 100) + ipr.submit() + + self.create_lcv(ipr.doctype, ipr.name, company, lcv_expense_account, charges=100) + ipr.reload() + + self.assertEqual(ipr.items[0].landed_cost_voucher_amount, 100) + self.assertEqual(ipr.items[0].valuation_rate, 120) + + # repost the receipt and check the stock ledger values + repost_doc = frappe.new_doc("Repost Item Valuation") + repost_doc.update( + { + "based_on": "Transaction", + "voucher_type": ipr.doctype, + "voucher_no": ipr.name, + "posting_date": ipr.posting_date, + "posting_time": ipr.posting_time, + "company": ipr.company, + "allow_negative_stock": 1, + "via_landed_cost_voucher": 0, + "allow_zero_rate": 0, + } + ) + repost_doc.save() + repost_doc.submit() + + stk_ledger = frappe.db.get_value( + "Stock Ledger Entry", + {"voucher_type": "Purchase Receipt", "voucher_no": ipr.name, "warehouse": from_warehouse}, + ["incoming_rate", "stock_value_difference"], + as_dict=True, + ) + + # check the incoming rate and stock value change + self.assertEqual(stk_ledger.incoming_rate, 120) + self.assertEqual(stk_ledger.stock_value_difference, 600) + def prepare_data_for_internal_transfer(): from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_internal_supplier diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py index be351b195e2..ae3730d4897 100644 --- a/erpnext/stock/stock_ledger.py +++ b/erpnext/stock/stock_ledger.py @@ -821,7 +821,6 @@ class update_entries_after: if not self.validate_negative_stock(sle): self.wh_data.qty_after_transaction += flt(sle.actual_qty) return - # Get dynamic incoming/outgoing rate if not self.args.get("sle_id"): self.get_dynamic_incoming_outgoing_rate(sle) From 621558a30c450fcdc7630c34225ff67890c1981d Mon Sep 17 00:00:00 2001 From: Frappe PR Bot Date: Thu, 29 Jan 2026 12:50:23 +0000 Subject: [PATCH 13/13] chore(release): Bumped to Version 15.95.2 ## [15.95.2](https://github.com/frappe/erpnext/compare/v15.95.1...v15.95.2) (2026-01-29) ### Bug Fixes * **stock:** set incoming_rate with lcv rate for internal purchase ([6ea4f1a](https://github.com/frappe/erpnext/commit/6ea4f1a03d82680117f4041ae14ad030f0e02a98)) --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 317d8b4b6b3..7450d8ee1cd 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.1" +__version__ = "15.95.2" def get_default_company(user=None):