Compare commits

..

787 Commits

Author SHA1 Message Date
Frappe PR Bot
ca21f16db2 chore(release): Bumped to Version 15.91.2
## [15.91.2](https://github.com/frappe/erpnext/compare/v15.91.1...v15.91.2) (2025-12-11)

### Bug Fixes

* putaway rule not applying on serial nos ([23c82d4](23c82d410b))
* Serial/Batches not fetching when creating Material Transfer from Purchase Receipt ([1e0532f](1e0532f387))
2025-12-11 10:48:40 +00:00
rohitwaghchaure
5324000e2e Merge pull request #51043 from frappe/mergify/bp/version-15/pr-51036
fix: put-away rule not applying on serial nos (backport #51035) (backport #51036)
2025-12-11 16:17:10 +05:30
rohitwaghchaure
9d2055c620 Merge pull request #51042 from frappe/mergify/bp/version-15/pr-51029
fix: Serial/Batches not fetching when creating Material Transfer from Purchase Receipt (backport #51027) (backport #51029)
2025-12-11 16:16:29 +05:30
Rohit Waghchaure
23c82d410b fix: putaway rule not applying on serial nos
(cherry picked from commit 6bb0bdcdca)
(cherry picked from commit df820aece6)
2025-12-11 10:15:31 +00:00
rohitwaghchaure
580e825ec2 chore: fix conflicts
(cherry picked from commit c8565c47a2)
2025-12-11 10:15:29 +00:00
Rohit Waghchaure
1e0532f387 fix: Serial/Batches not fetching when creating Material Transfer from Purchase Receipt
(cherry picked from commit d16c50486a)

# Conflicts:
#	erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
(cherry picked from commit f3c70a66b5)
2025-12-11 10:15:29 +00:00
Frappe PR Bot
a2b676b340 chore(release): Bumped to Version 15.91.1
## [15.91.1](https://github.com/frappe/erpnext/compare/v15.91.0...v15.91.1) (2025-12-09)

### Bug Fixes

* add return status for delivery note ([ebb6296](ebb62966d3))
* Adjust asset purchase amounts based on docstatus ([a31fb2a](a31fb2ac6c))
* change is_return value in filter from Yes to 1 ([52e26b6](52e26b6da8))
* conflicts ([bd00a48](bd00a484ea))
* conflicts ([1427b4a](1427b4ac3f))
* cost center not reset ([8a3148e](8a3148eee6))
* ensure payment request button only shows for submitted invoices ([b4053ee](b4053ee0d8))
* fg qty uom in manufacture entry ([70d5726](70d57260d6))
* handle duplicate description in item-wise report ([1a278e7](1a278e7ca0))
* include return invoice discount in discount validation ([bf1c606](bf1c606610))
* incorrect condition ([d9e9f35](d9e9f35230))
* inward same serial / batches in disassembly which were used ([cfbd716](cfbd71693b))
* LCV is not changing the valuation of the repacked item ([8b22d9d](8b22d9d95e))
* missing attribute error when restoring asset ([bde209b](bde209b077))
* performance of the reposting ([8d734df](8d734df63b))
* **picklist:** calculate picked qty excluding the delivered qty ([3785ffe](3785ffe5c9))
* quality inspection showing Not Saved ([abe599a](abe599a49d))
* remove comment ([da88196](da88196a89))
* remove set_only_once from is_fixed_asset ([fd6e42e](fd6e42e15e))
* **sales invoice:** 100% additional discount gl issue with discount accounting ([bd6210a](bd6210a212))
* tds for customer and supplier in Journal Entry (backport [#49963](https://github.com/frappe/erpnext/issues/49963)) ([#50985](https://github.com/frappe/erpnext/issues/50985)) ([f2c556a](f2c556a6cc))
* untranslated string in job card ([b2f6d07](b2f6d07c25))
* variant items not fetched while making BOM for Variant Item ([176ce0d](176ce0d4d6))
2025-12-09 17:00:25 +00:00
Diptanil Saha
691db5b877 Merge pull request #50981 from frappe/version-15-hotfix 2025-12-09 22:28:48 +05:30
Diptanil Saha
7bec3d19ac Merge pull request #50977 from ljain112/fix-item-wise-sales-register
fix: handle duplicate description in item-wise report (backport #50979)
2025-12-09 21:47:16 +05:30
Diptanil Saha
3f85aa3aea Merge pull request #50997 from frappe/mergify/bp/version-15-hotfix/pr-50944
fix: include return invoice discount in discount validation (backport #50944)
2025-12-09 21:39:17 +05:30
Diptanil Saha
9ccf4900fe chore: resolve conflict 2025-12-09 20:52:33 +05:30
ravibharathi656
bf1c606610 fix: include return invoice discount in discount validation
(cherry picked from commit fab1ef5d76)

# Conflicts:
#	erpnext/controllers/taxes_and_totals.py
2025-12-09 15:18:08 +00:00
Mihir Kandoi
6c53d31f2d Merge pull request #50994 from frappe/mergify/bp/version-15-hotfix/pr-50912
fix: add return status for delivery note (backport #50912)
2025-12-09 20:07:22 +05:30
Mihir Kandoi
4de1af498b chore: resolve conflicts 2025-12-09 19:51:26 +05:30
Mihir Kandoi
c65409c348 Merge pull request #50993 from frappe/mergify/bp/version-15-hotfix/pr-50910
fix: validate picklist partial reserved qty (backport #50910)
2025-12-09 18:50:37 +05:30
Pugazhendhi Velu
422aec12cb test: add test for return status in delivery note
(cherry picked from commit 445a255a7f)
2025-12-09 13:06:52 +00:00
Pugazhendhi Velu
52e26b6da8 fix: change is_return value in filter from Yes to 1
(cherry picked from commit af212f520d)
2025-12-09 13:06:52 +00:00
Pugazhendhi Velu
ebb62966d3 fix: add return status for delivery note
(cherry picked from commit dec67eecad)

# Conflicts:
#	erpnext/stock/doctype/delivery_note/delivery_note.py
2025-12-09 13:06:51 +00:00
Sudharsanan11
b05e2910d8 test(picklist): add test for reserved qty after partial delivery
(cherry picked from commit 758553b9fc)
2025-12-09 13:04:46 +00:00
Sudharsanan11
3785ffe5c9 fix(picklist): calculate picked qty excluding the delivered qty
(cherry picked from commit f5b75b27d7)
2025-12-09 13:04:45 +00:00
Diptanil Saha
a4ab198042 Merge pull request #50991 from frappe/mergify/bp/version-15-hotfix/pr-50970
fix: ensure payment request button only shows for submitted invoices (backport #50970)
2025-12-09 17:21:53 +05:30
Diptanil Saha
67c5249b38 Merge pull request #50988 from frappe/mergify/bp/version-15-hotfix/pr-50968 2025-12-09 17:18:10 +05:30
Diptanil Saha
af067d1c00 chore: resolve conflict 2025-12-09 17:17:27 +05:30
Abdeali Chharchhoda
b4053ee0d8 fix: ensure payment request button only shows for submitted invoices
(cherry picked from commit f26ee9e546)

# Conflicts:
#	erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
2025-12-09 11:42:22 +00:00
rohitwaghchaure
9f846e2636 Merge pull request #50990 from frappe/mergify/bp/version-15-hotfix/pr-50978
fix: performance of the reposting (backport #50978)
2025-12-09 16:54:21 +05:30
Rohit Waghchaure
8d734df63b fix: performance of the reposting
(cherry picked from commit 1bcfad8eb1)
2025-12-09 11:06:16 +00:00
Abdeali Chharchhoda
0998123e52 refactor: payment request status updates with bulk database operation
(cherry picked from commit 5154fa8259)
2025-12-09 10:59:11 +00:00
mergify[bot]
f2c556a6cc fix: tds for customer and supplier in Journal Entry (backport #49963) (#50985)
Co-authored-by: ljain112 <ljain112@gmail.com>
Co-authored-by: Smit Vora <smitvora203@gmail.com>
Co-authored-by: Diptanil Saha <diptanil@frappe.io>
2025-12-09 16:26:36 +05:30
Khushi Rawat
b41612bea8 Merge pull request #50982 from khushi8112/missing-attribute-issue
fix: Missing attribute error
2025-12-09 15:31:08 +05:30
khushi8112
da88196a89 fix: remove comment 2025-12-09 15:13:40 +05:30
khushi8112
bde209b077 fix: missing attribute error when restoring asset 2025-12-09 15:10:16 +05:30
ljain112
1a278e7ca0 fix: handle duplicate description in item-wise report 2025-12-09 12:03:50 +05:30
rohitwaghchaure
1637cb4168 Merge pull request #50973 from frappe/mergify/bp/version-15-hotfix/pr-50972
fix: incorrect condition (backport #50972)
2025-12-08 20:27:10 +05:30
Rohit Waghchaure
d9e9f35230 fix: incorrect condition
(cherry picked from commit 264baf34f6)
2025-12-08 14:39:16 +00:00
rohitwaghchaure
cbc73148d3 Merge pull request #50969 from frappe/mergify/bp/version-15-hotfix/pr-50742
fix: inward same serial / batches in disassembly which were used (backport #50742)
2025-12-08 19:53:36 +05:30
rohitwaghchaure
60a18247e1 chore: fix conflicts 2025-12-08 19:09:52 +05:30
rohitwaghchaure
7cc0436083 chore: fix conflicts 2025-12-08 19:08:45 +05:30
rohitwaghchaure
f8eb48472e chore: fix conflicts 2025-12-08 19:07:13 +05:30
rohitwaghchaure
8074d396d0 chore: fix conflicts
Removed posting_datetime and type_of_transaction from the query.
2025-12-08 19:05:51 +05:30
Rohit Waghchaure
cfbd71693b fix: inward same serial / batches in disassembly which were used
(cherry picked from commit 95e6c72539)

# Conflicts:
#	erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py
#	erpnext/stock/doctype/stock_entry/stock_entry.py
2025-12-08 12:57:58 +00:00
Diptanil Saha
3a2d7d18a3 Merge pull request #50946 from frappe/mergify/bp/version-15-hotfix/pr-50931
fix(bulk transaction process): skip records creation if original records are marked 'On Hold' or 'Closed' (backport #50931)
2025-12-05 16:56:52 +05:30
Diptanil Saha
b55cefc54f Merge pull request #50945 from frappe/mergify/bp/version-15-hotfix/pr-50943
fix(sales invoice): 100% additional discount gl issue with discount accounting (backport #50943)
2025-12-05 16:48:44 +05:30
Diptanil Saha
05778bb81a chore: resolve conflict 2025-12-05 16:40:57 +05:30
Diptanil Saha
a70296e9b5 Merge pull request #50931 from diptanilsaha/gh-49357
(cherry picked from commit 31d55248e4)

# Conflicts:
#	erpnext/utilities/bulk_transaction.py
2025-12-05 11:03:16 +00:00
diptanilsaha
bd6210a212 fix(sales invoice): 100% additional discount gl issue with discount accounting
(cherry picked from commit d6bdbfe266)
2025-12-05 11:02:16 +00:00
Khushi Rawat
944c9ad0b3 Merge pull request #50924 from frappe/mergify/bp/version-15-hotfix/pr-50879
fix: remove set_only_once from is_fixed_asset field (backport #50879)
2025-12-04 13:04:50 +05:30
Khushi Rawat
bd00a484ea fix: conflicts 2025-12-04 12:48:50 +05:30
Khushi Rawat
1427b4ac3f fix: conflicts 2025-12-04 12:48:07 +05:30
ravibharathi656
fd6e42e15e fix: remove set_only_once from is_fixed_asset
(cherry picked from commit 70521fb9bf)

# Conflicts:
#	erpnext/stock/doctype/item/item.json
#	erpnext/stock/doctype/item/item.py
2025-12-04 06:44:46 +00:00
rohitwaghchaure
8b071c0d22 Merge pull request #50922 from frappe/mergify/bp/version-15-hotfix/pr-50913
fix: variant items not fetched while making BOM for Variant Item (backport #50913)
2025-12-04 11:43:57 +05:30
Rohit Waghchaure
176ce0d4d6 fix: variant items not fetched while making BOM for Variant Item
(cherry picked from commit a0256bd798)
2025-12-04 04:38:17 +00:00
rohitwaghchaure
dd888fc30a Merge pull request #50909 from frappe/mergify/bp/version-15-hotfix/pr-50905
fix: LCV is not changing the valuation of the repacked item (backport #50905)
2025-12-04 10:06:31 +05:30
Mihir Kandoi
789adaeabe Merge pull request #50908 from frappe/mergify/bp/version-15-hotfix/pr-50906
fix: untranslated string in job card (backport #50906)
2025-12-03 20:05:11 +05:30
rohitwaghchaure
2342f8d710 chore: fix conflicts
Removed test for purchase expense account and repost GL entries.
2025-12-03 18:38:40 +05:30
Rohit Waghchaure
8b22d9d95e fix: LCV is not changing the valuation of the repacked item
(cherry picked from commit ccbbc60585)

# Conflicts:
#	erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
2025-12-03 12:58:22 +00:00
rohitwaghchaure
626c799b60 Merge pull request #50907 from frappe/mergify/bp/version-15-hotfix/pr-50902
fix: fg qty uom in manufacture entry (backport #50902)
2025-12-03 18:22:15 +05:30
Mihir Kandoi
b2f6d07c25 fix: untranslated string in job card
(cherry picked from commit ec06f4a71b)
2025-12-03 12:40:35 +00:00
Mihir Kandoi
70d57260d6 fix: fg qty uom in manufacture entry
(cherry picked from commit d9a377108c)
2025-12-03 12:37:19 +00:00
Khushi Rawat
9062b90237 Merge pull request #50887 from 0xD0M1M0/patch-1
fix: Reduce asset value on asset capitalization cancelation
2025-12-03 15:01:41 +05:30
rohitwaghchaure
40467bc26c Merge pull request #50901 from frappe/mergify/bp/version-15-hotfix/pr-50896
fix: quality inspection showing Not Saved (backport #50896)
2025-12-03 14:52:51 +05:30
Rohit Waghchaure
abe599a49d fix: quality inspection showing Not Saved
(cherry picked from commit 3f78d6afed)
2025-12-03 08:08:37 +00:00
rohitwaghchaure
9975f5fe69 Merge pull request #50889 from frappe/mergify/bp/version-15-hotfix/pr-50888
fix: cost center not reset (backport #50888)
2025-12-02 22:37:08 +05:30
Frappe PR Bot
dab17c194c chore(release): Bumped to Version 15.91.0
# [15.91.0](https://github.com/frappe/erpnext/compare/v15.90.1...v15.91.0) (2025-12-02)

### Bug Fixes

* add validation for cancelled reposting entries ([085d685](085d685488))
* add validation for company linked address fields ([0aed8c0](0aed8c04c6))
* **barcode_scanner:** set serial and batch before item to prevent FIFO override ([7d7f929](7d7f929cfc))
* conflicts ([199e25e](199e25ec06))
* correct field name for subcontracted items in material request ([4b49080](4b49080bc4))
* do not override source document in serial no ([69c6b2f](69c6b2f463))
* **email campaign:** send emails using bcc ([b660b90](b660b90adc))
* **Employee:** add/delete user permission (backport [#47016](https://github.com/frappe/erpnext/issues/47016)) ([#50761](https://github.com/frappe/erpnext/issues/50761)) ([821f3f5](821f3f5884))
* enhance SalesOrderController setup method to call super.setup ([7805ccf](7805ccf176))
* exclude is_group records ([a444325](a444325bd1))
* include accounting dimensions in stock entries created during asset repair. ([26872c3](26872c3c25))
* incorrect positional param for `get_field_precision` util (backport [#50764](https://github.com/frappe/erpnext/issues/50764)) ([#50795](https://github.com/frappe/erpnext/issues/50795)) ([ff1ca9d](ff1ca9d480))
* item price not considering based on valid_upto ([dfda8e6](dfda8e6241))
* **Job Card:** avoid Type Error when completed_qty is None ([#50447](https://github.com/frappe/erpnext/issues/50447)) ([cac9eed](cac9eed306))
* label for warehouse based on material request type ([8ee7c47](8ee7c47fdf))
* mandatory depends on for the rejected inventory dimension field ([8c62080](8c620802f0))
* negative batch in subcontracting receipt ([5def006](5def006033))
* **payment reconciliation:** added a hint that posting date can be changed on exchange gain/loss reconcile dialog ([0e03607](0e0360781e))
* **payment-recon:** add validation for outstanding of dr_cr ([70feb50](70feb500f6))
* **pos:** add negative stock validation for product bundle ([46a49a1](46a49a134d))
* remove unused translation files (<100 lines) ([7f7c5f2](7f7c5f2381))
* resolve conflict ([bd795f5](bd795f5546))
* **stock entry:** use fg item expense account for direct manufacturing entry ([4ca5e9e](4ca5e9eef8))
* two primary buttons ([1d2fccf](1d2fccfc0b))
* use asset in against_voucher while posting gl entries for capitalized asset repairs ([80642ed](80642edf4f))
* use posting_date instead of bill_date from purchase invoice ([c12a560](c12a560c63))

### Features

* add stock uom read only field to stock reconciliation item doctype ([5711225](57112258e6))
2025-12-02 16:31:39 +00:00
Rohit Waghchaure
8a3148eee6 fix: cost center not reset
(cherry picked from commit 29f2ecbd6f)
2025-12-02 16:30:41 +00:00
Diptanil Saha
1f79242366 Merge pull request #50868 from frappe/version-15-hotfix 2025-12-02 22:00:12 +05:30
Diptanil Saha
3f673a6848 Merge pull request #50886 from frappe/mergify/bp/version-15-hotfix/pr-50882
fix: mandatory depends on for the rejected inventory dimension field (backport #50882)
2025-12-02 21:26:26 +05:30
Diptanil Saha
293f114c9d Merge pull request #50847 from barredterra/rm-unused-translations 2025-12-02 21:19:55 +05:30
Diptanil Saha
252cc89ec7 Merge pull request #50871 from frappe/mergify/bp/version-15-hotfix/pr-50846 2025-12-02 21:19:40 +05:30
Diptanil Saha
3eaccfe201 Merge pull request #50873 from frappe/mergify/bp/version-15-hotfix/pr-50773
fix: add validation for cancelled reposting entries (backport #50773)
2025-12-02 21:15:56 +05:30
Diptanil Saha
653bb1072f Merge pull request #50885 from frappe/mergify/bp/version-15-hotfix/pr-50864
fix: exclude is_group records (backport #50864)
2025-12-02 21:14:35 +05:30
Diptanil Saha
0a64e43e92 chore: resolve linter issue 2025-12-02 21:04:00 +05:30
diptanilsaha
020db922b7 chore: resolve conflicts 2025-12-02 20:56:54 +05:30
rohitwaghchaure
a67a11e933 Merge pull request #50884 from rohitwaghchaure/fixed-donot-override-source
fix: do not override source document in serial no
2025-12-02 20:55:22 +05:30
Rohit Waghchaure
8c620802f0 fix: mandatory depends on for the rejected inventory dimension field
(cherry picked from commit 5daa625fe8)
2025-12-02 15:10:40 +00:00
0xD0M1M0
a31fb2ac6c fix: Adjust asset purchase amounts based on docstatus
allows cancelation
2025-12-02 16:09:56 +01:00
ravibharathi656
a444325bd1 fix: exclude is_group records
(cherry picked from commit e08805128b)

# Conflicts:
#	erpnext/setup/doctype/customer_group/customer_group.json
#	erpnext/setup/doctype/item_group/item_group.json
#	erpnext/setup/doctype/supplier_group/supplier_group.json
#	erpnext/setup/doctype/territory/territory.json
2025-12-02 15:07:39 +00:00
rohitwaghchaure
2f4b1341d2 Merge pull request #50878 from frappe/mergify/bp/version-15-hotfix/pr-50808
fix(stock entry): use fg item expense account for direct manufacturing entry (backport #50808)
2025-12-02 20:37:39 +05:30
Diptanil Saha
7640944bb9 Merge pull request #50881 from frappe/mergify/bp/version-15-hotfix/pr-50372
fix: add validation for company linked address field (backport #50372)
2025-12-02 20:36:22 +05:30
Rohit Waghchaure
69c6b2f463 fix: do not override source document in serial no 2025-12-02 20:34:55 +05:30
Pugazhendhi Velu
ef6f2389a0 test: add minimal test case
(cherry picked from commit e64b6db2eb)
2025-12-02 14:45:03 +00:00
Pugazhendhi Velu
1d4b97c619 test: add test for company linked address fields
(cherry picked from commit e10007c646)
2025-12-02 14:45:02 +00:00
Pugazhendhi Velu
0aed8c04c6 fix: add validation for company linked address fields
(cherry picked from commit 800a44a65f)
2025-12-02 14:45:02 +00:00
rohitwaghchaure
b1b6953aed chore: fix conflicts 2025-12-02 17:44:17 +05:30
rohitwaghchaure
b2ea5620b2 chore: fix conflicts
Removed the expense account assignment for subcontracting delivery.
2025-12-02 17:42:18 +05:30
rohitwaghchaure
743b179b08 Merge pull request #50877 from frappe/mergify/bp/version-15-hotfix/pr-50850
fix(barcode_scanner): set serial and batch before item to prevent FIFO override (backport #50850)
2025-12-02 17:41:31 +05:30
Pugazhendhi Velu
4553d04c38 test: add test for fg item expense account in direct manufacturing
(cherry picked from commit ba2411b4ee)

# Conflicts:
#	erpnext/stock/doctype/stock_entry/test_stock_entry.py
2025-12-02 12:03:37 +00:00
Pugazhendhi Velu
4ca5e9eef8 fix(stock entry): use fg item expense account for direct manufacturing entry
(cherry picked from commit ce1312764f)

# Conflicts:
#	erpnext/stock/doctype/stock_entry/stock_entry.py
2025-12-02 12:03:37 +00:00
Pugazhendhi Velu
7d7f929cfc fix(barcode_scanner): set serial and batch before item to prevent FIFO override
(cherry picked from commit 92ec633a5c)
2025-12-02 12:02:36 +00:00
l0gesh29
085d685488 fix: add validation for cancelled reposting entries
(cherry picked from commit d8fc369e38)
2025-12-02 11:47:36 +00:00
Diptanil Saha
0458c548ec chore: resolve conflict 2025-12-02 17:14:00 +05:30
Sudharsanan11
e5457f8bb7 test(pos): add test for product bundle negative stock validation
(cherry picked from commit 2612152456)

# Conflicts:
#	erpnext/accounts/doctype/pos_invoice/pos_invoice.py
2025-12-02 11:39:09 +00:00
Sudharsanan11
46a49a134d fix(pos): add negative stock validation for product bundle
(cherry picked from commit 38b4536300)
2025-12-02 11:39:08 +00:00
Khushi Rawat
25a9327b14 Merge pull request #50862 from frappe/mergify/bp/version-15-hotfix/pr-50794
fix: use asset in against_voucher while posting gl entries for capitalised asset repairs (backport #50794)
2025-12-02 12:45:20 +05:30
Mihir Kandoi
d0d38214c5 Merge pull request #50790 from Abdeali099/fix-incorrect-fieldname 2025-12-02 12:30:48 +05:30
Khushi Rawat
991c46d058 Merge pull request #50858 from frappe/mergify/bp/version-15-hotfix/pr-50793
fix: include accounting dimensions in stock entries created during asset repair. (backport #50793)
2025-12-02 12:23:10 +05:30
rohitwaghchaure
ca9bd8b499 Merge pull request #50845 from frappe/mergify/bp/version-15-hotfix/pr-50844
fix: label for warehouse based on material request type (backport #50844)
2025-12-02 12:22:18 +05:30
Khushi Rawat
199e25ec06 fix: conflicts 2025-12-02 12:20:48 +05:30
Navin-S-R
f38fb68d62 chore: reload asset doc before assertEqual
(cherry picked from commit 8c35a6ecdd)
2025-12-02 06:37:54 +00:00
Navin-S-R
3a22d29d7b test: add unit test to validate capitalized asset repair gl entries being booked against the asset
(cherry picked from commit bcf6deec9a)

# Conflicts:
#	erpnext/assets/doctype/asset_repair/test_asset_repair.py
2025-12-02 06:37:54 +00:00
Navin S R
80642edf4f fix: use asset in against_voucher while posting gl entries for capitalized asset repairs
(cherry picked from commit a7e43eddad)
2025-12-02 06:37:54 +00:00
ljain112
9a3e1058f6 refactor: show_general ledger for consistency with other doctyoes
(cherry picked from commit cdbe8b909b)
2025-12-02 06:27:21 +00:00
ljain112
26872c3c25 fix: include accounting dimensions in stock entries created during asset repair.
(cherry picked from commit 147a5ee953)
2025-12-02 06:27:21 +00:00
rohitwaghchaure
dba3f3d335 chore: fix conflicts 2025-12-02 11:04:27 +05:30
barredterra
7f7c5f2381 fix: remove unused translation files (<100 lines)
These translate <=1% of available strings, so cannot be deemed useful.
2025-12-01 17:38:13 +01:00
Rohit Waghchaure
8ee7c47fdf fix: label for warehouse based on material request type
(cherry picked from commit 699e9b4452)

# Conflicts:
#	erpnext/stock/doctype/material_request/material_request.js
2025-12-01 15:58:39 +00:00
Raffael Meyer
441a2bcf38 chore: backport translations from develop (#50842) 2025-12-01 14:50:04 +00:00
mergify[bot]
821f3f5884 fix(Employee): add/delete user permission (backport #47016) (#50761)
Co-authored-by: barredterra <14891507+barredterra@users.noreply.github.com>
2025-12-01 12:49:37 +01:00
Diptanil Saha
ca70e8e9a6 Merge pull request #50825 from frappe/mergify/bp/version-15-hotfix/pr-50797
fix(payment-recon): add validation for outstanding of dr_cr (backport #50797)
2025-12-01 13:27:15 +05:30
l0gesh29
70feb500f6 fix(payment-recon): add validation for outstanding of dr_cr
(cherry picked from commit 765f9a9bbf)
2025-12-01 07:41:28 +00:00
rohitwaghchaure
bf8b3d0546 Merge pull request #50818 from frappe/mergify/bp/version-15-hotfix/pr-50799
fix: negative batch in subcontracting receipt (backport #50799)
2025-12-01 12:50:42 +05:30
Diptanil Saha
07d8bc7852 Merge pull request #50819 from frappe/mergify/bp/version-15-hotfix/pr-50814
fix(email campaign): send emails using bcc (backport #50814)
2025-12-01 12:30:55 +05:30
diptanilsaha
b660b90adc fix(email campaign): send emails using bcc
(cherry picked from commit 7e8d19b0c8)
2025-12-01 06:17:15 +00:00
Rohit Waghchaure
5def006033 fix: negative batch in subcontracting receipt
(cherry picked from commit 71e46b3ef5)
2025-12-01 06:15:37 +00:00
Khushi Rawat
ade6acccfb Merge pull request #50800 from frappe/mergify/bp/version-15-hotfix/pr-50772
fix: use posting_date instead of bill_date from purchase invoice (backport #50772)
2025-11-29 00:28:11 +05:30
Khushi Rawat
bd795f5546 fix: resolve conflict 2025-11-28 17:26:33 +05:30
Navin S R
c12a560c63 fix: use posting_date instead of bill_date from purchase invoice
(cherry picked from commit 145d40dec8)

# Conflicts:
#	erpnext/assets/doctype/asset/asset.py
2025-11-28 11:49:33 +00:00
mergify[bot]
ff1ca9d480 fix: incorrect positional param for get_field_precision util (backport #50764) (#50795) 2025-11-28 08:50:03 +00:00
Abdeali Chharchhoda
4b49080bc4 fix: correct field name for subcontracted items in material request 2025-11-28 12:33:38 +05:30
Diptanil Saha
64e6b36d04 Merge pull request #50789 from frappe/mergify/bp/version-15-hotfix/pr-50642
fix(payment reconciliation): added a hint that posting date can be changed on exchange gain/loss reconcile dialog (backport #50642)
2025-11-28 11:54:32 +05:30
Jatin3128
0e0360781e fix(payment reconciliation): added a hint that posting date can be changed on exchange gain/loss reconcile dialog
(cherry picked from commit 4b612c64a8)
2025-11-28 06:22:00 +00:00
Mihir Kandoi
c62be10620 Merge pull request #50778 from frappe/mergify/bp/version-15-hotfix/pr-50777 2025-11-27 17:28:07 +05:30
Mihir Kandoi
fa541a2604 chore: make unnecessary field read only and show only when required
(cherry picked from commit aab7cd1ae6)
2025-11-27 11:41:54 +00:00
Diptanil Saha
5590b8d40b Merge pull request #50558 from efeone/pos_rate_issue 2025-11-27 16:33:50 +05:30
Mihir Kandoi
a32165016d Merge pull request #50774 from mihir-kandoi/gh50218 2025-11-27 14:56:44 +05:30
Mihir Kandoi
57112258e6 feat: add stock uom read only field to stock reconciliation item doctype 2025-11-27 14:39:19 +05:30
rohitwaghchaure
0bec404e69 Merge pull request #50770 from frappe/mergify/bp/version-15-hotfix/pr-50769
fix: two primary buttons (backport #50769)
2025-11-27 12:06:10 +05:30
Rohit Waghchaure
1d2fccfc0b fix: two primary buttons
(cherry picked from commit f68515210b)
2025-11-27 06:27:09 +00:00
Raffael Meyer
cac9eed306 fix(Job Card): avoid Type Error when completed_qty is None (#50447) 2025-11-26 13:16:47 +01:00
Frappe PR Bot
2bf12a6683 chore(release): Bumped to Version 15.90.1
## [15.90.1](https://github.com/frappe/erpnext/compare/v15.90.0...v15.90.1) (2025-11-26)

### Bug Fixes

* enhance SalesOrderController setup method to call super.setup ([38c4453](38c44533b3))
2025-11-26 09:12:23 +00:00
Diptanil Saha
6205be5e73 Merge pull request #50755 from frappe/mergify/bp/version-15/pr-50754
fix: enhance SalesOrderController setup method to call super.setup (backport #50752)
2025-11-26 14:40:58 +05:30
ljain112
38c44533b3 fix: enhance SalesOrderController setup method to call super.setup
(cherry picked from commit 563c2998ca)
(cherry picked from commit 7805ccf176)
2025-11-26 09:08:27 +00:00
Diptanil Saha
a6713b176b Merge pull request #50754 from frappe/mergify/bp/version-15-hotfix/pr-50752
fix: enhance SalesOrderController setup method to call super.setup (backport #50752)
2025-11-26 14:35:21 +05:30
ljain112
7805ccf176 fix: enhance SalesOrderController setup method to call super.setup
(cherry picked from commit 563c2998ca)
2025-11-26 09:02:56 +00:00
Frappe PR Bot
a66ce02520 chore(release): Bumped to Version 15.90.0
# [15.90.0](https://github.com/frappe/erpnext/compare/v15.89.2...v15.90.0) (2025-11-25)

### Bug Fixes

* add filter company and status to job card employee ([015f946](015f946a14))
* add missing translate function ([475eada](475eada727))
* add return status for purchase receipt ([8ccb9a5](8ccb9a5ad2))
* add validation for FG Items as per BOM qty (backport [#50579](https://github.com/frappe/erpnext/issues/50579)) ([#50715](https://github.com/frappe/erpnext/issues/50715)) ([1995291](1995291194))
* apply precision for scrap items amount ([5b60fbb](5b60fbbd30))
* **customer:** link contact and addresses if created from lead/opportunity/prospect ([b1d40de](b1d40de87e))
* ignore reserved batches from total available batches ([673b893](673b893942))
* incorrect query filter when selecting primary customer adr ([#50727](https://github.com/frappe/erpnext/issues/50727)) ([e8e09cf](e8e09cf8ea))
* **ledger-summary-report:** show party group and territory ([56f03ae](56f03aee02))
* **manufacturing:** apply precision for bom amount and rm_cost_per_qty ([2678694](2678694c5f))
* pick list status doesn't update when DN created from it and PL was created from SO ([2809c46](2809c46a6e))
* prevent pi status from changing on asset repair ([3f2081b](3f2081b440))
* pricing rule was ignoring time validity ([f62e5e6](f62e5e69b8))
* **product bundle:** fields reset if doc is new ([4ba4da0](4ba4da090d))
* **purchase_receipt:** add internal_and_external_links field to show purchase invoice connection count ([89fcdbf](89fcdbf56b))
* redundant message on bom save ([5b16740](5b1674018b))
* remove disabled warehouse in get_warehouses_based_on_account ([aa94c91](aa94c91c12))
* serial batch selector shown only once ([25cd230](25cd230471))
* show current company warehouse only in get material from bom MR ([1d6e3e4](1d6e3e4e7d))
* tests ([45bc218](45bc218acb))
* unhide zero val checkbox ([a247337](a24733791d))
* unknown column error ([2e9a0cb](2e9a0cb01c))
* use current_tax_amount value for base_total_taxes_and_charges ([7ed3c6d](7ed3c6d18a))
* validate sabb autocreation when disabled ([85c0c16](85c0c16964))
* validation for SABB deletion ([0bc98b6](0bc98b609f))

### Features

* **accounting-dimension:** add dynamic triggers for custom accounting dimensions ([#50621](https://github.com/frappe/erpnext/issues/50621)) ([2b7d586](2b7d58602d))
* modify accounting dimension as multiselect field ([6b6e017](6b6e017e36))
* **reports:** preserve accounting dimension filters while navigating between reports ([02a1f81](02a1f815da))
2025-11-25 15:02:30 +00:00
ruthra kumar
3c43b42a01 Merge pull request #50741 from frappe/version-15-hotfix
chore: release v15
2025-11-25 20:31:01 +05:30
ruthra kumar
8ed3a0ec65 Merge branch 'version-15' into version-15-hotfix 2025-11-25 20:14:37 +05:30
mergify[bot]
488d635dc9 chore: switched frankfurter domain from frankfurter.app to frankfurter.dev (backport #50734) (#50740)
Co-authored-by: diptanilsaha <diptanil@frappe.io>
2025-11-25 15:49:53 +05:30
ruthra kumar
08d230b3e3 Merge pull request #50731 from frappe/mergify/bp/version-15-hotfix/pr-50561
fix(ledger-summary-report): show party group and territory (backport #50561)
2025-11-25 12:33:49 +05:30
Mihir Kandoi
f383fafb15 Merge pull request #50728 from frappe/mergify/bp/version-15-hotfix/pr-50727
fix: incorrect query filter when selecting primary customer adr (backport #50727)
2025-11-25 12:14:17 +05:30
ruthra kumar
38124a7616 chore: resolve conflicts 2025-11-25 12:01:37 +05:30
l0gesh29
56cf5382f0 test: add party_group, territory in json
(cherry picked from commit 8f91919933)

# Conflicts:
#	erpnext/accounts/report/customer_ledger_summary/test_customer_ledger_summary.py
2025-11-25 05:38:57 +00:00
l0gesh29
56f03aee02 fix(ledger-summary-report): show party group and territory
(cherry picked from commit 231479a6e2)

# Conflicts:
#	erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py
2025-11-25 05:38:57 +00:00
Mihir Kandoi
841f5c24ad chore: resolve conflicts 2025-11-25 10:51:39 +05:30
ruthra kumar
e8051ba180 Merge pull request #50729 from frappe/mergify/bp/version-15-hotfix/pr-50621
feat(accounting-dimension): add dynamic triggers for custom accounting dimensions (backport #50621)
2025-11-25 10:26:47 +05:30
Logesh Periyasamy
2b7d58602d feat(accounting-dimension): add dynamic triggers for custom accounting dimensions (#50621)
* feat: add dynamic triggers for custom accounting dimensions

* feat: add accounting dimension trigger call in setup event

* chore: ignore cur_frm semgrep rules

* chore: move function to transaction.js

(cherry picked from commit 5e58e344b2)
2025-11-25 04:51:32 +00:00
Mihir Kandoi
e8e09cf8ea fix: incorrect query filter when selecting primary customer adr (#50727)
(cherry picked from commit c2b8b97d7d)

# Conflicts:
#	erpnext/selling/doctype/customer/customer.json
2025-11-25 04:49:20 +00:00
Khushi Rawat
188c633d6e Merge pull request #50544 from aerele/asset-repair-pi-status
fix: prevent pi status from changing on asset repair
2025-11-24 23:28:33 +05:30
mergify[bot]
1995291194 fix: add validation for FG Items as per BOM qty (backport #50579) (#50715)
Co-authored-by: Kavin <78342682+kavin0411@users.noreply.github.com>
Co-authored-by: Mihir Kandoi <kandoimihir@gmail.com>
Co-authored-by: Kavin <78342682+kavin-114@users.noreply.github.com>
fix: add validation for FG Items as per BOM qty (#50579)
2025-11-24 11:18:18 +00:00
Mihir Kandoi
bb0d75eb78 Merge pull request #50717 from frappe/mergify/bp/version-15-hotfix/pr-50716
fix: add missing translate function (backport #50716)
2025-11-24 13:53:48 +05:30
El-Shafei H.
475eada727 fix: add missing translate function
(cherry picked from commit 56def01240)
2025-11-24 07:39:09 +00:00
mergify[bot]
6cffba9a71 Merge pull request #50713 from frappe/mergify/bp/version-15-hotfix/pr-50712 2025-11-24 07:17:43 +00:00
Mihir Kandoi
35f9f9f330 Merge pull request #50711 from frappe/mergify/bp/version-15-hotfix/pr-50661
fix(manufacturing): apply precision for bom amount and rm_cost_per_qty (backport #50661)
2025-11-24 11:02:50 +05:30
Pugazhendhi Velu
5b60fbbd30 fix: apply precision for scrap items amount
(cherry picked from commit 9194e6350a)
2025-11-24 05:08:42 +00:00
Pugazhendhi Velu
2678694c5f fix(manufacturing): apply precision for bom amount and rm_cost_per_qty
(cherry picked from commit 57f9353d90)
2025-11-24 05:08:42 +00:00
Mihir Kandoi
b6a80da457 Merge pull request #50709 from frappe/mergify/bp/version-15-hotfix/pr-50707
fix: unknown column error (backport #50707)
2025-11-23 19:54:21 +05:30
Mihir Kandoi
2e9a0cb01c fix: unknown column error
(cherry picked from commit 3b7d7aed4c)
2025-11-23 14:08:48 +00:00
Frappe PR Bot
38c1867ade chore(release): Bumped to Version 15.89.2
## [15.89.2](https://github.com/frappe/erpnext/compare/v15.89.1...v15.89.2) (2025-11-21)

### Bug Fixes

* use current_tax_amount value for base_total_taxes_and_charges ([c082eda](c082edabf4))
2025-11-21 17:34:52 +00:00
Diptanil Saha
a48b999af9 Merge pull request #50691 from frappe/mergify/bp/version-15/pr-50690
fix: use current_tax_amount value for base_total_taxes_and_charges (backport #50476) (backport #50690)
2025-11-21 23:03:28 +05:30
Pugazhendhi Velu
c082edabf4 fix: use current_tax_amount value for base_total_taxes_and_charges
(cherry picked from commit 5a3fcbedb5)
(cherry picked from commit 7ed3c6d18a)
2025-11-21 17:16:54 +00:00
Diptanil Saha
60ec7d0fb8 Merge pull request #50690 from frappe/mergify/bp/version-15-hotfix/pr-50476
fix: use current_tax_amount value for base_total_taxes_and_charges (backport #50476)
2025-11-21 22:31:13 +05:30
Pugazhendhi Velu
7ed3c6d18a fix: use current_tax_amount value for base_total_taxes_and_charges
(cherry picked from commit 5a3fcbedb5)
2025-11-21 16:41:52 +00:00
Frappe PR Bot
b7e4fb9d83 chore(release): Bumped to Version 15.89.1
## [15.89.1](https://github.com/frappe/erpnext/compare/v15.89.0...v15.89.1) (2025-11-21)

### Bug Fixes

* ignore reserved batches from total available batches ([64950d3](64950d39b5))
2025-11-21 10:36:37 +00:00
rohitwaghchaure
e49e7b621d Merge pull request #50668 from frappe/mergify/bp/version-15/pr-50612
fix: ignore reserved batches from total available batches (backport #50612)
2025-11-21 16:05:05 +05:30
Mihir Kandoi
0a67d20ff8 Merge pull request #50671 from frappe/mergify/bp/version-15-hotfix/pr-50667
fix: pricing rule was ignoring time validity (backport #50667)
2025-11-21 13:08:25 +05:30
Mihir Kandoi
83c6d861eb Merge pull request #50670 from frappe/mergify/bp/version-15-hotfix/pr-50655
fix: pick list status doesn't update when DN created from it and PL w... (backport #50655)
2025-11-21 13:00:31 +05:30
Mihir Kandoi
f62e5e69b8 fix: pricing rule was ignoring time validity
(cherry picked from commit ffae7c4175)
2025-11-21 07:22:07 +00:00
Mihir Kandoi
45bc218acb fix: tests
(cherry picked from commit d26f8aa629)
2025-11-21 07:14:00 +00:00
Mihir Kandoi
2809c46a6e fix: pick list status doesn't update when DN created from it and PL was created from SO
(cherry picked from commit f7b3253683)
2025-11-21 07:14:00 +00:00
Kavin
15c41178d0 test: add unit test for reserved stock validation
(cherry picked from commit 55f2f1c515)
2025-11-21 06:46:17 +00:00
Kavin
64950d39b5 fix: ignore reserved batches from total available batches
(cherry picked from commit 673b893942)
2025-11-21 06:46:17 +00:00
Diptanil Saha
ff1b83025a Merge pull request #50666 from frappe/mergify/bp/version-15-hotfix/pr-50665
fix(customer): link contact and addresses if created from lead/opportunity/prospect (backport #50665)
2025-11-21 07:03:57 +05:30
diptanilsaha
b1d40de87e fix(customer): link contact and addresses if created from lead/opportunity/prospect
(cherry picked from commit 310099f4cd)
2025-11-21 01:18:18 +00:00
Mihir Kandoi
532031c21d Merge pull request #50650 from frappe/mergify/bp/version-15-hotfix/pr-50385
fix: remove disabled warehouse in get_warehouses_based_on_account (backport #50385)
2025-11-20 17:44:02 +05:30
Mihir Kandoi
cb70efb8ed Merge pull request #50653 from frappe/mergify/bp/version-15-hotfix/pr-50639
fix(product bundle): fields reset if doc is new (backport #50639)
2025-11-20 17:43:43 +05:30
Mihir Kandoi
ca0b4696ba Merge pull request #50652 from frappe/mergify/bp/version-15-hotfix/pr-50649
fix: unhide zero val checkbox in stock reco (backport #50649)
2025-11-20 17:43:26 +05:30
Mihir Kandoi
4ba4da090d fix(product bundle): fields reset if doc is new
(cherry picked from commit 7faee7edc2)
2025-11-20 10:42:53 +00:00
rohitwaghchaure
e3b2cc24b2 chore: fix conflicts 2025-11-20 16:12:41 +05:30
Mihir Kandoi
a24733791d fix: unhide zero val checkbox
(cherry picked from commit 20e0313a8c)

# Conflicts:
#	erpnext/stock/doctype/stock_reconciliation_item/stock_reconciliation_item.json
2025-11-20 10:41:55 +00:00
Mihir Kandoi
aa94c91c12 fix: remove disabled warehouse in get_warehouses_based_on_account
(cherry picked from commit ff2d9bf4cb)
2025-11-20 10:33:54 +00:00
Mihir Kandoi
87ffbdf129 Merge pull request #50641 from frappe/mergify/bp/version-15-hotfix/pr-50502
fix(purchase_receipt): add internal_and_external_links field to show … (backport #50502)
2025-11-20 15:45:43 +05:30
rohitwaghchaure
5ef7b8c526 Merge pull request #50648 from frappe/mergify/bp/version-15-hotfix/pr-50646
fix: serial batch selector shown only once (backport #50646)
2025-11-20 15:12:51 +05:30
Mihir Kandoi
25cd230471 fix: serial batch selector shown only once
(cherry picked from commit aa6f09e9a9)
2025-11-20 09:38:37 +00:00
rohitwaghchaure
f05933e814 Merge pull request #50645 from frappe/mergify/bp/version-15-hotfix/pr-50644
fix: validation for SABB deletion (backport #50644)
2025-11-20 14:33:05 +05:30
Diptanil Saha
8df2612694 Merge pull request #50643 from frappe/mergify/bp/version-15-hotfix/pr-50289 2025-11-20 13:58:58 +05:30
Rohit Waghchaure
0bc98b609f fix: validation for SABB deletion
(cherry picked from commit dd4bef0706)
2025-11-20 08:19:48 +00:00
l0gesh29
02a1f815da feat(reports): preserve accounting dimension filters while navigating between reports
(cherry picked from commit fcfcaa76c6)
2025-11-20 07:46:55 +00:00
l0gesh29
6b6e017e36 feat: modify accounting dimension as multiselect field
(cherry picked from commit 3fcd8d84ac)
2025-11-20 07:46:55 +00:00
Karuppasamy B
89fcdbf56b fix(purchase_receipt): add internal_and_external_links field to show purchase invoice connection count
(cherry picked from commit 6c1620ab8c)
2025-11-20 07:03:55 +00:00
rohitwaghchaure
eb2571492f Merge pull request #50612 from aerele/fix/validate-reserved-stock
fix: ignore reserved batches from total available batches
2025-11-19 22:16:00 +05:30
Kavin
55f2f1c515 test: add unit test for reserved stock validation 2025-11-19 17:51:10 +05:30
Kavin
673b893942 fix: ignore reserved batches from total available batches 2025-11-19 17:51:10 +05:30
mergify[bot]
c85ce55f27 Merge pull request #50631 from frappe/mergify/bp/version-15-hotfix/pr-50629
fix: process loss % can be negative (backport #50629)
2025-11-19 11:30:39 +00:00
Mihir Kandoi
a19252e3b3 Merge pull request #50628 from frappe/mergify/bp/version-15-hotfix/pr-50627
fix: show current company warehouse only in get material from bom MR (backport #50627)
2025-11-19 16:29:17 +05:30
Mihir Kandoi
7ece6fd558 Merge pull request #50626 from frappe/mergify/bp/version-15-hotfix/pr-50625
fix: add filter company and status to job card employee (backport #50625)
2025-11-19 16:24:08 +05:30
Mihir Kandoi
1d6e3e4e7d fix: show current company warehouse only in get material from bom MR
(cherry picked from commit 3271eaaf0e)
2025-11-19 10:46:47 +00:00
Mihir Kandoi
015f946a14 fix: add filter company and status to job card employee
(cherry picked from commit 3ca3a6d9bb)
2025-11-19 10:42:32 +00:00
rohitwaghchaure
533a2dbc32 Merge pull request #50607 from frappe/mergify/bp/version-15-hotfix/pr-50512
fix: add return status for purchase receipt (backport #50512)
2025-11-19 14:18:12 +05:30
rohitwaghchaure
99aeb8ecd1 Merge pull request #50606 from frappe/mergify/bp/version-15-hotfix/pr-50486
fix: validate sabb autocreation when disabled (backport #50486)
2025-11-19 14:18:00 +05:30
Mihir Kandoi
371030f8d4 Merge pull request #50615 from frappe/mergify/bp/version-15-hotfix/pr-50614
fix: redundant message on bom save (backport #50614)
2025-11-19 12:53:50 +05:30
Mihir Kandoi
2550b44db8 chore: resolve conflicts 2025-11-19 12:38:47 +05:30
Mihir Kandoi
5b1674018b fix: redundant message on bom save
(cherry picked from commit 074f07694f)

# Conflicts:
#	erpnext/manufacturing/doctype/bom/bom.py
2025-11-19 07:06:11 +00:00
Frappe PR Bot
d8dab986fa chore(release): Bumped to Version 15.89.0
# [15.89.0](https://github.com/frappe/erpnext/compare/v15.88.1...v15.89.0) (2025-11-19)

### Bug Fixes

* add cancelled option in status field ([623a0a9](623a0a932e))
* add condition for allow negative stock in pos (backport [#50369](https://github.com/frappe/erpnext/issues/50369)) ([#50600](https://github.com/frappe/erpnext/issues/50600)) ([2d6640a](2d6640ac61))
* add doctype parameter to lead details for correct company details ([f0eac47](f0eac47037))
* **asset repair:** validate pi status ([2db91ee](2db91ee67e))
* back calcalute total amount from rate and tax_amount in tax withholding details report ([5728299](57282999ad))
* construct batch_nos and serial_nos to avoid NoneType error ([0a0177c](0a0177cb9e))
* correct profit after tax calculation by reducing expenses from income ([627b34a](627b34a120))
* current qty in stock reco ([b4b8459](b4b8459f2c))
* enable allow_negative_stock settings ([2a5c9b4](2a5c9b469c))
* **financial reports:** set fiscal year associated with the default company ([ac40b59](ac40b59665))
* first and last name in supplier quick entry (backport [#50510](https://github.com/frappe/erpnext/issues/50510)) ([#50514](https://github.com/frappe/erpnext/issues/50514)) ([3b636d5](3b636d5db7))
* **general_ledger:** add translation for accounting dimension ([799119a](799119ad3e))
* handle NoneType object error for product bundle ([2b7abfb](2b7abfb34b))
* improve precision in tax amount calculations in tax withholding details report ([c150e57](c150e5795e))
* on changes of paid from/to account fetch company bank account ([3d8a344](3d8a344173))
* **period closing voucher:** add title to error log ([#50498](https://github.com/frappe/erpnext/issues/50498)) ([33962ac](33962ac995))
* prevent pos opening entry creation for disabled pos profile ([68747b5](68747b5818))
* **stock-entry:** prevent default warehouse from overriding parent warehouse ([a5ec0e4](a5ec0e4f50))
* unintended backported depends_on expression ([#50529](https://github.com/frappe/erpnext/issues/50529)) ([81a1628](81a16286a1))
* use dynamic account type to get average ratio balance ([a2c82b4](a2c82b4dc3))

### Features

* Add first and last name fields to quick entry customer creation (backport [#46281](https://github.com/frappe/erpnext/issues/46281)) ([#50522](https://github.com/frappe/erpnext/issues/50522)) ([8c98f16](8c98f1692a))
* **Company:** allow setting default sales contact, fetch into sales transaction (backport [#50159](https://github.com/frappe/erpnext/issues/50159)) ([#50599](https://github.com/frappe/erpnext/issues/50599)) ([f8294f1](f8294f1754))
* **Item Price:** validate UOM ([376da8d](376da8df0a))
* **pos:** prevent disabling POS Profile when open POS sessions exist ([87e8305](87e8305753))
2025-11-19 02:58:17 +00:00
Diptanil Saha
f25e2295d0 Merge pull request #50595 from frappe/version-15-hotfix 2025-11-19 08:26:48 +05:30
ruthra kumar
b4fd4812cd Merge pull request #50527 from aerele/default-report-fiscal-year-v15
fix(financial reports): set fiscal year associated with the default company
2025-11-18 18:12:21 +05:30
rohitwaghchaure
876dec5077 chore: fix conflicts 2025-11-18 18:05:08 +05:30
rohitwaghchaure
36e9aae9d0 chore: fix conflicts 2025-11-18 18:04:29 +05:30
Pugazhendhi Velu
8ccb9a5ad2 fix: add return status for purchase receipt
(cherry picked from commit 3a0e1e8ef9)
2025-11-18 12:33:18 +00:00
Kavin
85c0c16964 fix: validate sabb autocreation when disabled
(cherry picked from commit 3ca1940881)

# Conflicts:
#	erpnext/stock/doctype/stock_entry/stock_entry.py
2025-11-18 12:29:01 +00:00
ruthra kumar
6a46045804 Merge pull request #50603 from frappe/mergify/bp/version-15-hotfix/pr-50524
fix: use dynamic account type to get average ratio balance (backport #50524)
2025-11-18 17:44:31 +05:30
ruthra kumar
befa4bef0d Merge pull request #50601 from frappe/mergify/bp/version-15-hotfix/pr-50516
fix(general_ledger): add translation for accounting dimension (backport #50516)
2025-11-18 17:13:34 +05:30
mergify[bot]
f8294f1754 feat(Company): allow setting default sales contact, fetch into sales transaction (backport #50159) (#50599)
Co-authored-by: Raffael Meyer <14891507+barredterra@users.noreply.github.com>
Co-authored-by: Diptanil Saha <diptanil@frappe.io>
2025-11-18 17:05:58 +05:30
mergify[bot]
2d6640ac61 fix: add condition for allow negative stock in pos (backport #50369) (#50600)
Co-authored-by: Logesh Periyasamy <logeshperiyasamy24@gmail.com>
fix: add condition for allow negative stock in pos (#50369)
2025-11-18 17:05:47 +05:30
Navin-S-R
627b34a120 fix: correct profit after tax calculation by reducing expenses from income
(cherry picked from commit f420371a7e)
2025-11-18 11:22:38 +00:00
Navin-S-R
a2c82b4dc3 fix: use dynamic account type to get average ratio balance
(cherry picked from commit 9118f08e7b)
2025-11-18 11:22:38 +00:00
Logesh Periyasamy
799119ad3e fix(general_ledger): add translation for accounting dimension
(cherry picked from commit 113ff17c71)
2025-11-18 11:15:37 +00:00
ruthra kumar
a4a0a2a0fb Merge pull request #50554 from frappe/mergify/bp/version-15-hotfix/pr-50540
fix(stock-entry): prevent default warehouse from overriding parent warehouse (backport #50540)
2025-11-18 15:09:08 +05:30
ruthra kumar
35fb2b8ede Merge pull request #50573 from frappe/mergify/bp/version-15-hotfix/pr-50496
fix: back calcalute total amount from rate and tax_amount in tax withholding details report (backport #50496)
2025-11-18 15:08:26 +05:30
ruthra kumar
c844bf5547 Merge pull request #50574 from frappe/mergify/bp/version-15-hotfix/pr-50439
fix: add doctype parameter to lead details for correct company details (backport #50439)
2025-11-18 15:07:15 +05:30
Kavin
81a16286a1 fix: unintended backported depends_on expression (#50529)
Co-authored-by: Kavin <78342682+kavin0411@users.noreply.github.com>
2025-11-18 10:07:26 +02:00
Khushi Rawat
3c8534c4cc Merge pull request #50571 from aerele/fix/support-52685
fix: add cancelled option in status field
2025-11-18 11:15:53 +05:30
ravibharathi656
ac40b59665 fix(financial reports): set fiscal year associated with the default company 2025-11-18 11:14:40 +05:30
ravibharathi656
3f2081b440 fix: prevent pi status from changing on asset repair 2025-11-18 11:09:25 +05:30
Pugazhendhi Velu
2db91ee67e fix(asset repair): validate pi status 2025-11-17 14:06:26 +00:00
ljain112
f0eac47037 fix: add doctype parameter to lead details for correct company details
(cherry picked from commit 0b91338771)
2025-11-17 13:39:09 +00:00
ljain112
4df80c5b53 chore: typo in comment
(cherry picked from commit e056c0327d)
2025-11-17 13:36:08 +00:00
ljain112
c150e5795e fix: improve precision in tax amount calculations in tax withholding details report
(cherry picked from commit 7c5f5405cc)
2025-11-17 13:36:08 +00:00
ljain112
57282999ad fix: back calcalute total amount from rate and tax_amount in tax withholding details report
(cherry picked from commit d3751d9bb4)
2025-11-17 13:36:08 +00:00
Pugazhendhi Velu
623a0a932e fix: add cancelled option in status field 2025-11-17 13:09:38 +00:00
rohitwaghchaure
9b06eaab78 Merge pull request #50535 from aerele/support-53360
fix: construct batch_nos and serial_nos to avoid NoneType error
2025-11-17 16:24:20 +05:30
Sherin KR
dfda8e6241 fix: item price not considering based on valid_upto 2025-11-17 14:34:26 +05:30
Kavin
2a5c9b469c fix: enable allow_negative_stock settings 2025-11-17 13:53:55 +05:30
Kavin
0a0177cb9e fix: construct batch_nos and serial_nos to avoid NoneType error 2025-11-17 12:35:16 +05:30
Mihir Kandoi
eed144d7c9 Merge pull request #50231 from frappe/mergify/bp/version-15-hotfix/pr-40586 2025-11-17 10:26:43 +05:30
Pugazhendhi Velu
a5ec0e4f50 fix(stock-entry): prevent default warehouse from overriding parent warehouse
(cherry picked from commit 8b38578914)
2025-11-17 04:41:27 +00:00
mergify[bot]
8c98f1692a feat: Add first and last name fields to quick entry customer creation (backport #46281) (#50522)
Co-authored-by: Nabin Hait <nabinhait@gmail.com>
Co-authored-by: maasanto <73234812+maasanto@users.noreply.github.com>
Co-authored-by: Diptanil Saha <diptanil@frappe.io>
2025-11-13 21:58:34 +05:30
Diptanil Saha
182e84e94c Merge pull request #50521 from frappe/mergify/bp/version-15-hotfix/pr-50498
fix(period closing voucher): add title to error log (backport #50498)
2025-11-13 21:50:21 +05:30
PUGAZHENDHI V
33962ac995 fix(period closing voucher): add title to error log (#50498)
(cherry picked from commit 4f720b3969)
2025-11-13 15:56:37 +00:00
mergify[bot]
3b636d5db7 fix: first and last name in supplier quick entry (backport #50510) (#50514)
Co-authored-by: ljain112 <ljain112@gmail.com>
Co-authored-by: Diptanil Saha <diptanil@frappe.io>
2025-11-13 15:37:50 +05:30
Frappe PR Bot
70b8b3bb9e chore(release): Bumped to Version 15.88.1
## [15.88.1](https://github.com/frappe/erpnext/compare/v15.88.0...v15.88.1) (2025-11-12)

### Bug Fixes

* handle NoneType object error for product bundle ([eab6d69](eab6d69ec9))
2025-11-12 18:26:04 +00:00
rohitwaghchaure
c42954bec7 Merge pull request #50500 from frappe/mergify/bp/version-15/pr-50488
fix: handle NoneType object error for packed_items (backport #50488)
2025-11-12 23:54:34 +05:30
Kavin
eab6d69ec9 fix: handle NoneType object error for product bundle
(cherry picked from commit 2b7abfb34b)
2025-11-12 17:21:25 +00:00
rohitwaghchaure
3f0bea2d9f Merge pull request #50488 from aerele/support-53076
fix: handle NoneType object error for packed_items
2025-11-12 22:50:37 +05:30
rohitwaghchaure
34ed9b455f Merge pull request #50491 from frappe/mergify/bp/version-15-hotfix/pr-50487
fix: current qty in stock reconciliation  (backport #50487)
2025-11-12 22:49:44 +05:30
Kavin
2b7abfb34b fix: handle NoneType object error for product bundle 2025-11-12 18:26:19 +05:30
Diptanil Saha
2ba1731d3f Merge pull request #50484 from frappe/mergify/bp/version-15-hotfix/pr-50409 2025-11-12 15:14:53 +05:30
Rohit Waghchaure
b4b8459f2c fix: current qty in stock reco
(cherry picked from commit 58315bc963)
2025-11-12 08:26:01 +00:00
Diptanil Saha
d5160c4c86 test: delete outdated pos opening entry 2025-11-12 12:26:26 +05:30
Diptanil Saha
af19b81343 chore: resolve conflict 2025-11-12 11:35:02 +05:30
Diptanil Saha
650d2f74ba chore: resolve conflict 2025-11-12 11:33:56 +05:30
diptanilsaha
68747b5818 fix: prevent pos opening entry creation for disabled pos profile
(cherry picked from commit e35e8968f0)

# Conflicts:
#	erpnext/accounts/doctype/pos_opening_entry/test_pos_opening_entry.py
2025-11-12 05:44:01 +00:00
diptanilsaha
38848ff43b test: added test to validate disabled pos profile
(cherry picked from commit 69016a284f)

# Conflicts:
#	erpnext/accounts/doctype/pos_profile/test_pos_profile.py
2025-11-12 05:44:00 +00:00
diptanilsaha
87e8305753 feat(pos): prevent disabling POS Profile when open POS sessions exist
(cherry picked from commit c5219278fb)
2025-11-12 05:44:00 +00:00
Diptanil Saha
a2345d467e Merge pull request #50483 from frappe/mergify/bp/version-15-hotfix/pr-50323
fix(payment entry): on changes of paid from/to account fetch company bank account (backport #50323)
2025-11-12 11:11:37 +05:30
Abdeali Chharchhoda
3d8a344173 fix: on changes of paid from/to account fetch company bank account
(cherry picked from commit 4901dc2531)
2025-11-12 05:38:56 +00:00
Frappe PR Bot
e112290728 chore(release): Bumped to Version 15.88.0
# [15.88.0](https://github.com/frappe/erpnext/compare/v15.87.2...v15.88.0) (2025-11-11)

### Bug Fixes

* add company filter for default warehouse for sales return ([32d3fbf](32d3fbf1e8))
* add is_group filter in task for timesheet ([0f00581](0f00581f83))
* add missing stock entry UOM filtering based on item master ([#50135](https://github.com/frappe/erpnext/issues/50135)) ([8f2002d](8f2002d419))
* add validation to reject empty readings ([ac0375f](ac0375fc2e))
* apply company,is_group filter for cost center ([b181686](b1816864de))
* automatically append taxes if taxes_and_charges is set in Buying controller ([25f5fb7](25f5fb7637))
* **buying:** fetch Cost Center from Project ([e8e26a9](e8e26a91bb))
* change fieldtype from link to data for document_type in producti… (backport [#50443](https://github.com/frappe/erpnext/issues/50443)) ([#50455](https://github.com/frappe/erpnext/issues/50455)) ([a3ddc95](a3ddc9533a))
* change fieldtype from link to data for document_type in production plan summary ([9012a72](9012a72185))
* check warehouse account before accessing ([79b3af6](79b3af6d3e))
* ensure that additional discount amount is not mapped repeatedly ([44539f0](44539f0944))
* handle partial dn against reserved stock ([9d979e3](9d979e34ab))
* handle returns as well ([9ed40cc](9ed40cc17d))
* hide total row in general ledger report ([56bb88d](56bb88d281))
* ignore Department doctype ([32182d7](32182d7cc7))
* include cost_center and project upon accounting dimension fetch ([3f490f1](3f490f11d5))
* material request item quantity validation against sales order with over-receipt allowance ([f2fef54](f2fef54b83))
* **material request:** set default buying price list if not exists ([670c6dc](670c6dcdd7))
* Nonetype error if reserved stock is not present ([b8ec3ae](b8ec3ae23a))
* Pass stock_qty and picked_qty in transfer entry ([95ea9ca](95ea9ca66b))
* removed the validation ([080e9a3](080e9a3d73))
* reset billing and shipping address when company changes ([73b8a29](73b8a294cf))
* resolve conflict ([7d593dd](7d593dd3db))
* set company before creating asset movement to avoid permission error ([3fad90e](3fad90ebb9))
* show only stock items in delivered items to be billed and received items to be billed reports ([3dbc90a](3dbc90a0b4))
* state_to_state_province for translation ([#50244](https://github.com/frappe/erpnext/issues/50244)) ([d4f6ca3](d4f6ca3564))
* **stock:** ignore current voucher in reserved stock validation ([0e7f971](0e7f9711e1))
* **Timesheet:** don't use billing_hours for costing amount ([#50394](https://github.com/frappe/erpnext/issues/50394)) ([29c976e](29c976e9ae))
* trends report total mismatch with group filters ([7e3f30b](7e3f30baad))
* Update pick list locations quantity ([ce7ab8d](ce7ab8df9a))
* update uom when item changes ([2a2ae9a](2a2ae9a20c))
* validate is_group for parent task ([3380dea](3380deab02))
* validate that discount amount cannot exceed total before discount ([e559faf](e559fafa83))

### Features

* **account settings:** add checkbox to show balances in payment entry ([90500f0](90500f0ffc))
* add asset name column ([c486471](c48647100f))
* make material transfer warehouse validation optional (backport [#50461](https://github.com/frappe/erpnext/issues/50461)) ([#50462](https://github.com/frappe/erpnext/issues/50462)) ([1747e83](1747e83cb1))
* process period closing voucher ([c8e3da0](c8e3da0a71))

### Performance Improvements

* serial no creation ([6ba2491](6ba24912c3))
2025-11-11 14:49:50 +00:00
Diptanil Saha
3149785960 Merge pull request #50473 from frappe/resolve-payment-entry-settings-conflict 2025-11-11 20:18:23 +05:30
Diptanil Saha
736cff84f2 Merge branch 'version-15' into resolve-payment-entry-settings-conflict 2025-11-11 20:04:20 +05:30
rohitwaghchaure
0023476500 Merge pull request #50470 from frappe/mergify/bp/version-15-hotfix/pr-50187
fix: Update pick list locations quantity (backport #50187)
2025-11-11 16:11:03 +05:30
ruthra kumar
0c4295fb6f Merge pull request #50472 from frappe/mergify/bp/version-15-hotfix/pr-50469
fix: automatically append taxes if taxes_and_charges is set in Buying controller (backport #50469)
2025-11-11 15:57:52 +05:30
Sagar Vora
13371275db Merge pull request #50471 from frappe/mergify/bp/version-15-hotfix/pr-50155
fix: ensure that additional discount amount is not mapped repeatedly (backport #50155)
2025-11-11 15:13:48 +05:30
Sagar Vora
313e6af528 chore: resolve conflicts 2025-11-11 15:11:52 +05:30
ljain112
e2a0d6e5f6 test: add automatic tax addition for buying controller
(cherry picked from commit 3d0a668c50)
2025-11-11 09:34:16 +00:00
ljain112
25f5fb7637 fix: automatically append taxes if taxes_and_charges is set in Buying controller
(cherry picked from commit d171dc7328)
2025-11-11 09:34:16 +00:00
Sagar Vora
22848eb4da chore: remove unused import
(cherry picked from commit 81ab15351e)

# Conflicts:
#	erpnext/controllers/taxes_and_totals.py
2025-11-11 09:32:59 +00:00
Sagar Vora
b4df87e545 refactor: simplify logic
(cherry picked from commit 95f604457d)
2025-11-11 09:32:56 +00:00
Sagar Vora
9ed40cc17d fix: handle returns as well
(cherry picked from commit 0e026b9ccd)
2025-11-11 09:32:56 +00:00
Sagar Vora
22b6760164 test: some tests to ensure correct discount mapping
(cherry picked from commit 0968f435d2)
2025-11-11 09:32:56 +00:00
Sagar Vora
e559fafa83 fix: validate that discount amount cannot exceed total before discount
(cherry picked from commit f4f79d99e4)

# Conflicts:
#	erpnext/controllers/taxes_and_totals.py
2025-11-11 09:32:56 +00:00
Sagar Vora
44539f0944 fix: ensure that additional discount amount is not mapped repeatedly
(cherry picked from commit feb62102d9)
2025-11-11 09:32:55 +00:00
Kavin
a0d94c38c1 test: add test for pending qty calculation in Pick List
(cherry picked from commit 3f7a60d56c)
2025-11-11 09:24:34 +00:00
Kavin
95ea9ca66b fix: Pass stock_qty and picked_qty in transfer entry
(cherry picked from commit 6db605c443)
2025-11-11 09:24:34 +00:00
Kavin
ce7ab8df9a fix: Update pick list locations quantity
(cherry picked from commit bd9e240ca5)
2025-11-11 09:24:34 +00:00
rohitwaghchaure
798858bd4f Merge pull request #50467 from aerele/fix/update-uom-value
fix: update uom when item changes
2025-11-11 13:43:01 +05:30
ruthra kumar
c6774e35f2 Merge pull request #50465 from frappe/mergify/bp/version-15-hotfix/pr-50366
refactor: enqueue exchange rate revaluation per company (backport #50366)
2025-11-11 13:29:25 +05:30
Kavin
2a2ae9a20c fix: update uom when item changes 2025-11-11 13:17:21 +05:30
ravibharathi656
f039bfe35a refactor: enqueue exchange rate revaluation per company
(cherry picked from commit b10e7bf7b5)
2025-11-11 07:34:57 +00:00
mergify[bot]
1747e83cb1 feat: make material transfer warehouse validation optional (backport #50461) (#50462)
Co-authored-by: Mihir Kandoi <kandoimihir@gmail.com>
2025-11-11 07:18:41 +00:00
rohitwaghchaure
de14c0838c Merge pull request #50445 from frappe/mergify/bp/version-15-hotfix/pr-50436
perf: serial no creation (backport #50436)
2025-11-11 11:45:59 +05:30
ruthra kumar
3788d0f4f0 Merge pull request #50396 from aerele/show-party-and-account-balances
feat(account settings): add checkbox to show balances in payment entry
2025-11-11 11:14:25 +05:30
Mihir Kandoi
ba98a00c6c Merge pull request #50459 from frappe/mergify/bp/version-15-hotfix/pr-50418
fix: show only stock items in delivered items to be billed and received items to be billed reports (backport #50418)
2025-11-11 10:57:58 +05:30
Mihir Kandoi
2c4510ed1e Merge pull request #50458 from frappe/mergify/bp/version-15-hotfix/pr-50244
fix: state_to_state_province for translation (backport #50244)
2025-11-11 10:52:26 +05:30
rohitwaghchaure
87f3ba5794 chore: fix linters issue 2025-11-11 10:51:19 +05:30
Mihir Kandoi
197d09b90a Merge pull request #50460 from frappe/mergify/bp/version-15-hotfix/pr-50446
fix: add company filter for default warehouse for sales return (backport #50446)
2025-11-11 10:49:48 +05:30
Pugazhendhi Velu
32d3fbf1e8 fix: add company filter for default warehouse for sales return
(cherry picked from commit 0b614007bb)
2025-11-11 05:17:53 +00:00
rohitwaghchaure
4ec25ac82e chore: fix conflicts
Removed unused voucher_no and posting_date retrieval.
2025-11-11 10:47:06 +05:30
ravibharathi656
3dbc90a0b4 fix: show only stock items in delivered items to be billed and received items to be billed reports
(cherry picked from commit 1b2e5c9706)
2025-11-11 05:12:50 +00:00
Mihir Kandoi
f00236e669 Merge pull request #50456 from frappe/mergify/bp/version-15-hotfix/pr-50322
fix typo "show_disables_items" to "show_disabled_items" (backport #50322)
2025-11-11 10:41:20 +05:30
mahsem
d4f6ca3564 fix: state_to_state_province for translation (#50244)
Co-authored-by: Mihir Kandoi <kandoimihir@gmail.com>
(cherry picked from commit e148a38353)
2025-11-11 05:08:42 +00:00
Mihir Kandoi
10e7ae4dd3 Merge pull request #50457 from frappe/mergify/bp/version-15-hotfix/pr-50320
fix: add is_group filter in task for timesheet (backport #50320)
2025-11-11 10:37:44 +05:30
Pugazhendhi Velu
0f00581f83 fix: add is_group filter in task for timesheet
(cherry picked from commit 5bac896329)
2025-11-11 04:58:38 +00:00
Mihir Kandoi
a3ddc9533a fix: change fieldtype from link to data for document_type in producti… (backport #50443) (#50455)
Co-authored-by: Pugazhendhi Velu <pugazhendhi720@gmail.com>
2025-11-11 10:26:47 +05:30
rethik
2b766bca97 chore: fix typo "show_disables_items" to "show_disabled_items"
(cherry picked from commit d26c598daa)
2025-11-11 04:56:33 +00:00
Mihir Kandoi
38c2633594 Merge pull request #50454 from frappe/mergify/bp/version-15-hotfix/pr-50399
fix: mr item quantity validation against so over-receipt allowance (backport #50399)
2025-11-11 10:25:45 +05:30
Pugazhendhi Velu
9012a72185 fix: change fieldtype from link to data for document_type in production plan summary
(cherry picked from commit 462deb3755)
2025-11-11 04:41:26 +00:00
Pugazhendhi Velu
249d14b072 test: add test for validate mr item qty against so with over-receipt allowance
(cherry picked from commit 55f531bad6)
2025-11-11 04:40:25 +00:00
Pugazhendhi Velu
f2fef54b83 fix: material request item quantity validation against sales order with over-receipt allowance
(cherry picked from commit 8d7e31e3f2)
2025-11-11 04:40:25 +00:00
Mihir Kandoi
1b1e4e4688 Merge pull request #50453 from frappe/mergify/bp/version-15-hotfix/pr-50135
fix: add missing stock entry UOM filtering based on item master (backport #50135)
2025-11-11 10:05:05 +05:30
Rehan Ansari
8f2002d419 fix: add missing stock entry UOM filtering based on item master (#50135)
Co-authored-by: rehansari26 <rehan.ansari@cloverinfotech.com>
(cherry picked from commit 7baf6ec3d6)
2025-11-11 04:29:34 +00:00
Assem Bahnasy
5b643433e5 Fix: Product Bundle Purchase Order Creation Logic (#49831)
Co-authored-by: Mihir Kandoi <kandoimihir@gmail.com>
2025-11-11 09:53:25 +05:30
Diptanil Saha
e02aaa9f1b Merge pull request #50449 from frappe/mergify/bp/version-15-hotfix/pr-50339
fix: include cost_center and project upon accounting dimension fetch (backport #50339)
2025-11-11 00:10:52 +05:30
l0gesh29
b1816864de fix: apply company,is_group filter for cost center
(cherry picked from commit dcdc1c6a89)
2025-11-10 17:47:08 +00:00
l0gesh29
3f490f11d5 fix: include cost_center and project upon accounting dimension fetch
(cherry picked from commit 4680295303)
2025-11-10 17:47:07 +00:00
Diptanil Saha
b545b69e4b Merge pull request #50444 from frappe/mergify/bp/version-15-hotfix/pr-50361
fix: reset billing and shipping address when company changes (backport #50361)
2025-11-10 20:59:05 +05:30
Rohit Waghchaure
6ba24912c3 perf: serial no creation
(cherry picked from commit 19a9497273)

# Conflicts:
#	erpnext/stock/serial_batch_bundle.py
2025-11-10 15:11:27 +00:00
Pugazhendhi Velu
73b8a294cf fix: reset billing and shipping address when company changes
(cherry picked from commit 0510f7e13f)
2025-11-10 15:08:13 +00:00
ruthra kumar
b5485dc909 Merge pull request #50393 from frappe/mergify/bp/version-15-hotfix/pr-50340
fix: ignore Department doctype (backport #50340)
2025-11-10 16:37:43 +05:30
Frappe PR Bot
292f71bcef chore(release): Bumped to Version 15.87.2
## [15.87.2](https://github.com/frappe/erpnext/compare/v15.87.1...v15.87.2) (2025-11-10)

### Bug Fixes

* Nonetype error if reserved stock is not present ([cf66b5a](cf66b5aa34))
* **stock:** ignore current voucher in reserved stock validation ([9d2c456](9d2c456668))
2025-11-10 10:47:57 +00:00
rohitwaghchaure
1e4acb3703 Merge pull request #50434 from frappe/mergify/bp/version-15/pr-50431
fix(stock): ignore current voucher in reserved stock validation (backport #50431)
2025-11-10 16:16:31 +05:30
Kavin
cf66b5aa34 fix: Nonetype error if reserved stock is not present
(cherry picked from commit b8ec3ae23a)
2025-11-10 10:29:12 +00:00
Kavin
9d2c456668 fix(stock): ignore current voucher in reserved stock validation
(cherry picked from commit 0e7f9711e1)
2025-11-10 10:29:12 +00:00
rohitwaghchaure
5ed4fea3e3 Merge pull request #50431 from aerele/fix/reserved-stock-negative
fix(stock): ignore current voucher in reserved stock validation
2025-11-10 15:57:37 +05:30
Kavin
b8ec3ae23a fix: Nonetype error if reserved stock is not present 2025-11-10 14:51:35 +05:30
Kavin
0e7f9711e1 fix(stock): ignore current voucher in reserved stock validation 2025-11-10 14:29:04 +05:30
rohitwaghchaure
3cad1304a0 Merge pull request #50427 from frappe/mergify/bp/version-15-hotfix/pr-50374
fix: add validation to reject empty readings (backport #50374)
2025-11-10 14:04:23 +05:30
ruthra kumar
9dc1f5f649 Merge pull request #50405 from frappe/mergify/bp/version-15-hotfix/pr-50326
fix: validate is_group for parent task (backport #50326)
2025-11-10 12:58:34 +05:30
ruthra kumar
df6ca3af57 chore: resolve conflicts 2025-11-10 12:43:05 +05:30
ruthra kumar
95db1677e2 Merge pull request #50408 from aerele/support-52573
fix: check warehouse account before accessing
2025-11-10 12:39:14 +05:30
ruthra kumar
ca9f1b6c7b Merge pull request #50429 from frappe/mergify/bp/version-15-hotfix/pr-50423
fix(buying): fetch Cost Center from Project (backport #50423)
2025-11-10 12:35:29 +05:30
barredterra
e8e26a91bb fix(buying): fetch Cost Center from Project
(cherry picked from commit bdabcb081a)
2025-11-10 07:03:04 +00:00
Pugazhendhi Velu
dc88f7b30b refactor: add default reading value when creating a quality inspection
(cherry picked from commit 63fb9f55e7)
2025-11-10 05:38:42 +00:00
Pugazhendhi Velu
ac0375fc2e fix: add validation to reject empty readings
(cherry picked from commit 405d901514)
2025-11-10 05:38:42 +00:00
Frappe PR Bot
2863b0fe52 chore(release): Bumped to Version 15.87.1
## [15.87.1](https://github.com/frappe/erpnext/compare/v15.87.0...v15.87.1) (2025-11-07)

### Bug Fixes

* handle partial dn against reserved stock ([7466d91](7466d91e12))
2025-11-07 16:36:23 +00:00
rohitwaghchaure
6096b56a10 Merge pull request #50415 from frappe/mergify/bp/version-15/pr-50401
fix: handle partial dn against reserved stock (backport #50401)
2025-11-07 22:04:57 +05:30
Kavin
88fdab99a9 test: add test for partial dn against reserved stock
(cherry picked from commit ef719fe729)
2025-11-07 15:26:11 +00:00
Kavin
7466d91e12 fix: handle partial dn against reserved stock
(cherry picked from commit 9d979e34ab)
2025-11-07 15:26:10 +00:00
rohitwaghchaure
5bb2e8a8ff Merge pull request #50401 from aerele/support-52103
fix: handle partial dn against reserved stock
2025-11-07 20:53:43 +05:30
rohitwaghchaure
3989a7ede6 Merge pull request #50412 from frappe/mergify/bp/version-15-hotfix/pr-50411
fix: removed the validation (backport #50411)
2025-11-07 19:16:37 +05:30
Kavin
ef719fe729 test: add test for partial dn against reserved stock 2025-11-07 19:09:23 +05:30
Kavin
9d979e34ab fix: handle partial dn against reserved stock 2025-11-07 19:09:11 +05:30
Rohit Waghchaure
080e9a3d73 fix: removed the validation
(cherry picked from commit 10131333b2)
2025-11-07 12:33:11 +00:00
Kavin
79b3af6d3e fix: check warehouse account before accessing 2025-11-07 15:49:59 +05:30
Patrick Eißler
29c976e9ae fix(Timesheet): don't use billing_hours for costing amount (#50394) 2025-11-07 13:26:44 +05:30
Pugazhendhi Velu
635fe427fe refactor(task): use get_link_to_form for validation error messages
(cherry picked from commit 4cf02b4d78)
2025-11-07 07:28:59 +00:00
Pugazhendhi Velu
dc5b8367c5 test: add test for parent task is_group validation
(cherry picked from commit 291f0c7161)

# Conflicts:
#	erpnext/projects/doctype/task/test_task.py
2025-11-07 07:28:59 +00:00
Pugazhendhi Velu
3380deab02 fix: validate is_group for parent task
(cherry picked from commit ed1a1099cb)

# Conflicts:
#	erpnext/projects/doctype/task/task.py
2025-11-07 07:28:59 +00:00
Diptanil Saha
8e199af118 Merge pull request #50403 from frappe/mergify/bp/version-15-hotfix/pr-50402
fix: trends report total mismatch with group by filters (backport #50402)
2025-11-07 12:50:49 +05:30
diptanilsaha
7e3f30baad fix: trends report total mismatch with group filters
(cherry picked from commit f7d09f8760)
2025-11-07 07:03:51 +00:00
ravibharathi656
90500f0ffc feat(account settings): add checkbox to show balances in payment entry 2025-11-06 18:35:56 +05:30
rethik
32182d7cc7 fix: ignore Department doctype
(cherry picked from commit fff6f1fb23)
2025-11-06 11:14:55 +00:00
ruthra kumar
4f02677d6f Merge pull request #50387 from frappe/mergify/bp/version-15-hotfix/pr-50364
fix: hide total row in general ledger report (backport #50364)
2025-11-06 16:02:53 +05:30
Pugazhendhi Velu
56bb88d281 fix: hide total row in general ledger report
(cherry picked from commit ef38b26a73)
2025-11-06 10:11:46 +00:00
Khushi Rawat
124a0fe45d Merge pull request #50379 from frappe/mergify/bp/version-15-hotfix/pr-50367
fix: set company before creating asset movement to avoid permission error (backport #50367)
2025-11-06 10:03:20 +05:30
rehansari26
3fad90ebb9 fix: set company before creating asset movement to avoid permission error
(cherry picked from commit 8c49c9e500)
2025-11-05 21:50:22 +00:00
Khushi Rawat
99b6dc508e Merge pull request #50377 from frappe/mergify/bp/version-15-hotfix/pr-50342
feat: add asset name column (backport #50342)
2025-11-06 01:29:57 +05:30
Khushi Rawat
7d593dd3db fix: resolve conflict 2025-11-06 00:51:41 +05:30
Rehan Ansari
c48647100f feat: add asset name column
(cherry picked from commit f3eda02972)

# Conflicts:
#	erpnext/accounts/report/asset_depreciation_ledger/asset_depreciation_ledger.py
2025-11-05 18:52:50 +00:00
Frappe PR Bot
ad4fe2db9e chore(release): Bumped to Version 15.87.0
# [15.87.0](https://github.com/frappe/erpnext/compare/v15.86.0...v15.87.0) (2025-11-05)

### Features

* process period closing voucher ([8cdbaac](8cdbaacfff))
2025-11-05 12:37:51 +00:00
ruthra kumar
13de175b0f Merge pull request #50370 from frappe/mergify/bp/version-15/pr-50144
refactor: period closing voucher to handle large data volumes (backport #50144)
2025-11-05 18:06:29 +05:30
ruthra kumar
a333ec28e9 chore: resolve conflicts 2025-11-05 17:46:59 +05:30
ruthra kumar
e6d38d009f refactor: add paused to select option
(cherry picked from commit fca7abf4d6)
2025-11-05 12:15:04 +00:00
ruthra kumar
178eded259 refactor: minor changes on status
1. set to 'In Progress' on start of both legacy and new controller
2. force delete to avoid permission issues
3. default to 1hr timeout

(cherry picked from commit 9c13edc0b9)
2025-11-05 12:15:04 +00:00
ruthra kumar
5db7888a8d refactor: enable legacy controller by default for pcv
(cherry picked from commit fe39ce03bb)

# Conflicts:
#	erpnext/accounts/doctype/accounts_settings/accounts_settings.json
#	erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py
2025-11-05 12:15:04 +00:00
ruthra kumar
83e0ce4020 chore: progress bar
(cherry picked from commit 0b88f98a86)
2025-11-05 12:15:03 +00:00
ruthra kumar
6f58614ef2 chore: remove scaffolding
(cherry picked from commit 191c0e65a1)
2025-11-05 12:15:03 +00:00
ruthra kumar
a3068c8bf6 refactor: abort processing of all tasks upon cancellation
(cherry picked from commit 090e155fd0)
2025-11-05 12:15:03 +00:00
ruthra kumar
bdeee94c18 refactor: more changes
1. 'Accounts Manager' has access to submit, cancel and delete
2. cancel and delete operation of PCV is linked with Proces PCV

(cherry picked from commit cae1237859)
2025-11-05 12:15:02 +00:00
ruthra kumar
db5013fca1 refactor: smaller methods
(cherry picked from commit fa3bd6f5a7)
2025-11-05 12:15:02 +00:00
ruthra kumar
2712310c0a refactor: utility to consolidate results from all dates
(cherry picked from commit 7406d83260)
2025-11-05 12:15:02 +00:00
ruthra kumar
a624ae07f0 refactor: utility to convert tuple key to str
(cherry picked from commit 5b464ae4c1)
2025-11-05 12:15:02 +00:00
ruthra kumar
347a7e3b1f refactor: cleanup and for better readability
(cherry picked from commit 653ae84b3e)
2025-11-05 12:15:01 +00:00
ruthra kumar
df4347a6cb refactor: make Accounts Closing Balance as well
(cherry picked from commit 6e32769e37)
2025-11-05 12:15:01 +00:00
ruthra kumar
7edbf25e60 refactor: store closing balance for Balnace sheet accounts
(cherry picked from commit 09e37bc98c)
2025-11-05 12:15:01 +00:00
ruthra kumar
7c85d7f163 refactor: calculate both balances from single queue
(cherry picked from commit 643e1fdce8)
2025-11-05 12:15:01 +00:00
ruthra kumar
6216547027 refactor: populate opening balances calculation table
(cherry picked from commit 86edacb781)
2025-11-05 12:15:00 +00:00
ruthra kumar
ac0a837bf3 chore: rename closing balance field
(cherry picked from commit cef879bb3b)
2025-11-05 12:15:00 +00:00
ruthra kumar
8be8a73a36 refactor: balances for both P&L and Balance sheet accounts
(cherry picked from commit 324bebfd44)
2025-11-05 12:15:00 +00:00
ruthra kumar
f49f60b5f4 refactor: maintain report type on each date
(cherry picked from commit 186d540502)
2025-11-05 12:15:00 +00:00
ruthra kumar
3a13c04a71 refactor: more stable pause and resume
(cherry picked from commit 9e93298f12)
2025-11-05 12:14:59 +00:00
ruthra kumar
62e8d4753e refactor: process on submit
(cherry picked from commit c738b6d356)
2025-11-05 12:14:59 +00:00
ruthra kumar
18c7121230 refactor: for better readability
(cherry picked from commit 8ba199016a)
2025-11-05 12:14:59 +00:00
ruthra kumar
37c1d665e3 refactor: store results as is and convert at the end
(cherry picked from commit f25ee3c53f)
2025-11-05 12:14:59 +00:00
ruthra kumar
0d9c711b6d refactor: build and post gl entries
(cherry picked from commit e88074ddec)
2025-11-05 12:14:58 +00:00
ruthra kumar
3b0a1bce3d refactor: store daily balances based on dimensions key
dimensions key is manually converted to string

(cherry picked from commit 1846de0d49)
2025-11-05 12:14:58 +00:00
ruthra kumar
efd90f554f refactor: store closing balance as JSON
(cherry picked from commit 1a31825409)
2025-11-05 12:14:58 +00:00
ruthra kumar
5992ce533e refactor: stable start, pause, resume and completion stages
(cherry picked from commit c839ebf593)
2025-11-05 12:14:58 +00:00
ruthra kumar
1c044759ac refactor: barebones functions
(cherry picked from commit 1c92b01542)
2025-11-05 12:14:57 +00:00
ruthra kumar
86a36b3ef4 refactor: temporarily save balances in JSON
(cherry picked from commit f44c908a8d)
2025-11-05 12:14:57 +00:00
ruthra kumar
cd830a6b6c refactor: child table in process pcv
(cherry picked from commit 0d09d21d2e)
2025-11-05 12:14:57 +00:00
ruthra kumar
dc1147d504 refactor: more data structure changes
(cherry picked from commit a15578f8f4)
2025-11-05 12:14:56 +00:00
ruthra kumar
797b418af4 refactor: checkbox for pcv controller
(cherry picked from commit 4888461be2)

# Conflicts:
#	erpnext/accounts/doctype/accounts_settings/accounts_settings.json
#	erpnext/accounts/doctype/accounts_settings/accounts_settings.py
2025-11-05 12:14:56 +00:00
ruthra kumar
8cdbaacfff feat: process period closing voucher
(cherry picked from commit 7a93630629)
2025-11-05 12:14:56 +00:00
ruthra kumar
c54d995354 Merge pull request #50368 from frappe/mergify/bp/version-15-hotfix/pr-50144
refactor: period closing voucher to handle large data volumes (backport #50144)
2025-11-05 17:42:52 +05:30
ruthra kumar
5c6cc1ea2a chore: resolve conflicts 2025-11-05 17:27:14 +05:30
ruthra kumar
e09ee63d32 refactor: add paused to select option
(cherry picked from commit fca7abf4d6)
2025-11-05 11:28:44 +00:00
ruthra kumar
d8e5075424 refactor: minor changes on status
1. set to 'In Progress' on start of both legacy and new controller
2. force delete to avoid permission issues
3. default to 1hr timeout

(cherry picked from commit 9c13edc0b9)
2025-11-05 11:28:43 +00:00
ruthra kumar
d5a36fe8aa refactor: enable legacy controller by default for pcv
(cherry picked from commit fe39ce03bb)

# Conflicts:
#	erpnext/accounts/doctype/accounts_settings/accounts_settings.json
#	erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py
2025-11-05 11:28:43 +00:00
ruthra kumar
10df192275 chore: progress bar
(cherry picked from commit 0b88f98a86)
2025-11-05 11:28:43 +00:00
ruthra kumar
4ebddc591f chore: remove scaffolding
(cherry picked from commit 191c0e65a1)
2025-11-05 11:28:42 +00:00
ruthra kumar
5cc6a1771d refactor: abort processing of all tasks upon cancellation
(cherry picked from commit 090e155fd0)
2025-11-05 11:28:42 +00:00
ruthra kumar
29e8801b7f refactor: more changes
1. 'Accounts Manager' has access to submit, cancel and delete
2. cancel and delete operation of PCV is linked with Proces PCV

(cherry picked from commit cae1237859)
2025-11-05 11:28:42 +00:00
ruthra kumar
d94000fecf refactor: smaller methods
(cherry picked from commit fa3bd6f5a7)
2025-11-05 11:28:42 +00:00
ruthra kumar
5071cad161 refactor: utility to consolidate results from all dates
(cherry picked from commit 7406d83260)
2025-11-05 11:28:41 +00:00
ruthra kumar
0151f5f191 refactor: utility to convert tuple key to str
(cherry picked from commit 5b464ae4c1)
2025-11-05 11:28:41 +00:00
ruthra kumar
d139db296a refactor: cleanup and for better readability
(cherry picked from commit 653ae84b3e)
2025-11-05 11:28:41 +00:00
ruthra kumar
3406e44b03 refactor: make Accounts Closing Balance as well
(cherry picked from commit 6e32769e37)
2025-11-05 11:28:41 +00:00
ruthra kumar
449fa05d7d refactor: store closing balance for Balnace sheet accounts
(cherry picked from commit 09e37bc98c)
2025-11-05 11:28:40 +00:00
ruthra kumar
55222468f9 refactor: calculate both balances from single queue
(cherry picked from commit 643e1fdce8)
2025-11-05 11:28:40 +00:00
ruthra kumar
f381b99b14 refactor: populate opening balances calculation table
(cherry picked from commit 86edacb781)
2025-11-05 11:28:40 +00:00
ruthra kumar
2c880dd609 chore: rename closing balance field
(cherry picked from commit cef879bb3b)
2025-11-05 11:28:39 +00:00
ruthra kumar
87e297e899 refactor: balances for both P&L and Balance sheet accounts
(cherry picked from commit 324bebfd44)
2025-11-05 11:28:39 +00:00
ruthra kumar
6c94ca664f refactor: maintain report type on each date
(cherry picked from commit 186d540502)
2025-11-05 11:28:39 +00:00
ruthra kumar
d911e1dab2 refactor: more stable pause and resume
(cherry picked from commit 9e93298f12)
2025-11-05 11:28:39 +00:00
ruthra kumar
908f8ed462 refactor: process on submit
(cherry picked from commit c738b6d356)
2025-11-05 11:28:38 +00:00
ruthra kumar
633ccef2ff refactor: for better readability
(cherry picked from commit 8ba199016a)
2025-11-05 11:28:38 +00:00
ruthra kumar
e8f8abd685 refactor: store results as is and convert at the end
(cherry picked from commit f25ee3c53f)
2025-11-05 11:28:38 +00:00
ruthra kumar
b6b5524228 refactor: build and post gl entries
(cherry picked from commit e88074ddec)
2025-11-05 11:28:38 +00:00
ruthra kumar
76bdf7944c refactor: store daily balances based on dimensions key
dimensions key is manually converted to string

(cherry picked from commit 1846de0d49)
2025-11-05 11:28:37 +00:00
ruthra kumar
1999de0b75 refactor: store closing balance as JSON
(cherry picked from commit 1a31825409)
2025-11-05 11:28:37 +00:00
ruthra kumar
43acfdff82 refactor: stable start, pause, resume and completion stages
(cherry picked from commit c839ebf593)
2025-11-05 11:28:37 +00:00
ruthra kumar
19b911120c refactor: barebones functions
(cherry picked from commit 1c92b01542)
2025-11-05 11:28:37 +00:00
ruthra kumar
bc07de8c12 refactor: temporarily save balances in JSON
(cherry picked from commit f44c908a8d)
2025-11-05 11:28:36 +00:00
ruthra kumar
b484db3ffd refactor: child table in process pcv
(cherry picked from commit 0d09d21d2e)
2025-11-05 11:28:36 +00:00
ruthra kumar
902ce45a36 refactor: more data structure changes
(cherry picked from commit a15578f8f4)
2025-11-05 11:28:36 +00:00
ruthra kumar
bfc0044d23 refactor: checkbox for pcv controller
(cherry picked from commit 4888461be2)

# Conflicts:
#	erpnext/accounts/doctype/accounts_settings/accounts_settings.json
#	erpnext/accounts/doctype/accounts_settings/accounts_settings.py
2025-11-05 11:28:36 +00:00
ruthra kumar
c8e3da0a71 feat: process period closing voucher
(cherry picked from commit 7a93630629)
2025-11-05 11:28:35 +00:00
rohitwaghchaure
2eed8ee343 Merge pull request #50362 from frappe/mergify/bp/version-15-hotfix/pr-50335
fix(material request): set default buying price list if not exists (backport #50335)
2025-11-05 14:44:21 +05:30
ravibharathi656
670c6dcdd7 fix(material request): set default buying price list if not exists
(cherry picked from commit 9c0ff14060)
2025-11-05 08:42:09 +00:00
Frappe PR Bot
09d12f2f9f chore(release): Bumped to Version 15.86.0
# [15.86.0](https://github.com/frappe/erpnext/compare/v15.85.1...v15.86.0) (2025-11-04)

### Bug Fixes

* **accounts-receivable:** ensure report data with party account currency ([164333a](164333a730))
* **accounts-receivable:** ensure report data with party account currency (backport [#50035](https://github.com/frappe/erpnext/issues/50035)) ([#50311](https://github.com/frappe/erpnext/issues/50311)) ([ae23cdd](ae23cdd8e9))
* **accounts:** populate correct fields on GL Entry during discount accounting ([4076798](4076798707))
* added validation for default accounts on company ([d9d9230](d9d9230d4a))
* allow bulk edit for bill of material items ([afe42ee](afe42ee3e9))
* create GL entries via hooks only for submitted assets ([3d78277](3d7827731b))
* disallow material transfer if source and target warehouse are same ([#50331](https://github.com/frappe/erpnext/issues/50331)) ([d920520](d920520843)), closes [#48697](https://github.com/frappe/erpnext/issues/48697)
* handle None in last_valuation_rate check ([e3110b3](e3110b3993))
* job card timer ([053765a](053765a466))
* **pos:** order pos invoices by timestamp ([12903b1](12903b11ed))
* Respect allowed zero qty in SO and PO based on Buying/Selling settings when update items ([#49673](https://github.com/frappe/erpnext/issues/49673)) ([5d4da9c](5d4da9c68f))
* set valuation rate for rejected serial/batch item ([f72d14b](f72d14b1ca))

### Features

* option to exclude stand-alone returned sales invoices from the Gross Profit report ([017dc79](017dc792e6))

### Reverts

* Revert "refactor: add supplier filter in buying (backport [#50013](https://github.com/frappe/erpnext/issues/50013)) ([#50107](https://github.com/frappe/erpnext/issues/50107))" ([288570a](288570acde))
2025-11-04 12:32:53 +00:00
Diptanil Saha
19f66c6018 Merge pull request #50333 from frappe/version-15-hotfix
chore: release v15
2025-11-04 18:01:18 +05:30
rohitwaghchaure
de80215df5 Merge pull request #50338 from frappe/mergify/bp/version-15-hotfix/pr-50332
feat: option to exclude stand-alone returned sales invoices from the Gross Profit report (backport #50332)
2025-11-04 17:38:04 +05:30
Rohit Waghchaure
017dc792e6 feat: option to exclude stand-alone returned sales invoices from the Gross Profit report
(cherry picked from commit 52cf9d4950)
2025-11-04 11:30:46 +00:00
Mihir Kandoi
d920520843 fix: disallow material transfer if source and target warehouse are same (#50331)
* fix: disallow material transfer if source and target warehouse are same (#48697)

* fix: disallow material transfer if source and target warehouse are same

* fix: check on child row level instead of parent level

* chore: add docstring to function
2025-11-04 09:44:18 +00:00
mergify[bot]
ac901dee3c Add support for subcontract return from rejected warehouse (backport #50299) (#50330)
* Merge pull request #50299 from saadchaudharry/feature-subcontract-return-rejected

Add support for subcontract return from rejected warehouse

(cherry picked from commit 8854db51dd)

# Conflicts:
#	erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py

* chore: resolve conflicts

---------

Co-authored-by: Saad Chaudhary <47004596+saadchaudharry@users.noreply.github.com>
Co-authored-by: Mihir Kandoi <kandoimihir@gmail.com>
2025-11-04 09:09:41 +00:00
ruthra kumar
eed1abd272 Merge pull request #50313 from frappe/mergify/bp/version-15-hotfix/pr-49673
fix: Respect allowed zero qty in SO and PO based on Buying/Selling settings when update items (backport #49673)
2025-11-03 15:39:39 +05:30
ruthra kumar
ae23cdd8e9 fix(accounts-receivable): ensure report data with party account currency (backport #50035) (#50311)
* fix(accounts-receivable): ensure report data with party account currency

(cherry picked from commit 752ea7ee7d)

* test(accounts-receivable): add test case to validate report data with party account currency

(cherry picked from commit 3e4846ea3d)

---------

Co-authored-by: Bhavan23 <bhavan@aerele.in>
2025-11-03 15:30:24 +05:30
Kerolles Fathy
5d4da9c68f fix: Respect allowed zero qty in SO and PO based on Buying/Selling settings when update items (#49673)
* fix: respect allowed zero qty in SO and PO based on buying/selling settings

* refactor: remove parent_doctype param due to it's already avaliable

* refactor: rename is_allowed_zero_qty_for to is_allowed_zero_qty

* fix: prevent rate change for unit price items

* fix: unboundlocal variable rate_unchanged

* refactor: only throw on 'zero' qty items

---------

Co-authored-by: ruthra kumar <ruthra@erpnext.com>
(cherry picked from commit 44363c069e)
2025-11-03 09:47:30 +00:00
Khushi Rawat
990ada1656 Merge pull request #50312 from frappe/mergify/bp/version-15-hotfix/pr-50260
fix: create GL entries via hooks only for submitted assets (backport #50260)
2025-11-03 15:13:42 +05:30
Bhavan23
1e40fb00f5 test(accounts-receivable): add test case to validate report data with party account currency
(cherry picked from commit 3e4846ea3d)
2025-11-03 15:13:29 +05:30
khushi8112
3d7827731b fix: create GL entries via hooks only for submitted assets
(cherry picked from commit 33690975f6)
2025-11-03 09:21:58 +00:00
Bhavan23
164333a730 fix(accounts-receivable): ensure report data with party account currency
(cherry picked from commit 752ea7ee7d)
2025-11-03 09:12:44 +00:00
ruthra kumar
e1afcb39db Merge pull request #50309 from frappe/mergify/bp/version-15-hotfix/pr-50297
chore:there is no company field in bank (backport #50297)
2025-11-03 14:04:42 +05:30
Nihal Roshan
65e37756f6 refactor: remove company filter
'Bank' doctype has no 'company' field.

(cherry picked from commit f1682ea90e)
2025-11-03 08:31:56 +00:00
Diptanil Saha
c897220535 Merge pull request #50307 from frappe/mergify/bp/version-15-hotfix/pr-50305
fix(accounts): populate correct fields on GL Entry during discount accounting (backport #50305)
2025-11-03 13:58:28 +05:30
Diptanil Saha
b04c06e034 chore: resolve conflict 2025-11-03 13:22:33 +05:30
diptanilsaha
4076798707 fix(accounts): populate correct fields on GL Entry during discount accounting
(cherry picked from commit e41a7b8cd7)

# Conflicts:
#	erpnext/controllers/accounts_controller.py
2025-11-03 07:49:36 +00:00
rohitwaghchaure
8b8427cbf5 Merge pull request #50303 from frappe/mergify/bp/version-15-hotfix/pr-50300
fix: handle None in last_valuation_rate check (backport #50300)
2025-11-03 10:13:57 +05:30
Kavin
e3110b3993 fix: handle None in last_valuation_rate check
(cherry picked from commit a3058bf8cc)
2025-11-02 07:25:34 +00:00
Diptanil Saha
b5f8f2b6fa Merge pull request #50292 from frappe/mergify/bp/version-15-hotfix/pr-50291
fix: added validation for default accounts on company (backport #50291)
2025-11-01 10:04:59 +05:30
Diptanil Saha
1a3652bee1 chore: resolve conflict 2025-10-31 17:34:15 +05:30
Mihir Kandoi
253b945816 Merge pull request #50287 from frappe/revert-50107-mergify/bp/version-15-hotfix/pr-50013
Revert "refactor: add supplier filter in buying (backport #50013)"
2025-10-31 15:46:29 +05:30
diptanilsaha
d9d9230d4a fix: added validation for default accounts on company
(cherry picked from commit 4af1ae1470)

# Conflicts:
#	erpnext/setup/doctype/company/company.py
2025-10-31 10:07:42 +00:00
rohitwaghchaure
668ec641c1 Merge pull request #50290 from rohitwaghchaure/fixed-github-50262
fix: job card timer
2025-10-31 14:33:23 +05:30
Rohit Waghchaure
053765a466 fix: job card timer 2025-10-31 14:06:22 +05:30
Mihir Kandoi
288570acde Revert "refactor: add supplier filter in buying (backport #50013) (#50107)"
This reverts commit abb210bd18.
2025-10-31 13:59:58 +05:30
Frappe PR Bot
4ef07f97c9 chore(release): Bumped to Version 15.85.1
## [15.85.1](https://github.com/frappe/erpnext/compare/v15.85.0...v15.85.1) (2025-10-30)

### Bug Fixes

* **pos:** order pos invoices by timestamp ([8bd1e8f](8bd1e8ff74))
2025-10-30 15:42:14 +00:00
rohitwaghchaure
670579bde3 Merge pull request #50278 from frappe/mergify/bp/version-15/pr-50277
fix(pos): order pos invoices by timestamp (backport #50277)
2025-10-30 21:10:53 +05:30
Kavin
8bd1e8ff74 fix(pos): order pos invoices by timestamp
(cherry picked from commit 12903b11ed)
2025-10-30 13:20:53 +00:00
rohitwaghchaure
83f4970255 Merge pull request #50277 from aerele/support-51587
fix(pos): order pos invoices by timestamp
2025-10-30 18:49:44 +05:30
Kavin
12903b11ed fix(pos): order pos invoices by timestamp 2025-10-30 18:16:11 +05:30
rohitwaghchaure
7658076070 Merge pull request #50271 from frappe/mergify/bp/version-15-hotfix/pr-50270
fix: set valuation rate for rejected serial/batch item (backport #50270)
2025-10-30 09:27:57 +05:30
rohitwaghchaure
b019d2f45e chore: fix linters issue 2025-10-30 09:06:37 +05:30
venkat102
397bc96b40 test: add unit test for valuation rate on rejected serial/batch item
(cherry picked from commit d002959d35)
2025-10-30 03:32:00 +00:00
venkat102
f72d14b1ca fix: set valuation rate for rejected serial/batch item
(cherry picked from commit 614402cf6c)
2025-10-30 03:31:59 +00:00
rohitwaghchaure
0405d82b75 Merge pull request #50266 from frappe/mergify/bp/version-15-hotfix/pr-50264
fix: allow bulk edit for bill of material items (backport #50264)
2025-10-30 08:58:13 +05:30
Raffael Meyer
7d607b82f1 chore: resolve conflicts 2025-10-29 15:37:04 +01:00
Rohit Waghchaure
afe42ee3e9 fix: allow bulk edit for bill of material items
(cherry picked from commit 1f74e06791)
2025-10-29 12:51:38 +00:00
Frappe PR Bot
49f66a8a51 chore(release): Bumped to Version 15.85.0
# [15.85.0](https://github.com/frappe/erpnext/compare/v15.84.0...v15.85.0) (2025-10-28)

### Bug Fixes

* **accounts:** update payment mode account retrieval to use namespaced function ([2300660](23006601b2))
* add message for missing purchase orders in production plan ([5798409](5798409f69))
* **asset depreciations and balances:** showing opening entries ([81f19b9](81f19b950d))
* avoid group columns mutation ([158e1b2](158e1b28a9))
* **Bank Transaction:** make transaction ID non-unique ([b52b04a](b52b04a10c))
* fiscal year overlap validation for company-specific years ([482a796](482a796212))
* get valuation rate based of previous SLEs for material receipt ([e9f4a34](e9f4a34d8d))
* **gross profit:** remove customer name from columns ([a767253](a7672530f4))
* **journal-entry:** allow copy account currency when duplicating JV ([1b227b8](1b227b8b4f))
* optimized the slow query to get the batchwise available qty ([85bf936](85bf9366b0))
* Pass uom field name to update existing item qty ([93b2786](93b2786865))
* provision to find and fix incorrect serial and batch bundles ([2276741](22767410d5))
* recalculate amount based on allocated amount ([2a90bff](2a90bffb5f))
* resolve conflicts ([97147a4](97147a484d))
* sabb missed in the incorrect serial no valuation report ([8a995f2](8a995f28c9))
* set default value for as zero for additional asset cost ([ee5e4ec](ee5e4eccec))
* set status to Draft for auto-created assets from Purchase Receipt ([d8eddbf](d8eddbfd03))
* stock difference value for adjustment entry ([6c0694f](6c0694ff17))
* **Task:** make Timesheet-dependent fields no_copy (backport [#50130](https://github.com/frappe/erpnext/issues/50130)) ([#50196](https://github.com/frappe/erpnext/issues/50196)) ([4988ff8](4988ff84df))
* use correct field name ([a82fa8c](a82fa8c26b))

### Features

* Add posting date param for reverse GL entries ([1a7092d](1a7092d7b6))
* add project filter to Delayed Tasks Summary report ([82ca729](82ca729e2b))
2025-10-28 13:48:43 +00:00
Diptanil Saha
0a09bb8d17 Merge pull request #50249 from frappe/version-15-hotfix
chore: release v15
2025-10-28 19:17:10 +05:30
rohitwaghchaure
ba700bce90 Merge pull request #50252 from frappe/mergify/bp/version-15-hotfix/pr-50247
fix: provision to find and fix incorrect serial and batch bundles (backport #50247)
2025-10-28 18:21:46 +05:30
Rohit Waghchaure
22767410d5 fix: provision to find and fix incorrect serial and batch bundles
(cherry picked from commit 10ad56060c)
2025-10-28 12:15:11 +00:00
Diptanil Saha
89e7a260fd Merge pull request #50251 from frappe/mergify/bp/version-15-hotfix/pr-50137
fix(payment-reco): recalculate amount based on allocated amount (backport #50137)
2025-10-28 17:34:10 +05:30
l0gesh29
2a90bffb5f fix: recalculate amount based on allocated amount
(cherry picked from commit 5a7a6a9bd5)
2025-10-28 11:58:10 +00:00
Diptanil Saha
7434522ea1 Merge pull request #50250 from frappe/mergify/bp/version-15-hotfix/pr-50220
fix(gross profit): remove customer name from columns (backport #50220)
2025-10-28 15:37:53 +05:30
ravibharathi656
158e1b28a9 fix: avoid group columns mutation
(cherry picked from commit 7ce81127d2)
2025-10-28 09:51:23 +00:00
ravibharathi656
a7672530f4 fix(gross profit): remove customer name from columns
(cherry picked from commit 0009925af0)
2025-10-28 09:51:23 +00:00
Diptanil Saha
ad33735541 Merge pull request #50245 from frappe/mergify/bp/version-15-hotfix/pr-50213
fix(Bank Transaction)!: make transaction ID non-unique (backport #50213)
2025-10-28 10:20:49 +05:30
Diptanil Saha
977f385006 chore: resolve conflict 2025-10-28 09:07:14 +05:30
barredterra
b52b04a10c fix(Bank Transaction): make transaction ID non-unique
(cherry picked from commit a2a41a0eaa)

# Conflicts:
#	erpnext/accounts/doctype/bank_transaction/bank_transaction.json
2025-10-28 02:45:52 +00:00
Diptanil Saha
05b89b4121 Merge pull request #50243 from frappe/mergify/bp/version-15-hotfix/pr-49599
fix(accounts): reference get_payment_mode_account correctly in Sales Invoice (backport #49599)
2025-10-28 08:08:36 +05:30
Diptanil Saha
36983c97cb chore: resolve conflict 2025-10-28 08:06:10 +05:30
KerollesFathy
23006601b2 fix(accounts): update payment mode account retrieval to use namespaced function
(cherry picked from commit 0af74aef00)

# Conflicts:
#	erpnext/public/js/controllers/accounts.js
2025-10-27 16:50:10 +00:00
rohitwaghchaure
37e9461ece Merge pull request #50239 from frappe/mergify/bp/version-15-hotfix/pr-50233
fix: optimized the slow query to get the batch-wise available qty (backport #50233)
2025-10-27 17:31:15 +05:30
Mihir Kandoi
126d79dcd2 Merge pull request #50241 from frappe/mergify/bp/version-15-hotfix/pr-50221
fix: Pass uom field name to update existing item qty (backport #50221)
2025-10-27 17:29:29 +05:30
Kavin
93b2786865 fix: Pass uom field name to update existing item qty
(cherry picked from commit 23d69389ec)
2025-10-27 11:48:44 +00:00
rohitwaghchaure
2680f85430 chore: fix linters issue 2025-10-27 17:06:45 +05:30
rohitwaghchaure
2d7fde024d chore: fix conflicts 2025-10-27 16:57:00 +05:30
Rohit Waghchaure
85bf9366b0 fix: optimized the slow query to get the batchwise available qty
(cherry picked from commit 9c21567309)

# Conflicts:
#	erpnext/stock/serial_batch_bundle.py
2025-10-27 11:19:24 +00:00
Khushi Rawat
86f507bb6e Merge pull request #50238 from frappe/mergify/bp/version-15-hotfix/pr-50222
fix(asset depreciations and balances): showing opening entries (backport #50222)
2025-10-27 16:35:46 +05:30
ravibharathi656
81f19b950d fix(asset depreciations and balances): showing opening entries
(cherry picked from commit d3afa67be3)
2025-10-27 10:48:36 +00:00
Mihir Kandoi
7b4eac2294 Merge pull request #50236 from Abdeali099/fix-msg
fix: add message for missing purchase orders in production plan
2025-10-27 15:54:09 +05:30
Diptanil Saha
aff4b62258 Merge pull request #50234 from frappe/mergify/bp/version-15-hotfix/pr-50039
fix(journal-entry): allow copy account currency when duplicating JV (backport #50039)
2025-10-27 15:36:40 +05:30
Abdeali Chharchhoda
5798409f69 fix: add message for missing purchase orders in production plan 2025-10-27 15:09:22 +05:30
Bhavan23
1b227b8b4f fix(journal-entry): allow copy account currency when duplicating JV
(cherry picked from commit 76748e4573)
2025-10-27 08:45:01 +00:00
barredterra
376da8df0a feat(Item Price): validate UOM
(cherry picked from commit 69824eff80)

# Conflicts:
#	erpnext/stock/doctype/item_price/item_price.py
2025-10-27 06:32:01 +00:00
Diptanil Saha
4eca7f0524 Merge pull request #50230 from frappe/mergify/bp/version-15-hotfix/pr-50103
fix: fiscal year overlap validation for company-specific years (backport #50103)
2025-10-27 11:01:57 +05:30
rehansari26
4bb66179ab test: replace get_doc with new_doc in fiscal year tests
(cherry picked from commit d59e55fb08)
2025-10-27 05:08:36 +00:00
Rehan Ansari
d84a29e1a1 test: fiscal year overlap validation for company-specific years
(cherry picked from commit 94ae098854)
2025-10-27 05:08:36 +00:00
Rehan Ansari
482a796212 fix: fiscal year overlap validation for company-specific years
(cherry picked from commit 57aaf34d3e)
2025-10-27 05:08:36 +00:00
Diptanil Saha
41694d3751 Merge pull request #50223 from frappe/mergify/bp/version-15-hotfix/pr-49889
feat: add project filter to Delayed Tasks Summary report (backport #49889)
2025-10-24 22:27:54 +05:30
Rehan Ansari
82ca729e2b feat: add project filter to Delayed Tasks Summary report
(cherry picked from commit 88097e78d2)
2025-10-24 16:42:15 +00:00
rohitwaghchaure
e67361257e Merge pull request #50216 from frappe/mergify/bp/version-15-hotfix/pr-50215
fix: get valuation rate based of previous SLEs for material receipt (backport #50215)
2025-10-24 00:05:12 +05:30
Rohit Waghchaure
e9f4a34d8d fix: get valuation rate based of previous SLEs for material receipt
(cherry picked from commit fa9ef6708f)
2025-10-23 18:30:20 +00:00
Khushi Rawat
c6c4e31b32 Merge pull request #50211 from frappe/mergify/bp/version-15-hotfix/pr-50209
fix: set status to Draft for auto-created assets from Purchase Receipt (backport #50209)
2025-10-23 23:33:42 +05:30
khushi8112
ee5e4eccec fix: set default value for as zero for additional asset cost 2025-10-23 22:51:30 +05:30
khushi8112
a82fa8c26b fix: use correct field name 2025-10-23 20:45:08 +05:30
khushi8112
97147a484d fix: resolve conflicts 2025-10-23 19:09:30 +05:30
khushi8112
d8eddbfd03 fix: set status to Draft for auto-created assets from Purchase Receipt
(cherry picked from commit 20c2cb40d1)

# Conflicts:
#	erpnext/assets/doctype/asset/asset.py
#	erpnext/patches.txt
2025-10-23 13:03:17 +00:00
Deepesh Garg
977464e6a7 Merge pull request #50206 from frappe/mergify/bp/version-15-hotfix/pr-50204
feat: Add posting date param for reverse GL entries (#50204)
2025-10-23 16:02:07 +05:30
Deepesh Garg
db84df0cbd chore: Linting issues
(cherry picked from commit 05e1a737f1)
2025-10-23 08:12:31 +00:00
Deepesh Garg
1a7092d7b6 feat: Add posting date param for reverse GL entries
(cherry picked from commit 38988bf797)
2025-10-23 08:12:30 +00:00
rohitwaghchaure
fcd05bb7e4 Merge pull request #50202 from frappe/mergify/bp/version-15-hotfix/pr-50200
fix: stock difference value for adjustment entry (backport #50200)
2025-10-23 10:31:00 +05:30
Rohit Waghchaure
6c0694ff17 fix: stock difference value for adjustment entry
(cherry picked from commit fb4c7de86c)
2025-10-22 17:03:12 +00:00
mergify[bot]
4988ff84df fix(Task): make Timesheet-dependent fields no_copy (backport #50130) (#50196)
* fix(Task): make Timesheet-dependent fields no_copy

(cherry picked from commit 2a2e4b5423)

# Conflicts:
#	erpnext/projects/doctype/task/task.json

* chore: resolve conflicts

---------

Co-authored-by: Patrick Eissler <77415730+PatrickDEissler@users.noreply.github.com>
Co-authored-by: Mihir Kandoi <kandoimihir@gmail.com>
2025-10-22 08:34:11 +00:00
Mihir Kandoi
e5d0116924 Merge pull request #50194 from frappe/mergify/bp/version-15-hotfix/pr-50151
chore: remove print statement (backport #50151)
2025-10-22 14:01:04 +05:30
Mihir Kandoi
38d3b17dfe Merge pull request #50195 from frappe/mergify/bp/version-15-hotfix/pr-50153
fix: Address title error when create new transporter on driver  (backport #50153)
2025-10-22 13:48:31 +05:30
Kerolles Fathy
89d305ac9f Merge pull request #50153 from KerollesFathy/fix-address-error-when-create-transporter
fix: Address title error when create new transporter on driver
(cherry picked from commit 8efcf6cb38)
2025-10-22 08:14:25 +00:00
Abdeali Chharchhoda
8b2be43897 chore: remove print statement
(cherry picked from commit 1ad4dc9066)
2025-10-22 08:14:24 +00:00
rohitwaghchaure
0bd3b5aac2 Merge pull request #50192 from frappe/mergify/bp/version-15-hotfix/pr-50191
fix: sabb missed in the incorrect serial no valuation report (backport #50191)
2025-10-22 12:17:53 +05:30
Rohit Waghchaure
8a995f28c9 fix: sabb missed in the incorrect serial no valuation report
(cherry picked from commit b50bac6788)
2025-10-22 06:26:01 +00:00
Frappe PR Bot
e714b82802 chore(release): Bumped to Version 15.84.0
# [15.84.0](https://github.com/frappe/erpnext/compare/v15.83.2...v15.84.0) (2025-10-21)

### Bug Fixes

* added exception handling on service level agreement apply hook ([#50096](https://github.com/frappe/erpnext/issues/50096)) ([a3a6d39](a3a6d39436))
* adjustment entry ([76cfa28](76cfa28a42))
* correct monthly sales history (backport [#50056](https://github.com/frappe/erpnext/issues/50056)) ([#50179](https://github.com/frappe/erpnext/issues/50179)) ([afc2d95](afc2d95736))
* handle flt conversion for prev_ordered_qty ([3d3e116](3d3e116797))
* internal transfer entry with serial/batch ([d67a439](d67a439051))
* **point-of-sale:** render payment methods only payment component is visible ([2b0281c](2b0281c510))
* preview stock ledger for manual serial and batch values ([c64dcf3](c64dcf3423))
* **stock:** remove duplicate fields ([58a1383](58a1383380))
* validation for negative batch ([b9dd05f](b9dd05f292))

### Features

* set options for IBAN fields (backport [#49377](https://github.com/frappe/erpnext/issues/49377)) ([#49413](https://github.com/frappe/erpnext/issues/49413)) ([bd3a132](bd3a132868))

### Performance Improvements

* Add index for faster queries ([#50175](https://github.com/frappe/erpnext/issues/50175)) ([0571ed0](0571ed0735))
2025-10-21 12:44:58 +00:00
Diptanil Saha
7ec6ef3139 Merge pull request #50182 from frappe/version-15-hotfix
chore: release v15
2025-10-21 18:13:27 +05:30
mergify[bot]
afc2d95736 fix: correct monthly sales history (backport #50056) (#50179)
fix: correct monthly sales history (#50056)

* fix: correct monthly sales history

* fix: correct monthly sales history calculation

* chore: remove unrelated file accidentally committed

---------


(cherry picked from commit f51ed30c23)

Co-authored-by: Ahmed AbuKhatwa <82771130+AhmedAbokhatwa@users.noreply.github.com>
Co-authored-by: AhmedAbukhatwa <Ahmedabukhatwa1@gmail.com>
2025-10-21 11:06:02 +05:30
Deepesh Garg
1e9ffe351b Merge pull request #50178 from frappe/mergify/bp/version-15-hotfix/pr-50175
perf: Add index for faster queries
2025-10-21 09:56:35 +05:30
Deepesh Garg
0571ed0735 perf: Add index for faster queries (#50175)
(cherry picked from commit 7a91ec3e33)
2025-10-20 18:43:48 +00:00
mergify[bot]
43941ecd5e refactor: simplify expression (backport #50168) (#50170)
Co-authored-by: barredterra <14891507+barredterra@users.noreply.github.com>
2025-10-19 23:59:27 +02:00
Frappe PR Bot
8b9788ca74 chore(release): Bumped to Version 15.83.2
## [15.83.2](https://github.com/frappe/erpnext/compare/v15.83.1...v15.83.2) (2025-10-18)

### Bug Fixes

* internal transfer entry with serial/batch ([97cdac1](97cdac10d7))
* **stock:** remove duplicate fields ([5e8e6ef](5e8e6ef2f3))
2025-10-18 04:42:12 +00:00
rohitwaghchaure
eb38bcdab7 Merge pull request #50164 from frappe/mergify/bp/version-15/pr-50158
fix: internal transfer entry with serial/batch (backport #50156) (backport #50158)
2025-10-18 10:10:35 +05:30
rohitwaghchaure
9876d1c7e6 Merge pull request #50165 from frappe/mergify/bp/version-15/pr-50157
fix(stock-settings): remove duplicate fields (backport #50157)
2025-10-18 10:10:20 +05:30
Kavin
5e8e6ef2f3 fix(stock): remove duplicate fields
(cherry picked from commit 58a1383380)
2025-10-18 03:49:50 +00:00
rohitwaghchaure
2055c4e8d3 Merge pull request #50157 from aerele/support-51015
fix(stock-settings): remove duplicate fields
2025-10-18 09:19:21 +05:30
Rohit Waghchaure
97cdac10d7 fix: internal transfer entry with serial/batch
(cherry picked from commit 9b4e62a758)
(cherry picked from commit d67a439051)
2025-10-18 03:47:47 +00:00
rohitwaghchaure
df22902035 Merge pull request #50158 from frappe/mergify/bp/version-15-hotfix/pr-50156
fix: internal transfer entry with serial/batch (backport #50156)
2025-10-17 21:32:16 +05:30
Rohit Waghchaure
d67a439051 fix: internal transfer entry with serial/batch
(cherry picked from commit 9b4e62a758)
2025-10-17 15:34:30 +00:00
Kavin
58a1383380 fix(stock): remove duplicate fields 2025-10-17 18:35:53 +05:30
Frappe PR Bot
5e21c9c5c9 chore(release): Bumped to Version 15.83.1
## [15.83.1](https://github.com/frappe/erpnext/compare/v15.83.0...v15.83.1) (2025-10-17)

### Bug Fixes

* validation for negative batch ([555d5da](555d5da611))
2025-10-17 09:19:51 +00:00
rohitwaghchaure
6262566c53 Merge pull request #50150 from frappe/mergify/bp/version-15/pr-50145
fix: validation for negative batch (backport #50123) (backport #50145)
2025-10-17 14:48:04 +05:30
Rohit Waghchaure
555d5da611 fix: validation for negative batch
(cherry picked from commit f9c8f27586)
(cherry picked from commit b9dd05f292)
2025-10-17 08:06:54 +00:00
rohitwaghchaure
f5af5dd8c0 Merge pull request #50145 from frappe/mergify/bp/version-15-hotfix/pr-50123
fix: validation for negative batch (backport #50123)
2025-10-17 12:34:15 +05:30
Rohit Waghchaure
b9dd05f292 fix: validation for negative batch
(cherry picked from commit f9c8f27586)
2025-10-17 06:07:37 +00:00
Diptanil Saha
44f39e0b43 Merge pull request #50142 from frappe/mergify/bp/version-15-hotfix/pr-50141
fix(point-of-sale): render payment methods only when payment component is visible (backport #50141)
2025-10-17 01:46:05 +05:30
diptanilsaha
2b0281c510 fix(point-of-sale): render payment methods only payment component is visible
(cherry picked from commit 7dc4306640)
2025-10-16 20:13:33 +00:00
rohitwaghchaure
03766e8980 Merge pull request #50117 from frappe/mergify/bp/version-15-hotfix/pr-50113
fix: adjustment entry (backport #50113)
2025-10-15 21:31:32 +05:30
Diptanil Saha
e7b7377b7e Merge pull request #50120 from frappe/mergify/bp/version-15-hotfix/pr-50096
fix: added exception handling on service level agreement apply hook (backport #50096)
2025-10-15 19:51:23 +05:30
Diptanil Saha
a3a6d39436 fix: added exception handling on service level agreement apply hook (#50096)
* fix: added exception handling on service level agreement apply hook

* Revert "fix: added exception handling on service level agreement apply hook"

This reverts commit dae93aa96f.

* fix: Ignore missing SLA table during install/uninstall

---------

Co-authored-by: Ankush Menat <ankush@frappe.io>
(cherry picked from commit 182c9fd966)
2025-10-15 14:04:17 +00:00
Rohit Waghchaure
76cfa28a42 fix: adjustment entry
(cherry picked from commit c0851abaee)
2025-10-15 10:30:33 +00:00
Diptanil Saha
afa7d2b595 Merge pull request #50109 from frappe/mergify/bp/version-15-hotfix/pr-50095
fix: preview stock ledger for manual serial and batch values (backport #50095)
2025-10-15 13:14:13 +05:30
Kavin
c64dcf3423 fix: preview stock ledger for manual serial and batch values
(cherry picked from commit c5f68d0b27)
2025-10-15 05:47:41 +00:00
Mihir Kandoi
3fa38d0b4e Merge pull request #50106 from frappe/mergify/bp/version-15-hotfix/pr-50078
fix: handle flt conversion for prev_ordered_qty (backport #50078)
2025-10-15 00:02:09 +05:30
mergify[bot]
abb210bd18 refactor: add supplier filter in buying (backport #50013) (#50107)
* refactor: add supplier filter in buying

(cherry picked from commit 108b108d64)

# Conflicts:
#	erpnext/public/js/controllers/buying.js

* chore: resolve conflicts

---------

Co-authored-by: manikandan-s-18 <manikandansundar18@gmail.com>
Co-authored-by: Mihir Kandoi <kandoimihir@gmail.com>
2025-10-14 18:22:20 +00:00
Kavin
3d3e116797 fix: handle flt conversion for prev_ordered_qty
(cherry picked from commit 77c35ef47f)
2025-10-14 18:10:30 +00:00
mergify[bot]
bd3a132868 feat: set options for IBAN fields (backport #49377) (#49413)
Co-authored-by: barredterra <14891507+barredterra@users.noreply.github.com>
2025-10-14 14:42:08 +00:00
Frappe PR Bot
779074e6a6 chore(release): Bumped to Version 15.83.0
# [15.83.0](https://github.com/frappe/erpnext/compare/v15.82.2...v15.83.0) (2025-10-14)

### Bug Fixes

* add GROUP BY for dn_detail and convert SQL query to QB ([9aa9b18](9aa9b181e5))
* **asset movement:** clear custodian if not present ([4ec5b28](4ec5b28fd2))
* Batch ordering based on the method mentioned in settings ([50266d3](50266d3b6b))
* batch qty for expired batches ([f4816e4](f4816e4960))
* consider negative qty in batch qty calculation ([4370a59](4370a59183))
* **deferred revenue:** validate service stop date ([557d53a](557d53a953))
* do reposting of first transfer entry based on item-wh combination ([e9d71e0](e9d71e013a))
* duplicate serial nos ([9854ded](9854dedc06))
* enhance sub-assembly item handling in raw material request calculations ([467fcea](467fcea728))
* filter sales team to show only active individual salespersons ([38efd5c](38efd5cb0b))
* fixed asset register showing opening entries ([1ea6e1d](1ea6e1db12))
* hide sales invoice creation for fully returned delivery notes ([b426b8c](b426b8c07f))
* incorrect field valuation_rate ([93df11a](93df11a0cf))
* negative error not throw for backdated entry ([1fc21d6](1fc21d60c6))
* performance issue by adding index ([e4fd49e](e4fd49e991))
* preserve address if present ([aaf470c](aaf470cf5c))
* prevent empty Create dropdown when In Process (backport [#49891](https://github.com/frappe/erpnext/issues/49891)) ([#50063](https://github.com/frappe/erpnext/issues/50063)) ([b67b292](b67b29200c))
* **production plan:** filter sales orders by item ([20c2809](20c2809437))
* reset raw materials considering not available batches ([2184a28](2184a28e91))
* Reset Raw Materials Table button not working ([81ed32f](81ed32ff51))
* resolve conflict ([dccc561](dccc561eec))
* resolve conflict ([38e1ca1](38e1ca1362))
* revert unrelated manual modified timestamp change ([c4cba78](c4cba78124))
* sales return for product bundle items ([ac46b3d](ac46b3d1ca))
* sanitize projects field in tasks webform ([#50089](https://github.com/frappe/erpnext/issues/50089)) ([432201f](432201f634))
* set default roles on role_profile during reinstallation ([c93fbf3](c93fbf3982))
* skip auto-cancel of depreciation for components during asset capitalization ([6d5f2b5](6d5f2b5024))
* skip party validation for payroll & it's journal & GL entry submission (backport [#49638](https://github.com/frappe/erpnext/issues/49638)) ([#49826](https://github.com/frappe/erpnext/issues/49826)) ([957b47f](957b47f351))
* stock ledger adjustment entry ([8020159](8020159c14))
* **stock-entry:** fetch empty batch for finished item ([af3d7ef](af3d7ef300))
* **stock-reconciliation:** include inventory dimensions in duplicate validation ([21a972a](21a972ad95))
* **Supplier Quotation Comparison:** add a missing translate function (backport [#49497](https://github.com/frappe/erpnext/issues/49497)) ([#50055](https://github.com/frappe/erpnext/issues/50055)) ([b7c2405](b7c2405113))
* swap warehouse labels for return entry ([c5dc810](c5dc810642))
* warehouse source reference in production report ([db93e50](db93e50f16))

### Features

* add asset name to Asset Depreciations and Balances report ([0776b30](0776b300e8))

### Performance Improvements

* add composite indexes to Advance Payment Ledger Entry table ([5652e92](5652e926d7))
* optimize sql query ([79a8e26](79a8e2656b))
2025-10-14 14:03:31 +00:00
Diptanil Saha
c521a6495d Merge pull request #50087 from frappe/version-15-hotfix
chore: release v15
2025-10-14 19:27:40 +05:30
rohitwaghchaure
6f02362765 Merge pull request #50098 from frappe/mergify/bp/version-15-hotfix/pr-50089
fix: sanitize projects field in tasks webform (backport #50089)
2025-10-14 19:07:50 +05:30
Akhil Narang
432201f634 fix: sanitize projects field in tasks webform (#50089)
Signed-off-by: Akhil Narang <me@akhilnarang.dev>
(cherry picked from commit f8b50d3ffa)
2025-10-14 13:08:51 +00:00
rohitwaghchaure
f9dc00f8ad Merge pull request #50094 from frappe/mergify/bp/version-15-hotfix/pr-50080
perf: optimize sql query (backport #50080)
2025-10-14 18:17:00 +05:30
rohitwaghchaure
0dd79e8c2b Merge pull request #50092 from frappe/mergify/bp/version-15-hotfix/pr-50091
fix: negative error not throw for backdated entry (backport #50091)
2025-10-14 18:16:42 +05:30
Khushi Rawat
f70e61ab31 Merge pull request #50093 from frappe/mergify/bp/version-15-hotfix/pr-50033
fix: filter sales team to show only active individual salespersons (backport #50033)
2025-10-14 17:51:15 +05:30
mergify[bot]
b67b29200c fix: prevent empty Create dropdown when In Process (backport #49891) (#50063) 2025-10-14 17:49:27 +05:30
mergify[bot]
fd72b55852 Merge pull request #50081 from frappe/mergify/bp/version-15-hotfix/pr-49960
Fix/Support 50220 (backport #49960)
2025-10-14 12:12:14 +00:00
Khushi Rawat
dccc561eec fix: resolve conflict 2025-10-14 17:25:48 +05:30
rohitwaghchaure
8bf553bbce chore: fix conflicts 2025-10-14 17:17:12 +05:30
Rohit Waghchaure
79a8e2656b perf: optimize sql query
(cherry picked from commit e7b64175fd)

# Conflicts:
#	erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json
2025-10-14 11:44:04 +00:00
Rehan Ansari
38efd5cb0b fix: filter sales team to show only active individual salespersons
(cherry picked from commit 2fcd406b18)

# Conflicts:
#	erpnext/accounts/doctype/sales_invoice/sales_invoice.js
2025-10-14 11:40:00 +00:00
Rohit Waghchaure
1fc21d60c6 fix: negative error not throw for backdated entry
(cherry picked from commit 88a947ff4e)
2025-10-14 11:39:06 +00:00
Khushi Rawat
a777a11919 Merge pull request #50088 from khushi8112/composite-component-depr-jv-cancellation-issue
fix: skip auto-cancel of depreciation for components during asset capitalization
2025-10-14 16:57:50 +05:30
Diptanil Saha
6cc046362f Merge branch 'version-15' into version-15-hotfix 2025-10-14 16:56:32 +05:30
khushi8112
02ebde43bf refactor: Ensure flag cleanup with try-finally to prevent state corruption 2025-10-14 16:32:32 +05:30
khushi8112
6d5f2b5024 fix: skip auto-cancel of depreciation for components during asset capitalization 2025-10-14 15:19:07 +05:30
Mihir Kandoi
a50313f990 Merge pull request #50084 from frappe/mergify/bp/version-15-hotfix/pr-50004
fix: add GROUP BY for dn_detail and convert SQL query to QB (backport #50004)
2025-10-14 15:13:59 +05:30
Mihir Kandoi
7d533b7086 chore: resolve conflicts 2025-10-14 14:57:28 +05:30
l0gesh29
9aa9b181e5 fix: add GROUP BY for dn_detail and convert SQL query to QB
(cherry picked from commit fd9167f2af)

# Conflicts:
#	erpnext/stock/doctype/delivery_note/delivery_note.py
2025-10-14 09:20:17 +00:00
l0gesh29
b426b8c07f fix: hide sales invoice creation for fully returned delivery notes
(cherry picked from commit 1f831d8783)
2025-10-14 09:20:16 +00:00
Mihir Kandoi
6682a25532 Merge pull request #50082 from frappe/mergify/bp/version-15-hotfix/pr-50079
chore: replace broken links with correct ones (backport #50079)
2025-10-14 14:43:05 +05:30
Mihir Kandoi
01fe1c658e chore: replace broken links with correct ones
(cherry picked from commit 11be07086f)
2025-10-14 08:58:06 +00:00
rohitwaghchaure
82e392bc0c Merge pull request #50074 from frappe/mergify/bp/version-15-hotfix/pr-50070
fix: performance issue by adding index (backport #50070)
2025-10-14 13:57:10 +05:30
rohitwaghchaure
b6f99a127b Merge pull request #50075 from frappe/mergify/bp/version-15-hotfix/pr-50065
fix(stock-reconciliation): include inventory dimensions in duplicate validation (backport #50065)
2025-10-14 13:56:55 +05:30
rohitwaghchaure
7d34a39137 Merge pull request #50076 from frappe/mergify/bp/version-15-hotfix/pr-50073
fix(stock-entry): fetch empty batch for finished item (backport #50073)
2025-10-14 13:56:41 +05:30
rohitwaghchaure
76fe4e26ea Merge pull request #50077 from frappe/mergify/bp/version-15-hotfix/pr-50072
fix: swap warehouse labels for return entry (backport #50072)
2025-10-14 13:56:17 +05:30
Kavin
c5dc810642 fix: swap warehouse labels for return entry
(cherry picked from commit f0c3f0d0be)
2025-10-14 08:07:00 +00:00
venkat102
af3d7ef300 fix(stock-entry): fetch empty batch for finished item
(cherry picked from commit 74a7ddf66d)
2025-10-14 08:05:57 +00:00
rohitwaghchaure
61f7309695 chore: fix conflicts 2025-10-14 13:33:56 +05:30
Rohit Waghchaure
9854dedc06 fix: duplicate serial nos
(cherry picked from commit c95465cba1)
2025-10-14 08:03:44 +00:00
venkat102
21a972ad95 fix(stock-reconciliation): include inventory dimensions in duplicate validation
(cherry picked from commit 4b21c2cc46)
2025-10-14 08:03:43 +00:00
rohitwaghchaure
967ee78415 chore: fix conflicts 2025-10-14 13:33:24 +05:30
Rohit Waghchaure
e4fd49e991 fix: performance issue by adding index
(cherry picked from commit 1afc75b15a)

# Conflicts:
#	erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json
#	erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json
2025-10-14 08:02:28 +00:00
rohitwaghchaure
b82f8648f1 Merge pull request #50068 from frappe/mergify/bp/version-15-hotfix/pr-50061
fix: do reposting of first transfer entry based on item-wh combination (backport #50061)
2025-10-14 13:21:13 +05:30
rohitwaghchaure
141b70ce8b Merge pull request #50069 from frappe/mergify/bp/version-15-hotfix/pr-50027
fix: reset raw materials considering not available batches (backport #50027)
2025-10-14 13:21:03 +05:30
Rohit Waghchaure
2184a28e91 fix: reset raw materials considering not available batches
(cherry picked from commit ec1636db12)
2025-10-14 07:19:43 +00:00
Rohit Waghchaure
e9d71e013a fix: do reposting of first transfer entry based on item-wh combination
(cherry picked from commit 2f25b445ab)
2025-10-14 07:19:08 +00:00
Mihir Kandoi
5909b0e1a2 Merge pull request #50064 from frappe/mergify/bp/version-15-hotfix/pr-49445
fix(production plan): filter sales orders by item (backport #49445)
2025-10-14 12:20:56 +05:30
Mihir Kandoi
525dd42e86 Merge pull request #50062 from frappe/mergify/bp/version-15-hotfix/pr-50058
fix: warehouse source reference in production report (backport #50058)
2025-10-14 12:10:53 +05:30
ravibharathi656
20c2809437 fix(production plan): filter sales orders by item
(cherry picked from commit bfff945fb1)
2025-10-14 06:32:58 +00:00
matteo.arosti
db93e50f16 fix: warehouse source reference in production report
(cherry picked from commit 451651e350)
2025-10-14 06:22:44 +00:00
mergify[bot]
957b47f351 fix: skip party validation for payroll & it's journal & GL entry submission (backport #49638) (#49826)
* fix: skip party validation for payroll & it's journal & GL entry submission (#49638)

* fix: skip validation for manual je & gl submission linked with payroll entry

* refactor: change condition

* fix: add checkbox in jouranl entry account and passed it true from payroll to skip party validation

* refactor: add checkbox to skip party validation in journal entry

(cherry picked from commit 35474d997d)

# Conflicts:
#	erpnext/accounts/doctype/journal_entry/journal_entry.json
#	erpnext/accounts/doctype/journal_entry/journal_entry.py

* fix: conflicts raised because of cherry pick while backporting

* fix: conflicts

---------

Co-authored-by: Raheel Khan <raheel@frappe.io>
2025-10-14 11:36:15 +05:30
mergify[bot]
b7c2405113 fix(Supplier Quotation Comparison): add a missing translate function (backport #49497) (#50055)
fix(Supplier Quotation Comparison): add a missing translate function (#49497)

* Update supplier_quotation_comparison.py

* refactor: text cleaning

(cherry picked from commit 6cacead726)

Co-authored-by: El-Shafei H. <el.shafei.developer@gmail.com>
2025-10-14 00:36:15 +05:30
rohitwaghchaure
f8a1ef055d Merge pull request #50051 from frappe/mergify/bp/version-15-hotfix/pr-50047
fix: enhance sub-assembly item handling in raw material request calculations (backport #50047)
2025-10-14 00:00:29 +05:30
Mihir Kandoi
664ac3d422 Merge pull request #50052 from frappe/mergify/bp/version-15-hotfix/pr-50025 2025-10-13 20:04:14 +05:30
Mihir Kandoi
5603467cee refactor: move value inline
(cherry picked from commit 1717a7c983)
2025-10-13 14:16:47 +00:00
thomasantony12
e23616f9ea chore: use get_single_value instead of get_cached_doc
(cherry picked from commit fab7f9ee53)
2025-10-13 14:16:47 +00:00
thomasantony12
50266d3b6b fix: Batch ordering based on the method mentioned in settings
(cherry picked from commit 7fa800b874)
2025-10-13 14:16:47 +00:00
Smit Vora
75d14985e0 chore: resolve conflicts 2025-10-13 19:45:04 +05:30
Smit Vora
467fcea728 fix: enhance sub-assembly item handling in raw material request calculations
(cherry picked from commit f912c8419a)

# Conflicts:
#	erpnext/manufacturing/doctype/production_plan/production_plan.py
2025-10-13 14:06:34 +00:00
Diptanil Saha
6a7004e4f7 Merge pull request #50046 from frappe/mergify/bp/version-15-hotfix/pr-49939
fix: preserve address if present (backport #49939)
2025-10-13 16:41:48 +05:30
diptanilsaha
5d1aa4050d chore: resolve conflicts 2025-10-13 16:36:36 +05:30
Khushi Rawat
ce6336d5d6 Merge pull request #50045 from frappe/mergify/bp/version-15-hotfix/pr-50040
perf: add composite indexes to Advance Payment Ledger Entry (backport #50040)
2025-10-13 16:25:52 +05:30
ravibharathi656
aaf470cf5c fix: preserve address if present
(cherry picked from commit 0678638106)

# Conflicts:
#	erpnext/public/js/controllers/transaction.js
2025-10-13 10:46:23 +00:00
khushi8112
c4cba78124 fix: revert unrelated manual modified timestamp change
(cherry picked from commit 59bd35c64d)
2025-10-13 10:38:12 +00:00
khushi8112
5652e926d7 perf: add composite indexes to Advance Payment Ledger Entry table
(cherry picked from commit 7fcf277055)
2025-10-13 10:38:12 +00:00
ruthra kumar
f68f7aba0b Merge pull request #50038 from frappe/mergify/bp/version-15-hotfix/pr-50017
fix(deferred revenue): validate service stop date (backport #50017)
2025-10-13 12:54:39 +05:30
ruthra kumar
f36da0543b Merge pull request #50037 from frappe/mergify/bp/version-15-hotfix/pr-50034
fix: set default roles on Role Profiles during reinstallation (backport #50034)
2025-10-13 12:38:01 +05:30
ravibharathi656
557d53a953 fix(deferred revenue): validate service stop date
(cherry picked from commit 58203a89f1)
2025-10-13 07:07:54 +00:00
diptanilsaha
c93fbf3982 fix: set default roles on role_profile during reinstallation
(cherry picked from commit 12c1b8a910)
2025-10-13 06:38:40 +00:00
rohitwaghchaure
d7bf7d0f4d Merge pull request #50026 from frappe/mergify/bp/version-15-hotfix/pr-50024
fix: stock ledger adjustment entry (backport #50024)
2025-10-12 12:12:59 +05:30
Rohit Waghchaure
8020159c14 fix: stock ledger adjustment entry
(cherry picked from commit 8b6e58d02a)
2025-10-12 06:11:44 +00:00
mergify[bot]
1e91c0f5aa Merge pull request #50006 from frappe/mergify/bp/version-15-hotfix/pr-49993
fix: incorrect PR status when using set landed cost based on PI rate (backport #49993)
2025-10-10 11:18:30 +00:00
Diptanil Saha
47af5747bd Merge pull request #50001 from diptanilsaha/backport_49764
feat: Cache employee name in session data on boot (backport #49764)
2025-10-10 12:33:39 +05:30
Khushi Rawat
3e8bf03e80 Merge pull request #50000 from frappe/mergify/bp/version-15-hotfix/pr-49980
fix: fixed asset register showing opening entries (backport #49980)
2025-10-10 12:01:10 +05:30
Khushi Rawat
fe32257450 Merge pull request #49999 from frappe/mergify/bp/version-15-hotfix/pr-49995
feat: add asset name to Asset Depreciations and Balances report (backport #49995)
2025-10-10 12:00:54 +05:30
Diptanil Saha
97b89da7c7 Merge pull request #49764 from elshafei-developer/add-employee-name-to-session-user
feat: Cache employee name in session data on boot
2025-10-10 11:45:38 +05:30
ravibharathi656
1ea6e1db12 fix: fixed asset register showing opening entries
(cherry picked from commit c9d98eb4f0)
2025-10-10 05:44:27 +00:00
Rehan Ansari
0776b300e8 feat: add asset name to Asset Depreciations and Balances report
(cherry picked from commit b4cf6a1fb9)
2025-10-10 05:35:25 +00:00
rohitwaghchaure
c350e9dabd Merge pull request #49994 from frappe/mergify/bp/version-15-hotfix/pr-49991
fix: consider negative qty in batch qty calculation (backport #49991)
2025-10-09 22:45:02 +05:30
Rohit Waghchaure
4370a59183 fix: consider negative qty in batch qty calculation
(cherry picked from commit 912ffc2d64)
2025-10-09 15:23:47 +00:00
Frappe PR Bot
cc0a895760 chore(release): Bumped to Version 15.82.2
## [15.82.2](https://github.com/frappe/erpnext/compare/v15.82.1...v15.82.2) (2025-10-09)

### Bug Fixes

* Reset Raw Materials Table button not working ([00db37e](00db37e306))
* sales return for product bundle items ([2ea583e](2ea583ee16))
2025-10-09 12:31:16 +00:00
rohitwaghchaure
6ec370ad86 Merge pull request #49989 from frappe/mergify/bp/version-15/pr-49974
fix: Reset Raw Materials Table button not working (backport #49973) (backport #49974)
2025-10-09 17:59:42 +05:30
rohitwaghchaure
994f992fcf Merge pull request #49990 from frappe/mergify/bp/version-15/pr-49984
fix: sales return for product bundle items (backport #49975) (backport #49984)
2025-10-09 17:59:28 +05:30
rohitwaghchaure
3e816f6ea1 chore: fix conflicts
(cherry picked from commit 1fbc03c104)
2025-10-09 12:09:21 +00:00
Rohit Waghchaure
789cea9a85 test: test case for sales return for product bundle
(cherry picked from commit 1d57bbca11)

# Conflicts:
#	erpnext/stock/doctype/delivery_note/test_delivery_note.py
(cherry picked from commit 6ba55bbee0)
2025-10-09 12:09:21 +00:00
Rohit Waghchaure
2ea583ee16 fix: sales return for product bundle items
(cherry picked from commit 13ce7279a8)
(cherry picked from commit ac46b3d1ca)
2025-10-09 12:09:20 +00:00
rohitwaghchaure
1ab45386a8 Merge pull request #49984 from frappe/mergify/bp/version-15-hotfix/pr-49975
fix: sales return for product bundle items (backport #49975)
2025-10-09 17:38:55 +05:30
Rohit Waghchaure
00db37e306 fix: Reset Raw Materials Table button not working
(cherry picked from commit 128e243945)
(cherry picked from commit 81ed32ff51)
2025-10-09 12:06:21 +00:00
rohitwaghchaure
1fbc03c104 chore: fix conflicts 2025-10-09 17:21:03 +05:30
Rohit Waghchaure
6ba55bbee0 test: test case for sales return for product bundle
(cherry picked from commit 1d57bbca11)

# Conflicts:
#	erpnext/stock/doctype/delivery_note/test_delivery_note.py
2025-10-09 09:40:27 +00:00
Rohit Waghchaure
ac46b3d1ca fix: sales return for product bundle items
(cherry picked from commit 13ce7279a8)
2025-10-09 09:40:26 +00:00
rohitwaghchaure
6e55f53cf6 Merge pull request #49974 from frappe/mergify/bp/version-15-hotfix/pr-49973
fix: Reset Raw Materials Table button not working (backport #49973)
2025-10-08 23:45:42 +05:30
Rohit Waghchaure
81ed32ff51 fix: Reset Raw Materials Table button not working
(cherry picked from commit 128e243945)
2025-10-08 17:05:21 +00:00
Khushi Rawat
5d9c245ddd Merge pull request #49956 from frappe/mergify/bp/version-15-hotfix/pr-49954
fix(asset movement): clear custodian if not present (backport #49954)
2025-10-08 21:33:20 +05:30
Frappe PR Bot
c84952169f chore(release): Bumped to Version 15.82.1
## [15.82.1](https://github.com/frappe/erpnext/compare/v15.82.0...v15.82.1) (2025-10-08)

### Bug Fixes

* batch qty for expired batches ([4e2a42d](4e2a42d092))
* incorrect field valuation_rate ([9c3f4b6](9c3f4b69af))
2025-10-08 14:32:21 +00:00
rohitwaghchaure
d103409077 Merge pull request #49972 from frappe/mergify/bp/version-15/pr-49971
fix: batch qty for expired batches (backport #49967) (backport #49971)
2025-10-08 20:00:34 +05:30
rohitwaghchaure
d1dd3ca097 Merge pull request #49970 from frappe/mergify/bp/version-15/pr-49968
fix: incorrect field valuation_rate (backport #49966) (backport #49968)
2025-10-08 20:00:19 +05:30
Rohit Waghchaure
4e2a42d092 fix: batch qty for expired batches
(cherry picked from commit ff2faf36a7)
(cherry picked from commit f4816e4960)
2025-10-08 14:12:42 +00:00
rohitwaghchaure
fda021430d Merge pull request #49971 from frappe/mergify/bp/version-15-hotfix/pr-49967
fix: batch qty for expired batches (backport #49967)
2025-10-08 19:41:42 +05:30
Rohit Waghchaure
f4816e4960 fix: batch qty for expired batches
(cherry picked from commit ff2faf36a7)
2025-10-08 13:49:28 +00:00
Rohit Waghchaure
9c3f4b69af fix: incorrect field valuation_rate
(cherry picked from commit 630d873214)
(cherry picked from commit 93df11a0cf)
2025-10-08 13:38:13 +00:00
rohitwaghchaure
33f67012b4 Merge pull request #49968 from frappe/mergify/bp/version-15-hotfix/pr-49966
fix: incorrect field valuation_rate (backport #49966)
2025-10-08 19:07:29 +05:30
Rohit Waghchaure
93df11a0cf fix: incorrect field valuation_rate
(cherry picked from commit 630d873214)
2025-10-08 13:15:53 +00:00
Khushi Rawat
38e1ca1362 fix: resolve conflict 2025-10-08 12:53:25 +05:30
ravibharathi656
4ec5b28fd2 fix(asset movement): clear custodian if not present
(cherry picked from commit 323d8eaccd)

# Conflicts:
#	erpnext/assets/doctype/asset_movement/asset_movement.py
2025-10-08 07:05:10 +00:00
Frappe PR Bot
e2e1ac0dba chore(release): Bumped to Version 15.82.0
# [15.82.0](https://github.com/frappe/erpnext/compare/v15.81.3...v15.82.0) (2025-10-07)

### Bug Fixes

* **accounting:** ensure proper removal of advance references during unreconcillation ([825ccd3](825ccd3422))
* add default scrap warehouse in wo ([a5ed9fd](a5ed9fdc67))
* Add try-finally for setting buying price list ([e21baec](e21baec246))
* check is_rejected attribute ([bdf150b](bdf150bdf8))
* clear asset custodian  when asset take back from employee without assign to another employee ([f4cdb49](f4cdb49126))
* **Common Code:** fetch canonical URI from Code List (backport [#49882](https://github.com/frappe/erpnext/issues/49882)) ([#49884](https://github.com/frappe/erpnext/issues/49884)) ([2c0501b](2c0501b05f))
* delete column dynamically based on the naming by ([040873a](040873a442))
* do not consider draft bundles ([75323fd](75323fda01))
* do not fetch disabled item tax template ([c42dcbe](c42dcbe739))
* exclude opening entries ([ed1c270](ed1c270398))
* failing patch ([0dad195](0dad1957c8))
* get unconsumed qty as per BOM qty ([82386b1](82386b18aa))
* linter; dont change doc after DB update ([#49907](https://github.com/frappe/erpnext/issues/49907)) ([6c47353](6c47353205))
* **manufacturing:** prevent KeyError in BOM Creator when sub-assembly reused ([07c3755](07c3755f31))
* optimize SQL query by adding index on batch ([a83331b](a83331bd2f))
* **profit and loss statement:** incorrect total calculation ([e132c45](e132c457f2))
* remove allow_on_submit for pick list items ([4ccdede](4ccdedeb12))
* resolved conflict ([a39bc62](a39bc626c7))
* retain shipping address in doc ([20c21a4](20c21a4dc0))
* set fg_completed_qty based upon fg item qty ([b6d57ff](b6d57ff8a5))
* Set paid amount automatically only if return entry validated and has negative grand total ([#49829](https://github.com/frappe/erpnext/issues/49829)) ([bd3503a](bd3503a3d8))
* SQL operator precedence in Project query customer filter ([d950de2](d950de2d09))
* **subscription:** include days before ([f27b754](f27b754570))
* too many writes on patch run ([a2bf53f](a2bf53ff0a))
* use item valuation rate if no bin ([a4b5a74](a4b5a74644))
* validate transfer_qty based on overproduction wo percentage ([7ce97ce](7ce97ce0c2))
* warning message if the batch has incorrect qty ([3f3fd20](3f3fd20b31))

### Features

* allow fallback to default selling price list (backport [#49634](https://github.com/frappe/erpnext/issues/49634)) ([#49704](https://github.com/frappe/erpnext/issues/49704)) ([95387b4](95387b4bf0))
* dynamic due date in payment terms when fetched from order (backport [#48864](https://github.com/frappe/erpnext/issues/48864)) ([#49938](https://github.com/frappe/erpnext/issues/49938)) ([baa6d2b](baa6d2bcdc))
* recalculate batch qty ([d49b64d](d49b64dc7c))
* validating asset scrap date ([#43093](https://github.com/frappe/erpnext/issues/43093)) ([0eb76f4](0eb76f4d2c))

### Performance Improvements

* serial nos / batches reposting ([8a310ef](8a310efc97))
2025-10-07 13:23:00 +00:00
ruthra kumar
b557a03ba7 Merge pull request #49942 from frappe/version-15-hotfix
chore: release v15
2025-10-07 18:51:39 +05:30
mergify[bot]
11eab0c852 Merge pull request #49946 from frappe/mergify/bp/version-15-hotfix/pr-49721
feat: add company links to Email Account and Communication (backport #49721)
2025-10-07 17:01:37 +05:30
rohitwaghchaure
8683f49e8b Merge pull request #49945 from frappe/mergify/bp/version-15-hotfix/pr-49935
refactor: old serial nos filter (backport #49935)
2025-10-07 16:29:16 +05:30
rohitwaghchaure
6ea07ba56d chore: fix conflicts 2025-10-07 16:02:30 +05:30
Rohit Waghchaure
e02a55b188 refactor: old serial nos filter
(cherry picked from commit 6a8bd0ae9e)

# Conflicts:
#	erpnext/stock/deprecated_serial_batch.py
2025-10-07 09:52:27 +00:00
mergify[bot]
baa6d2bcdc feat: dynamic due date in payment terms when fetched from order (backport #48864) (#49938)
* feat: dynamic due date in payment terms when fetched from order (#48864)

* fix: dynamic due date when payment terms are fetched from order

* fix(test): use change_settings decorator for settings enable and disable

* fix(test): compare schedule for due_date dynamically

* fix: save conditions for due date at invoice level

* fix: make fields read only and on change of date unset the date condition fields

* fix: remove fetch_form

* fix: correct field assingment

* fix: revert unwanted changes

* refactor: streamline payment term field assignments and enhance discount date handling

* refactor: remove payment_term from fields_to_copy and optimize currency handling in transaction callback

* refactor: ensure default values for payment schedule and discount validity fields

(cherry picked from commit 3c70cbbaf8)

# Conflicts:
#	erpnext/public/js/controllers/transaction.js
#	erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py

* chore: resolve conflicts

---------

Co-authored-by: Lakshit Jain <ljain112@gmail.com>
2025-10-07 14:10:15 +05:30
rohitwaghchaure
631ffd55ef Merge pull request #49934 from frappe/mergify/bp/version-15-hotfix/pr-49846
chore(Stock Qty vs Serial No Count): add show_disabled_items filter (backport #49846)
2025-10-07 11:49:20 +05:30
rethik
7a457dafe0 chore: add show_disabled_items filter to show both enabled and disabled items
(cherry picked from commit bf5f24c0e0)
2025-10-07 05:59:36 +00:00
rohitwaghchaure
94a5867303 Merge pull request #49933 from frappe/mergify/bp/version-15-hotfix/pr-49762
fix(manufacturing): prevent KeyError in BOM Creator when sub-assembly reused (backport #49762)
2025-10-07 11:23:12 +05:30
rohitwaghchaure
1663b875c0 Merge pull request #49932 from frappe/mergify/bp/version-15-hotfix/pr-49702
fix: do not fetch disabled item tax template (backport #49702)
2025-10-07 11:22:57 +05:30
ljain112
d47f3cc101 chore: resolve conflicts 2025-10-07 11:01:47 +05:30
KerollesFathy
07c3755f31 fix(manufacturing): prevent KeyError in BOM Creator when sub-assembly reused
Ensure missing (fg_item, fg_reference_id) keys are initialized in
production_item_wise_rm before appending items. This avoids crashes
when the same sub-assembly is referenced under multiple parents.

(cherry picked from commit 4f8b2e520a)
2025-10-07 05:27:18 +00:00
ljain112
c42dcbe739 fix: do not fetch disabled item tax template
(cherry picked from commit b10cf4a928)

# Conflicts:
#	erpnext/public/js/controllers/transaction.js
#	erpnext/stock/get_item_details.py
2025-10-07 05:26:09 +00:00
rohitwaghchaure
233fe9b7e6 Merge pull request #49929 from frappe/mergify/bp/version-15-hotfix/pr-49928
fix: warning message if the batch has incorrect qty (backport #49928)
2025-10-07 10:42:23 +05:30
Rohit Waghchaure
3f3fd20b31 fix: warning message if the batch has incorrect qty
(cherry picked from commit 870181de87)
2025-10-07 04:50:35 +00:00
ruthra kumar
f84a6c0d3a Merge pull request #49927 from frappe/mergify/bp/version-15-hotfix/pr-49743
fix: use valuation_rate from item master if no bin is present (backport #49743)
2025-10-07 10:03:27 +05:30
ruthra kumar
5c9c17c649 Merge pull request #49925 from frappe/mergify/bp/version-15-hotfix/pr-49870
fix: show asset value as revaluation amount or gross purchase amount (backport #49870)
2025-10-07 10:02:28 +05:30
ravibharathi656
a4b5a74644 fix: use item valuation rate if no bin
(cherry picked from commit 23b1b7ee04)
2025-10-07 04:13:26 +00:00
l0gesh29
ed1c270398 fix: exclude opening entries
(cherry picked from commit 3773f56b0b)
2025-10-06 21:40:58 +00:00
rohitwaghchaure
56d04761f8 Merge pull request #49924 from frappe/mergify/bp/version-15-hotfix/pr-49923
feat: recalculate batch qty (backport #49923)
2025-10-06 22:33:22 +05:30
Rohit Waghchaure
d49b64dc7c feat: recalculate batch qty
(cherry picked from commit 70117d3b06)
2025-10-06 16:30:14 +00:00
Frappe PR Bot
42b43b372a chore(release): Bumped to Version 15.81.3
## [15.81.3](https://github.com/frappe/erpnext/compare/v15.81.2...v15.81.3) (2025-10-06)

### Bug Fixes

* check is_rejected attribute ([b017f07](b017f07343))
* do not consider draft bundles ([92afae7](92afae7185))
2025-10-06 14:45:22 +00:00
rohitwaghchaure
4dae4b987e Merge pull request #49922 from frappe/mergify/bp/version-15/pr-49918
fix: check is_rejected attribute (backport #49913) (backport #49918)
2025-10-06 20:13:46 +05:30
rohitwaghchaure
54e672e078 Merge pull request #49921 from frappe/mergify/bp/version-15/pr-49919
fix: do not consider draft bundles (backport #49917) (backport #49919)
2025-10-06 20:13:38 +05:30
rohitwaghchaure
62a09a3cb0 Merge pull request #49920 from frappe/mergify/bp/version-15-hotfix/pr-49890
perf: serial nos / batches reposting (backport #49890)
2025-10-06 19:58:25 +05:30
Kavin
b017f07343 fix: check is_rejected attribute
(cherry picked from commit 2ac2e02b2f)
(cherry picked from commit bdf150bdf8)
2025-10-06 14:25:55 +00:00
Rohit Waghchaure
92afae7185 fix: do not consider draft bundles
(cherry picked from commit a60f7eaf3a)
(cherry picked from commit 75323fda01)
2025-10-06 14:25:46 +00:00
rohitwaghchaure
eb9d656b8f Merge pull request #49918 from frappe/mergify/bp/version-15-hotfix/pr-49913
fix: check is_rejected attribute (backport #49913)
2025-10-06 19:54:59 +05:30
rohitwaghchaure
7ddf63faa8 Merge pull request #49919 from frappe/mergify/bp/version-15-hotfix/pr-49917
fix: do not consider draft bundles (backport #49917)
2025-10-06 19:54:51 +05:30
Rohit Waghchaure
8a310efc97 perf: serial nos / batches reposting
(cherry picked from commit acb3ef78a7)
2025-10-06 14:11:43 +00:00
Kavin
bdf150bdf8 fix: check is_rejected attribute
(cherry picked from commit 2ac2e02b2f)
2025-10-06 14:08:30 +00:00
Rohit Waghchaure
75323fda01 fix: do not consider draft bundles
(cherry picked from commit a60f7eaf3a)
2025-10-06 14:08:30 +00:00
ruthra kumar
f94f628884 Merge pull request #49912 from frappe/mergify/bp/version-15-hotfix/pr-49600
fix(profit and loss statement): incorrect total calculation (backport #49600)
2025-10-06 17:27:55 +05:30
ravibharathi656
e132c457f2 fix(profit and loss statement): incorrect total calculation
(cherry picked from commit b7c6d8e2a6)
2025-10-06 11:40:38 +00:00
ruthra kumar
048d6f6942 Merge pull request #49908 from frappe/mergify/bp/version-15-hotfix/pr-49635
fix(subscription): include days before (backport #49635)
2025-10-06 15:39:59 +05:30
Raffael Meyer
6c47353205 fix: linter; dont change doc after DB update (#49907)
Co-authored-by: ruthra kumar <ruthra@erpnext.com>
2025-10-06 10:02:05 +00:00
ravibharathi656
4f067085e7 test: add invoice generation before period with prorate
(cherry picked from commit b452e06b82)
2025-10-06 09:52:07 +00:00
ravibharathi656
3fcbb10155 refactor(subscription): default prorate 0
(cherry picked from commit eda1dae882)
2025-10-06 09:52:07 +00:00
ravibharathi656
f27b754570 fix(subscription): include days before
(cherry picked from commit 9164162a9e)
2025-10-06 09:52:06 +00:00
mergify[bot]
95387b4bf0 feat: allow fallback to default selling price list (backport #49634) (#49704)
Co-authored-by: barredterra <14891507+barredterra@users.noreply.github.com>
Co-authored-by: Henning Wendtland <156231187+HenningWendtland@users.noreply.github.com>
2025-10-06 11:49:40 +02:00
ruthra kumar
7f2d26ec20 Merge pull request #49900 from frappe/mergify/bp/version-15-hotfix/pr-49852
fix: SQL operator precedence in Project query customer filter (backport #49852)
2025-10-06 13:21:58 +05:30
Fawaz Alhafiz
d950de2d09 fix: SQL operator precedence in Project query customer filter
Added explicit parentheses around customer OR conditions in get_project_name()
to ensure proper grouping with AND filters. Without these parentheses, SQL
operator precedence caused the status filter to be bypassed when a customer
filter was applied, resulting in completed and cancelled projects appearing
in link field dropdowns.

Before:
WHERE customer='X' OR customer IS NULL OR customer='' AND status NOT IN (...)
was interpreted as:
WHERE customer='X' OR customer IS NULL OR (customer='' AND status NOT IN (...))

After:
WHERE (customer='X' OR customer IS NULL OR customer='') AND status NOT IN (...)

Fixes: Completed/cancelled projects showing in Project link fields
Affected: Any doctype using Project link fields with customer filters
(cherry picked from commit 0ec30a1cea)
2025-10-06 07:34:55 +00:00
ruthra kumar
5d8a368ad2 Merge pull request #49893 from frappe/mergify/bp/version-15-hotfix/pr-49829
fix: Set paid amount automatically only if return entry validated and has negative grand total (backport #49829)
2025-10-06 12:58:33 +05:30
ruthra kumar
615a5fa5ba Merge pull request #49898 from frappe/mergify/bp/version-15-hotfix/pr-49865
fix: delete column dynamically based on the naming by (backport #49865)
2025-10-06 12:51:23 +05:30
ruthra kumar
823cdf211d Merge pull request #49894 from frappe/mergify/bp/version-15-hotfix/pr-49871
fix: retain shipping address in doc (backport #49871)
2025-10-06 12:37:21 +05:30
ravibharathi656
20c21a4dc0 fix: retain shipping address in doc
(cherry picked from commit 039f5e6143)

# Conflicts:
#	erpnext/public/js/controllers/buying.js
2025-10-06 12:35:21 +05:30
l0gesh29
040873a442 fix: delete column dynamically based on the naming by
(cherry picked from commit 4f503ac7f6)
2025-10-06 07:05:04 +00:00
Nabin Hait
a39bc626c7 fix: resolved conflict 2025-10-06 12:17:57 +05:30
Nabin Hait
bd3503a3d8 fix: Set paid amount automatically only if return entry validated and has negative grand total (#49829)
(cherry picked from commit dcbcc596f2)

# Conflicts:
#	erpnext/public/js/controllers/taxes_and_totals.js
2025-10-06 05:58:29 +00:00
Frappe PR Bot
161c1fb7a4 chore(release): Bumped to Version 15.81.2
## [15.81.2](https://github.com/frappe/erpnext/compare/v15.81.1...v15.81.2) (2025-10-06)

### Bug Fixes

* failing patch ([65061cc](65061cc459))
2025-10-06 03:54:42 +00:00
ruthra kumar
4d506d2d9c Merge pull request #49873 from frappe/mergify/bp/version-15/pr-49868
fix: failing patch (backport #49867) (backport #49868)
2025-10-06 09:23:17 +05:30
ruthra kumar
04abc6b5e5 Merge pull request #49877 from frappe/mergify/bp/version-15-hotfix/pr-49872
fix: remove allow_on_submit for pick list items (backport #49872)
2025-10-06 09:21:33 +05:30
mergify[bot]
2c0501b05f fix(Common Code): fetch canonical URI from Code List (backport #49882) (#49884)
Co-authored-by: Raffael Meyer <14891507+barredterra@users.noreply.github.com>
fix(Common Code): fetch canonical URI from Code List (#49882)
2025-10-04 19:22:28 +02:00
rohitwaghchaure
7b484de0a9 Merge pull request #49878 from frappe/mergify/bp/version-15-hotfix/pr-49876
fix: optimize SQL query by adding index on batch (backport #49876)
2025-10-04 13:18:07 +05:30
Rohit Waghchaure
a83331bd2f fix: optimize SQL query by adding index on batch
(cherry picked from commit 8756f91857)
2025-10-04 05:30:10 +00:00
Kavin
4ccdedeb12 fix: remove allow_on_submit for pick list items
(cherry picked from commit da716b824f)
2025-10-04 04:36:08 +00:00
Mihir Kandoi
65061cc459 fix: failing patch
(cherry picked from commit 41d1703e7c)
(cherry picked from commit 0dad1957c8)
2025-10-03 19:04:15 +00:00
Mihir Kandoi
fe0739aadf Merge pull request #49868 from frappe/mergify/bp/version-15-hotfix/pr-49867
fix: failing patch (backport #49867)
2025-10-04 00:33:18 +05:30
Mihir Kandoi
0dad1957c8 fix: failing patch
(cherry picked from commit 41d1703e7c)
2025-10-03 10:02:09 +00:00
rohitwaghchaure
bf39ae6db0 Merge pull request #49856 from frappe/mergify/bp/version-15-hotfix/pr-49806
fix: validate transfer_qty based on overproduction wo percentage (backport #49806)
2025-10-02 22:43:52 +05:30
Khushi Rawat
09bcff13ad Merge pull request #49522 from KerollesFathy/clear-custodian-when-asset-take-backed
fix: clear asset custodian when asset take back from employee without assign to another employee
2025-10-02 22:16:35 +05:30
rohitwaghchaure
b91fb6b280 Merge pull request #49855 from frappe/mergify/bp/version-15-hotfix/pr-49850
fix: add default scrap warehouse in wo (backport #49850)
2025-10-02 20:22:20 +05:30
Kavin
0fec34e886 test: test overproduction allowed qty in wo
(cherry picked from commit b527d38bfa)
2025-10-02 14:36:24 +00:00
Kavin
b6d57ff8a5 fix: set fg_completed_qty based upon fg item qty
(cherry picked from commit 526b850e61)
2025-10-02 14:36:24 +00:00
Kavin
7ce97ce0c2 fix: validate transfer_qty based on overproduction wo percentage
(cherry picked from commit 4024d8846b)
2025-10-02 14:36:23 +00:00
Kavin
a5ed9fdc67 fix: add default scrap warehouse in wo
(cherry picked from commit 7e51346946)
2025-10-02 14:35:22 +00:00
mergify[bot]
5e5850d89a refactor(Supplier): custom buttons call make methods (backport #49840) (#49842)
Co-authored-by: Raffael Meyer <14891507+barredterra@users.noreply.github.com>
2025-10-02 00:16:34 +02:00
Diptanil Saha
56aa86f77e Merge pull request #49839 from diptanilsaha/backport_49496
fix(Accounts Payable Summary): add a missing translate function (backport #49496)
2025-10-02 00:24:42 +05:30
Diptanil Saha
f321725b49 Merge pull request #49496 from elshafei-developer/Add-a-missing-translate-function
fix(Accounts Payable Summary): add a missing translate function
2025-10-02 00:07:06 +05:30
Diptanil Saha
4e3697284e Merge pull request #49838 from diptanilsaha/backport_49820
fix: financial ratios translation and pdf export error (backport #49820)
2025-10-01 23:57:09 +05:30
Frappe PR Bot
4c1cada222 chore(release): Bumped to Version 15.81.1
## [15.81.1](https://github.com/frappe/erpnext/compare/v15.81.0...v15.81.1) (2025-10-01)

### Bug Fixes

* Add try-finally for setting buying price list ([e10ed89](e10ed89be5))
* too many writes on patch run ([c455e73](c455e7390e))
2025-10-01 14:55:26 +00:00
Mihir Kandoi
8bb19eece4 Merge pull request #49835 from frappe/mergify/bp/version-15/pr-49833
fix: too many writes on patch run (backport #49832) (backport #49833)
2025-10-01 20:23:45 +05:30
Mihir Kandoi
e10ed89be5 fix: Add try-finally for setting buying price list
(cherry picked from commit 35a8d02866)
(cherry picked from commit e21baec246)
2025-10-01 13:44:41 +00:00
Mihir Kandoi
c455e7390e fix: too many writes on patch run
(cherry picked from commit 44ff6ed6a1)
(cherry picked from commit a2bf53ff0a)
2025-10-01 13:44:41 +00:00
Mihir Kandoi
3f9fbb7b75 Merge pull request #49833 from frappe/mergify/bp/version-15-hotfix/pr-49832 2025-10-01 19:13:21 +05:30
Mihir Kandoi
e21baec246 fix: Add try-finally for setting buying price list
(cherry picked from commit 35a8d02866)
2025-10-01 13:27:40 +00:00
Mihir Kandoi
a2bf53ff0a fix: too many writes on patch run
(cherry picked from commit 44ff6ed6a1)
2025-10-01 13:27:40 +00:00
ruthra kumar
06cd48feaa Merge pull request #49823 from frappe/mergify/bp/version-15-hotfix/pr-49689
fix(accounting): ensure proper removal of advance references during u… (backport #49689)
2025-10-01 12:56:19 +05:30
Pandiyan P
825ccd3422 fix(accounting): ensure proper removal of advance references during unreconcillation
(cherry picked from commit a7ec01bf21)
2025-10-01 06:40:55 +00:00
rohitwaghchaure
c56da286f7 Merge pull request #49811 from frappe/mergify/bp/version-15-hotfix/pr-49750
fix: get unconsumed qty as per BOM required qty (backport #49750)
2025-09-30 22:19:55 +05:30
Khushi Rawat
a7577d428f Merge pull request #49817 from khushi8112/backport-v15-pr-43093
feat: validating asset scrap date (backport #43093)
2025-09-30 21:23:26 +05:30
Khushi Rawat
e81b85b241 chore: resolve conflict 2025-09-30 21:02:39 +05:30
rahulgupta8848
0eb76f4d2c feat: validating asset scrap date (#43093)
* feat: validating asset scrap date

* refactor: refactorization of scrap asset function

---------

Co-authored-by: “rahulgupta8848” <“rahul.gupta@8848digital.com”>
(cherry picked from commit e07bc5af41)

# Conflicts:
#	erpnext/assets/doctype/asset/asset.js
2025-09-30 21:02:15 +05:30
Frappe PR Bot
24013ddf27 chore(release): Bumped to Version 15.81.0
# [15.81.0](https://github.com/frappe/erpnext/compare/v15.80.1...v15.81.0) (2025-09-30)

### Bug Fixes

* add date filter for getting return invoice items ([bc77704](bc77704462))
* auto batch not set for raw materials in subcontracting receipt ([6c8e838](6c8e8384d5))
* **bank transaction:** change reference number to small text ([5a0bf7a](5a0bf7a5e1))
* convert with flt ([3975627](3975627b33))
* do not validate cost center in cancelled gl entry ([366bb82](366bb8269c))
* don't recalculate stock_qty with conversion_factor ([c88a277](c88a277ad9))
* include precision in validation ([abffbca](abffbcad99))
* **payment entry:** trigger currency on account set ([84a2596](84a2596ce5))
* remove item name to avoid overriding item row name ([d0e511f](d0e511fd2f))
* set cost center in taxes if not set ([4dcd502](4dcd502b76))
* **stock entry:** set expense account from company for manufacture ([50f9521](50f9521feb))
* update item details only in draft state ([30f6b53](30f6b53240))
* update subcontracted_quantity with set_value ([17e415d](17e415d03a))
* use get_value instead of get_doc ([f706811](f706811757))
* use sales_order from data instead of doc ([7ee8281](7ee82813fd))
* use stock adjustment account  if no expense account ([9c81f44](9c81f448c8))
* valuation rate for old batch ([37a03f1](37a03f10ab))

### Features

* add show zero value filter in profit and loss and balance sheet ([c32ad97](c32ad9711f))
* service expense account in the subcontracting receipt ([ba9b63a](ba9b63af49))

### Performance Improvements

* reposting for backdated transactions ([cd5a836](cd5a836685))
2025-09-30 13:28:59 +00:00
ruthra kumar
e8ee5f8c9b Merge pull request #49801 from frappe/version-15-hotfix
chore: release v15
2025-09-30 18:56:45 +05:30
rohitwaghchaure
0fb5f75e93 chore: fix conflicts
Removed the test for additional material transfer in work orders.
2025-09-30 18:43:38 +05:30
rohitwaghchaure
4847e24553 Merge branch 'version-15' into version-15-hotfix 2025-09-30 18:38:20 +05:30
Kavin
f548f0b231 test: required_qty clamping in manufacture entry
(cherry picked from commit 34d2c8d9c2)

# Conflicts:
#	erpnext/manufacturing/doctype/work_order/test_work_order.py
2025-09-30 12:28:34 +00:00
Kavin
82386b18aa fix: get unconsumed qty as per BOM qty
(cherry picked from commit cf4b395ee3)
2025-09-30 12:28:33 +00:00
rohitwaghchaure
bbbcb456ce Merge pull request #49810 from frappe/mergify/bp/version-15-hotfix/pr-49803
fix: valuation rate for old batch (backport #49803)
2025-09-30 17:50:13 +05:30
rohitwaghchaure
4c78f9b9cb Merge pull request #49807 from frappe/mergify/bp/version-15-hotfix/pr-49794
fix: don't recalculate stock_qty with conversion_factor (backport #49794)
2025-09-30 17:12:18 +05:30
Rohit Waghchaure
37a03f10ab fix: valuation rate for old batch
(cherry picked from commit d864d166f9)
2025-09-30 11:42:15 +00:00
rohitwaghchaure
c2dd37a89e Merge pull request #49808 from frappe/mergify/bp/version-15-hotfix/pr-49766
fix: use sales_order from data instead of doc (backport #49766)
2025-09-30 17:12:07 +05:30
rohitwaghchaure
f458faa819 Merge pull request #49809 from frappe/mergify/bp/version-15-hotfix/pr-49748
fix: update item details only in draft state (backport #49748)
2025-09-30 17:11:56 +05:30
Kavin
30f6b53240 fix: update item details only in draft state
(cherry picked from commit 689172ff22)
2025-09-30 11:08:59 +00:00
Kavin
7ee82813fd fix: use sales_order from data instead of doc
(cherry picked from commit 9f9120451b)
2025-09-30 11:06:48 +00:00
Kavin
c88a277ad9 fix: don't recalculate stock_qty with conversion_factor
(cherry picked from commit fed8236919)
2025-09-30 11:03:47 +00:00
rohitwaghchaure
9e73d083b5 Merge pull request #49793 from frappe/mergify/bp/version-15-hotfix/pr-49790
fix: update subcontracted_quantity with set_value (backport #49790)
2025-09-30 16:32:13 +05:30
rohitwaghchaure
03c8d92796 Merge pull request #49792 from frappe/mergify/bp/version-15-hotfix/pr-49791
refactor: convert item warehouse based reposting (backport #49791)
2025-09-30 16:31:57 +05:30
ruthra kumar
31ad9a6346 Merge pull request #49805 from frappe/mergify/bp/version-15-hotfix/pr-49639
fix(Credit-limit): consider current voucher for credit limit validation (backport #49639)
2025-09-30 16:30:17 +05:30
PRASATHRAJA
fc40a3c376 Merge pull request #49639 from aerele/credit-limit-jv
fix(Credit-limit): consider current voucher for credit limit validation

(cherry picked from commit 4a01c53cca)
2025-09-30 10:39:35 +00:00
ruthra kumar
b8e3db0179 Merge pull request #49800 from frappe/mergify/bp/version-15-hotfix/pr-49799
fix: do not validate cost center in cancelled gl entry (backport #49799)
2025-09-30 15:14:11 +05:30
ljain112
366bb8269c fix: do not validate cost center in cancelled gl entry
(cherry picked from commit 29cbddbc77)
2025-09-30 09:04:24 +00:00
venkat102
3975627b33 fix: convert with flt
(cherry picked from commit 81614939ab)
2025-09-29 16:20:27 +00:00
venkat102
f706811757 fix: use get_value instead of get_doc
(cherry picked from commit 89a603f20c)
2025-09-29 16:20:26 +00:00
venkat102
17e415d03a fix: update subcontracted_quantity with set_value
(cherry picked from commit ea63bfc9af)
2025-09-29 16:20:26 +00:00
Rohit Waghchaure
8911bad792 refactor: convert item-wh based reposting
(cherry picked from commit 8411e4c5b2)
2025-09-29 16:20:25 +00:00
ruthra kumar
a30c481ca1 Merge pull request #49787 from frappe/mergify/bp/version-15-hotfix/pr-49773
fix(bank transaction): change reference number to small text (backport #49773)
2025-09-29 17:15:06 +05:30
ravibharathi656
5a0bf7a5e1 fix(bank transaction): change reference number to small text
(cherry picked from commit 90f399d0fc)

# Conflicts:
#	erpnext/accounts/doctype/bank_transaction/bank_transaction.json
2025-09-29 16:59:31 +05:30
ruthra kumar
f135954944 Merge pull request #49784 from frappe/mergify/bp/version-15-hotfix/pr-49708
feat: add show zero value filter in profit and loss and balance sheet (backport #49708)
2025-09-29 16:47:54 +05:30
ravibharathi656
c32ad9711f feat: add show zero value filter in profit and loss and balance sheet
(cherry picked from commit 33ab24943c)

# Conflicts:
#	erpnext/accounts/report/balance_sheet/balance_sheet.js
#	erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.js
2025-09-29 16:32:21 +05:30
ruthra kumar
f6842041c9 Merge pull request #49782 from frappe/mergify/bp/version-15-hotfix/pr-49718
fix: set cost center in taxes if not set (backport #49718)
2025-09-29 16:26:35 +05:30
ravibharathi656
4dcd502b76 fix: set cost center in taxes if not set
(cherry picked from commit b75940bf0e)

# Conflicts:
#	erpnext/public/js/controllers/transaction.js
2025-09-29 15:53:19 +05:30
ruthra kumar
19f81c9204 Merge pull request #49777 from frappe/mergify/bp/version-15-hotfix/pr-49735
fix(payment entry): trigger currency on account set (backport #49735)
2025-09-29 14:56:14 +05:30
ruthra kumar
67b6b3779d Merge pull request #49775 from frappe/mergify/bp/version-15-hotfix/pr-49618
fix: add date filter for getting return invoice items (backport #49618)
2025-09-29 14:31:45 +05:30
ruthra kumar
c836016358 Merge pull request #49774 from frappe/mergify/bp/version-15-hotfix/pr-49640
fix: include precision in validation (backport #49640)
2025-09-29 14:29:45 +05:30
ravibharathi656
84a2596ce5 fix(payment entry): trigger currency on account set
(cherry picked from commit 096e74b1ee)
2025-09-29 08:58:03 +00:00
Navin-S-R
98bc7b41fc test: validate profit values for later period returns
(cherry picked from commit d5c457b8c5)

# Conflicts:
#	erpnext/accounts/report/gross_profit/test_gross_profit.py
2025-09-29 14:16:52 +05:30
l0gesh29
abffbcad99 fix: include precision in validation
(cherry picked from commit 1de0c46c51)
2025-09-29 08:44:29 +00:00
Navin-S-R
bc77704462 fix: add date filter for getting return invoice items
(cherry picked from commit 2abb011816)
2025-09-29 08:44:28 +00:00
rohitwaghchaure
5abb2d510d Merge pull request #49772 from frappe/mergify/bp/version-15-hotfix/pr-49770
chore: removed print statement (backport #49770)
2025-09-29 13:06:44 +05:30
Rohit Waghchaure
ae040024af chore: removed print statement
(cherry picked from commit 324bdcb177)
2025-09-29 06:32:32 +00:00
rohitwaghchaure
fe1247dd4b Merge pull request #49758 from frappe/mergify/bp/version-15-hotfix/pr-49757
feat: service expense account in the subcontracting receipt (backport #49757)
2025-09-27 10:20:23 +05:30
rohitwaghchaure
84789daf59 Merge pull request #49756 from frappe/mergify/bp/version-15-hotfix/pr-49741
fix(stock entry): set expense account from company for manufacture (backport #49741)
2025-09-27 10:04:06 +05:30
rohitwaghchaure
cecd177286 chore: fix conflicts
Removed fields related to job card and landed cost voucher amount from subcontracting receipt item.
2025-09-27 10:03:27 +05:30
rohitwaghchaure
c26ed80d67 chore: fix conflicts 2025-09-27 10:02:40 +05:30
rohitwaghchaure
15f0c28cda chore: fix conflicts 2025-09-27 10:01:53 +05:30
Rohit Waghchaure
ba9b63af49 feat: service expense account in the subcontracting receipt
(cherry picked from commit 6e597b9c42)

# Conflicts:
#	erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py
#	erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py
#	erpnext/subcontracting/doctype/subcontracting_receipt_item/subcontracting_receipt_item.json
2025-09-26 15:44:26 +00:00
ravibharathi656
9c81f448c8 fix: use stock adjustment account if no expense account
(cherry picked from commit b2e109318f)
2025-09-26 13:28:43 +00:00
ravibharathi656
50f9521feb fix(stock entry): set expense account from company for manufacture
(cherry picked from commit 06177ffaff)
2025-09-26 13:28:43 +00:00
ruthra kumar
0ff32ac554 Merge pull request #49738 from frappe/mergify/bp/version-15-hotfix/pr-49717
refactor: improve trial balance performance (backport #49717)
2025-09-26 11:58:26 +05:30
rohitwaghchaure
fe72ea6d6b Merge pull request #49739 from frappe/mergify/bp/version-15-hotfix/pr-49734
fix: auto batch not set for raw materials in subcontracting receipt (backport #49734)
2025-09-26 11:43:04 +05:30
rohitwaghchaure
62959e5a70 chore: fix conflicts 2025-09-26 11:21:16 +05:30
Rohit Waghchaure
6c8e8384d5 fix: auto batch not set for raw materials in subcontracting receipt
(cherry picked from commit 23f9d4c600)

# Conflicts:
#	erpnext/controllers/subcontracting_controller.py
2025-09-26 05:07:12 +00:00
ruthra kumar
0c8004530a refactor: improve trial balance performance
(cherry picked from commit cee3813ced)
2025-09-26 04:46:00 +00:00
Raffael Meyer
b18afa8bdd chore(Bank Guarante): move to leaner doctype definition (#49737) 2025-09-25 22:05:59 +00:00
Frappe PR Bot
f54933e657 chore(release): Bumped to Version 15.80.1
## [15.80.1](https://github.com/frappe/erpnext/compare/v15.80.0...v15.80.1) (2025-09-25)

### Bug Fixes

* remove item name to avoid overriding item row name ([a80e0d9](a80e0d9d39))

### Performance Improvements

* reposting for backdated transactions ([f43fac5](f43fac50ed))
2025-09-25 15:14:17 +00:00
rohitwaghchaure
a1862020e8 Merge pull request #49732 from frappe/mergify/bp/version-15/pr-49728
fix: remove item name in get_item_details (backport #49725) (backport #49728)
2025-09-25 20:42:44 +05:30
rohitwaghchaure
249d6b3619 Merge pull request #49729 from frappe/mergify/bp/version-15/pr-49724
perf: reposting for backdated transactions (backport #49720) (backport #49724)
2025-09-25 20:42:35 +05:30
Kavin
a80e0d9d39 fix: remove item name to avoid overriding item row name
(cherry picked from commit 47055901c0)
(cherry picked from commit d0e511fd2f)
2025-09-25 14:23:33 +00:00
rohitwaghchaure
6b3bb45900 Merge pull request #49728 from frappe/mergify/bp/version-15-hotfix/pr-49725
fix: remove item name in get_item_details (backport #49725)
2025-09-25 19:52:28 +05:30
Rohit Waghchaure
f43fac50ed perf: reposting for backdated transactions
(cherry picked from commit 1b0fc0541b)
(cherry picked from commit cd5a836685)
2025-09-25 13:23:30 +00:00
Kavin
d0e511fd2f fix: remove item name to avoid overriding item row name
(cherry picked from commit 47055901c0)
2025-09-25 13:23:29 +00:00
rohitwaghchaure
d50538dbf7 Merge pull request #49724 from frappe/mergify/bp/version-15-hotfix/pr-49720
perf: reposting for backdated transactions (backport #49720)
2025-09-25 18:52:32 +05:30
Rohit Waghchaure
cd5a836685 perf: reposting for backdated transactions
(cherry picked from commit 1b0fc0541b)
2025-09-25 12:16:41 +00:00
KerollesFathy
4bc76be130 refactor: optimize asset location and custodian update logic to avoid multiple updates 2025-09-10 19:01:14 +03:00
KerollesFathy
f4cdb49126 fix: clear asset custodian when asset take back from employee without assign to another employee 2025-09-10 18:27:39 +03:00
322 changed files with 34355 additions and 3048 deletions

View File

@@ -6,7 +6,7 @@ Feature requests are also a great way to take the product forward. New ideas can
When you are raising an Issue, you should keep a few things in mind. Remember that the developer does not have access to your machine so you must give all the information you can while raising an Issue. If you are suggesting a feature, you should be very clear about what you want.
The Issue list is not the right place to ask a question or start a general discussion. If you want to do that , then the right place is the forum [https://discuss.erpnext.com](https://discuss.erpnext.com).
The Issue list is not the right place to ask a question or start a general discussion. If you want to do that , then the right place is the forum [https://discuss.frappe.io](https://discuss.frappe.io/c/erpnext/6).
### Reply and Closing Policy

View File

@@ -9,7 +9,7 @@ body:
Welcome to ERPNext issue tracker! Before creating an issue, please heed the following:
1. This tracker should only be used to report bugs and request features / enhancements to ERPNext
- For questions and general support, checkout the [user manual](https://docs.erpnext.com/) or use [forum](https://discuss.erpnext.com)
- For questions and general support, checkout the [user manual](https://docs.erpnext.com/) or use [forum](https://discuss.frappe.io/c/erpnext/6)
- For documentation issues, propose edit on [documentation site](https://docs.erpnext.com/) directly.
2. When making a bug report, make sure you provide all required information. The easier it is for
maintainers to reproduce, the faster it'll be fixed.

View File

@@ -1,5 +1,5 @@
blank_issues_enabled: false
contact_links:
- name: Community Forum
url: https://discuss.erpnext.com/
url: https://discuss.frappe.io/c/erpnext/6
about: For general QnA, discussions and community help.

View File

@@ -11,7 +11,7 @@ assignees: ''
Welcome to ERPNext issue tracker! Before creating an issue, please heed the following:
1. This tracker should only be used to report bugs and request features / enhancements to ERPNext
- For questions and general support, checkout the manual https://erpnext.com/docs/user/manual/en or use https://discuss.erpnext.com
- For questions and general support, checkout the manual https://docs.erpnext.com or use https://discuss.frappe.io/c/erpnext/6
2. Use the search function before creating a new issue. Duplicates will be closed and directed to
the original discussion.
3. When making a feature request, make sure to be as verbose as possible. The better you convey your message, the greater the drive to make it happen.
@@ -21,7 +21,7 @@ Please keep in mind that we get many many requests and we can't possibly work on
If you're in urgent need to a feature, please try the following channels to get paid developments done quickly:
1. Certified ERPNext partners: https://erpnext.com/partners
2. Developer community on ERPNext forums: https://discuss.erpnext.com/c/developers/5
2. Developer community on ERPNext forums: https://discuss.frappe.io/c/framework/5
3. Telegram group for ERPNext/Frappe development work: https://t.me/erpnext_opps
-->

View File

@@ -64,7 +64,7 @@ New passwords will be created for the ERPNext "Administrator" user, the MariaDB
1. [Frappe School](https://school.frappe.io) - Learn Frappe Framework and ERPNext from the various courses by the maintainers or from the community.
2. [Official documentation](https://docs.erpnext.com/) - Extensive documentation for ERPNext.
3. [Discussion Forum](https://discuss.erpnext.com/) - Engage with community of ERPNext users and service providers.
3. [Discussion Forum](https://discuss.frappe.io/c/erpnext/6) - Engage with community of ERPNext users and service providers.
4. [Telegram Group](https://erpnext_public.t.me) - Get instant help from huge community of users.

View File

@@ -4,7 +4,7 @@ import inspect
import frappe
from frappe.utils.user import is_website_user
__version__ = "15.80.0"
__version__ = "15.91.2"
def get_default_company(user=None):

View File

@@ -46,7 +46,8 @@ def validate_service_stop_date(doc):
if (
old_stop_dates
and old_stop_dates.get(item.name)
and item.service_stop_date != old_stop_dates.get(item.name)
and item.service_stop_date
and getdate(item.service_stop_date) != getdate(old_stop_dates.get(item.name))
):
frappe.throw(_("Cannot change Service Stop Date for item in row {0}").format(item.idx))

View File

@@ -110,6 +110,7 @@ class Account(NestedSet):
self.validate_parent_child_account_type()
self.validate_root_details()
self.validate_account_number()
self.validate_disabled()
self.validate_group_or_ledger()
self.set_root_and_report_type()
self.validate_mandatory()
@@ -254,6 +255,14 @@ class Account(NestedSet):
self.create_account_for_child_company(parent_acc_name_map, descendants, parent_acc_name)
def validate_disabled(self):
doc_before_save = self.get_doc_before_save()
if not doc_before_save or cint(doc_before_save.disabled) == cint(self.disabled):
return
if cint(self.disabled):
self.validate_default_accounts_in_company()
def validate_group_or_ledger(self):
doc_before_save = self.get_doc_before_save()
if not doc_before_save or cint(doc_before_save.is_group) == cint(self.is_group):
@@ -264,9 +273,32 @@ class Account(NestedSet):
elif cint(self.is_group):
if self.account_type and not self.flags.exclude_account_type_check:
throw(_("Cannot covert to Group because Account Type is selected."))
self.validate_default_accounts_in_company()
elif self.check_if_child_exists():
throw(_("Account with child nodes cannot be set as ledger"))
def validate_default_accounts_in_company(self):
default_account_fields = get_company_default_account_fields()
company_default_accounts = frappe.db.get_value(
"Company", self.company, list(default_account_fields.keys()), as_dict=1
)
msg = _("Account {0} cannot be disabled as it is already set as {1} for {2}.")
if not self.disabled:
msg = _("Account {0} cannot be converted to Group as it is already set as {1} for {2}.")
for d in default_account_fields:
if company_default_accounts.get(d) == self.name:
throw(
msg.format(
frappe.bold(self.name),
frappe.bold(default_account_fields.get(d)),
frappe.bold(self.company),
)
)
def validate_frozen_accounts_modifier(self):
doc_before_save = self.get_doc_before_save()
if not doc_before_save or doc_before_save.freeze_account == self.freeze_account:
@@ -627,3 +659,27 @@ def _ensure_idle_system():
).format(pretty_date(last_gl_update)),
title=_("System In Use"),
)
def get_company_default_account_fields():
return {
"default_bank_account": "Default Bank Account",
"default_cash_account": "Default Cash Account",
"default_receivable_account": "Default Receivable Account",
"default_payable_account": "Default Payable Account",
"default_expense_account": "Default Expense Account",
"default_income_account": "Default Income Account",
"stock_received_but_not_billed": "Stock Received But Not Billed Account",
"stock_adjustment_account": "Stock Adjustment Account",
"write_off_account": "Write Off Account",
"default_discount_account": "Default Payment Discount Account",
"unrealized_profit_loss_account": "Unrealized Profit / Loss Account",
"exchange_gain_loss_account": "Exchange Gain / Loss Account",
"unrealized_exchange_gain_loss_account": "Unrealized Exchange Gain / Loss Account",
"round_off_account": "Round Off Account",
"default_deferred_revenue_account": "Default Deferred Revenue Account",
"default_deferred_expense_account": "Default Deferred Expense Account",
"accumulated_depreciation_account": "Accumulated Depreciation Account",
"depreciation_expense_account": "Depreciation Expense Account",
"disposal_account": "Gain/Loss Account on Asset Disposal",
}

View File

@@ -309,8 +309,8 @@ def get_dimensions(with_cost_center_and_project=False):
if with_cost_center_and_project:
dimension_filters.extend(
[
{"fieldname": "cost_center", "document_type": "Cost Center"},
{"fieldname": "project", "document_type": "Project"},
frappe._dict({"fieldname": "cost_center", "document_type": "Cost Center"}),
frappe._dict({"fieldname": "project", "document_type": "Project"}),
]
)

View File

@@ -56,6 +56,9 @@
"reconciliation_queue_size",
"column_break_resa",
"exchange_gain_loss_posting_date",
"payment_entry_settings",
"show_account_balance",
"show_party_balance",
"invoicing_settings_tab",
"accounts_transactions_settings_section",
"over_billing_allowance",
@@ -75,6 +78,7 @@
"period_closing_settings_section",
"acc_frozen_upto",
"ignore_account_closing_balance",
"use_legacy_controller_for_pcv",
"column_break_25",
"frozen_accounts_modifier",
"tab_break_dpet",
@@ -94,7 +98,8 @@
"legacy_section",
"ignore_is_opening_check_for_reporting",
"payment_request_settings",
"create_pr_in_draft_status"
"create_pr_in_draft_status",
"column_break_xrnd"
],
"fields": [
{
@@ -629,6 +634,29 @@
"fieldname": "fetch_valuation_rate_for_internal_transaction",
"fieldtype": "Check",
"label": "Fetch Valuation Rate for Internal Transaction"
},
{
"default": "1",
"fieldname": "use_legacy_controller_for_pcv",
"fieldtype": "Check",
"label": "Use Legacy Controller For Period Closing Voucher"
},
{
"fieldname": "payment_entry_settings",
"fieldtype": "Section Break",
"label": "Payment Entry Settings"
},
{
"default": "0",
"fieldname": "show_account_balance",
"fieldtype": "Check",
"label": "Show Account Balance"
},
{
"default": "0",
"fieldname": "show_party_balance",
"fieldtype": "Check",
"label": "Show Party Balance"
}
],
"icon": "icon-cog",
@@ -636,7 +664,7 @@
"index_web_pages_for_search": 1,
"issingle": 1,
"links": [],
"modified": "2025-07-18 13:56:47.192437",
"modified": "2025-11-06 17:48:07.682837",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Accounts Settings",
@@ -661,8 +689,9 @@
}
],
"quick_entry": 1,
"row_format": "Dynamic",
"sort_field": "modified",
"sort_order": "ASC",
"states": [],
"track_changes": 1
}
}

View File

@@ -65,14 +65,17 @@ class AccountsSettings(Document):
role_allowed_to_over_bill: DF.Link | None
role_to_override_stop_action: DF.Link | None
round_row_wise_tax: DF.Check
show_account_balance: DF.Check
show_balance_in_coa: DF.Check
show_inclusive_tax_in_print: DF.Check
show_party_balance: DF.Check
show_payment_schedule_in_print: DF.Check
show_taxes_as_table_in_print: DF.Check
stale_days: DF.Int
submit_journal_entries: DF.Check
unlink_advance_payment_on_cancelation_of_order: DF.Check
unlink_payment_on_cancellation_of_invoice: DF.Check
use_legacy_controller_for_pcv: DF.Check
# end: auto-generated types
def validate(self):
@@ -104,6 +107,7 @@ class AccountsSettings(Document):
frappe.clear_cache()
self.validate_and_sync_auto_reconcile_config()
self.hide_or_show_party_and_account_balance()
def validate_stale_days(self):
if not self.allow_stale and cint(self.stale_days) <= 0:
@@ -111,6 +115,18 @@ class AccountsSettings(Document):
_("Stale Days should start from 1."), title="Error", indicator="red", raise_exception=1
)
def hide_or_show_party_and_account_balance(self):
def set_property(fieldname, value):
make_property_setter("Payment Entry", fieldname, "hidden", value, "Check")
if self.has_value_changed("show_party_balance"):
set_property("party_balance", not self.show_party_balance)
if self.has_value_changed("show_account_balance"):
account_fields = ["paid_from_account_balance", "paid_to_account_balance"]
for field in account_fields:
set_property(field, not self.show_account_balance)
def enable_payment_schedule_in_print(self):
show_in_print = cint(self.show_payment_schedule_in_print)
for doctype in ("Sales Order", "Sales Invoice", "Purchase Order", "Purchase Invoice"):

View File

@@ -82,7 +82,7 @@
"in_create": 1,
"index_web_pages_for_search": 1,
"links": [],
"modified": "2025-07-29 11:37:42.678556",
"modified": "2025-10-13 15:11:58.300836",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Advance Payment Ledger Entry",

View File

@@ -34,3 +34,15 @@ class AdvancePaymentLedgerEntry(Document):
and not frappe.flags.is_reverse_depr_entry
):
update_voucher_outstanding(self.against_voucher_type, self.against_voucher_no, None, None, None)
def on_doctype_update():
frappe.db.add_index(
"Advance Payment Ledger Entry",
["against_voucher_type", "against_voucher_no"],
)
frappe.db.add_index(
"Advance Payment Ledger Entry",
["voucher_type", "voucher_no"],
)

View File

@@ -132,7 +132,8 @@
"fieldtype": "Data",
"in_list_view": 1,
"label": "IBAN",
"length": 30
"length": 34,
"options": "IBAN"
},
{
"fieldname": "column_break_12",
@@ -208,6 +209,7 @@
"label": "Disabled"
}
],
"grid_page_length": 50,
"links": [
{
"group": "Transactions",
@@ -250,7 +252,7 @@
"link_fieldname": "default_bank_account"
}
],
"modified": "2024-10-30 09:41:14.113414",
"modified": "2025-08-29 12:32:01.081687",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Bank Account",
@@ -282,6 +284,7 @@
"write": 1
}
],
"row_format": "Dynamic",
"search_fields": "bank,account",
"sort_field": "modified",
"sort_order": "DESC",

View File

@@ -9,7 +9,8 @@ from frappe.contacts.address_and_contact import (
load_address_and_contact,
)
from frappe.model.document import Document
from frappe.utils import comma_and, get_link_to_form
from frappe.utils import comma_and, get_link_to_form, validate_iban
from frappe.utils.deprecations import deprecated
class BankAccount(Document):
@@ -52,7 +53,6 @@ class BankAccount(Document):
def validate(self):
self.validate_company()
self.validate_iban()
self.validate_account()
self.update_default_bank_account()
@@ -72,34 +72,10 @@ class BankAccount(Document):
if self.is_company_account and not self.company:
frappe.throw(_("Company is manadatory for company account"))
@deprecated
def validate_iban(self):
"""
Algorithm: https://en.wikipedia.org/wiki/International_Bank_Account_Number#Validating_the_IBAN
"""
# IBAN field is optional
if not self.iban:
return
def encode_char(c):
# Position in the alphabet (A=1, B=2, ...) plus nine
return str(9 + ord(c) - 64)
# remove whitespaces, upper case to get the right number from ord()
iban = "".join(self.iban.split(" ")).upper()
# Move country code and checksum from the start to the end
flipped = iban[4:] + iban[:4]
# Encode characters as numbers
encoded = [encode_char(c) if ord(c) >= 65 and ord(c) <= 90 else c for c in flipped]
try:
to_check = int("".join(encoded))
except ValueError:
frappe.throw(_("IBAN is not valid"))
if to_check % 97 != 1:
frappe.throw(_("IBAN is not valid"))
"""Kept for backward compatibility, will be removed in v16."""
validate_iban(self.iban, throw=True)
def update_default_bank_account(self):
if self.is_default and not self.disabled:

View File

@@ -3,45 +3,8 @@
import unittest
import frappe
from frappe import ValidationError
# test_records = frappe.get_test_records('Bank Account')
class TestBankAccount(unittest.TestCase):
def test_validate_iban(self):
valid_ibans = [
"GB82 WEST 1234 5698 7654 32",
"DE91 1000 0000 0123 4567 89",
"FR76 3000 6000 0112 3456 7890 189",
]
invalid_ibans = [
# wrong checksum (3rd place)
"GB72 WEST 1234 5698 7654 32",
"DE81 1000 0000 0123 4567 89",
"FR66 3000 6000 0112 3456 7890 189",
]
bank_account = frappe.get_doc({"doctype": "Bank Account"})
try:
bank_account.validate_iban()
except AttributeError:
msg = "BankAccount.validate_iban() failed for empty IBAN"
self.fail(msg=msg)
for iban in valid_ibans:
bank_account.iban = iban
try:
bank_account.validate_iban()
except ValidationError:
msg = f"BankAccount.validate_iban() failed for valid IBAN {iban}"
self.fail(msg=msg)
for not_iban in invalid_ibans:
bank_account.iban = not_iban
msg = f"BankAccount.validate_iban() accepted invalid IBAN {not_iban}"
with self.assertRaises(ValidationError, msg=msg):
bank_account.validate_iban()
pass

View File

@@ -9,13 +9,6 @@ cur_frm.add_fetch("bank", "swift_number", "swift_number");
frappe.ui.form.on("Bank Guarantee", {
setup: function (frm) {
frm.set_query("bank", function () {
return {
filters: {
company: frm.doc.company,
},
};
});
frm.set_query("bank_account", function () {
return {
filters: {

File diff suppressed because it is too large Load Diff

View File

@@ -116,15 +116,14 @@
{
"allow_on_submit": 1,
"fieldname": "reference_number",
"fieldtype": "Data",
"fieldtype": "Small Text",
"label": "Reference Number"
},
{
"fieldname": "transaction_id",
"fieldtype": "Data",
"label": "Transaction ID",
"read_only": 1,
"unique": 1
"read_only": 1
},
{
"allow_on_submit": 1,
@@ -223,7 +222,8 @@
{
"fieldname": "bank_party_iban",
"fieldtype": "Data",
"label": "Party IBAN (Bank Statement)"
"label": "Party IBAN (Bank Statement)",
"options": "IBAN"
},
{
"fieldname": "bank_party_account_number",
@@ -238,7 +238,7 @@
"grid_page_length": 50,
"is_submittable": 1,
"links": [],
"modified": "2025-06-18 17:24:57.044666",
"modified": "2025-10-23 17:32:58.514807",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Bank Transaction",

View File

@@ -36,7 +36,7 @@ class BankTransaction(Document):
party: DF.DynamicLink | None
party_type: DF.Link | None
payment_entries: DF.Table[BankTransactionPayments]
reference_number: DF.Data | None
reference_number: DF.SmallText | None
status: DF.Literal["", "Pending", "Settled", "Unreconciled", "Reconciled", "Cancelled"]
transaction_id: DF.Data | None
transaction_type: DF.Data | None

View File

@@ -19,7 +19,7 @@ frappe.ui.form.on("Currency Exchange Settings", {
to: "{to_currency}",
};
add_param(frm, r.message, params, result);
} else if (frm.doc.service_provider == "frankfurter.app") {
} else if (frm.doc.service_provider == "frankfurter.dev") {
let result = ["rates", "{to_currency}"];
let params = {
base: "{from_currency}",

View File

@@ -78,7 +78,7 @@
"fieldname": "service_provider",
"fieldtype": "Select",
"label": "Service Provider",
"options": "frankfurter.app\nexchangerate.host\nCustom",
"options": "frankfurter.dev\nexchangerate.host\nCustom",
"reqd": 1
},
{
@@ -104,7 +104,7 @@
"index_web_pages_for_search": 1,
"issingle": 1,
"links": [],
"modified": "2024-03-18 08:32:26.895076",
"modified": "2025-11-25 13:03:41.896424",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Currency Exchange Settings",
@@ -141,8 +141,9 @@
"write": 1
}
],
"sort_field": "modified",
"row_format": "Dynamic",
"sort_field": "creation",
"sort_order": "DESC",
"states": [],
"track_changes": 1
}
}

View File

@@ -29,7 +29,7 @@ class CurrencyExchangeSettings(Document):
disabled: DF.Check
req_params: DF.Table[CurrencyExchangeSettingsDetails]
result_key: DF.Table[CurrencyExchangeSettingsResult]
service_provider: DF.Literal["frankfurter.app", "exchangerate.host", "Custom"]
service_provider: DF.Literal["frankfurter.dev", "exchangerate.host", "Custom"]
url: DF.Data | None
use_http: DF.Check
# end: auto-generated types
@@ -60,7 +60,7 @@ class CurrencyExchangeSettings(Document):
self.append("req_params", {"key": "date", "value": "{transaction_date}"})
self.append("req_params", {"key": "from", "value": "{from_currency}"})
self.append("req_params", {"key": "to", "value": "{to_currency}"})
elif self.service_provider == "frankfurter.app":
elif self.service_provider == "frankfurter.dev":
self.set("result_key", [])
self.set("req_params", [])
@@ -105,11 +105,11 @@ class CurrencyExchangeSettings(Document):
@frappe.whitelist()
def get_api_endpoint(service_provider: str | None = None, use_http: bool = False):
if service_provider and service_provider in ["exchangerate.host", "frankfurter.app"]:
if service_provider and service_provider in ["exchangerate.host", "frankfurter.dev"]:
if service_provider == "exchangerate.host":
api = "api.exchangerate.host/convert"
elif service_provider == "frankfurter.app":
api = "api.frankfurter.app/{transaction_date}"
elif service_provider == "frankfurter.dev":
api = "api.frankfurter.dev/v1/{transaction_date}"
protocol = "https://"
if use_http:

View File

@@ -252,7 +252,7 @@ class ExchangeRateRevaluation(Document):
company_currency = erpnext.get_company_currency(company)
precision = get_field_precision(
frappe.get_meta("Exchange Rate Revaluation Account").get_field("new_balance_in_base_currency"),
company_currency,
currency=company_currency,
)
if account_details:

View File

@@ -99,7 +99,7 @@ class FiscalYear(Document):
)
overlap = False
if not self.get("companies") or not company_for_existing:
if not self.get("companies") and not company_for_existing:
overlap = True
for d in self.get("companies"):

View File

@@ -26,6 +26,27 @@ class TestFiscalYear(unittest.TestCase):
self.assertRaises(frappe.exceptions.InvalidDates, fy.insert)
def test_company_fiscal_year_overlap(self):
for name in ["_Test Global FY 2001", "_Test Company FY 2001"]:
if frappe.db.exists("Fiscal Year", name):
frappe.delete_doc("Fiscal Year", name)
global_fy = frappe.new_doc("Fiscal Year")
global_fy.year = "_Test Global FY 2001"
global_fy.year_start_date = "2001-04-01"
global_fy.year_end_date = "2002-03-31"
global_fy.insert()
company_fy = frappe.new_doc("Fiscal Year")
company_fy.year = "_Test Company FY 2001"
company_fy.year_start_date = "2001-01-01"
company_fy.year_end_date = "2001-12-31"
company_fy.append("companies", {"company": "_Test Company"})
company_fy.insert()
self.assertTrue(frappe.db.exists("Fiscal Year", global_fy.name))
self.assertTrue(frappe.db.exists("Fiscal Year", company_fy.name))
def test_record_generator():
test_records = [

View File

@@ -131,8 +131,8 @@ class GLEntry(Document):
if not self.is_cancelled and not (self.party_type and self.party):
account_type = frappe.get_cached_value("Account", self.account, "account_type")
# skipping validation for payroll entry creation in case party is not required
if not frappe.flags.party_not_required_for_receivable_payable:
if not frappe.flags.party_not_required: # skipping validation if party is not required
if account_type == "Receivable":
frappe.throw(
_("{0} {1}: Customer is required against Receivable account {2}").format(
@@ -253,7 +253,7 @@ class GLEntry(Document):
)
def validate_cost_center(self):
if not self.cost_center:
if not self.cost_center or self.is_cancelled:
return
is_group, company = frappe.get_cached_value("Cost Center", self.cost_center, ["is_group", "company"])
@@ -420,7 +420,7 @@ def update_against_account(voucher_type, voucher_no):
if not entries:
return
company_currency = erpnext.get_company_currency(entries[0].company)
precision = get_field_precision(frappe.get_meta("GL Entry").get_field("debit"), company_currency)
precision = get_field_precision(frappe.get_meta("GL Entry").get_field("debit"), currency=company_currency)
accounts_debited, accounts_credited = [], []
for d in entries:

View File

@@ -59,6 +59,7 @@
"addtional_info",
"mode_of_payment",
"payment_order",
"party_not_required",
"column_break3",
"is_opening",
"stock_entry",
@@ -543,6 +544,14 @@
"label": "Is System Generated",
"no_copy": 1,
"read_only": 1
},
{
"default": "0",
"fieldname": "party_not_required",
"fieldtype": "Check",
"hidden": 1,
"label": "Party Not Required",
"no_copy": 1
}
],
"icon": "fa fa-file-text",
@@ -557,7 +566,7 @@
"table_fieldname": "payment_entries"
}
],
"modified": "2024-07-18 15:32:29.413598",
"modified": "2025-09-29 13:05:46.982277",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Journal Entry",

View File

@@ -33,6 +33,7 @@ from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_sched
get_depr_schedule,
)
from erpnext.controllers.accounts_controller import AccountsController
from erpnext.setup.utils import get_exchange_rate as _get_exchange_rate
class StockAccountInvalidTransaction(frappe.ValidationError):
@@ -72,6 +73,7 @@ class JournalEntry(AccountsController):
multi_currency: DF.Check
naming_series: DF.Literal["ACC-JV-.YYYY.-"]
paid_loan: DF.Data | None
party_not_required: DF.Check
pay_to_recd_from: DF.Data | None
payment_order: DF.Link | None
posting_date: DF.Date
@@ -189,8 +191,8 @@ class JournalEntry(AccountsController):
def on_submit(self):
self.validate_cheque_info()
self.check_credit_limit()
self.make_gl_entries()
self.check_credit_limit()
self.update_asset_value()
self.update_inter_company_jv()
self.update_invoice_discounting()
@@ -272,93 +274,7 @@ class JournalEntry(AccountsController):
)
def apply_tax_withholding(self):
from erpnext.accounts.report.general_ledger.general_ledger import get_account_type_map
if not self.apply_tds or self.voucher_type not in ("Debit Note", "Credit Note"):
return
parties = [d.party for d in self.get("accounts") if d.party]
parties = list(set(parties))
if len(parties) > 1:
frappe.throw(_("Cannot apply TDS against multiple parties in one entry"))
account_type_map = get_account_type_map(self.company)
party_type = "supplier" if self.voucher_type == "Credit Note" else "customer"
doctype = "Purchase Invoice" if self.voucher_type == "Credit Note" else "Sales Invoice"
debit_or_credit = (
"debit_in_account_currency"
if self.voucher_type == "Credit Note"
else "credit_in_account_currency"
)
rev_debit_or_credit = (
"credit_in_account_currency"
if debit_or_credit == "debit_in_account_currency"
else "debit_in_account_currency"
)
party_account = get_party_account(party_type.title(), parties[0], self.company)
net_total = sum(
d.get(debit_or_credit)
for d in self.get("accounts")
if account_type_map.get(d.account) not in ("Tax", "Chargeable")
)
party_amount = sum(
d.get(rev_debit_or_credit) for d in self.get("accounts") if d.account == party_account
)
inv = frappe._dict(
{
party_type: parties[0],
"doctype": doctype,
"company": self.company,
"posting_date": self.posting_date,
"net_total": net_total,
}
)
tax_withholding_details, advance_taxes, voucher_wise_amount = get_party_tax_withholding_details(
inv, self.tax_withholding_category
)
if not tax_withholding_details:
return
accounts = []
for d in self.get("accounts"):
if d.get("account") == tax_withholding_details.get("account_head"):
d.update(
{
"account": tax_withholding_details.get("account_head"),
debit_or_credit: tax_withholding_details.get("tax_amount"),
}
)
accounts.append(d.get("account"))
if d.get("account") == party_account:
d.update({rev_debit_or_credit: party_amount - tax_withholding_details.get("tax_amount")})
if not accounts or tax_withholding_details.get("account_head") not in accounts:
self.append(
"accounts",
{
"account": tax_withholding_details.get("account_head"),
rev_debit_or_credit: tax_withholding_details.get("tax_amount"),
"against_account": parties[0],
},
)
to_remove = [
d
for d in self.get("accounts")
if not d.get(rev_debit_or_credit) and d.account == tax_withholding_details.get("account_head")
]
for d in to_remove:
self.remove(d)
JournalEntryTaxWithholding(self).apply()
def update_asset_value(self):
if self.flags.planned_depr_entry or self.voucher_type != "Depreciation Entry":
@@ -543,10 +459,10 @@ class JournalEntry(AccountsController):
for d in self.get("accounts"):
account_type = frappe.get_cached_value("Account", d.account, "account_type")
# skipping validation for payroll entry creation
skip_validation = frappe.flags.party_not_required_for_receivable_payable
if account_type in ["Receivable", "Payable"]:
if not (d.party_type and d.party) and not skip_validation:
if (
not (d.party_type and d.party) and not self.party_not_required
): # skipping validation if party_not_required is passed via payroll entry
frappe.throw(
_(
"Row {0}: Party Type and Party is required for Receivable / Payable account {1}"
@@ -1139,6 +1055,11 @@ class JournalEntry(AccountsController):
}
)
# set flag to skip party validation
account_type = frappe.get_cached_value("Account", d.account, "account_type")
if account_type in ["Receivable", "Payable"] and self.party_not_required:
frappe.flags.party_not_required = True
gl_map.append(
self.get_gl_dict(
row,
@@ -1166,6 +1087,7 @@ class JournalEntry(AccountsController):
merge_entries=merge_entries,
update_outstanding=update_outstanding,
)
frappe.flags.party_not_required = False
if cancel:
cancel_exchange_gain_loss_journal(frappe._dict(doctype=self.doctype, name=self.name))
@@ -1274,6 +1196,230 @@ class JournalEntry(AccountsController):
frappe.throw(_("Accounts table cannot be blank."))
class JournalEntryTaxWithholding:
def __init__(self, journal_entry):
self.doc: JournalEntry = journal_entry
self.party = None
self.party_type = None
self.party_account = None
self.party_row = None
self.existing_tds_rows = []
self.precision = None
self.has_multiple_parties = False
# Direction fields based on party type
self.party_field = None # "credit" for Supplier, "debit" for Customer
self.reverse_field = None # opposite of party_field
def apply(self):
if not self._set_party_info():
return
self._setup_direction_fields()
self._reset_existing_tds()
if not self._should_apply_tds():
self._cleanup_duplicate_tds_rows(None)
return
if self.has_multiple_parties:
frappe.throw(_("Cannot apply TDS against multiple parties in one entry"))
net_total = self._calculate_net_total()
if net_total <= 0:
return
tds_details = self._get_tds_details(net_total)
if not tds_details or not tds_details.get("tax_amount"):
return
self._create_or_update_tds_row(tds_details)
self._update_party_amount(tds_details.get("tax_amount"), is_reversal=False)
self._recalculate_totals()
def _should_apply_tds(self):
return self.doc.apply_tds and self.doc.voucher_type in ("Debit Note", "Credit Note")
def _set_party_info(self):
for row in self.doc.get("accounts"):
if row.party_type in ("Customer", "Supplier") and row.party:
if self.party and row.party != self.party:
self.has_multiple_parties = True
if not self.party:
self.party = row.party
self.party_type = row.party_type
self.party_account = row.account
self.party_row = row
if row.get("is_tax_withholding_account"):
self.existing_tds_rows.append(row)
return bool(self.party)
def _setup_direction_fields(self):
"""
For Supplier (TDS): party has credit, TDS reduces credit
For Customer (TCS): party has debit, TCS increases debit
"""
if self.party_type == "Supplier":
self.party_field = "credit"
self.reverse_field = "debit"
else: # Customer
self.party_field = "debit"
self.reverse_field = "credit"
self.precision = self.doc.precision(self.party_field, self.party_row)
def _reset_existing_tds(self):
for row in self.existing_tds_rows:
# TDS amount is always in credit (liability to government)
tds_amount = flt(row.get("credit") - row.get("debit"), self.precision)
if not tds_amount:
continue
self._update_party_amount(tds_amount, is_reversal=True)
# zero_out_tds_row
row.update(
{
"credit": 0,
"credit_in_account_currency": 0,
"debit": 0,
"debit_in_account_currency": 0,
}
)
def _update_party_amount(self, amount, is_reversal=False):
amount = flt(amount, self.precision)
amount_in_party_currency = flt(amount / self.party_row.get("exchange_rate", 1), self.precision)
# Determine which field the party amount is in
active_field = self.party_field if self.party_row.get(self.party_field) else self.reverse_field
# If amount is in reverse field, flip the signs
if active_field == self.reverse_field:
amount = -amount
amount_in_party_currency = -amount_in_party_currency
# Direction multiplier based on party type:
# Customer (TCS): +1 (add to debit)
# Supplier (TDS): -1 (subtract from credit)
direction = 1 if self.party_type == "Customer" else -1
# Reversal inverts the direction
if is_reversal:
direction = -direction
adjustment = amount * direction
adjustment_in_party_currency = amount_in_party_currency * direction
active_field_account_currency = f"{active_field}_in_account_currency"
self.party_row.update(
{
active_field: flt(self.party_row.get(active_field) + adjustment, self.precision),
active_field_account_currency: flt(
self.party_row.get(active_field_account_currency) + adjustment_in_party_currency,
self.precision,
),
}
)
def _calculate_net_total(self):
from erpnext.accounts.report.general_ledger.general_ledger import get_account_type_map
account_type_map = get_account_type_map(self.doc.company)
return flt(
sum(
d.get(self.reverse_field) - d.get(self.party_field)
for d in self.doc.get("accounts")
if account_type_map.get(d.account) not in ("Tax", "Chargeable")
and d.account != self.party_account
and not d.get("is_tax_withholding_account")
),
self.precision,
)
def _get_tds_details(self, net_total):
return get_party_tax_withholding_details(
frappe._dict(
{
"party_type": self.party_type,
"party": self.party,
"doctype": self.doc.doctype,
"company": self.doc.company,
"posting_date": self.doc.posting_date,
"tax_withholding_net_total": net_total,
"base_tax_withholding_net_total": net_total,
"grand_total": net_total,
}
),
self.doc.tax_withholding_category,
)
def _create_or_update_tds_row(self, tds_details):
tax_account = tds_details.get("account_head")
account_currency = get_account_currency(tax_account)
company_currency = frappe.get_cached_value("Company", self.doc.company, "default_currency")
exchange_rate = _get_exchange_rate(account_currency, company_currency, self.doc.posting_date)
tax_amount = flt(tds_details.get("tax_amount"), self.precision)
tax_amount_in_account_currency = flt(tax_amount / exchange_rate, self.precision)
# Find existing TDS row for this account
tax_row = None
for row in self.doc.get("accounts"):
if row.account == tax_account and row.get("is_tax_withholding_account"):
tax_row = row
break
if not tax_row:
tax_row = self.doc.append(
"accounts",
{
"account": tax_account,
"account_currency": account_currency,
"exchange_rate": exchange_rate,
"cost_center": tds_details.get("cost_center"),
"credit": 0,
"credit_in_account_currency": 0,
"debit": 0,
"debit_in_account_currency": 0,
"is_tax_withholding_account": 1,
},
)
# TDS/TCS is always credited (liability to government)
tax_row.update(
{
"credit": tax_amount,
"credit_in_account_currency": tax_amount_in_account_currency,
"debit": 0,
"debit_in_account_currency": 0,
}
)
self._cleanup_duplicate_tds_rows(tax_row)
def _cleanup_duplicate_tds_rows(self, current_tax_row):
rows_to_remove = [
row
for row in self.doc.get("accounts")
if row.get("is_tax_withholding_account") and row != current_tax_row
]
for row in rows_to_remove:
self.doc.remove(row)
def _recalculate_totals(self):
self.doc.set_amounts_in_company_currency()
self.doc.set_total_debit_credit()
self.doc.set_against_account()
@frappe.whitelist()
def get_default_bank_cash_account(company, account_type=None, mode_of_payment=None, account=None):
from erpnext.accounts.doctype.sales_invoice.sales_invoice import get_bank_cash_account
@@ -1642,8 +1788,6 @@ def get_exchange_rate(
credit=None,
exchange_rate=None,
):
from erpnext.setup.utils import get_exchange_rate
account_details = frappe.get_cached_value(
"Account", account, ["account_type", "root_type", "account_currency", "company"], as_dict=1
)
@@ -1665,8 +1809,8 @@ def get_exchange_rate(
# The date used to retreive the exchange rate here is the date passed
# in as an argument to this function.
elif (not exchange_rate or flt(exchange_rate) == 1) and account_currency and posting_date:
exchange_rate = get_exchange_rate(account_currency, company_currency, posting_date)
elif (not flt(exchange_rate) or flt(exchange_rate) == 1) and account_currency and posting_date:
exchange_rate = _get_exchange_rate(account_currency, company_currency, posting_date)
else:
exchange_rate = 1

View File

@@ -11,6 +11,7 @@ from frappe.utils import flt, nowdate
from erpnext.accounts.doctype.account.test_account import get_inventory_account
from erpnext.accounts.doctype.journal_entry.journal_entry import StockAccountInvalidTransaction
from erpnext.exceptions import InvalidAccountCurrency
from erpnext.selling.doctype.customer.test_customer import make_customer, set_credit_limit
class TestJournalEntry(unittest.TestCase):
@@ -592,6 +593,15 @@ class TestJournalEntry(unittest.TestCase):
self.assertEqual(jv.pay_to_recd_from, "_Test Receiver 2")
def test_credit_limit_for_customer(self):
customer = make_customer("_Test New Customer")
set_credit_limit("_Test New Customer", "_Test Company", 50)
jv = make_journal_entry(account1="Debtors - _TC", account2="_Test Cash - _TC", amount=100, save=False)
jv.accounts[0].party_type = "Customer"
jv.accounts[0].party = customer
jv.save()
self.assertRaises(frappe.ValidationError, jv.submit)
def make_journal_entry(
account1,

View File

@@ -34,6 +34,7 @@
"reference_detail_no",
"advance_voucher_type",
"advance_voucher_no",
"is_tax_withholding_account",
"col_break3",
"is_advance",
"user_remark",
@@ -106,7 +107,6 @@
"fieldname": "account_currency",
"fieldtype": "Link",
"label": "Account Currency",
"no_copy": 1,
"options": "Currency",
"print_hide": 1,
"read_only": 1
@@ -272,7 +272,8 @@
"label": "Advance Voucher Type",
"no_copy": 1,
"options": "DocType",
"read_only": 1
"read_only": 1,
"search_index": 1
},
{
"fieldname": "advance_voucher_no",
@@ -280,13 +281,21 @@
"label": "Advance Voucher No",
"no_copy": 1,
"options": "advance_voucher_type",
"read_only": 1,
"search_index": 1
},
{
"default": "0",
"fieldname": "is_tax_withholding_account",
"fieldtype": "Check",
"label": "Is Tax Withholding Account",
"read_only": 1
}
],
"idx": 1,
"istable": 1,
"links": [],
"modified": "2025-07-25 04:45:28.117715",
"modified": "2025-11-27 12:23:33.157655",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Journal Entry Account",

View File

@@ -28,6 +28,7 @@ class JournalEntryAccount(Document):
debit_in_account_currency: DF.Currency
exchange_rate: DF.Float
is_advance: DF.Literal["No", "Yes"]
is_tax_withholding_account: DF.Check
parent: DF.Data
parentfield: DF.Data
parenttype: DF.Data

View File

@@ -592,6 +592,8 @@ frappe.ui.form.on("Payment Entry", {
paid_from: function (frm) {
if (frm.set_party_account_based_on_party) return;
frm.events.set_company_bank_account(frm);
frm.events.set_account_currency_and_balance(
frm,
frm.doc.paid_from,
@@ -601,6 +603,7 @@ frappe.ui.form.on("Payment Entry", {
if (frm.doc.payment_type == "Pay") {
frm.events.paid_amount(frm);
}
frm.events.paid_from_account_currency(frm);
}
);
},
@@ -608,6 +611,8 @@ frappe.ui.form.on("Payment Entry", {
paid_to: function (frm) {
if (frm.set_party_account_based_on_party) return;
frm.events.set_company_bank_account(frm);
frm.events.set_account_currency_and_balance(
frm,
frm.doc.paid_to,
@@ -624,6 +629,7 @@ frappe.ui.form.on("Payment Entry", {
frm.events.received_amount(frm);
}
}
frm.events.paid_to_account_currency(frm);
}
);
},
@@ -1348,6 +1354,8 @@ frappe.ui.form.on("Payment Entry", {
},
bank_account: function (frm) {
if (frm.set_company_bank_account_based_on_coa) return;
const field = frm.doc.payment_type == "Pay" ? "paid_from" : "paid_to";
if (frm.doc.bank_account && ["Pay", "Receive"].includes(frm.doc.payment_type)) {
frappe.call({
@@ -1386,6 +1394,34 @@ frappe.ui.form.on("Payment Entry", {
}
},
set_company_bank_account: function (frm) {
if (!["Pay", "Receive"].includes(frm.doc.payment_type)) return;
const field = frm.doc.payment_type == "Pay" ? "paid_from" : "paid_to";
if (!frm.doc.company || !frm.doc[field]) return;
frm.set_company_bank_account_based_on_coa = true;
frappe.call({
method: "frappe.client.get_value",
args: {
doctype: "Bank Account",
filters: {
company: frm.doc.company,
account: frm.doc[field],
disabled: 0,
},
fieldname: ["name"],
},
callback: async function (r) {
if (r.message) await frm.set_value("bank_account", r.message.name);
frm.set_company_bank_account_based_on_coa = false;
},
});
},
sales_taxes_and_charges_template: function (frm) {
frm.trigger("fetch_taxes_from_template");
},

View File

@@ -449,7 +449,7 @@ class PaymentEntry(AccountsController):
self.contact_person = get_default_contact(self.party_type, self.party)
complete_contact_details(self)
if not self.party_balance:
if not self.party_balance and frappe.get_single_value("Accounts Settings", "show_party_balance"):
self.party_balance = get_balance_on(
party_type=self.party_type, party=self.party, date=self.posting_date, company=self.company
)
@@ -1800,7 +1800,7 @@ class PaymentEntry(AccountsController):
else:
self.total_taxes_and_charges += current_tax_amount
self.base_total_taxes_and_charges += tax.base_tax_amount
self.base_total_taxes_and_charges += current_tax_amount
if self.get("taxes"):
self.paid_amount_after_tax = self.get("taxes")[-1].base_total
@@ -2684,11 +2684,17 @@ def get_party_details(company, party_type, party, date, cost_center=None):
party_account = get_party_account(party_type, party, company)
account_currency = get_account_currency(party_account)
account_balance = get_balance_on(party_account, date, cost_center=cost_center)
account_balance = (
get_balance_on(party_account, date, cost_center=cost_center)
if frappe.get_single_value("Accounts Settings", "show_account_balance")
else 0
)
_party_name = "title" if party_type == "Shareholder" else party_type.lower() + "_name"
party_name = frappe.db.get_value(party_type, party, _party_name)
party_balance = get_balance_on(
party_type=party_type, party=party, company=company, cost_center=cost_center
party_balance = (
get_balance_on(party_type=party_type, party=party, company=company, cost_center=cost_center)
if frappe.get_single_value("Accounts Settings", "show_party_balance")
else 0
)
if party_type in ["Customer", "Supplier"]:
party_bank_account = get_party_bank_account(party_type, party)
@@ -2717,7 +2723,11 @@ def get_account_details(account, date, cost_center=None):
if not account_list:
frappe.throw(_("Account: {0} is not permitted under Payment Entry").format(account))
account_balance = get_balance_on(account, date, cost_center=cost_center, ignore_account_permission=True)
account_balance = (
get_balance_on(account, date, cost_center=cost_center, ignore_account_permission=True)
if frappe.get_single_value("Accounts Settings", "show_account_balance")
else 0
)
return frappe._dict(
{
@@ -3529,11 +3539,18 @@ def get_paid_amount(dt, dn, party_type, party, account, due_date):
def get_party_and_account_balance(
company, date, paid_from=None, paid_to=None, ptype=None, pty=None, cost_center=None
):
show_account_balance = frappe.get_single_value("Accounts Settings", "show_account_balance")
return frappe._dict(
{
"party_balance": get_balance_on(party_type=ptype, party=pty, cost_center=cost_center),
"paid_from_account_balance": get_balance_on(paid_from, date, cost_center=cost_center),
"paid_to_account_balance": get_balance_on(paid_to, date=date, cost_center=cost_center),
"party_balance": get_balance_on(party_type=ptype, party=pty, cost_center=cost_center)
if frappe.get_single_value("Accounts Settings", "show_party_balance")
else 0,
"paid_from_account_balance": get_balance_on(paid_from, date, cost_center=cost_center)
if show_account_balance
else 0,
"paid_to_account_balance": get_balance_on(paid_to, date=date, cost_center=cost_center)
if show_account_balance
else 0,
}
)

View File

@@ -61,6 +61,22 @@ erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationCo
},
};
});
this.frm.set_query("cost_center", "payments", () => {
return {
filters: {
company: this.frm.doc.company,
is_group: 0,
},
};
});
this.frm.set_query("cost_center", "allocation", () => {
return {
filters: {
company: this.frm.doc.company,
is_group: 0,
},
};
});
}
refresh() {
@@ -318,7 +334,9 @@ erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationCo
},
{
fieldtype: "HTML",
options: "<b> New Journal Entry will be posted for the difference amount </b>",
options: __(
"New Journal Entry will be posted for the difference amount. The Posting Date can be modified."
).bold(),
},
],
primary_action: () => {
@@ -385,6 +403,16 @@ frappe.ui.form.on("Payment Reconciliation Allocation", {
// filter payment
let payment = frm.doc.payments.filter((x) => x.reference_name == row.reference_name);
let amount = payment[0].amount;
for (const d of frm.doc.allocation) {
if (row.reference_name == d.reference_name && amount) {
if (d.allocated_amount <= amount) {
d.amount = amount;
amount -= d.allocated_amount;
}
}
}
frm.call({
doc: frm.doc,
method: "calculate_difference_on_allocation_change",

View File

@@ -72,7 +72,7 @@ class PaymentReconciliation(Document):
self.common_filter_conditions = []
self.accounting_dimension_filter_conditions = []
self.ple_posting_date_filter = []
self.dimensions = get_dimensions()[0]
self.dimensions = get_dimensions(with_cost_center_and_project=True)[0]
def load_from_db(self):
# 'modified' attribute is required for `run_doc_method` to work properly.
@@ -765,6 +765,14 @@ class PaymentReconciliation(Document):
def reconcile_dr_cr_note(dr_cr_notes, company, active_dimensions=None):
for inv in dr_cr_notes:
if (
abs(frappe.db.get_value(inv.voucher_type, inv.voucher_no, "outstanding_amount"))
< inv.allocated_amount
):
frappe.throw(
_("{0} has been modified after you pulled it. Please pull it again.").format(inv.voucher_type)
)
voucher_type = "Credit Note" if inv.voucher_type == "Sales Invoice" else "Debit Note"
reconcile_dr_or_cr = (

View File

@@ -226,7 +226,8 @@
"fetch_from": "bank_account.iban",
"fieldname": "iban",
"fieldtype": "Read Only",
"label": "IBAN"
"label": "IBAN",
"options": "IBAN"
},
{
"fetch_from": "bank_account.branch_code",
@@ -443,11 +444,12 @@
"label": "Phone Number"
}
],
"grid_page_length": 50,
"in_create": 1,
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
"modified": "2024-12-27 21:29:10.361894",
"modified": "2025-08-29 11:52:48.555415",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Request",
@@ -482,8 +484,9 @@
"write": 1
}
],
"row_format": "Dynamic",
"show_preview_popup": 1,
"sort_field": "modified",
"sort_order": "DESC",
"states": []
}
}

View File

@@ -127,7 +127,13 @@ class PaymentRequest(Document):
existing_payment_request_amount = flt(get_existing_payment_request_amount(ref_doc))
if existing_payment_request_amount + flt(self.grand_total) > ref_amount:
if (
flt(
existing_payment_request_amount + flt(self.grand_total, self.precision("grand_total")),
get_currency_precision(),
)
> ref_amount
):
frappe.throw(
_("Total Payment Request amount cannot be greater than {0} amount").format(
self.reference_doctype
@@ -844,6 +850,7 @@ def update_payment_requests_as_per_pe_references(references=None, cancel=False):
)
referenced_payment_requests = {pr.name: pr for pr in referenced_payment_requests}
doc_updates = {}
for ref in references:
if not ref.payment_request:
@@ -869,7 +876,7 @@ def update_payment_requests_as_per_pe_references(references=None, cancel=False):
title=_("Invalid Allocated Amount"),
)
# update status
# determine status
if new_outstanding_amount == payment_request["grand_total"]:
status = "Initiated" if payment_request["payment_request_type"] == "Outward" else "Requested"
elif new_outstanding_amount == 0:
@@ -877,12 +884,15 @@ def update_payment_requests_as_per_pe_references(references=None, cancel=False):
elif new_outstanding_amount > 0:
status = "Partially Paid"
# update database
frappe.db.set_value(
"Payment Request",
ref.payment_request,
{"outstanding_amount": new_outstanding_amount, "status": status},
)
# prepare bulk update data
doc_updates[ref.payment_request] = {
"outstanding_amount": new_outstanding_amount,
"status": status,
}
# bulk update all payment requests
if doc_updates:
frappe.db.bulk_update("Payment Request", doc_updates)
def get_dummy_message(doc):

View File

@@ -10,14 +10,19 @@
"description",
"section_break_4",
"due_date",
"invoice_portion",
"mode_of_payment",
"column_break_5",
"invoice_portion",
"due_date_based_on",
"credit_days",
"credit_months",
"section_break_6",
"discount_type",
"discount_date",
"column_break_9",
"discount",
"discount_type",
"column_break_9",
"discount_validity_based_on",
"discount_validity",
"section_break_9",
"payment_amount",
"outstanding",
@@ -172,12 +177,50 @@
"label": "Paid Amount (Company Currency)",
"options": "Company:company:default_currency",
"read_only": 1
},
{
"fieldname": "due_date_based_on",
"fieldtype": "Select",
"label": "Due Date Based On",
"options": "\nDay(s) after invoice date\nDay(s) after the end of the invoice month\nMonth(s) after the end of the invoice month",
"read_only": 1
},
{
"depends_on": "eval:in_list(['Day(s) after invoice date', 'Day(s) after the end of the invoice month'], doc.due_date_based_on)",
"fieldname": "credit_days",
"fieldtype": "Int",
"label": "Credit Days",
"non_negative": 1,
"read_only": 1
},
{
"depends_on": "eval:doc.due_date_based_on=='Month(s) after the end of the invoice month'",
"fieldname": "credit_months",
"fieldtype": "Int",
"label": "Credit Months",
"non_negative": 1,
"read_only": 1
},
{
"depends_on": "discount",
"fieldname": "discount_validity_based_on",
"fieldtype": "Select",
"label": "Discount Validity Based On",
"options": "\nDay(s) after invoice date\nDay(s) after the end of the invoice month\nMonth(s) after the end of the invoice month",
"read_only": 1
},
{
"depends_on": "discount_validity_based_on",
"fieldname": "discount_validity",
"fieldtype": "Int",
"label": "Discount Validity",
"read_only": 1
}
],
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2025-03-11 11:06:51.792982",
"modified": "2025-07-31 08:38:25.820701",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Schedule",
@@ -189,4 +232,4 @@
"sort_order": "DESC",
"states": [],
"track_changes": 1
}
}

View File

@@ -17,12 +17,27 @@ class PaymentSchedule(Document):
base_outstanding: DF.Currency
base_paid_amount: DF.Currency
base_payment_amount: DF.Currency
credit_days: DF.Int
credit_months: DF.Int
description: DF.SmallText | None
discount: DF.Float
discount_date: DF.Date | None
discount_type: DF.Literal["Percentage", "Amount"]
discount_validity: DF.Int
discount_validity_based_on: DF.Literal[
"",
"Day(s) after invoice date",
"Day(s) after the end of the invoice month",
"Month(s) after the end of the invoice month",
]
discounted_amount: DF.Currency
due_date: DF.Date
due_date_based_on: DF.Literal[
"",
"Day(s) after invoice date",
"Day(s) after the end of the invoice month",
"Month(s) after the end of the invoice month",
]
invoice_portion: DF.Percent
mode_of_payment: DF.Link | None
outstanding: DF.Currency

View File

@@ -161,4 +161,4 @@
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1
}
}

View File

@@ -4,6 +4,8 @@
frappe.ui.form.on("Period Closing Voucher", {
onload: function (frm) {
if (!frm.doc.transaction_date) frm.doc.transaction_date = frappe.datetime.obj_to_str(new Date());
frm.ignore_doctypes_on_cancel_all = ["Process Period Closing Voucher"];
},
setup: function (frm) {

View File

@@ -132,7 +132,11 @@ class PeriodClosingVoucher(AccountsController):
def on_submit(self):
self.db_set("gle_processing_status", "In Progress")
self.make_gl_entries()
if frappe.get_single_value("Accounts Settings", "use_legacy_controller_for_pcv"):
self.make_gl_entries()
else:
ppcv = frappe.get_doc({"doctype": "Process Period Closing Voucher", "parent_pcv": self.name})
ppcv.save().submit()
def on_cancel(self):
self.ignore_linked_doctypes = (
@@ -140,11 +144,29 @@ class PeriodClosingVoucher(AccountsController):
"Stock Ledger Entry",
"Payment Ledger Entry",
"Account Closing Balance",
"Process Period Closing Voucher",
)
self.block_if_future_closing_voucher_exists()
if not frappe.get_single_value("Accounts Settings", "use_legacy_controller_for_pcv"):
self.cancel_process_pcv_docs()
self.db_set("gle_processing_status", "In Progress")
self.cancel_gl_entries()
def cancel_process_pcv_docs(self):
ppcvs = frappe.db.get_all("Process Period Closing Voucher", {"parent_pcv": self.name, "docstatus": 1})
for x in ppcvs:
frappe.get_doc("Process Period Closing Voucher", x.name).cancel()
def on_trash(self):
super().on_trash()
ppcvs = frappe.db.get_all(
"Process Period Closing Voucher", {"parent_pcv": self.name, "docstatus": ["in", [1, 2]]}
)
for x in ppcvs:
frappe.delete_doc("Process Period Closing Voucher", x.name, force=True, ignore_permissions=True)
def make_gl_entries(self):
if frappe.db.estimate_count("GL Entry") > 100_000:
frappe.enqueue(
@@ -453,8 +475,15 @@ def process_gl_and_closing_entries(doc):
frappe.db.set_value(doc.doctype, doc.name, "gle_processing_status", "Completed")
except Exception as e:
frappe.db.rollback()
frappe.log_error(e)
frappe.db.set_value(doc.doctype, doc.name, "gle_processing_status", "Failed")
frappe.log_error(title=_("Period Closing Voucher {0} GL Entry Processing Failed").format(doc.name))
frappe.db.set_value(
doc.doctype,
doc.name,
{
"error_message": str(e),
"gle_processing_status": "Failed",
},
)
def process_cancellation(voucher_type, voucher_no):
@@ -466,8 +495,17 @@ def process_cancellation(voucher_type, voucher_no):
frappe.db.set_value("Period Closing Voucher", voucher_no, "gle_processing_status", "Completed")
except Exception as e:
frappe.db.rollback()
frappe.log_error(e)
frappe.db.set_value("Period Closing Voucher", voucher_no, "gle_processing_status", "Failed")
frappe.log_error(
title=_("Period Closing Voucher {0} GL Entry Cancellation Failed").format(voucher_no)
)
frappe.db.set_value(
voucher_type,
voucher_no,
{
"error_message": str(e),
"gle_processing_status": "Failed",
},
)
def delete_closing_entries(voucher_no):

View File

@@ -14,6 +14,10 @@ from erpnext.accounts.utils import get_fiscal_year
class TestPeriodClosingVoucher(unittest.TestCase):
def setUp(self):
super().setUp()
frappe.db.set_single_value("Accounts Settings", "use_legacy_controller_for_pcv", 1)
def test_closing_entry(self):
frappe.db.sql("delete from `tabGL Entry` where company='Test PCV Company'")
frappe.db.sql("delete from `tabPeriod Closing Voucher` where company='Test PCV Company'")

View File

@@ -161,6 +161,8 @@ def get_pos_invoices(start, end, pos_profile, user):
`tabPOS Invoice`
where
owner = %s and docstatus = 1 and pos_profile = %s and ifnull(consolidated_invoice,'') = ''
order by
timestamp
""",
(user, pos_profile),
as_dict=1,

View File

@@ -18,12 +18,17 @@ from erpnext.accounts.doctype.sales_invoice.sales_invoice import (
from erpnext.accounts.party import get_due_date, get_party_account
from erpnext.controllers.queries import item_query as _item_query
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
from erpnext.stock.stock_ledger import is_negative_stock_allowed
class PartialPaymentValidationError(frappe.ValidationError):
pass
class ProductBundleStockValidationError(frappe.ValidationError):
pass
class POSInvoice(SalesInvoice):
# begin: auto-generated types
# This code is auto-generated. Do not modify anything in this block.
@@ -189,6 +194,9 @@ class POSInvoice(SalesInvoice):
super().__init__(*args, **kwargs)
def validate(self):
if not self.customer:
frappe.throw(_("Please select Customer first"))
if not cint(self.is_pos):
frappe.throw(
_("POS Invoice should have the field {0} checked.").format(frappe.bold(_("Include Payment")))
@@ -345,34 +353,69 @@ class POSInvoice(SalesInvoice):
):
return
from erpnext.stock.stock_ledger import is_negative_stock_allowed
for d in self.get("items"):
if not d.serial_and_batch_bundle:
if is_negative_stock_allowed(item_code=d.item_code):
return
if frappe.db.exists("Product Bundle", d.item_code):
(
availability,
is_stock_item,
is_negative_stock_allowed,
) = get_product_bundle_stock_availability(d.item_code, d.warehouse, d.stock_qty)
available_stock, is_stock_item = get_stock_availability(d.item_code, d.warehouse)
else:
availability, is_stock_item, is_negative_stock_allowed = get_stock_availability(
d.item_code, d.warehouse
)
item_code, warehouse, _qty = (
frappe.bold(d.item_code),
frappe.bold(d.warehouse),
frappe.bold(d.qty),
)
if is_stock_item and flt(available_stock) <= 0:
frappe.throw(
_("Row #{}: Item Code: {} is not available under warehouse {}.").format(
d.idx, item_code, warehouse
),
title=_("Item Unavailable"),
)
elif is_stock_item and flt(available_stock) < flt(d.stock_qty):
frappe.throw(
_("Row #{}: Stock quantity not enough for Item Code: {} under warehouse {}.").format(
d.idx, item_code, warehouse
),
title=_("Item Unavailable"),
)
if is_negative_stock_allowed:
continue
if isinstance(availability, list):
error_msgs = []
for item in availability:
if flt(item["available"]) < flt(item["required"]):
error_msgs.append(
_("<li>Packed Item {0}: Required {1}, Available {2}</li>").format(
frappe.bold(item["item_code"]),
frappe.bold(flt(item["required"], 2)),
frappe.bold(flt(item["available"], 2)),
)
)
if error_msgs:
frappe.throw(
_(
"<b>Row #{0}:</b> Bundle {1} in warehouse {2} has insufficient packed items:<br><div style='margin-top: 15px;'><ul style='line-height: 0.8;'>{3}</ul></div>"
).format(
d.idx,
frappe.bold(d.item_code),
frappe.bold(d.warehouse),
"<br>".join(error_msgs),
),
title=_("Insufficient Stock for Product Bundle Items"),
exc=ProductBundleStockValidationError,
)
else:
item_code, warehouse = frappe.bold(d.item_code), frappe.bold(d.warehouse)
if is_stock_item and flt(availability) <= 0:
frappe.throw(
_("Row #{0}: Item {1} has no stock in warehouse {2}.").format(
d.idx, item_code, warehouse
),
title=_("Item Out of Stock"),
)
elif is_stock_item and flt(availability) < flt(d.stock_qty):
frappe.throw(
_("Row #{0}: Item {1} in warehouse {2}: Available {3}, Needed {4}.").format(
d.idx,
item_code,
warehouse,
frappe.bold(flt(availability, 2)),
frappe.bold(flt(d.stock_qty, 2)),
),
title=_("Insufficient Stock"),
)
def validate_serialised_or_batched_item(self):
error_msg = []
@@ -765,15 +808,35 @@ def get_stock_availability(item_code, warehouse):
bin_qty = get_bin_qty(item_code, warehouse)
pos_sales_qty = get_pos_reserved_qty(item_code, warehouse)
return bin_qty - pos_sales_qty, is_stock_item
return bin_qty - pos_sales_qty, is_stock_item, is_negative_stock_allowed(item_code=item_code)
else:
is_stock_item = True
if frappe.db.exists("Product Bundle", {"name": item_code, "disabled": 0}):
return get_bundle_availability(item_code, warehouse), is_stock_item
return get_bundle_availability(item_code, warehouse), is_stock_item, False
else:
is_stock_item = False
# Is a service item or non_stock item
return 0, is_stock_item
return 0, is_stock_item, False
def get_product_bundle_stock_availability(item_code, warehouse, item_qty):
is_stock_item = True
bundle = frappe.get_doc("Product Bundle", item_code)
availabilities = []
for bundle_item in bundle.items:
if frappe.get_value("Item", bundle_item.item_code, "is_stock_item"):
bin_qty = get_bin_qty(bundle_item.item_code, warehouse)
reserved_qty = get_pos_reserved_qty(bundle_item.item_code, warehouse)
available = bin_qty - reserved_qty
availabilities.append(
{
"item_code": bundle_item.item_code,
"required": bundle_item.qty * item_qty,
"available": available,
}
)
return availabilities, is_stock_item, is_negative_stock_allowed(item_code=item_code)
def get_bundle_availability(bundle_item_code, warehouse):

View File

@@ -964,6 +964,84 @@ class TestPOSInvoice(unittest.TestCase):
frappe.db.rollback(save_point="before_test_delivered_serial_no_case")
frappe.set_user("Administrator")
def test_bundle_stock_availability_validation(self):
from erpnext.accounts.doctype.pos_invoice.pos_invoice import ProductBundleStockValidationError
from erpnext.accounts.doctype.pos_invoice_merge_log.test_pos_invoice_merge_log import (
init_user_and_profile,
)
from erpnext.selling.doctype.product_bundle.test_product_bundle import make_product_bundle
from erpnext.stock.doctype.item.test_item import create_item
init_user_and_profile()
frappe.set_user("Administrator")
warehouse = "_Test Warehouse - _TC"
company = "_Test Company"
# Create stock sub-items
sub_item_a = "_Test Bundle SubA"
if not frappe.db.exists("Item", sub_item_a):
create_item(
item_code=sub_item_a,
is_stock_item=1,
)
sub_item_b = "_Test Bundle SubB"
if not frappe.db.exists("Item", sub_item_b):
create_item(
item_code=sub_item_b,
is_stock_item=1,
)
# Add initial stock: SubA=5, SubB=2
make_stock_entry(item_code=sub_item_a, target=warehouse, qty=5, company=company)
make_stock_entry(item_code=sub_item_b, target=warehouse, qty=2, company=company)
# Create Product Bundle: Test Bundle (SubA x2 + SubB x1)
bundle_item = "_Test Bundle"
if not frappe.db.exists("Item", bundle_item):
create_item(
item_code=bundle_item,
is_stock_item=0,
)
if not frappe.db.exists("Product Bundle", bundle_item):
make_product_bundle(parent=bundle_item, items=[sub_item_a, sub_item_b])
# Test Case 1: Sufficient stock (bundle qty=1: requires SubA=2 (<=5), SubB=1 (<=2)) -> No error
pos_inv_sufficient = create_pos_invoice(
item=bundle_item,
qty=1,
rate=100,
warehouse=warehouse,
pos_profile=self.pos_profile.name,
do_not_save=1,
)
pos_inv_sufficient.append("payments", {"mode_of_payment": "Cash", "amount": 100, "default": 1})
pos_inv_sufficient.insert()
pos_inv_sufficient.submit()
pos_inv_sufficient.cancel()
pos_inv_sufficient.delete()
# Test Case 2: Insufficient stock (reduce SubB to 1, bundle qty=2: requires SubB=2 >1) -> Error with details
make_stock_entry(item_code=sub_item_b, from_warehouse=warehouse, qty=1, company=company)
pos_inv_insufficient = create_pos_invoice(
item=bundle_item,
qty=2,
rate=100,
warehouse=warehouse,
pos_profile=self.pos_profile.name,
do_not_save=1,
)
pos_inv_insufficient.append("payments", {"mode_of_payment": "Cash", "amount": 200, "default": 1})
pos_inv_insufficient.save()
self.assertRaises(ProductBundleStockValidationError, pos_inv_insufficient.submit)
frappe.set_user("test@example.com")
def create_pos_invoice(**args):
args = frappe._dict(args)

View File

@@ -41,9 +41,19 @@ class POSOpeningEntry(StatusUpdater):
self.set_status()
def validate_pos_profile_and_cashier(self):
if self.company != frappe.db.get_value("POS Profile", self.pos_profile, "company"):
if not frappe.db.exists("POS Profile", self.pos_profile):
frappe.throw(_("POS Profile {} does not exist.").format(self.pos_profile))
pos_profile_company, pos_profile_disabled = frappe.db.get_value(
"POS Profile", self.pos_profile, ["company", "disabled"]
)
if pos_profile_disabled:
frappe.throw(_("POS Profile {} is disabled.").format(frappe.bold(self.pos_profile)))
if self.company != pos_profile_company:
frappe.throw(
_("POS Profile {} does not belongs to company {}").format(self.pos_profile, self.company)
_("POS Profile {} does not belong to company {}").format(self.pos_profile, self.company)
)
if not cint(frappe.db.get_value("User", self.user, "enabled")):

View File

@@ -70,6 +70,7 @@ class POSProfile(Document):
# end: auto-generated types
def validate(self):
self.validate_disabled()
self.validate_default_profile()
self.validate_all_link_fields()
self.validate_duplicate_groups()
@@ -94,6 +95,21 @@ class POSProfile(Document):
title=_("Mandatory Accounting Dimension"),
)
def validate_disabled(self):
old_doc = self.get_doc_before_save()
if (
old_doc
and self.disabled
and old_doc.disabled != self.disabled
and frappe.db.exists("POS Opening Entry", {"pos_profile": self.name, "status": "Open"})
):
frappe.throw(
_("POS Profile {0} cannot be disabled as there are ongoing POS sessions.").format(
frappe.bold(self.name)
)
)
def validate_default_profile(self):
for row in self.applicable_for_users:
res = frappe.db.sql(

View File

@@ -4,6 +4,7 @@
import unittest
import frappe
from frappe.utils import cint
from erpnext.accounts.doctype.pos_profile.pos_profile import (
get_child_nodes,
@@ -38,6 +39,51 @@ class TestPOSProfile(unittest.TestCase):
frappe.db.sql("delete from `tabPOS Profile`")
def test_disabled_pos_profile_creation(self):
make_pos_profile(name="_Test POS Profile 001", disabled=1)
pos_profile = frappe.get_doc("POS Profile", "_Test POS Profile 001")
if pos_profile:
self.assertEqual(pos_profile.disabled, 1)
def test_disabled_pos_profile_after_opening(self):
from erpnext.accounts.doctype.pos_closing_entry.test_pos_closing_entry import init_user_and_profile
from erpnext.accounts.doctype.pos_opening_entry.test_pos_opening_entry import create_opening_entry
test_user, pos_profile = init_user_and_profile()
if pos_profile:
create_opening_entry(pos_profile, test_user.name)
self.assertEqual(pos_profile.disabled, 0)
pos_profile.disabled = 1
self.assertRaises(frappe.ValidationError, pos_profile.save)
def test_disabled_pos_profile_after_completing_session(self):
from erpnext.accounts.doctype.pos_closing_entry.pos_closing_entry import (
make_closing_entry_from_opening,
)
from erpnext.accounts.doctype.pos_closing_entry.test_pos_closing_entry import init_user_and_profile
from erpnext.accounts.doctype.pos_opening_entry.test_pos_opening_entry import (
create_opening_entry,
)
test_user, pos_profile = init_user_and_profile()
frappe.db.delete("POS Opening Entry", {"pos_profile": pos_profile.name})
if pos_profile:
opening_entry = create_opening_entry(pos_profile, test_user.name)
closing_entry = make_closing_entry_from_opening(opening_entry)
closing_entry.submit()
pos_profile.disabled = 1
pos_profile.save()
pos_profile.reload()
self.assertEqual(pos_profile.disabled, 1)
def get_customers_list(pos_profile=None):
if pos_profile is None:
@@ -117,6 +163,7 @@ def make_pos_profile(**args):
"write_off_account": args.write_off_account or "_Test Write Off - _TC",
"write_off_cost_center": args.write_off_cost_center or "_Test Write Off Cost Center - _TC",
"location": "Block 1" if not args.do_not_set_accounting_dimension else None,
"disabled": cint(args.disabled) or 0,
}
)

View File

@@ -243,10 +243,13 @@ def get_other_conditions(conditions, values, args):
if group_condition:
conditions += " and " + group_condition
if args.get("transaction_date"):
date = args.get("transaction_date") or frappe.get_value(
args.get("doctype"), args.get("name"), "posting_date", ignore=True
)
if date:
conditions += """ and %(transaction_date)s between ifnull(`tabPricing Rule`.valid_from, '2000-01-01')
and ifnull(`tabPricing Rule`.valid_upto, '2500-12-31')"""
values["transaction_date"] = args.get("transaction_date")
values["transaction_date"] = date
if args.get("doctype") in [
"Quotation",

View File

@@ -0,0 +1,71 @@
// Copyright (c) 2025, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on("Process Period Closing Voucher", {
refresh(frm) {
if (frm.doc.docstatus == 1 && ["Queued"].find((x) => x == frm.doc.status)) {
let execute_btn = __("Start");
frm.add_custom_button(execute_btn, () => {
frm.call({
method: "erpnext.accounts.doctype.process_period_closing_voucher.process_period_closing_voucher.start_pcv_processing",
args: {
docname: frm.doc.name,
},
}).then((r) => {
if (!r.exc) {
frappe.show_alert(__("Job Started"));
frm.reload_doc();
}
});
});
}
if (frm.doc.docstatus == 1 && ["Running"].find((x) => x == frm.doc.status)) {
let execute_btn = __("Pause");
frm.add_custom_button(execute_btn, () => {
frm.call({
method: "erpnext.accounts.doctype.process_period_closing_voucher.process_period_closing_voucher.pause_pcv_processing",
args: {
docname: frm.doc.name,
},
}).then((r) => {
if (!r.exc) {
frappe.show_alert(__("PCV Paused"));
frm.reload_doc();
}
});
});
}
if (frm.doc.docstatus == 1 && ["Paused"].find((x) => x == frm.doc.status)) {
let execute_btn = __("Resume");
frm.add_custom_button(execute_btn, () => {
frm.call({
method: "erpnext.accounts.doctype.process_period_closing_voucher.process_period_closing_voucher.resume_pcv_processing",
args: {
docname: frm.doc.name,
},
}).then((r) => {
if (!r.exc) {
frappe.show_alert(__("PCV Resumed"));
frm.reload_doc();
}
});
});
}
// progress bar
let progress = 0;
let normal_finished = frm.doc.normal_balances.filter((x) => x.status == "Completed").length;
let opening_finished = frm.doc.z_opening_balances.filter((x) => x.status == "Completed").length;
progress =
((normal_finished + opening_finished) /
(frm.doc.normal_balances.length + frm.doc.z_opening_balances.length)) *
100;
frm.dashboard.add_progress("Books closure progress", progress, "");
},
});

View File

@@ -0,0 +1,113 @@
{
"actions": [],
"autoname": "format:Process-PCV-{###}",
"creation": "2025-09-25 15:44:03.534699",
"doctype": "DocType",
"engine": "InnoDB",
"field_order": [
"parent_pcv",
"status",
"p_l_closing_balance",
"normal_balances",
"bs_closing_balance",
"z_opening_balances",
"amended_from"
],
"fields": [
{
"fieldname": "parent_pcv",
"fieldtype": "Link",
"in_list_view": 1,
"label": "PCV",
"options": "Period Closing Voucher",
"reqd": 1
},
{
"default": "Queued",
"fieldname": "status",
"fieldtype": "Select",
"label": "Status",
"no_copy": 1,
"options": "Queued\nRunning\nPaused\nCompleted\nCancelled"
},
{
"fieldname": "amended_from",
"fieldtype": "Link",
"label": "Amended From",
"no_copy": 1,
"options": "Process Period Closing Voucher",
"print_hide": 1,
"read_only": 1,
"search_index": 1
},
{
"fieldname": "p_l_closing_balance",
"fieldtype": "JSON",
"label": "P&L Closing Balance",
"no_copy": 1
},
{
"fieldname": "normal_balances",
"fieldtype": "Table",
"label": "Dates to Process",
"no_copy": 1,
"options": "Process Period Closing Voucher Detail"
},
{
"fieldname": "z_opening_balances",
"fieldtype": "Table",
"label": "Opening Balances",
"no_copy": 1,
"options": "Process Period Closing Voucher Detail"
},
{
"fieldname": "bs_closing_balance",
"fieldtype": "JSON",
"label": "Balance Sheet Closing Balance"
}
],
"grid_page_length": 50,
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
"modified": "2025-11-05 11:40:24.996403",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Process Period Closing Voucher",
"naming_rule": "Expression",
"owner": "Administrator",
"permissions": [
{
"cancel": 1,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"share": 1,
"submit": 1,
"write": 1
},
{
"cancel": 1,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts Manager",
"share": 1,
"submit": 1,
"write": 1
}
],
"row_format": "Dynamic",
"sort_field": "creation",
"sort_order": "DESC",
"states": []
}

View File

@@ -0,0 +1,559 @@
# Copyright (c) 2025, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
import copy
from datetime import timedelta
import frappe
from frappe import qb
from frappe.model.document import Document
from frappe.query_builder.functions import Count, Max, Min, Sum
from frappe.utils import add_days, flt, get_datetime
from frappe.utils.scheduler import is_scheduler_inactive
from erpnext.accounts.doctype.account_closing_balance.account_closing_balance import (
make_closing_entries,
)
class ProcessPeriodClosingVoucher(Document):
# begin: auto-generated types
# This code is auto-generated. Do not modify anything in this block.
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from frappe.types import DF
from erpnext.accounts.doctype.process_period_closing_voucher_detail.process_period_closing_voucher_detail import (
ProcessPeriodClosingVoucherDetail,
)
amended_from: DF.Link | None
bs_closing_balance: DF.JSON | None
normal_balances: DF.Table[ProcessPeriodClosingVoucherDetail]
p_l_closing_balance: DF.JSON | None
parent_pcv: DF.Link
status: DF.Literal["Queued", "Running", "Paused", "Completed", "Cancelled"]
z_opening_balances: DF.Table[ProcessPeriodClosingVoucherDetail]
# end: auto-generated types
def validate(self):
self.status = "Queued"
self.populate_processing_tables()
def populate_processing_tables(self):
self.generate_pcv_dates()
self.generate_opening_balances_dates()
def get_dates(self, start, end):
return [start + timedelta(days=x) for x in range((end - start).days + 1)]
def generate_pcv_dates(self):
self.normal_balances = []
pcv = frappe.get_doc("Period Closing Voucher", self.parent_pcv)
dates = self.get_dates(get_datetime(pcv.period_start_date), get_datetime(pcv.period_end_date))
for x in dates:
self.append(
"normal_balances",
{"processing_date": x, "status": "Queued", "report_type": "Profit and Loss"},
)
self.append(
"normal_balances", {"processing_date": x, "status": "Queued", "report_type": "Balance Sheet"}
)
def generate_opening_balances_dates(self):
self.z_opening_balances = []
pcv = frappe.get_doc("Period Closing Voucher", self.parent_pcv)
if pcv.is_first_period_closing_voucher():
gl = qb.DocType("GL Entry")
min = qb.from_(gl).select(Min(gl.posting_date)).where(gl.company.eq(pcv.company)).run()[0][0]
max = qb.from_(gl).select(Max(gl.posting_date)).where(gl.company.eq(pcv.company)).run()[0][0]
dates = self.get_dates(get_datetime(min), get_datetime(max))
for x in dates:
self.append(
"z_opening_balances",
{"processing_date": x, "status": "Queued", "report_type": "Balance Sheet"},
)
def on_submit(self):
start_pcv_processing(self.name)
def on_cancel(self):
cancel_pcv_processing(self.name)
@frappe.whitelist()
def start_pcv_processing(docname: str):
if frappe.db.get_value("Process Period Closing Voucher", docname, "status") in ["Queued", "Running"]:
frappe.db.set_value("Process Period Closing Voucher", docname, "status", "Running")
if normal_balances := frappe.db.get_all(
"Process Period Closing Voucher Detail",
filters={"parent": docname, "status": "Queued"},
fields=["processing_date", "report_type", "parentfield"],
order_by="parentfield, idx, processing_date",
limit=4,
):
if not is_scheduler_inactive():
for x in normal_balances:
frappe.db.set_value(
"Process Period Closing Voucher Detail",
{
"processing_date": x.processing_date,
"parent": docname,
"report_type": x.report_type,
"parentfield": x.parentfield,
},
"status",
"Running",
)
frappe.enqueue(
method="erpnext.accounts.doctype.process_period_closing_voucher.process_period_closing_voucher.process_individual_date",
queue="long",
timeout="3600",
is_async=True,
enqueue_after_commit=True,
docname=docname,
date=x.processing_date,
report_type=x.report_type,
parentfield=x.parentfield,
)
else:
frappe.db.set_value("Process Period Closing Voucher", docname, "status", "Completed")
@frappe.whitelist()
def pause_pcv_processing(docname: str):
ppcv = qb.DocType("Process Period Closing Voucher")
qb.update(ppcv).set(ppcv.status, "Paused").where(ppcv.name.eq(docname)).run()
if queued_dates := frappe.db.get_all(
"Process Period Closing Voucher Detail",
filters={"parent": docname, "status": "Queued"},
pluck="name",
):
ppcvd = qb.DocType("Process Period Closing Voucher Detail")
qb.update(ppcvd).set(ppcvd.status, "Paused").where(ppcvd.name.isin(queued_dates)).run()
@frappe.whitelist()
def cancel_pcv_processing(docname: str):
ppcv = qb.DocType("Process Period Closing Voucher")
qb.update(ppcv).set(ppcv.status, "Cancelled").where(ppcv.name.eq(docname)).run()
if queued_dates := frappe.db.get_all(
"Process Period Closing Voucher Detail",
filters={"parent": docname, "status": "Queued"},
pluck="name",
):
ppcvd = qb.DocType("Process Period Closing Voucher Detail")
qb.update(ppcvd).set(ppcvd.status, "Cancelled").where(ppcvd.name.isin(queued_dates)).run()
@frappe.whitelist()
def resume_pcv_processing(docname: str):
ppcv = qb.DocType("Process Period Closing Voucher")
qb.update(ppcv).set(ppcv.status, "Running").where(ppcv.name.eq(docname)).run()
if paused_dates := frappe.db.get_all(
"Process Period Closing Voucher Detail",
filters={"parent": docname, "status": "Paused"},
pluck="name",
):
ppcvd = qb.DocType("Process Period Closing Voucher Detail")
qb.update(ppcvd).set(ppcvd.status, "Queued").where(ppcvd.name.isin(paused_dates)).run()
start_pcv_processing(docname)
def update_default_dimensions(dimension_fields, gl_entry, dimension_values):
for i, dimension in enumerate(dimension_fields):
gl_entry[dimension] = dimension_values[i]
def get_gle_for_pl_account(pcv, acc, balances, dimensions):
balance_in_account_currency = flt(balances.debit_in_account_currency) - flt(
balances.credit_in_account_currency
)
balance_in_company_currency = flt(balances.debit) - flt(balances.credit)
gl_entry = frappe._dict(
{
"company": pcv.company,
"posting_date": pcv.period_end_date,
"account": acc,
"account_currency": balances.account_currency,
"debit_in_account_currency": abs(balance_in_account_currency)
if balance_in_account_currency < 0
else 0,
"debit": abs(balance_in_company_currency) if balance_in_company_currency < 0 else 0,
"credit_in_account_currency": abs(balance_in_account_currency)
if balance_in_account_currency > 0
else 0,
"credit": abs(balance_in_company_currency) if balance_in_company_currency > 0 else 0,
"is_period_closing_voucher_entry": 1,
"voucher_type": "Period Closing Voucher",
"voucher_no": pcv.name,
"fiscal_year": pcv.fiscal_year,
"remarks": pcv.remarks,
"is_opening": "No",
}
)
# update dimensions
update_default_dimensions(get_dimensions(), gl_entry, dimensions)
return gl_entry
def get_gle_for_closing_account(pcv, dimension_balance, dimensions):
balance_in_company_currency = flt(dimension_balance.balance_in_company_currency)
debit = balance_in_company_currency if balance_in_company_currency > 0 else 0
credit = abs(balance_in_company_currency) if balance_in_company_currency < 0 else 0
gl_entry = frappe._dict(
{
"company": pcv.company,
"posting_date": pcv.period_end_date,
"account": pcv.closing_account_head,
"account_currency": frappe.db.get_value("Account", pcv.closing_account_head, "account_currency"),
"debit_in_account_currency": debit,
"debit": debit,
"credit_in_account_currency": credit,
"credit": credit,
"is_period_closing_voucher_entry": 1,
"voucher_type": "Period Closing Voucher",
"voucher_no": pcv.name,
"fiscal_year": pcv.fiscal_year,
"remarks": pcv.remarks,
"is_opening": "No",
}
)
# update dimensions
update_default_dimensions(get_dimensions(), gl_entry, dimensions)
return gl_entry
@frappe.whitelist()
def schedule_next_date(docname: str):
if to_process := frappe.db.get_all(
"Process Period Closing Voucher Detail",
filters={"parent": docname, "status": "Queued"},
fields=["processing_date", "report_type", "parentfield"],
order_by="parentfield, idx, processing_date",
limit=1,
):
if not is_scheduler_inactive():
frappe.db.set_value(
"Process Period Closing Voucher Detail",
{
"processing_date": to_process[0].processing_date,
"parent": docname,
"report_type": to_process[0].report_type,
"parentfield": to_process[0].parentfield,
},
"status",
"Running",
)
frappe.enqueue(
method="erpnext.accounts.doctype.process_period_closing_voucher.process_period_closing_voucher.process_individual_date",
queue="long",
timeout="3600",
is_async=True,
enqueue_after_commit=True,
docname=docname,
date=to_process[0].processing_date,
report_type=to_process[0].report_type,
parentfield=to_process[0].parentfield,
)
else:
ppcvd = qb.DocType("Process Period Closing Voucher Detail")
total_no_of_dates = (
qb.from_(ppcvd).select(Count(ppcvd.star)).where(ppcvd.parent.eq(docname)).run()[0][0]
)
completed = (
qb.from_(ppcvd)
.select(Count(ppcvd.star))
.where(ppcvd.parent.eq(docname) & ppcvd.status.eq("Completed"))
.run()[0][0]
)
# Ensure both normal and opening balances are processed for all dates
if total_no_of_dates == completed:
summarize_and_post_ledger_entries(docname)
def make_dict_json_compliant(dimension_wise_balance) -> dict:
"""
convert tuple -> str
JSON doesn't support dictionary with tuple keys
"""
converted_dict = {}
for k, v in dimension_wise_balance.items():
str_key = [str(x) for x in k]
str_key = ",".join(str_key)
converted_dict[str_key] = v
return converted_dict
def get_consolidated_gles(balances, report_type) -> list:
gl_entries = []
for x in balances:
if x.report_type == report_type:
closing_balances = [frappe._dict(gle) for gle in frappe.json.loads(x.closing_balance)]
gl_entries.extend(closing_balances)
return gl_entries
def get_gl_entries(docname):
"""
Calculate total closing balance of all P&L accounts across PCV start and end date
"""
ppcv = frappe.get_doc("Process Period Closing Voucher", docname)
# calculate balance
gl_entries = get_consolidated_gles(ppcv.normal_balances, "Profit and Loss")
pl_dimension_wise_acc_balance = build_dimension_wise_balance_dict(gl_entries)
# save
json_dict = make_dict_json_compliant(pl_dimension_wise_acc_balance)
frappe.db.set_value(
"Process Period Closing Voucher", docname, "p_l_closing_balance", frappe.json.dumps(json_dict)
)
# build gl map
pcv = frappe.get_doc("Period Closing Voucher", ppcv.parent_pcv)
pl_accounts_reverse_gle = []
closing_account_gle = []
for dimensions, account_balances in pl_dimension_wise_acc_balance.items():
for acc, balances in account_balances.items():
balance_in_company_currency = flt(balances.debit) - flt(balances.credit)
if balance_in_company_currency:
pl_accounts_reverse_gle.append(get_gle_for_pl_account(pcv, acc, balances, dimensions))
closing_account_gle.append(get_gle_for_closing_account(pcv, account_balances["balances"], dimensions))
return pl_accounts_reverse_gle, closing_account_gle
def calculate_balance_sheet_balance(docname):
"""
Calculate total closing balance of all P&L accounts across PCV start and end date.
If it is first PCV, opening entries are also considered
"""
ppcv = frappe.get_doc("Process Period Closing Voucher", docname)
gl_entries = get_consolidated_gles(ppcv.normal_balances + ppcv.z_opening_balances, "Balance Sheet")
# build dimension wise dictionary from all GLE's
bs_dimension_wise_acc_balance = build_dimension_wise_balance_dict(gl_entries)
# save
json_dict = make_dict_json_compliant(bs_dimension_wise_acc_balance)
frappe.db.set_value(
"Process Period Closing Voucher", docname, "bs_closing_balance", frappe.json.dumps(json_dict)
)
return bs_dimension_wise_acc_balance
def get_p_l_closing_entries(pl_gles, pcv):
pl_closing_entries = copy.deepcopy(pl_gles)
for d in pl_gles:
# reverse debit and credit
gle_copy = copy.deepcopy(d)
gle_copy.debit = d.credit
gle_copy.credit = d.debit
gle_copy.debit_in_account_currency = d.credit_in_account_currency
gle_copy.credit_in_account_currency = d.debit_in_account_currency
gle_copy.is_period_closing_voucher_entry = 0
gle_copy.period_closing_voucher = pcv.name
pl_closing_entries.append(gle_copy)
return pl_closing_entries
def get_bs_closing_entries(dimension_wise_balance, pcv):
closing_entries = []
for dimensions, account_balances in dimension_wise_balance.items():
for acc, balances in account_balances.items():
balance_in_company_currency = flt(balances.debit) - flt(balances.credit)
if acc != "balances" and balance_in_company_currency:
closing_entries.append(get_closing_entry(pcv, acc, balances, dimensions))
return closing_entries
def get_closing_account_closing_entry(closing_account_gle, pcv):
closing_entries_for_closing_account = copy.deepcopy(closing_account_gle)
for d in closing_entries_for_closing_account:
d.period_closing_voucher = pcv.name
return closing_entries_for_closing_account
def summarize_and_post_ledger_entries(docname):
# P&L accounts
pl_accounts_reverse_gle, closing_account_gle = get_gl_entries(docname)
gl_entries = pl_accounts_reverse_gle + closing_account_gle
from erpnext.accounts.general_ledger import make_gl_entries
if gl_entries:
make_gl_entries(gl_entries, merge_entries=False)
pcv_name = frappe.db.get_value("Process Period Closing Voucher", docname, "parent_pcv")
pcv = frappe.get_doc("Period Closing Voucher", pcv_name)
# Balance sheet accounts
bs_dimension_wise_acc_balance = calculate_balance_sheet_balance(docname)
pl_closing_entries = get_p_l_closing_entries(pl_accounts_reverse_gle, pcv)
bs_closing_entries = get_bs_closing_entries(bs_dimension_wise_acc_balance, pcv)
closing_entries_for_closing_account = get_closing_account_closing_entry(closing_account_gle, pcv)
closing_entries = pl_closing_entries + bs_closing_entries + closing_entries_for_closing_account
make_closing_entries(closing_entries, pcv.name, pcv.company, pcv.period_end_date)
frappe.db.set_value("Period Closing Voucher", pcv.name, "gle_processing_status", "Completed")
frappe.db.set_value("Process Period Closing Voucher", docname, "status", "Completed")
def get_closing_entry(pcv, account, balances, dimensions):
closing_entry = frappe._dict(
{
"company": pcv.company,
"closing_date": pcv.period_end_date,
"period_closing_voucher": pcv.name,
"account": account,
"account_currency": balances.account_currency,
"debit_in_account_currency": flt(balances.debit_in_account_currency),
"debit": flt(balances.debit),
"credit_in_account_currency": flt(balances.credit_in_account_currency),
"credit": flt(balances.credit),
"is_period_closing_voucher_entry": 0,
}
)
# update dimensions
update_default_dimensions(get_dimensions(), closing_entry, dimensions)
return closing_entry
def get_dimensions():
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import (
get_accounting_dimensions,
)
default_dimensions = ["cost_center", "finance_book", "project"]
dimensions = default_dimensions + get_accounting_dimensions()
return dimensions
def get_dimension_key(res):
return tuple([res.get(dimension) for dimension in get_dimensions()])
def build_dimension_wise_balance_dict(gl_entries):
dimension_balances = frappe._dict()
for x in gl_entries:
dimension_key = get_dimension_key(x)
dimension_balances.setdefault(dimension_key, frappe._dict()).setdefault(
x.account,
frappe._dict(
{
"debit_in_account_currency": 0,
"credit_in_account_currency": 0,
"debit": 0,
"credit": 0,
"account_currency": x.account_currency,
}
),
)
dimension_balances[dimension_key][x.account].debit_in_account_currency += flt(
x.debit_in_account_currency
)
dimension_balances[dimension_key][x.account].credit_in_account_currency += flt(
x.credit_in_account_currency
)
dimension_balances[dimension_key][x.account].debit += flt(x.debit)
dimension_balances[dimension_key][x.account].credit += flt(x.credit)
# dimension-wise total balances
dimension_balances[dimension_key].setdefault(
"balances",
frappe._dict(
{
"balance_in_account_currency": 0,
"balance_in_company_currency": 0,
}
),
)
balance_in_account_currency = flt(x.debit_in_account_currency) - flt(x.credit_in_account_currency)
balance_in_company_currency = flt(x.debit) - flt(x.credit)
dimension_balances[dimension_key][
"balances"
].balance_in_account_currency += balance_in_account_currency
dimension_balances[dimension_key][
"balances"
].balance_in_company_currency += balance_in_company_currency
return dimension_balances
def process_individual_date(docname: str, date, report_type, parentfield):
current_date_status = frappe.db.get_value(
"Process Period Closing Voucher Detail",
{"processing_date": date, "report_type": report_type, "parentfield": parentfield},
"status",
)
if current_date_status != "Running":
return
pcv_name = frappe.db.get_value("Process Period Closing Voucher", docname, "parent_pcv")
company = frappe.db.get_value("Period Closing Voucher", pcv_name, "company")
dimensions = get_dimensions()
accounts = frappe.db.get_all(
"Account", filters={"company": company, "report_type": report_type}, pluck="name"
)
# summarize
gle = qb.DocType("GL Entry")
query = qb.from_(gle).select(gle.account)
for dim in dimensions:
query = query.select(gle[dim])
query = query.select(
Sum(gle.debit).as_("debit"),
Sum(gle.credit).as_("credit"),
Sum(gle.debit_in_account_currency).as_("debit_in_account_currency"),
Sum(gle.credit_in_account_currency).as_("credit_in_account_currency"),
gle.account_currency,
).where(
(gle.company.eq(company))
& (gle.is_cancelled.eq(0))
& (gle.posting_date.eq(date))
& (gle.account.isin(accounts))
)
if parentfield == "z_opening_balances":
query = query.where(gle.is_opening.eq("Yes"))
query = query.groupby(gle.account)
for dim in dimensions:
query = query.groupby(gle[dim])
res = query.run(as_dict=True)
# save results
frappe.db.set_value(
"Process Period Closing Voucher Detail",
{"processing_date": date, "parent": docname, "report_type": report_type, "parentfield": parentfield},
"closing_balance",
frappe.json.dumps(res),
)
frappe.db.set_value(
"Process Period Closing Voucher Detail",
{"processing_date": date, "parent": docname, "report_type": report_type, "parentfield": parentfield},
"status",
"Completed",
)
# chain call
schedule_next_date(docname)

View File

@@ -0,0 +1,4 @@
# Copyright (c) 2025, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
# import frappe

View File

@@ -0,0 +1,58 @@
{
"actions": [],
"allow_rename": 1,
"creation": "2025-10-01 15:58:17.544153",
"doctype": "DocType",
"engine": "InnoDB",
"field_order": [
"processing_date",
"report_type",
"status",
"closing_balance"
],
"fields": [
{
"fieldname": "processing_date",
"fieldtype": "Date",
"in_list_view": 1,
"label": "Processing Date"
},
{
"default": "Queued",
"fieldname": "status",
"fieldtype": "Select",
"in_list_view": 1,
"label": "Status",
"options": "Queued\nRunning\nPaused\nCompleted\nCancelled"
},
{
"fieldname": "closing_balance",
"fieldtype": "JSON",
"in_list_view": 1,
"label": "Closing Balance"
},
{
"default": "Profit and Loss",
"fieldname": "report_type",
"fieldtype": "Select",
"in_list_view": 1,
"label": "Report Type",
"options": "Profit and Loss\nBalance Sheet"
}
],
"grid_page_length": 50,
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2025-10-20 12:03:59.106931",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Process Period Closing Voucher Detail",
"owner": "Administrator",
"permissions": [],
"row_format": "Dynamic",
"rows_threshold_for_grid_search": 20,
"sort_field": "creation",
"sort_order": "DESC",
"states": []
}

View File

@@ -0,0 +1,26 @@
# Copyright (c) 2025, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
# import frappe
from frappe.model.document import Document
class ProcessPeriodClosingVoucherDetail(Document):
# begin: auto-generated types
# This code is auto-generated. Do not modify anything in this block.
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from frappe.types import DF
closing_balance: DF.JSON | None
parent: DF.Data
parentfield: DF.Data
parenttype: DF.Data
processing_date: DF.Date | None
report_type: DF.Literal["Profit and Loss", "Balance Sheet"]
status: DF.Literal["Queued", "Running", "Paused", "Completed", "Cancelled"]
# end: auto-generated types
pass

View File

@@ -12,6 +12,7 @@ erpnext.buying.setup_buying_controller();
erpnext.accounts.PurchaseInvoice = class PurchaseInvoice extends erpnext.buying.BuyingController {
setup(doc) {
this.setup_accounting_dimension_triggers();
this.setup_posting_date_time_check();
super.setup(doc);
@@ -125,8 +126,8 @@ erpnext.accounts.PurchaseInvoice = class PurchaseInvoice extends erpnext.buying.
}
}
if (doc.outstanding_amount > 0 && !cint(doc.is_return) && !doc.on_hold) {
cur_frm.add_custom_button(
if (doc.docstatus == 1 && doc.outstanding_amount > 0 && !cint(doc.is_return) && !doc.on_hold) {
this.frm.add_custom_button(
__("Payment Request"),
function () {
me.make_payment_request();

View File

@@ -2150,19 +2150,16 @@ class TestPurchaseInvoice(FrappeTestCase, StockTestMixin):
rate = flt(sle.stock_value_difference) / flt(sle.actual_qty)
self.assertAlmostEqual(rate, 500)
@change_settings("Accounts Settings", {"automatically_fetch_payment_terms": 1})
def test_payment_allocation_for_payment_terms(self):
from erpnext.buying.doctype.purchase_order.test_purchase_order import (
create_pr_against_po,
create_purchase_order,
)
from erpnext.selling.doctype.sales_order.test_sales_order import (
automatically_fetch_payment_terms,
)
from erpnext.stock.doctype.purchase_receipt.purchase_receipt import (
make_purchase_invoice as make_pi_from_pr,
)
automatically_fetch_payment_terms()
frappe.db.set_value(
"Payment Terms Template",
"_Test Payment Term Template",
@@ -2188,7 +2185,6 @@ class TestPurchaseInvoice(FrappeTestCase, StockTestMixin):
pi = make_pi_from_pr(pr.name)
self.assertEqual(pi.payment_schedule[0].payment_amount, 1000)
automatically_fetch_payment_terms(enable=0)
frappe.db.set_value(
"Payment Terms Template",
"_Test Payment Term Template",
@@ -2644,6 +2640,38 @@ class TestPurchaseInvoice(FrappeTestCase, StockTestMixin):
frappe.db.set_single_value("Buying Settings", "maintain_same_rate", 1)
@change_settings(
"Buying Settings", {"maintain_same_rate": 0, "set_landed_cost_based_on_purchase_invoice_rate": 1}
)
def test_pr_status_rate_adjusted_from_pi(self):
pr = make_purchase_receipt(qty=5, rate=100)
pi = create_purchase_invoice_from_receipt(pr.name)
pi.submit()
pr.reload()
# Inital check
self.assertEqual(pr.status, "Completed")
pi.reload()
pi.cancel()
pi = create_purchase_invoice_from_receipt(pr.name)
pi.items[0].rate = 80
pi.submit()
pr.reload()
# Test 1 : Adjustment amount is negative
self.assertEqual(pr.status, "Completed")
pi.reload()
pi.cancel()
pi = create_purchase_invoice_from_receipt(pr.name)
pi.items[0].rate = 120
pi.submit()
pr.reload()
# Test 2 : Adjustment amount is positive
self.assertEqual(pr.status, "Completed")
def test_opening_invoice_rounding_adjustment_validation(self):
pi = make_purchase_invoice(do_not_save=1)
pi.items[0].rate = 99.98

View File

@@ -912,7 +912,8 @@
"label": "Rejected Serial and Batch Bundle",
"no_copy": 1,
"options": "Serial and Batch Bundle",
"print_hide": 1
"print_hide": 1,
"search_index": 1
},
{
"fieldname": "wip_composite_asset",
@@ -983,7 +984,7 @@
"idx": 1,
"istable": 1,
"links": [],
"modified": "2025-03-12 16:33:13.453290",
"modified": "2025-10-14 13:01:54.441511",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice Item",
@@ -993,4 +994,4 @@
"sort_field": "modified",
"sort_order": "DESC",
"states": []
}
}

View File

@@ -14,6 +14,7 @@ erpnext.accounts.SalesInvoiceController = class SalesInvoiceController extends (
erpnext.selling.SellingController
) {
setup(doc) {
this.setup_accounting_dimension_triggers();
this.setup_posting_date_time_check();
super.setup(doc);
this.frm.make_methods = {
@@ -798,6 +799,15 @@ frappe.ui.form.on("Sales Invoice", {
},
};
};
frm.set_query("sales_person", "sales_team", function () {
return {
filters: {
is_group: 0,
enabled: 1,
},
};
});
},
onload: function (frm) {
frm.redemption_conversion_factor = null;

View File

@@ -1349,7 +1349,11 @@ class SalesInvoice(SellingController):
)
for item in self.get("items"):
if flt(item.base_net_amount, item.precision("base_net_amount")) or item.is_fixed_asset:
if (
flt(item.base_net_amount, item.precision("base_net_amount"))
or item.is_fixed_asset
or enable_discount_accounting
):
# Do not book income for transfer within same company
if self.is_internal_transfer():
continue
@@ -2411,6 +2415,9 @@ def make_inter_company_transaction(doctype, source_name, target_doc=None):
target.purchase_order = source.purchase_order
target.po_detail = source.purchase_order_item
if (source.get("serial_no") or source.get("batch_no")) and not source.get("serial_and_batch_bundle"):
target.use_serial_batch_fields = 1
item_field_map = {
"doctype": target_doctype + " Item",
"field_no_map": ["income_account", "expense_account", "cost_center", "warehouse"],

View File

@@ -483,18 +483,23 @@ class Subscription(Document):
return invoice
def get_items_from_plans(self, plans: list[dict[str, str]], prorate: bool | None = None) -> list[dict]:
def get_items_from_plans(self, plans: list[dict[str, str]], prorate: int = 0) -> list[dict]:
"""
Returns the `Item`s linked to `Subscription Plan`
"""
if prorate is None:
prorate = False
prorate_factor = 1
if prorate:
prorate_factor = get_prorata_factor(
self.current_invoice_end,
self.current_invoice_start,
cint(self.generate_invoice_at == "Beginning of the current subscription period"),
cint(
self.generate_invoice_at
in [
"Beginning of the current subscription period",
"Days before the current subscription period",
]
),
)
items = []
@@ -511,33 +516,19 @@ class Subscription(Document):
deferred = frappe.db.get_value("Item", item_code, deferred_field)
if not prorate:
item = {
"item_code": item_code,
"qty": plan.qty,
"rate": get_plan_rate(
plan.plan,
plan.qty,
party,
self.current_invoice_start,
self.current_invoice_end,
),
"cost_center": plan_doc.cost_center,
}
else:
item = {
"item_code": item_code,
"qty": plan.qty,
"rate": get_plan_rate(
plan.plan,
plan.qty,
party,
self.current_invoice_start,
self.current_invoice_end,
prorate_factor,
),
"cost_center": plan_doc.cost_center,
}
item = {
"item_code": item_code,
"qty": plan.qty,
"rate": get_plan_rate(
plan.plan,
plan.qty,
party,
self.current_invoice_start,
self.current_invoice_end,
prorate_factor,
),
"cost_center": plan_doc.cost_center,
}
if deferred:
item.update(

View File

@@ -8,6 +8,7 @@ from frappe.utils.data import (
add_days,
add_months,
add_to_date,
add_years,
cint,
date_diff,
flt,
@@ -555,6 +556,33 @@ class TestSubscription(FrappeTestCase):
subscription.reload()
self.assertEqual(len(subscription.invoices), 0)
def test_invoice_generation_days_before_subscription_period_with_prorate(self):
settings = frappe.get_single("Subscription Settings")
settings.prorate = 1
settings.save()
create_plan(
plan_name="_Test Plan Name 5",
cost=1000,
billing_interval="Year",
billing_interval_count=1,
currency="INR",
)
start_date = add_days(nowdate(), 2)
subscription = create_subscription(
start_date=start_date,
party_type="Supplier",
party="_Test Supplier",
generate_invoice_at="Days before the current subscription period",
generate_new_invoices_past_due_date=1,
number_of_days=2,
plans=[{"plan": "_Test Plan Name 5", "qty": 1}],
)
subscription.process(nowdate())
self.assertEqual(len(subscription.invoices), 1)
def make_plans():
create_plan(plan_name="_Test Plan Name", cost=900, currency="INR")

View File

@@ -85,6 +85,9 @@ def get_party_details(inv):
if inv.doctype == "Sales Invoice":
party_type = "Customer"
party = inv.customer
elif inv.doctype == "Journal Entry":
party_type = inv.party_type
party = inv.party
else:
party_type = "Supplier"
party = inv.supplier
@@ -155,7 +158,7 @@ def get_party_tax_withholding_details(inv, tax_withholding_category=None):
party_type, parties, inv, tax_details, posting_date, pan_no
)
if party_type == "Supplier":
if party_type == "Supplier" or inv.doctype == "Journal Entry":
tax_row = get_tax_row_for_tds(tax_details, tax_amount)
else:
tax_row = get_tax_row_for_tcs(inv, tax_details, tax_amount, tax_deducted)
@@ -346,7 +349,10 @@ def get_tax_amount(party_type, parties, inv, tax_details, posting_date, pan_no=N
elif party_type == "Customer":
if tax_deducted:
# if already TCS is charged, then amount will be calculated based on 'Previous Row Total'
tax_amount = 0
if inv.doctype == "Sales Invoice":
tax_amount = 0
else:
tax_amount = inv.base_tax_withholding_net_total * tax_details.rate / 100
else:
# if no TCS has been charged in FY,
# then chargeable value is "prev invoices + advances - advance_adjusted" value which cross the threshold
@@ -718,7 +724,7 @@ def get_advance_adjusted_in_invoice(inv):
def get_invoice_total_without_tcs(inv, tax_details):
tcs_tax_row = [d for d in inv.taxes if d.account_head == tax_details.account_head]
tcs_tax_row = [d for d in inv.get("taxes") or [] if d.account_head == tax_details.account_head]
tcs_tax_row_amount = tcs_tax_row[0].base_tax_amount if tcs_tax_row else 0
return inv.grand_total - tcs_tax_row_amount

View File

@@ -848,6 +848,90 @@ class TestTaxWithholdingCategory(FrappeTestCase):
self.assertEqual(payment.taxes[0].tax_amount, 6000)
self.assertEqual(payment.taxes[0].allocated_amount, 6000)
def test_tds_on_journal_entry_for_supplier(self):
"""Test TDS deduction for Supplier in Debit Note"""
frappe.db.set_value(
"Supplier", "Test TDS Supplier", "tax_withholding_category", "Cumulative Threshold TDS"
)
jv = make_journal_entry_with_tax_withholding(
party_type="Supplier",
party="Test TDS Supplier",
voucher_type="Debit Note",
amount=50000,
save=False,
)
jv.apply_tds = 1
jv.tax_withholding_category = "Cumulative Threshold TDS"
jv.save()
# Again saving should not change tds amount
jv.user_remark = "Test TDS on Journal Entry for Supplier"
jv.save()
jv.submit()
# TDS = 50000 * 10% = 5000
self.assertEqual(len(jv.accounts), 3)
# Find TDS account row
tds_row = None
supplier_row = None
for row in jv.accounts:
if row.account == "TDS - _TC":
tds_row = row
elif row.party == "Test TDS Supplier":
supplier_row = row
self.assertEqual(tds_row.credit, 5000)
self.assertEqual(tds_row.debit, 0)
# Supplier amount should be reduced by TDS
self.assertEqual(supplier_row.credit, 45000)
jv.cancel()
def test_tcs_on_journal_entry_for_customer(self):
"""Test TCS collection for Customer in Credit Note"""
frappe.db.set_value(
"Customer", "Test TCS Customer", "tax_withholding_category", "Cumulative Threshold TCS"
)
# Create Credit Note with amount exceeding threshold
jv = make_journal_entry_with_tax_withholding(
party_type="Customer",
party="Test TCS Customer",
voucher_type="Credit Note",
amount=50000,
save=False,
)
jv.apply_tds = 1
jv.tax_withholding_category = "Cumulative Threshold TCS"
jv.save()
# Again saving should not change tds amount
jv.user_remark = "Test TCS on Journal Entry for Customer"
jv.save()
jv.submit()
# Assert TCS calculation (10% on amount above threshold of 30000)
self.assertEqual(len(jv.accounts), 3)
# Find TCS account row
tcs_row = None
customer_row = None
for row in jv.accounts:
if row.account == "TCS - _TC":
tcs_row = row
elif row.party == "Test TCS Customer":
customer_row = row
# TCS should be credited (liability to government)
self.assertEqual(tcs_row.credit, 2000) # above threshold 20000*10%
self.assertEqual(tcs_row.debit, 0)
# Customer amount should be increased by TCS
self.assertEqual(customer_row.debit, 52000)
jv.cancel()
def cancel_invoices():
purchase_invoices = frappe.get_all(
@@ -996,6 +1080,88 @@ def create_payment_entry(**args):
return pe
def make_journal_entry_with_tax_withholding(
party_type,
party,
voucher_type,
amount,
cost_center=None,
posting_date=None,
save=True,
submit=False,
):
"""Helper function to create Journal Entry for tax withholding"""
if not cost_center:
cost_center = "_Test Cost Center - _TC"
jv = frappe.new_doc("Journal Entry")
jv.posting_date = posting_date or today()
jv.company = "_Test Company"
jv.voucher_type = voucher_type
jv.multi_currency = 0
if party_type == "Supplier":
# Debit Note: Expense Dr, Supplier Cr
expense_account = "Stock Received But Not Billed - _TC"
party_account = "Creditors - _TC"
jv.append(
"accounts",
{
"account": expense_account,
"cost_center": cost_center,
"debit_in_account_currency": amount,
"exchange_rate": 1,
},
)
jv.append(
"accounts",
{
"account": party_account,
"party_type": party_type,
"party": party,
"cost_center": cost_center,
"credit_in_account_currency": amount,
"exchange_rate": 1,
},
)
else: # Customer
# Credit Note: Customer Dr, Income Cr
party_account = "Debtors - _TC"
income_account = "Sales - _TC"
jv.append(
"accounts",
{
"account": party_account,
"party_type": party_type,
"party": party,
"cost_center": cost_center,
"debit_in_account_currency": amount,
"exchange_rate": 1,
},
)
jv.append(
"accounts",
{
"account": income_account,
"cost_center": cost_center,
"credit_in_account_currency": amount,
"exchange_rate": 1,
},
)
if save or submit:
jv.insert()
if submit:
jv.submit()
return jv
def create_records():
# create a new suppliers
for name in [

View File

@@ -289,7 +289,9 @@ def merge_similar_entries(gl_map, precision=None):
company_currency = erpnext.get_company_currency(company)
if not precision:
precision = get_field_precision(frappe.get_meta("GL Entry").get_field("debit"), company_currency)
precision = get_field_precision(
frappe.get_meta("GL Entry").get_field("debit"), currency=company_currency
)
# filter zero debit and credit entries
merged_gl_map = filter(
@@ -648,6 +650,7 @@ def make_reverse_gl_entries(
adv_adj=False,
update_outstanding="Yes",
partial_cancel=False,
posting_date=None,
):
"""
Get original gl entries of the voucher
@@ -745,6 +748,8 @@ def make_reverse_gl_entries(
if immutable_ledger_enabled:
new_gle["is_cancelled"] = 0
new_gle["posting_date"] = frappe.form_dict.get("posting_date") or getdate()
elif posting_date:
new_gle["posting_date"] = posting_date
if new_gle["debit"] or new_gle["credit"]:
make_entry(new_gle, adv_adj, "Yes")

View File

@@ -26,16 +26,13 @@ frappe.query_reports["Accounts Payable"] = {
{
fieldname: "cost_center",
label: __("Cost Center"),
fieldtype: "Link",
options: "Cost Center",
get_query: () => {
var company = frappe.query_report.get_filter_value("company");
return {
filters: {
company: company,
},
};
fieldtype: "MultiSelectList",
get_data: function (txt) {
return frappe.db.get_link_options("Cost Center", txt, {
company: frappe.query_report.get_filter_value("company"),
});
},
options: "Cost Center",
},
{
fieldname: "party_account",

View File

@@ -45,16 +45,13 @@ frappe.query_reports["Accounts Payable Summary"] = {
{
fieldname: "cost_center",
label: __("Cost Center"),
fieldtype: "Link",
options: "Cost Center",
get_query: () => {
var company = frappe.query_report.get_filter_value("company");
return {
filters: {
company: company,
},
};
fieldtype: "MultiSelectList",
get_data: function (txt) {
return frappe.db.get_link_options("Cost Center", txt, {
company: frappe.query_report.get_filter_value("company"),
});
},
options: "Cost Center",
},
{
fieldname: "party_type",

View File

@@ -28,16 +28,13 @@ frappe.query_reports["Accounts Receivable"] = {
{
fieldname: "cost_center",
label: __("Cost Center"),
fieldtype: "Link",
options: "Cost Center",
get_query: () => {
var company = frappe.query_report.get_filter_value("company");
return {
filters: {
company: company,
},
};
fieldtype: "MultiSelectList",
get_data: function (txt) {
return frappe.db.get_link_options("Cost Center", txt, {
company: frappe.query_report.get_filter_value("company"),
});
},
options: "Cost Center",
},
{
fieldname: "party_type",

View File

@@ -15,6 +15,7 @@ from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import (
get_accounting_dimensions,
get_dimension_with_children,
)
from erpnext.accounts.report.financial_statements import get_cost_centers_with_children
from erpnext.accounts.utils import (
build_qb_match_conditions,
get_advance_payment_doctypes,
@@ -664,7 +665,16 @@ class ReceivablePayableReport:
invoiced = d.base_payment_amount
paid_amount = d.base_paid_amount
if company_currency == d.party_account_currency or self.filters.get("in_party_currency"):
in_party_currency = self.filters.get("in_party_currency")
# company, billing, and party account currencies are the same
if company_currency == d.currency and company_currency == d.party_account_currency:
in_party_currency = False
# When filtered by party currency and the billing currency not matches the party account currency
if in_party_currency and d.currency != d.party_account_currency:
in_party_currency = False
if in_party_currency:
invoiced = d.payment_amount
paid_amount = d.paid_amount
@@ -985,11 +995,7 @@ class ReceivablePayableReport:
self.add_accounting_dimensions_filters()
def get_cost_center_conditions(self):
lft, rgt = frappe.db.get_value("Cost Center", self.filters.cost_center, ["lft", "rgt"])
cost_center_list = [
center.name
for center in frappe.get_list("Cost Center", filters={"lft": (">=", lft), "rgt": ("<=", rgt)})
]
cost_center_list = get_cost_centers_with_children(self.filters.cost_center)
self.qb_selection_filter.append(self.ple.cost_center.isin(cost_center_list))
def add_common_filters(self):
@@ -1270,7 +1276,7 @@ class ReceivablePayableReport:
def setup_ageing_columns(self):
# for charts
self.ageing_column_labels = []
ranges = [*self.ranges, "Above"]
ranges = [*self.ranges, _("Above")]
prev_range_value = 0
for idx, curr_range_value in enumerate(ranges):

View File

@@ -199,6 +199,81 @@ class TestAccountsReceivable(AccountsTestMixin, FrappeTestCase):
row = report[1]
self.assertTrue(len(row) == 0)
@change_settings(
"Accounts Settings",
{"allow_multi_currency_invoices_against_single_party_account": 1},
)
def test_allow_multi_currency_invoices_against_single_party_account(self):
filters = {
"company": self.company,
"based_on_payment_terms": 1,
"report_date": today(),
"range": "30, 60, 90, 120",
"show_remarks": True,
"in_party_currency": 1,
}
# CASE 1: Company currency and party account currency are the same
si = self.create_sales_invoice(qty=1, no_payment_schedule=True, do_not_submit=True)
si.currency = "USD"
si.conversion_rate = 80
si.save().submit()
filters.update(
{
"party_type": "Customer",
"party": [self.customer],
}
)
report = execute(filters)
row = report[1][0]
expected_data = [8000, 8000, "No Remarks"] # Data in company currency
self.assertEqual(expected_data, [row.invoice_grand_total, row.invoiced, row.remarks])
# CASE 2: Transaction currency and party account currency are the same
self.create_customer(
"USD Customer", currency="USD", default_account=self.debtors_usd, company=self.company
)
si = create_sales_invoice(
item=self.item,
company=self.company,
customer=self.customer,
debit_to=self.debtors_usd,
posting_date=today(),
parent_cost_center=self.cost_center,
cost_center=self.cost_center,
rate=100,
currency="USD",
conversion_rate=80,
price_list_rate=100,
do_not_save=1,
)
si.save().submit()
filters.update(
{
"party_type": "Customer",
"party": [self.customer],
}
)
report = execute(filters)
row = report[1][0]
expected_data = [100, 100, "No Remarks"] # Data in Part Account Currency
self.assertEqual(expected_data, [row.invoice_grand_total, row.invoiced, row.remarks])
# View in Company currency
filters.pop("in_party_currency")
report = execute(filters)
row = report[1][0]
expected_data = [8000, 8000, "No Remarks"] # Data in Company Currency
self.assertEqual(expected_data, [row.invoice_grand_total, row.invoiced, row.remarks])
def test_accounts_receivable_with_partial_payment(self):
filters = {
"company": self.company,

View File

@@ -45,16 +45,13 @@ frappe.query_reports["Accounts Receivable Summary"] = {
{
fieldname: "cost_center",
label: __("Cost Center"),
fieldtype: "Link",
options: "Cost Center",
get_query: () => {
var company = frappe.query_report.get_filter_value("company");
return {
filters: {
company: company,
},
};
fieldtype: "MultiSelectList",
get_data: function (txt) {
return frappe.db.get_link_options("Cost Center", txt, {
company: frappe.query_report.get_filter_value("company"),
});
},
options: "Cost Center",
},
{
fieldname: "party_type",

View File

@@ -171,7 +171,7 @@ class AccountsReceivableSummary(ReceivablePayableReport):
self.add_column(_("Difference"), fieldname="diff")
self.setup_ageing_columns()
self.add_column(label="Total Amount Due", fieldname="total_due")
self.add_column(label=_("Total Amount Due"), fieldname="total_due")
if self.filters.show_future_payments:
self.add_column(label=_("Future Payment Amount"), fieldname="future_amount")

View File

@@ -119,6 +119,7 @@ def get_assets_details(assets):
fields = [
"name as asset",
"asset_name",
"gross_purchase_amount",
"opening_accumulated_depreciation",
"asset_category",
@@ -143,6 +144,12 @@ def get_columns():
"options": "Asset",
"width": 120,
},
{
"label": _("Asset Name"),
"fieldname": "asset_name",
"fieldtype": "Data",
"width": 140,
},
{
"label": _("Depreciation Date"),
"fieldname": "depreciation_date",

View File

@@ -273,6 +273,7 @@ def get_asset_value_adjustment_map_by_category(filters):
AND a.company = %(company)s
AND a.purchase_date <= %(to_date)s
AND gle.account = aca.fixed_asset_account
AND gle.is_opening = 'No'
GROUP BY a.asset_category
""",
{"from_date": filters.from_date, "to_date": filters.to_date, "company": filters.company},
@@ -354,7 +355,7 @@ def get_asset_details_for_grouped_by_category(filters):
# nosemgrep
return frappe.db.sql(
f"""
SELECT a.name,
SELECT a.name, a.asset_name,
ifnull(sum(case when a.purchase_date < %(from_date)s then
case when ifnull(a.disposal_date, 0) = 0 or a.disposal_date >= %(from_date)s then
a.gross_purchase_amount
@@ -543,6 +544,7 @@ def get_asset_value_adjustment_map(filters):
AND a.company = %(company)s
AND a.purchase_date <= %(to_date)s
AND gle.account = aca.fixed_asset_account
AND gle.is_opening = 'No'
GROUP BY a.name
""",
{"from_date": filters.from_date, "to_date": filters.to_date, "company": filters.company},
@@ -583,6 +585,14 @@ def get_columns(filters):
"width": 120,
}
)
columns.append(
{
"label": _("Asset Name"),
"fieldname": "asset_name",
"fieldtype": "Data",
"width": 140,
}
)
columns += [
{

View File

@@ -5,28 +5,33 @@ frappe.query_reports["Balance Sheet"] = $.extend({}, erpnext.financial_statement
erpnext.utils.add_dimensions("Balance Sheet", 10);
frappe.query_reports["Balance Sheet"]["filters"].push({
fieldname: "selected_view",
label: __("Select View"),
fieldtype: "Select",
options: [
{ value: "Report", label: __("Report View") },
{ value: "Growth", label: __("Growth View") },
],
default: "Report",
reqd: 1,
});
frappe.query_reports["Balance Sheet"]["filters"].push({
fieldname: "accumulated_values",
label: __("Accumulated Values"),
fieldtype: "Check",
default: 1,
});
frappe.query_reports["Balance Sheet"]["filters"].push({
fieldname: "include_default_book_entries",
label: __("Include Default FB Entries"),
fieldtype: "Check",
default: 1,
});
frappe.query_reports["Balance Sheet"]["filters"].push(
{
fieldname: "selected_view",
label: __("Select View"),
fieldtype: "Select",
options: [
{ value: "Report", label: __("Report View") },
{ value: "Growth", label: __("Growth View") },
],
default: "Report",
reqd: 1,
},
{
fieldname: "accumulated_values",
label: __("Accumulated Values"),
fieldtype: "Check",
default: 1,
},
{
fieldname: "include_default_book_entries",
label: __("Include Default FB Entries"),
fieldtype: "Check",
default: 1,
},
{
fieldname: "show_zero_values",
label: __("Show zero values"),
fieldtype: "Check",
}
);

View File

@@ -69,12 +69,18 @@ class PartyLedgerSummaryReport:
party_type = self.filters.party_type
doctype = qb.DocType(party_type)
party_details_fields = [
doctype.name.as_("party"),
f"{scrub(party_type)}_name",
f"{scrub(party_type)}_group",
]
if party_type == "Customer":
party_details_fields.append(doctype.territory)
conditions = self.get_party_conditions(doctype)
query = (
qb.from_(doctype)
.select(doctype.name.as_("party"), f"{scrub(party_type)}_name")
.where(Criterion.all(conditions))
)
query = qb.from_(doctype).select(*party_details_fields).where(Criterion.all(conditions))
from frappe.desk.reportview import build_match_conditions
@@ -153,6 +159,31 @@ class PartyLedgerSummaryReport:
credit_or_debit_note = "Credit Note" if self.filters.party_type == "Customer" else "Debit Note"
if self.filters.party_type == "Customer":
columns += [
{
"label": _("Customer Group"),
"fieldname": "customer_group",
"fieldtype": "Link",
"options": "Customer Group",
},
{
"label": _("Territory"),
"fieldname": "territory",
"fieldtype": "Link",
"options": "Territory",
},
]
else:
columns += [
{
"label": _("Supplier Group"),
"fieldname": "supplier_group",
"fieldtype": "Link",
"options": "Supplier Group",
}
]
columns += [
{
"label": _("Opening Balance"),
@@ -213,35 +244,6 @@ class PartyLedgerSummaryReport:
},
]
# Hidden columns for handling 'User Permissions'
if self.filters.party_type == "Customer":
columns += [
{
"label": _("Territory"),
"fieldname": "territory",
"fieldtype": "Link",
"options": "Territory",
"hidden": 1,
},
{
"label": _("Customer Group"),
"fieldname": "customer_group",
"fieldtype": "Link",
"options": "Customer Group",
"hidden": 1,
},
]
else:
columns += [
{
"label": _("Supplier Group"),
"fieldname": "supplier_group",
"fieldtype": "Link",
"options": "Supplier Group",
"hidden": 1,
}
]
return columns
def get_data(self):

View File

@@ -52,7 +52,7 @@ frappe.query_reports["Financial Ratios"] = {
},
],
formatter: function (value, row, column, data, default_formatter) {
let heading_ratios = ["Liquidity Ratios", "Solvency Ratios", "Turnover Ratios"];
let heading_ratios = [__("Liquidity Ratios"), __("Solvency Ratios"), __("Turnover Ratios")];
if (heading_ratios.includes(value)) {
value = $(`<span>${value}</span>`);
@@ -60,7 +60,7 @@ frappe.query_reports["Financial Ratios"] = {
value = $value.wrap("<p></p>").parent().html();
}
if (heading_ratios.includes(row[1].content) && column.fieldtype == "Float") {
if (heading_ratios.includes(row[1]?.content) && column.fieldtype == "Float") {
column.fieldtype = "Data";
}

View File

@@ -147,9 +147,9 @@ def get_gl_data(filters, period_list, years):
def add_liquidity_ratios(data, years, current_asset, current_liability, quick_asset):
precision = frappe.db.get_single_value("System Settings", "float_precision")
data.append({"ratio": "Liquidity Ratios"})
data.append({"ratio": _("Liquidity Ratios")})
ratio_data = [["Current Ratio", current_asset], ["Quick Ratio", quick_asset]]
ratio_data = [[_("Current Ratio"), current_asset], [_("Quick Ratio"), quick_asset]]
for d in ratio_data:
row = {
@@ -165,16 +165,16 @@ def add_solvency_ratios(
data, years, total_asset, total_liability, net_sales, cogs, total_income, total_expense
):
precision = frappe.db.get_single_value("System Settings", "float_precision")
data.append({"ratio": "Solvency Ratios"})
data.append({"ratio": _("Solvency Ratios")})
debt_equity_ratio = {"ratio": "Debt Equity Ratio"}
gross_profit_ratio = {"ratio": "Gross Profit Ratio"}
net_profit_ratio = {"ratio": "Net Profit Ratio"}
return_on_asset_ratio = {"ratio": "Return on Asset Ratio"}
return_on_equity_ratio = {"ratio": "Return on Equity Ratio"}
debt_equity_ratio = {"ratio": _("Debt Equity Ratio")}
gross_profit_ratio = {"ratio": _("Gross Profit Ratio")}
net_profit_ratio = {"ratio": _("Net Profit Ratio")}
return_on_asset_ratio = {"ratio": _("Return on Asset Ratio")}
return_on_equity_ratio = {"ratio": _("Return on Equity Ratio")}
for year in years:
profit_after_tax = flt(total_income.get(year)) + flt(total_expense.get(year))
profit_after_tax = flt(total_income.get(year)) - flt(total_expense.get(year))
share_holder_fund = flt(total_asset.get(year)) - flt(total_liability.get(year))
debt_equity_ratio[year] = calculate_ratio(total_liability.get(year), share_holder_fund, precision)
@@ -195,11 +195,11 @@ def add_solvency_ratios(
def add_turnover_ratios(data, years, period_list, filters, total_asset, net_sales, cogs, direct_expense):
precision = frappe.db.get_single_value("System Settings", "float_precision")
data.append({"ratio": "Turnover Ratios"})
data.append({"ratio": _("Turnover Ratios")})
avg_data = {}
for d in ["Receivable", "Payable", "Stock"]:
avg_data[frappe.scrub(d)] = avg_ratio_balance("Receivable", period_list, precision, filters)
avg_data[frappe.scrub(d)] = avg_ratio_balance(d, period_list, precision, filters)
avg_debtors, avg_creditors, avg_stock = (
avg_data.get("receivable"),
@@ -208,10 +208,10 @@ def add_turnover_ratios(data, years, period_list, filters, total_asset, net_sale
)
ratio_data = [
["Fixed Asset Turnover Ratio", net_sales, total_asset],
["Debtor Turnover Ratio", net_sales, avg_debtors],
["Creditor Turnover Ratio", direct_expense, avg_creditors],
["Inventory Turnover Ratio", cogs, avg_stock],
[_("Fixed Asset Turnover Ratio"), net_sales, total_asset],
[_("Debtor Turnover Ratio"), net_sales, avg_debtors],
[_("Creditor Turnover Ratio"), direct_expense, avg_creditors],
[_("Inventory Turnover Ratio"), cogs, avg_stock],
]
for ratio in ratio_data:
row = {

View File

@@ -212,7 +212,7 @@ def get_data(
company_currency,
accumulated_values=filters.accumulated_values,
)
out = filter_out_zero_value_rows(out, parent_children_map)
out = filter_out_zero_value_rows(out, parent_children_map, filters.show_zero_values)
if out and total:
add_total_row(out, root_type, balance_must_be, period_list, company_currency)
@@ -323,18 +323,24 @@ def prepare_data(accounts, balance_must_be, period_list, company_currency, accum
def filter_out_zero_value_rows(data, parent_children_map, show_zero_values=False):
def get_all_parents(account, parent_children_map):
for parent, children in parent_children_map.items():
for child in children:
if child["name"] == account and parent:
accounts_to_show.add(parent)
get_all_parents(parent, parent_children_map)
data_with_value = []
accounts_to_show = set()
for d in data:
if show_zero_values or d.get("has_value"):
accounts_to_show.add(d.get("account"))
get_all_parents(d.get("account"), parent_children_map)
for d in data:
if d.get("account") in accounts_to_show:
data_with_value.append(d)
else:
# show group with zero balance, if there are balances against child
children = [child.name for child in parent_children_map.get(d.get("account")) or []]
if children:
for row in data:
if row.get("account") in children and row.get("has_value"):
data_with_value.append(d)
break
return data_with_value

View File

@@ -1,5 +1,5 @@
{
"add_total_row": 1,
"add_total_row": 0,
"add_translate_data": 0,
"columns": [],
"creation": "2013-12-06 13:22:23",
@@ -10,7 +10,7 @@
"idx": 3,
"is_standard": "Yes",
"letterhead": null,
"modified": "2025-08-13 12:47:27.645023",
"modified": "2025-11-05 15:47:59.597853",
"modified_by": "Administrator",
"module": "Accounts",
"name": "General Ledger",

View File

@@ -566,6 +566,13 @@ def get_accountwise_gle(filters, accounting_dimensions, gl_entries, gle_map, tot
else:
update_value_in_dict(consolidated_gle, key, gle)
if filters.get("include_dimensions"):
dimensions = [*accounting_dimensions, "cost_center", "project"]
for dimension in dimensions:
if val := gle.get(dimension):
gle[dimension] = _(val)
for value in consolidated_gle.values():
update_value_in_dict(totals, "total", value)
update_value_in_dict(totals, "closing", value)

View File

@@ -85,6 +85,12 @@ frappe.query_reports["Gross Profit"] = {
});
},
},
{
fieldname: "include_returned_invoices",
label: __("Include Returned Invoices (Stand-alone)"),
fieldtype: "Check",
default: 1,
},
],
tree: true,
name_field: "parent",

View File

@@ -178,7 +178,12 @@ def get_data_when_grouped_by_invoice(columns, gross_profit_data, filters, group_
# to display item as Item Code: Item Name
columns[0] = "Sales Invoice:Link/Item:300"
# removing Item Code and Item Name columns
del columns[4:6]
supplier_master_name = frappe.db.get_single_value("Buying Settings", "supp_master_name")
customer_master_name = frappe.db.get_single_value("Selling Settings", "cust_master_name")
if supplier_master_name == "Supplier Name" and customer_master_name == "Customer Name":
del columns[4:6]
else:
del columns[5:7]
total_base_amount = 0
total_buying_amount = 0
@@ -226,6 +231,15 @@ def get_data_when_not_grouped_by_invoice(gross_profit_data, filters, group_wise_
group_columns = group_wise_columns.get(scrub(filters.group_by))
# removing customer_name from group columns
customer_master_name = frappe.db.get_single_value("Selling Settings", "cust_master_name")
supplier_master_name = frappe.db.get_single_value("Buying Settings", "supp_master_name")
if "customer_name" in group_columns and (
supplier_master_name == "Supplier Name" and customer_master_name == "Customer Name"
):
group_columns = [col for col in group_columns if col != "customer_name"]
for src in gross_profit_data.grouped_data:
total_base_amount += src.base_amount or 0.00
total_buying_amount += src.buying_amount or 0.00
@@ -275,7 +289,7 @@ def get_columns(group_wise_columns, filters):
"label": _("Posting Date"),
"fieldname": "posting_date",
"fieldtype": "Date",
"width": 100,
"width": 120,
},
"posting_time": {
"label": _("Posting Time"),
@@ -677,7 +691,9 @@ class GrossProfitGenerator:
si.name = si_item.parent
and si.docstatus = 1
and si.is_return = 1
and si.posting_date between %(from_date)s and %(to_date)s
""",
{"from_date": self.filters.from_date, "to_date": self.filters.to_date},
as_dict=1,
)
@@ -843,7 +859,10 @@ class GrossProfitGenerator:
if self.filters.to_date:
conditions += " and posting_date <= %(to_date)s"
conditions += " and (is_return = 0 or (is_return=1 and return_against is null))"
if self.filters.include_returned_invoices:
conditions += " and (is_return = 0 or (is_return=1 and return_against is null))"
else:
conditions += " and is_return = 0"
if self.filters.item_group:
conditions += f" and {get_item_group_condition(self.filters.item_group)}"

View File

@@ -1,9 +1,9 @@
import frappe
from frappe import qb
from frappe.tests.utils import FrappeTestCase
from frappe.utils import flt, nowdate
from frappe.utils import add_days, flt, get_first_day, get_last_day, nowdate
from erpnext.accounts.doctype.sales_invoice.sales_invoice import make_delivery_note
from erpnext.accounts.doctype.sales_invoice.sales_invoice import make_delivery_note, make_sales_return
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
from erpnext.accounts.report.gross_profit.gross_profit import execute
from erpnext.stock.doctype.delivery_note.delivery_note import make_sales_invoice
@@ -392,7 +392,6 @@ class TestGrossProfit(FrappeTestCase):
"""
Item Qty for Sales Invoices with multiple instances of same item go in the -ve. Ideally, the credit noteshould cancel out the invoice items.
"""
from erpnext.accounts.doctype.sales_invoice.sales_invoice import make_sales_return
# Invoice with an item added twice
sinv = self.create_sales_invoice(qty=1, rate=100, posting_date=nowdate(), do_not_submit=True)
@@ -443,7 +442,11 @@ class TestGrossProfit(FrappeTestCase):
sinv = sinv.save().submit()
filters = frappe._dict(
company=self.company, from_date=nowdate(), to_date=nowdate(), group_by="Invoice"
company=self.company,
from_date=nowdate(),
to_date=nowdate(),
group_by="Invoice",
include_returned_invoices=1,
)
columns, data = execute(filters=filters)
@@ -635,3 +638,42 @@ class TestGrossProfit(FrappeTestCase):
self.assertEqual(total.buying_amount, 0.0)
self.assertEqual(total.gross_profit, 100.0)
self.assertEqual(total.get("gross_profit_%"), 100.0)
def test_profit_for_later_period_return(self):
month_start_date, month_end_date = get_first_day(nowdate()), get_last_day(nowdate())
# create sales invoice on month start date
sinv = self.create_sales_invoice(qty=1, rate=100, do_not_save=True, do_not_submit=True)
sinv.set_posting_time = 1
sinv.posting_date = month_start_date
sinv.save().submit()
# create credit note on next month start date
cr_note = make_sales_return(sinv.name)
cr_note.set_posting_time = 1
cr_note.posting_date = add_days(month_end_date, 1)
cr_note.save().submit()
# apply filters for invoiced period
filters = frappe._dict(
company=self.company, from_date=month_start_date, to_date=month_end_date, group_by="Invoice"
)
_, data = execute(filters=filters)
total = data[-1]
self.assertEqual(total.selling_amount, 100.0)
self.assertEqual(total.buying_amount, 0.0)
self.assertEqual(total.gross_profit, 100.0)
self.assertEqual(total.get("gross_profit_%"), 100.0)
# extend filters upto returned period
filters.update(to_date=add_days(month_end_date, 1))
_, data = execute(filters=filters)
total = data[-1]
self.assertEqual(total.selling_amount, 0.0)
self.assertEqual(total.buying_amount, 0.0)
self.assertEqual(total.gross_profit, 0.0)
self.assertEqual(total.get("gross_profit_%"), 0.0)

View File

@@ -5,7 +5,6 @@
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 (
@@ -16,7 +15,7 @@ from erpnext.accounts.report.item_wise_sales_register.item_wise_sales_register i
get_group_by_and_display_fields,
get_tax_accounts,
)
from erpnext.accounts.report.utils import get_query_columns, get_values_for_columns
from erpnext.accounts.report.utils import get_values_for_columns
def execute(filters=None):
@@ -41,16 +40,6 @@ def _execute(filters=None, additional_table_columns=None):
tax_doctype="Purchase Taxes and Charges",
)
scrubbed_tax_fields = {}
for tax in tax_columns:
scrubbed_tax_fields.update(
{
tax + " Rate": frappe.scrub(tax + " Rate"),
tax + " Amount": frappe.scrub(tax + " Amount"),
}
)
po_pr_map = get_purchase_receipts_against_purchase_order(item_list)
data = []
@@ -100,8 +89,8 @@ def _execute(filters=None, additional_table_columns=None):
item_tax = itemised_tax.get(d.name, {}).get(tax, {})
row.update(
{
scrubbed_tax_fields[tax + " Rate"]: item_tax.get("tax_rate", 0),
scrubbed_tax_fields[tax + " Amount"]: item_tax.get("tax_amount", 0),
f"{tax}_rate": item_tax.get("tax_rate", 0),
f"{tax}_amount": item_tax.get("tax_amount", 0),
}
)
total_tax += flt(item_tax.get("tax_amount"))

View File

@@ -6,7 +6,7 @@ import frappe
from frappe import _
from frappe.model.meta import get_field_precision
from frappe.query_builder import functions as fn
from frappe.utils import cstr, flt
from frappe.utils import flt
from frappe.utils.nestedset import get_descendants_of
from frappe.utils.xlsxutils import handle_html
@@ -32,16 +32,6 @@ def _execute(filters=None, additional_table_columns=None, additional_conditions=
if item_list:
itemised_tax, tax_columns = get_tax_accounts(item_list, columns, company_currency)
scrubbed_tax_fields = {}
for tax in tax_columns:
scrubbed_tax_fields.update(
{
tax + " Rate": frappe.scrub(tax + " Rate"),
tax + " Amount": frappe.scrub(tax + " Amount"),
}
)
mode_of_payments = get_mode_of_payments(set(d.parent for d in item_list))
so_dn_map = get_delivery_notes_against_sales_order(item_list)
@@ -102,8 +92,8 @@ def _execute(filters=None, additional_table_columns=None, additional_conditions=
item_tax = itemised_tax.get(d.name, {}).get(tax, {})
row.update(
{
scrubbed_tax_fields[tax + " Rate"]: item_tax.get("tax_rate", 0),
scrubbed_tax_fields[tax + " Amount"]: item_tax.get("tax_amount", 0),
f"{tax}_rate": item_tax.get("tax_rate", 0),
f"{tax}_amount": item_tax.get("tax_amount", 0),
}
)
if item_tax.get("is_other_charges"):
@@ -546,9 +536,10 @@ def get_tax_accounts(
import json
item_row_map = {}
tax_columns = []
tax_columns = {}
invoice_item_row = {}
itemised_tax = {}
scrubbed_description_map = {}
add_deduct_tax = "charge_type"
tax_amount_precision = (
@@ -605,9 +596,14 @@ def get_tax_accounts(
tax_amount,
) in tax_details:
description = handle_html(description)
if description not in tax_columns and tax_amount:
scrubbed_description = scrubbed_description_map.get(description)
if not scrubbed_description:
scrubbed_description = frappe.scrub(description)
scrubbed_description_map[description] = scrubbed_description
if scrubbed_description not in tax_columns and tax_amount:
# as description is text editor earlier and markup can break the column convention in reports
tax_columns.append(description)
tax_columns[scrubbed_description] = description
if item_wise_tax_detail:
try:
@@ -641,7 +637,7 @@ def get_tax_accounts(
else tax_value
)
itemised_tax.setdefault(d.name, {})[description] = frappe._dict(
itemised_tax.setdefault(d.name, {})[scrubbed_description] = frappe._dict(
{
"tax_rate": tax_rate,
"tax_amount": tax_value,
@@ -653,7 +649,7 @@ def get_tax_accounts(
continue
elif charge_type == "Actual" and tax_amount:
for d in invoice_item_row.get(parent, []):
itemised_tax.setdefault(d.name, {})[description] = frappe._dict(
itemised_tax.setdefault(d.name, {})[scrubbed_description] = frappe._dict(
{
"tax_rate": "NA",
"tax_amount": flt(
@@ -662,12 +658,14 @@ def get_tax_accounts(
}
)
tax_columns.sort()
for desc in tax_columns:
tax_columns_list = list(tax_columns.keys())
tax_columns_list.sort()
for scrubbed_desc in tax_columns_list:
desc = tax_columns[scrubbed_desc]
columns.append(
{
"label": _(desc + " Rate"),
"fieldname": frappe.scrub(desc + " Rate"),
"fieldname": f"{scrubbed_desc}_rate",
"fieldtype": "Float",
"width": 100,
}
@@ -676,7 +674,7 @@ def get_tax_accounts(
columns.append(
{
"label": _(desc + " Amount"),
"fieldname": frappe.scrub(desc + " Amount"),
"fieldname": f"{scrubbed_desc}_amount",
"fieldtype": "Currency",
"options": "currency",
"width": 100,
@@ -714,7 +712,7 @@ def get_tax_accounts(
},
]
return itemised_tax, tax_columns
return itemised_tax, tax_columns_list
def add_total_row(
@@ -807,5 +805,5 @@ def add_sub_total_row(item, total_row_map, group_by_value, tax_columns):
total_row["percent_gt"] += item["percent_gt"]
for tax in tax_columns:
total_row.setdefault(frappe.scrub(tax + " Amount"), 0.0)
total_row[frappe.scrub(tax + " Amount")] += flt(item[frappe.scrub(tax + " Amount")])
total_row.setdefault(f"{tax}_amount", 0.0)
total_row[f"{tax}_amount"] += flt(item[f"{tax}_amount"])

View File

@@ -21,6 +21,7 @@ def get_ordered_to_be_billed_data(args, filters=None):
doctype = frappe.qb.DocType(doctype)
child_doctype = frappe.qb.DocType(child_tab)
item = frappe.qb.DocType("Item")
docname = filters.get(args.get("reference_field"), None)
project_field = get_project_field(doctype, child_doctype, party)
@@ -29,6 +30,8 @@ def get_ordered_to_be_billed_data(args, filters=None):
frappe.qb.from_(doctype)
.inner_join(child_doctype)
.on(doctype.name == child_doctype.parent)
.join(item)
.on(item.name == child_doctype.item_code)
.select(
doctype.name,
doctype[args.get("date")].as_("date"),
@@ -54,6 +57,7 @@ def get_ordered_to_be_billed_data(args, filters=None):
& (doctype.company == filters.get("company"))
& (doctype.posting_date <= filters.get("posting_date"))
& (child_doctype.amount > 0)
& (item.is_stock_item == 1)
& (
child_doctype.base_amount
- Round(child_doctype.billed_amt * IfNull(doctype.conversion_rate, 1), precision)

View File

@@ -5,29 +5,34 @@ frappe.query_reports["Profit and Loss Statement"] = $.extend({}, erpnext.financi
erpnext.utils.add_dimensions("Profit and Loss Statement", 10);
frappe.query_reports["Profit and Loss Statement"]["filters"].push({
fieldname: "selected_view",
label: __("Select View"),
fieldtype: "Select",
options: [
{ value: "Report", label: __("Report View") },
{ value: "Growth", label: __("Growth View") },
{ value: "Margin", label: __("Margin View") },
],
default: "Report",
reqd: 1,
});
frappe.query_reports["Profit and Loss Statement"]["filters"].push({
fieldname: "accumulated_values",
label: __("Accumulated Values"),
fieldtype: "Check",
default: 1,
});
frappe.query_reports["Profit and Loss Statement"]["filters"].push({
fieldname: "include_default_book_entries",
label: __("Include Default FB Entries"),
fieldtype: "Check",
default: 1,
});
frappe.query_reports["Profit and Loss Statement"]["filters"].push(
{
fieldname: "selected_view",
label: __("Select View"),
fieldtype: "Select",
options: [
{ value: "Report", label: __("Report View") },
{ value: "Growth", label: __("Growth View") },
{ value: "Margin", label: __("Margin View") },
],
default: "Report",
reqd: 1,
},
{
fieldname: "accumulated_values",
label: __("Accumulated Values"),
fieldtype: "Check",
default: 1,
},
{
fieldname: "include_default_book_entries",
label: __("Include Default FB Entries"),
fieldtype: "Check",
default: 1,
},
{
fieldname: "show_zero_values",
label: __("Show zero values"),
fieldtype: "Check",
}
);

View File

@@ -1,32 +1,37 @@
{
"add_total_row": 1,
"apply_user_permissions": 1,
"creation": "2013-06-13 18:46:55",
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"idx": 3,
"is_standard": "Yes",
"modified": "2018-02-21 01:28:31.261299",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice Trends",
"owner": "Administrator",
"ref_doctype": "Purchase Invoice",
"report_name": "Purchase Invoice Trends",
"report_type": "Script Report",
"add_total_row": 0,
"add_translate_data": 0,
"columns": [],
"creation": "2013-06-13 18:46:55",
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"filters": [],
"idx": 3,
"is_standard": "Yes",
"letterhead": null,
"modified": "2025-11-05 11:55:49.950442",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice Trends",
"owner": "Administrator",
"prepared_report": 0,
"ref_doctype": "Purchase Invoice",
"report_name": "Purchase Invoice Trends",
"report_type": "Script Report",
"roles": [
{
"role": "Accounts User"
},
},
{
"role": "Purchase User"
},
},
{
"role": "Accounts Manager"
},
},
{
"role": "Auditor"
}
]
}
],
"timeout": 0
}

View File

@@ -1,26 +1,31 @@
{
"add_total_row": 1,
"apply_user_permissions": 1,
"creation": "2013-06-13 18:44:21",
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"idx": 3,
"is_standard": "Yes",
"modified": "2018-02-21 01:28:03.622485",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice Trends",
"owner": "Administrator",
"ref_doctype": "Sales Invoice",
"report_name": "Sales Invoice Trends",
"report_type": "Script Report",
"add_total_row": 0,
"add_translate_data": 0,
"columns": [],
"creation": "2013-06-13 18:44:21",
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"filters": [],
"idx": 3,
"is_standard": "Yes",
"letterhead": null,
"modified": "2025-11-05 11:55:50.070651",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice Trends",
"owner": "Administrator",
"prepared_report": 0,
"ref_doctype": "Sales Invoice",
"report_name": "Sales Invoice Trends",
"report_type": "Script Report",
"roles": [
{
"role": "Accounts Manager"
},
},
{
"role": "Accounts User"
}
]
}
],
"timeout": 0
}

View File

@@ -4,7 +4,9 @@
import frappe
from frappe import _
from frappe.utils import getdate
from frappe.utils import flt, getdate
from erpnext.accounts.utils import get_currency_precision
def execute(filters=None):
@@ -43,6 +45,7 @@ def get_result(filters, tds_docs, tds_accounts, tax_category_map, journal_entry_
party_map = get_party_pan_map(filters.get("party_type"))
tax_rate_map = get_tax_rate_map(filters)
gle_map = get_gle_map(tds_docs)
precision = get_currency_precision()
out = []
entries = {}
@@ -72,17 +75,28 @@ def get_result(filters, tds_docs, tds_accounts, tax_category_map, journal_entry_
tax_withholding_category = party_map.get(party, {}).get("tax_withholding_category")
rate = get_tax_withholding_rates(tax_rate_map.get(tax_withholding_category, []), posting_date)
if net_total_map.get((voucher_type, name)):
values = net_total_map.get((voucher_type, name))
if values:
if voucher_type == "Journal Entry" and tax_amount and rate:
# back calcalute total amount from rate and tax_amount
base_total = min(tax_amount / (rate / 100), net_total_map.get((voucher_type, name))[0])
# back calculate total amount from rate and tax_amount
base_total = min(flt(tax_amount / (rate / 100), precision=precision), values[0])
total_amount = grand_total = base_total
elif voucher_type == "Purchase Invoice":
total_amount, grand_total, base_total, bill_no, bill_date = net_total_map.get(
(voucher_type, name)
)
else:
total_amount, grand_total, base_total = net_total_map.get((voucher_type, name))
if tax_amount and rate:
# back calculate total amount from rate and tax_amount
total_amount = flt((tax_amount * 100) / rate, precision=precision)
else:
total_amount = values[0]
grand_total = values[1]
base_total = values[2]
if voucher_type == "Purchase Invoice":
bill_no = values[3]
bill_date = values[4]
else:
total_amount += entry.credit

View File

@@ -47,22 +47,23 @@ frappe.query_reports["Trial Balance"] = {
{
fieldname: "cost_center",
label: __("Cost Center"),
fieldtype: "Link",
options: "Cost Center",
get_query: function () {
var company = frappe.query_report.get_filter_value("company");
return {
doctype: "Cost Center",
filters: {
company: company,
},
};
fieldtype: "MultiSelectList",
get_data: function (txt) {
return frappe.db.get_link_options("Cost Center", txt, {
company: frappe.query_report.get_filter_value("company"),
});
},
options: "Cost Center",
},
{
fieldname: "project",
label: __("Project"),
fieldtype: "Link",
fieldtype: "MultiSelectList",
get_data: function (txt) {
return frappe.db.get_link_options("Project", txt, {
company: frappe.query_report.get_filter_value("company"),
});
},
options: "Project",
},
{

View File

@@ -15,6 +15,7 @@ from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import (
from erpnext.accounts.report.financial_statements import (
filter_accounts,
filter_out_zero_value_rows,
get_cost_centers_with_children,
set_gl_entries_by_account,
)
from erpnext.accounts.report.utils import convert_to_presentation_currency, get_currency
@@ -103,10 +104,6 @@ def get_data(filters):
opening_balances = get_opening_balances(filters, ignore_is_opening)
# add filter inside list so that the query in financial_statements.py doesn't break
if filters.project:
filters.project = [filters.project]
set_gl_entries_by_account(
filters.company,
filters.from_date,
@@ -216,7 +213,7 @@ def get_opening_balance(
ignore_is_opening=0,
):
closing_balance = frappe.qb.DocType(doctype)
account = frappe.qb.DocType("Account")
accounts = frappe.db.get_all("Account", filters={"report_type": report_type}, pluck="name")
opening_balance = (
frappe.qb.from_(closing_balance)
@@ -228,14 +225,7 @@ def get_opening_balance(
Sum(closing_balance.debit_in_account_currency).as_("debit_in_account_currency"),
Sum(closing_balance.credit_in_account_currency).as_("credit_in_account_currency"),
)
.where(
(closing_balance.company == filters.company)
& (
closing_balance.account.isin(
frappe.qb.from_(account).select("name").where(account.report_type == report_type)
)
)
)
.where((closing_balance.company == filters.company) & (closing_balance.account.isin(accounts)))
.groupby(closing_balance.account)
)
@@ -277,34 +267,31 @@ def get_opening_balance(
opening_balance = opening_balance.where(closing_balance.voucher_type != "Period Closing Voucher")
if filters.cost_center:
lft, rgt = frappe.db.get_value("Cost Center", filters.cost_center, ["lft", "rgt"])
cost_center = frappe.qb.DocType("Cost Center")
opening_balance = opening_balance.where(
closing_balance.cost_center.isin(
frappe.qb.from_(cost_center)
.select("name")
.where((cost_center.lft >= lft) & (cost_center.rgt <= rgt))
)
closing_balance.cost_center.isin(get_cost_centers_with_children(filters.get("cost_center")))
)
if filters.project:
opening_balance = opening_balance.where(closing_balance.project == filters.project)
opening_balance = opening_balance.where(closing_balance.project.isin(filters.project))
if filters.get("include_default_book_entries"):
company_fb = frappe.get_cached_value("Company", filters.company, "default_finance_book")
if frappe.db.count("Finance Book"):
if filters.get("include_default_book_entries"):
company_fb = frappe.get_cached_value("Company", filters.company, "default_finance_book")
if filters.finance_book and company_fb and cstr(filters.finance_book) != cstr(company_fb):
frappe.throw(_("To use a different finance book, please uncheck 'Include Default FB Entries'"))
if filters.finance_book and company_fb and cstr(filters.finance_book) != cstr(company_fb):
frappe.throw(
_("To use a different finance book, please uncheck 'Include Default FB Entries'")
)
opening_balance = opening_balance.where(
(closing_balance.finance_book.isin([cstr(filters.finance_book), cstr(company_fb), ""]))
| (closing_balance.finance_book.isnull())
)
else:
opening_balance = opening_balance.where(
(closing_balance.finance_book.isin([cstr(filters.finance_book), ""]))
| (closing_balance.finance_book.isnull())
)
opening_balance = opening_balance.where(
(closing_balance.finance_book.isin([cstr(filters.finance_book), cstr(company_fb), ""]))
| (closing_balance.finance_book.isnull())
)
else:
opening_balance = opening_balance.where(
(closing_balance.finance_book.isin([cstr(filters.finance_book), ""]))
| (closing_balance.finance_book.isnull())
)
if accounting_dimensions:
for dimension in accounting_dimensions:

View File

@@ -5,7 +5,9 @@ from erpnext.stock.doctype.item.test_item import create_item
class AccountsTestMixin:
def create_customer(self, customer_name="_Test Customer", currency=None):
def create_customer(
self, customer_name="_Test Customer", currency=None, default_account=None, company=None
):
if not frappe.db.exists("Customer", customer_name):
customer = frappe.new_doc("Customer")
customer.customer_name = customer_name
@@ -13,9 +15,28 @@ class AccountsTestMixin:
if currency:
customer.default_currency = currency
if company and default_account:
customer.append(
"accounts",
{
"company": company,
"account": default_account,
},
)
customer.save()
self.customer = customer.name
else:
if company and default_account:
customer = frappe.get_doc("Customer", customer_name)
customer.accounts = []
customer.append(
"accounts",
{
"company": company,
"account": default_account,
},
)
customer.save()
self.customer = customer_name
def create_supplier(self, supplier_name="_Test Supplier", currency=None):

View File

@@ -947,19 +947,28 @@ def update_accounting_ledgers_after_reference_removal(
adv_ple.run()
def remove_ref_from_advance_section(ref_doc: object = None):
def remove_ref_from_advance_section(ref_doc: object = None, payment_name: str | None = None):
# TODO: this might need some testing
if ref_doc.doctype in ("Sales Invoice", "Purchase Invoice"):
ref_doc.set("advances", [])
adv_type = qb.DocType(f"{ref_doc.doctype} Advance")
qb.from_(adv_type).delete().where(adv_type.parent == ref_doc.name).run()
row_names = []
for adv in ref_doc.get("advances") or []:
if adv.get("reference_name", None) == payment_name:
row_names.append(adv.name)
if not row_names:
return
child_table = (
"Sales Invoice Advance" if ref_doc.doctype == "Sales Invoice" else "Purchase Invoice Advance"
)
frappe.db.delete(child_table, {"name": ("in", row_names)})
def unlink_ref_doc_from_payment_entries(ref_doc: object = None, payment_name: str | None = None):
remove_ref_doc_link_from_jv(ref_doc.doctype, ref_doc.name, payment_name)
remove_ref_doc_link_from_pe(ref_doc.doctype, ref_doc.name, payment_name)
update_accounting_ledgers_after_reference_removal(ref_doc.doctype, ref_doc.name, payment_name)
remove_ref_from_advance_section(ref_doc)
remove_ref_from_advance_section(ref_doc, payment_name)
def remove_ref_doc_link_from_jv(
@@ -1026,7 +1035,6 @@ def remove_ref_doc_link_from_pe(
query = query.where(per.parent == payment_name)
reference_rows = query.run(as_dict=True)
if not reference_rows:
return
@@ -1747,24 +1755,22 @@ def check_and_delete_linked_reports(report):
frappe.delete_doc("Desktop Icon", icon)
def create_err_and_its_journals(companies: list | None = None) -> None:
if companies:
for company in companies:
err = frappe.new_doc("Exchange Rate Revaluation")
err.company = company.name
err.posting_date = nowdate()
err.rounding_loss_allowance = 0.0
def create_err_and_its_journals(company: dict) -> None:
err = frappe.new_doc("Exchange Rate Revaluation")
err.company = company.name
err.posting_date = nowdate()
err.rounding_loss_allowance = 0.0
err.fetch_and_calculate_accounts_data()
if err.accounts:
err.save().submit()
response = err.make_jv_entries()
err.fetch_and_calculate_accounts_data()
if err.accounts:
err.save().submit()
response = err.make_jv_entries()
if company.submit_err_jv:
jv = response.get("revaluation_jv", None)
jv and frappe.get_doc("Journal Entry", jv).submit()
jv = response.get("zero_balance_jv", None)
jv and frappe.get_doc("Journal Entry", jv).submit()
if company.submit_err_jv:
jv = response.get("revaluation_jv", None)
jv and frappe.get_doc("Journal Entry", jv).submit()
jv = response.get("zero_balance_jv", None)
jv and frappe.get_doc("Journal Entry", jv).submit()
def _auto_create_exchange_rate_revaluation_for(frequency: str) -> None:
@@ -1777,7 +1783,14 @@ def _auto_create_exchange_rate_revaluation_for(frequency: str) -> None:
filters={"auto_exchange_rate_revaluation": 1, "auto_err_frequency": frequency},
fields=["name", "submit_err_jv"],
)
create_err_and_its_journals(companies)
if companies:
for company in companies:
frappe.enqueue(
"erpnext.accounts.utils.create_err_and_its_journals",
company=company,
queue="long",
)
def auto_create_exchange_rate_revaluation_daily() -> None:

View File

@@ -202,7 +202,7 @@ frappe.ui.form.on("Asset", {
callback: function (r) {
if (!r.message) {
$(".primary-action").prop("hidden", true);
$(".form-message").text("Capitalize this asset to confirm");
$(".form-message").text(__("Capitalize this asset to confirm"));
frm.add_custom_button(__("Capitalize Asset"), function () {
frm.trigger("create_asset_capitalization");
@@ -790,17 +790,33 @@ frappe.ui.form.on("Asset Finance Book", {
});
erpnext.asset.scrap_asset = function (frm) {
frappe.confirm(__("Do you really want to scrap this asset?"), function () {
frappe.call({
args: {
asset_name: frm.doc.name,
var scrap_dialog = new frappe.ui.Dialog({
title: __("Enter date to scrap asset"),
fields: [
{
label: __("Select the date"),
fieldname: "scrap_date",
fieldtype: "Date",
reqd: 1,
},
method: "erpnext.assets.doctype.asset.depreciation.scrap_asset",
callback: function (r) {
cur_frm.reload_doc();
},
});
],
size: "medium",
primary_action_label: "Submit",
primary_action(values) {
frappe.call({
args: {
asset_name: frm.doc.name,
scrap_date: values.scrap_date,
},
method: "erpnext.assets.doctype.asset.depreciation.scrap_asset",
callback: function (r) {
frm.reload_doc();
scrap_dialog.hide();
},
});
},
});
scrap_dialog.show();
};
erpnext.asset.restore_asset = function (frm) {

Some files were not shown because too many files have changed in this diff Show More