Compare commits

..

782 Commits

Author SHA1 Message Date
Frappe PR Bot
66d0ad1bc6 chore(release): Bumped to Version 15.55.3
## [15.55.3](https://github.com/frappe/erpnext/compare/v15.55.2...v15.55.3) (2025-03-29)

### Bug Fixes

* incorrect condition ([0721816](0721816763))
2025-03-29 07:03:05 +00:00
rohitwaghchaure
3395e7c2cd Merge pull request #46785 from frappe/mergify/bp/version-15/pr-46781
fix: incorrect condition (backport #46777) (backport #46781)
2025-03-29 12:31:36 +05:30
Rohit Waghchaure
0721816763 fix: incorrect condition
(cherry picked from commit 0c1a8e9c58)
(cherry picked from commit 502b8f25b3)
2025-03-29 06:48:03 +00:00
rohitwaghchaure
e45d0779ef Merge pull request #46752 from frappe/mergify/bp/version-15/pr-46749
Revert "perf: timeout while renaming cost center (backport #46641)" (backport #46749)
2025-03-27 13:13:17 +05:30
rohitwaghchaure
c6ce76170b Revert "perf: timeout while renaming cost center (backport #46641)"
(cherry picked from commit 326126e741)
2025-03-27 06:54:18 +00:00
Frappe PR Bot
de3e6922b5 chore(release): Bumped to Version 15.55.2
## [15.55.2](https://github.com/frappe/erpnext/compare/v15.55.1...v15.55.2) (2025-03-27)

### Bug Fixes

* do not use self object for setting party and party type ([7795030](7795030b7b))
2025-03-27 06:05:55 +00:00
ruthra kumar
ae6d3f27a2 Merge pull request #46747 from frappe/mergify/bp/version-15/pr-46719
fix: do not use self object for setting party and party type  (backport #46719)
2025-03-27 11:34:32 +05:30
ljain112
7795030b7b fix: do not use self object for setting party and party type
(cherry picked from commit 80b746d4dd)
2025-03-27 05:39:52 +00:00
Frappe PR Bot
9bac43acff chore(release): Bumped to Version 15.55.1
## [15.55.1](https://github.com/frappe/erpnext/compare/v15.55.0...v15.55.1) (2025-03-27)

### Bug Fixes

* decimal values causing incorrect batch picking ([1b6aeba](1b6aeba267))
* expense account in the stock entry ([e393ce9](e393ce9a47))
* slow query ([f3ba5a8](f3ba5a81ab))
2025-03-27 03:45:26 +00:00
rohitwaghchaure
1e987153c9 Merge pull request #46735 from frappe/mergify/bp/version-15/pr-46730
fix: expense account in the stock entry (backport #46710) (backport #46730)
2025-03-27 09:14:05 +05:30
rohitwaghchaure
d36a7c2389 Merge pull request #46741 from frappe/mergify/bp/version-15/pr-46734
fix: decimal values causing incorrect batch picking (backport #46733) (backport #46734)
2025-03-27 09:13:56 +05:30
rohitwaghchaure
b548cc411d Merge pull request #46742 from frappe/mergify/bp/version-15/pr-46740
fix: slow query (backport #46739) (backport #46740)
2025-03-27 09:13:47 +05:30
rohitwaghchaure
ad3f985dc4 chore: fix conflicts
(cherry picked from commit 41f20a9c64)
2025-03-26 17:09:42 +00:00
Rohit Waghchaure
f3ba5a81ab fix: slow query
(cherry picked from commit 5ddb36af87)

# Conflicts:
#	erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json
(cherry picked from commit af0fb131a2)
2025-03-26 17:09:42 +00:00
Rohit Waghchaure
1b6aeba267 fix: decimal values causing incorrect batch picking
(cherry picked from commit 7bfe703b04)
(cherry picked from commit c5efddae16)
2025-03-26 16:43:35 +00:00
Rohit Waghchaure
e393ce9a47 fix: expense account in the stock entry
(cherry picked from commit 89569d4b32)
(cherry picked from commit 62f342ef8b)
2025-03-26 10:18:49 +00:00
Frappe PR Bot
8951efb457 chore(release): Bumped to Version 15.55.0
# [15.55.0](https://github.com/frappe/erpnext/compare/v15.54.5...v15.55.0) (2025-03-25)

### Bug Fixes

* add base_outstanding and base_paid_amount in payment schedule table ([412e6be](412e6be502))
* add patch to update base_outstanding and base_paid_amount ([c3221c4](c3221c4e93))
* correct accumulated depreciation calculation for disposed assets (backport [#46660](https://github.com/frappe/erpnext/issues/46660)) ([#46661](https://github.com/frappe/erpnext/issues/46661)) ([4df5f18](4df5f18d85))
* correct invoice order in payment reconcillaiton ([2a70791](2a70791bba))
* customer credit limit check based on `bypass_credit_limit_check` in Journal Entry ([6c443bd](6c443bd85a))
* date added to wrong patch ([2bfaf64](2bfaf64fff))
* do not validate if conversion rate is 1 for different currency ([391b5c4](391b5c4226))
* don't filter payment entries on Bank Account in Payment Clearance ([dc3b5e2](dc3b5e2f3a))
* **Payment Entry:** get contact details from existing contact ([#40556](https://github.com/frappe/erpnext/issues/40556)) ([f964178](f964178008))
* unwired order_by argument in get_transaction_list (backport [#46636](https://github.com/frappe/erpnext/issues/46636)) ([#46643](https://github.com/frappe/erpnext/issues/46643)) ([2ebea88](2ebea8866a))

### Features

* **accounting:** allow chart_of_account.get_chart to be whilelist ([e69c722](e69c722534))
* **projects:** add option to hide timesheets for project users ([#46173](https://github.com/frappe/erpnext/issues/46173)) ([3834d6f](3834d6fbce))
* repost accounting ledger for purchase receipt ([4edfc6f](4edfc6f125))

### Performance Improvements

* timeout while renaming cost center ([58eb184](58eb1849d7))
2025-03-25 13:50:33 +00:00
ruthra kumar
5db2a19778 Merge pull request #46715 from frappe/version-15-hotfix
chore: release v15
2025-03-25 19:16:44 +05:30
ruthra kumar
288206bdcd Merge pull request #46634 from frappe/mergify/bp/version-15-hotfix/pr-46627
fix: date added to wrong patch (backport #46627)
2025-03-25 18:45:21 +05:30
ruthra kumar
b3c3733286 chore: resolve conflict 2025-03-25 17:53:29 +05:30
ruthra kumar
b2b49446d4 Merge pull request #46713 from frappe/mergify/bp/version-15-hotfix/pr-46616
fix: do not validate if conversion rate is 1 for different currency (backport #46616)
2025-03-25 14:29:09 +05:30
ljain112
391b5c4226 fix: do not validate if conversion rate is 1 for different currency
(cherry picked from commit e8a66d03bc)
2025-03-25 08:42:31 +00:00
ruthra kumar
ce454d5202 Merge pull request #46707 from frappe/mergify/bp/version-15-hotfix/pr-46617
refactor: removed redundant message display for each item row cost center update (backport #46617)
2025-03-25 12:28:43 +05:30
ljain112
f93feb18fb refactor: removed redundant message display for each item row cost center update
(cherry picked from commit 4376ca5f1d)
2025-03-25 06:47:13 +00:00
ruthra kumar
0793213981 Merge pull request #46705 from frappe/mergify/bp/version-15-hotfix/pr-46622
feat: repost accounting ledger for purchase receipt (backport #46622)
2025-03-25 12:13:56 +05:30
ljain112
4edfc6f125 feat: repost accounting ledger for purchase receipt
(cherry picked from commit b36e356469)
2025-03-25 06:19:43 +00:00
mergify[bot]
98df0614ab ci: apply label "skip-release-notes" based on PR title (backport #46694) (#46697)
ci: apply label "skip-release-notes" based on PR title (#46694)

Workflow copied from frappe/frappe

(cherry picked from commit eb350012b0)

Co-authored-by: Raffael Meyer <14891507+barredterra@users.noreply.github.com>
2025-03-24 16:55:11 +01:00
Sagar Vora
59d0ff493f Merge pull request #46688 from frappe/mergify/bp/version-15-hotfix/pr-46669
fix: don't filter payment entries on Bank Account in Payment Clearance (backport #46669)
2025-03-24 18:17:59 +05:30
vishakhdesai
dc3b5e2f3a fix: don't filter payment entries on Bank Account in Payment Clearance
(cherry picked from commit fa2fd5bf88)
2025-03-24 12:22:09 +00:00
ruthra kumar
058a2f0c42 Merge pull request #46677 from frappe/mergify/bp/version-15-hotfix/pr-46577
fix: customer credit limit check based on `bypass_credit_limit_check` in Journal Entry (backport #46577)
2025-03-24 13:58:10 +05:30
ljain112
6c443bd85a fix: customer credit limit check based on bypass_credit_limit_check in Journal Entry
(cherry picked from commit 8a84faebed)
2025-03-24 08:02:17 +00:00
ruthra kumar
a228d1edc5 Merge pull request #46672 from frappe/mergify/bp/version-15-hotfix/pr-46574
fix: correct invoice order in payment reconcillaiton (backport #46574)
2025-03-24 13:13:35 +05:30
ruthra kumar
87628835bf Merge pull request #46673 from frappe/mergify/bp/version-15-hotfix/pr-46386
feat(accounting/regional): allow chart_of_account.get_chart to be whilelist (backport #46386)
2025-03-24 13:13:06 +05:30
Florian HENRY
e69c722534 feat(accounting): allow chart_of_account.get_chart to be whilelist
(cherry picked from commit 49dcd96909)
2025-03-24 07:03:37 +00:00
ruthra kumar
326c37a051 chore: resolve conflict 2025-03-24 12:29:52 +05:30
ljain112
2a70791bba fix: correct invoice order in payment reconcillaiton
(cherry picked from commit 5c34a5aaed)

# Conflicts:
#	erpnext/accounts/utils.py
2025-03-24 06:54:24 +00:00
ruthra kumar
e5fb77c65f Merge pull request #46670 from frappe/mergify/bp/version-15-hotfix/pr-46440
fix: add base_outstanding and base_paid_amount in payment schedule table (backport #46440)
2025-03-24 12:13:51 +05:30
ruthra kumar
4a7d401dc5 chore: resolve conflict 2025-03-24 11:53:14 +05:30
Sugesh393
c3221c4e93 fix: add patch to update base_outstanding and base_paid_amount
(cherry picked from commit 7e92e4967a)
2025-03-24 06:14:41 +00:00
Sugesh393
412e6be502 fix: add base_outstanding and base_paid_amount in payment schedule table
(cherry picked from commit 6c2f9a563e)

# Conflicts:
#	erpnext/accounts/doctype/payment_schedule/payment_schedule.json
2025-03-24 06:14:41 +00:00
mergify[bot]
4df5f18d85 fix: correct accumulated depreciation calculation for disposed assets (backport #46660) (#46661)
fix: correct accumulated depreciation calculation for disposed assets (#46660)

(cherry picked from commit eec2e7e833)

Co-authored-by: Khushi Rawat <142375893+khushi8112@users.noreply.github.com>
2025-03-23 18:53:49 +05:30
rohitwaghchaure
d58e527b6b Merge pull request #46647 from frappe/mergify/bp/version-15-hotfix/pr-46641
perf: timeout while renaming cost center (backport #46641)
2025-03-22 20:49:18 +05:30
Rohit Waghchaure
58eb1849d7 perf: timeout while renaming cost center
(cherry picked from commit 92be7cbbbf)
2025-03-21 12:38:51 +00:00
mergify[bot]
2ebea8866a fix: unwired order_by argument in get_transaction_list (backport #46636) (#46643)
* fix: unwired order_by argument

* lol on how it was updated from modified in both the places (version 15), but wasn't fixed

(cherry picked from commit 2c1077d332)

# Conflicts:
#	erpnext/controllers/website_list_for_contact.py

* fix: merge conflicts

* fix: sort by creation only

---------

Co-authored-by: Hussain Nagaria <hussainbhaitech@gmail.com>
Co-authored-by: Md Hussain Nagaria <34810212+NagariaHussain@users.noreply.github.com>
2025-03-21 16:27:05 +05:30
Smit Vora
4e65b7873d Merge pull request #46638 from frappe/mergify/bp/version-15-hotfix/pr-40556
fix(Payment Entry): get contact details from existing contact (backport #40556)
2025-03-21 15:22:44 +05:30
Smit Vora
7dc23d9733 chore: resolve conflicts #39748 2025-03-21 14:09:21 +05:30
David Arnold
f964178008 fix(Payment Entry): get contact details from existing contact (#40556)
(cherry picked from commit 462204fc65)

# Conflicts:
#	erpnext/accounts/doctype/payment_entry/payment_entry.py
2025-03-21 08:28:59 +00:00
Mihir Kandoi
2bfaf64fff fix: date added to wrong patch
(cherry picked from commit dc45c3b39c)

# Conflicts:
#	erpnext/patches.txt
2025-03-20 18:26:02 +00:00
ruthra kumar
6da00319e6 Merge pull request #46612 from frappe/mergify/bp/version-15-hotfix/pr-46173
feat(projects): add option to hide timesheets for project users (backport #46173)
2025-03-19 16:50:42 +05:30
Frappe PR Bot
35ac96f1ec chore(release): Bumped to Version 15.54.5
## [15.54.5](https://github.com/frappe/erpnext/compare/v15.54.4...v15.54.5) (2025-03-19)

### Bug Fixes

* add parenttype condition to payment schedule query in accounts receivable report (backport [#46370](https://github.com/frappe/erpnext/issues/46370)) ([#46499](https://github.com/frappe/erpnext/issues/46499)) ([32335da](32335da839))
* add validation to rename_subcontracting_fields patch ([bc408d9](bc408d979a))
* also consider CRM Deal as party type for ERPNext CRM Integration ([65a80cf](65a80cffe7))
* dashboard link for QC from PR ([426222d](426222d8e0))
* Debit and Credit not equal for Purchase Invoice ([46b6e62](46b6e621c2))
* debit in transaction currency ([8e19b46](8e19b46bd9))
* ensure qty conversion when creating production plan from SO ([8162fb3](8162fb3e5d))
* exclude current doc when checking for duplicate ([b638aed](b638aed758))
* fetch bom_no when updating items in sales order ([41d8b26](41d8b26dd2))
* fetch quality inspection parameter group ([cd0abba](cd0abbae51))
* get bom_no from sales order item and material request item ([e241810](e2418101ab))
* hide subcontracted qty field if PO is not subcontracted ([62feec5](62feec5cc3))
* incorrect production item and bom no in job card ([d071a6c](d071a6c900))
* not able to make PR against stand alone Debit Note ([d62960e](d62960e925))
* not able to select the item in the BOM ([59c653e](59c653ef3f))
* patch ([36ffc2e](36ffc2ee67))
* performance issue for item list view ([34d6e4b](34d6e4bdaa))
* remove duplicate ([e5b2801](e5b2801830))
* repost future sle and gle after capitalization ([#46576](https://github.com/frappe/erpnext/issues/46576)) ([2144f89](2144f89624))
* SABB validation for packed items ([2d6626e](2d6626e906))
* set correct currency for offset account gl entries ([e6dd3f3](e6dd3f3e64))
* set landed cost based on purchase invoice rate ([56bc26a](56bc26aecc))
* set stock adjustment account in difference account ([6202e30](6202e302b1))
* take function call outside loop ([ec1a3a1](ec1a3a1e6b))
* **Transaction Deletion Record:** sql syntax error while fetching lead address ([ea68cae](ea68caec7d))
* UOM conversion error when creating pick list from material transfer request ([2f3dcc2](2f3dcc2137))
* use base currency total ([3e2749d](3e2749d6d5))
* use party explicitly ([5dd5784](5dd5784716))
* use shipping_address_name for address validation in sales invoice ([#46473](https://github.com/frappe/erpnext/issues/46473)) ([38dabdf](38dabdf584))
* using `in` for lookup in list instead of directly assigning ([#46492](https://github.com/frappe/erpnext/issues/46492)) ([950656d](950656d6f7))
* valuation for moving average with batches ([5f1bb1f](5f1bb1f1ba))
* wrong field mapping ([be3e083](be3e083e7d))

### Performance Improvements

* faster count estimation (backport [#46550](https://github.com/frappe/erpnext/issues/46550)) ([#46551](https://github.com/frappe/erpnext/issues/46551)) ([01bab8f](01bab8f22b))
2025-03-19 11:18:07 +00:00
ruthra kumar
187ebaaecd Merge pull request #46582 from frappe/version-15-hotfix
chore: release v15
2025-03-19 16:46:43 +05:30
rohitwaghchaure
a2cb9c1791 Merge pull request #46615 from frappe/mergify/bp/version-15-hotfix/pr-46608
fix: fetch bom_no when updating items in sales order (backport #46608)
2025-03-19 16:31:38 +05:30
rohitwaghchaure
0d8842e387 Merge pull request #46614 from frappe/mergify/bp/version-15-hotfix/pr-46573
Fix set landed cost based on pi (backport #46573)
2025-03-19 16:31:09 +05:30
rohitwaghchaure
38213b31da chore: fix conflicts 2025-03-19 15:47:43 +05:30
Mihir Kandoi
e5b2801830 fix: remove duplicate
(cherry picked from commit 386df968c2)

# Conflicts:
#	erpnext/public/js/utils.js
2025-03-19 10:15:18 +00:00
Mihir Kandoi
41d8b26dd2 fix: fetch bom_no when updating items in sales order
(cherry picked from commit 508727a57a)

# Conflicts:
#	erpnext/public/js/utils.js
2025-03-19 10:15:18 +00:00
rohitwaghchaure
5b802ae527 chore: fix conflicts 2025-03-19 15:35:26 +05:30
rohitwaghchaure
1b8e8e92ae Merge pull request #46611 from frappe/mergify/bp/version-15-hotfix/pr-46595
fix: not able to make PR against stand alone Debit Note (backport #46595)
2025-03-19 15:28:57 +05:30
Mihir Kandoi
ec1a3a1e6b fix: take function call outside loop
(cherry picked from commit b3c400f998)
2025-03-19 09:52:28 +00:00
Mihir Kandoi
36ffc2ee67 fix: patch
(cherry picked from commit 7e669c0728)
2025-03-19 09:52:28 +00:00
Mihir Kandoi
56bc26aecc fix: set landed cost based on purchase invoice rate
(cherry picked from commit 75ab5f2bd0)

# Conflicts:
#	erpnext/patches.txt
2025-03-19 09:52:27 +00:00
Marc Ramser
3834d6fbce feat(projects): add option to hide timesheets for project users (#46173)
* feat: add option to hide timesheets for project users

* Added a new "Hide timesheets" checkbox field to Project User doctype that allows to control timesheet visibility for specific users. When enabled, the timesheets section will not be displayed on the project page for that user.

* Update projects.html

(cherry picked from commit f4aba561ce)
2025-03-19 08:05:42 +00:00
Rohit Waghchaure
d62960e925 fix: not able to make PR against stand alone Debit Note
(cherry picked from commit 6a52c30591)
2025-03-19 08:05:33 +00:00
ruthra kumar
c6de50b2a5 Merge pull request #46606 from frappe/mergify/bp/version-15-hotfix/pr-46596
fix: debit in transaction currency (backport #46596)
2025-03-19 12:11:09 +05:30
Rohit Waghchaure
8e19b46bd9 fix: debit in transaction currency
(cherry picked from commit e4acf20a62)
2025-03-19 06:26:26 +00:00
rohitwaghchaure
f6a4855e7f Merge pull request #46594 from frappe/mergify/bp/version-15-hotfix/pr-46593
test: test case for FIFO batch valuation (backport #46593)
2025-03-18 21:23:03 +05:30
Rohit Waghchaure
95718acc9a test: test case for FIFO batch valuation
(cherry picked from commit ad9ac1f058)
2025-03-18 13:50:36 +00:00
rohitwaghchaure
2528acd803 Merge pull request #46592 from frappe/mergify/bp/version-15-hotfix/pr-46588
fix: SABB validation for packed items (backport #46588)
2025-03-18 18:38:50 +05:30
Rohit Waghchaure
2d6626e906 fix: SABB validation for packed items
(cherry picked from commit 3756bf231b)
2025-03-18 12:03:18 +00:00
rohitwaghchaure
a07eb556cf Merge pull request #46584 from frappe/mergify/bp/version-15-hotfix/pr-46575
fix: fetch quality inspection parameter group (backport #46575)
2025-03-18 17:28:33 +05:30
rohitwaghchaure
48edc86845 Merge pull request #46587 from frappe/mergify/bp/version-15-hotfix/pr-46576
fix: repost future sle and gle after capitalization (backport #46576)
2025-03-18 17:27:56 +05:30
rohitwaghchaure
7f5ce4f29d Merge pull request #46585 from frappe/mergify/bp/version-15-hotfix/pr-46554
fix: add validation to rename_subcontracting_fields patch (backport #46554)
2025-03-18 17:27:20 +05:30
rohitwaghchaure
cd7056842d Merge pull request #46589 from frappe/mergify/bp/version-15-hotfix/pr-46579
fix: valuation for moving average with batches (backport #46579)
2025-03-18 17:26:41 +05:30
Rohit Waghchaure
5f1bb1f1ba fix: valuation for moving average with batches
(cherry picked from commit cdfbc73f4c)
2025-03-18 11:05:06 +00:00
rohitwaghchaure
79dacfdef8 Merge pull request #46560 from frappe/mergify/bp/version-15-hotfix/pr-46555
fix: performance issue for item list view (backport #46555)
2025-03-18 16:34:00 +05:30
Khushi Rawat
2144f89624 fix: repost future sle and gle after capitalization (#46576)
(cherry picked from commit 29d77aa19f)
2025-03-18 10:31:47 +00:00
Mihir Kandoi
bc408d979a fix: add validation to rename_subcontracting_fields patch
(cherry picked from commit 6c3117dc0d)
2025-03-18 10:30:41 +00:00
rohitwaghchaure
496f43e7e9 Merge pull request #46556 from frappe/st33974
fix: incorrect production item and bom no in job card
2025-03-18 15:58:26 +05:30
Mihir Kandoi
cd0abbae51 fix: fetch quality inspection parameter group
(cherry picked from commit 0a482c7ea8)
2025-03-18 10:27:30 +00:00
Smit Vora
004ecc53e5 Merge pull request #46578 from frappe/mergify/bp/version-15-hotfix/pr-46515
fix: ensure qty conversion when creating production plan from SO (backport #46515)
2025-03-18 15:00:34 +05:30
Smit Vora
8162fb3e5d fix: ensure qty conversion when creating production plan from SO
(cherry picked from commit 75882cc81c)
2025-03-18 08:56:21 +00:00
rohitwaghchaure
e8047ab2ca chore: fix conflicts 2025-03-18 12:01:11 +05:30
rohitwaghchaure
8dc371dac2 Merge pull request #46558 from frappe/mergify/bp/version-15-hotfix/pr-46553
fix: not able to select the item in the BOM (backport #46553)
2025-03-18 11:59:56 +05:30
rohitwaghchaure
0351faa8c0 Merge pull request #46559 from frappe/mergify/bp/version-15-hotfix/pr-46552
fix: Debit and Credit not equal for Purchase Invoice (backport #46552)
2025-03-18 11:59:38 +05:30
ruthra kumar
7e46845fea Merge pull request #46572 from frappe/mergify/bp/version-15-hotfix/pr-46566
fix: set correct currency for offset account gl entries (backport #46566)
2025-03-18 11:32:05 +05:30
ruthra kumar
e84333e5f2 Merge pull request #46571 from frappe/mergify/bp/version-15-hotfix/pr-46508
fix: use base currency total for UAE VAT 201 report (backport #46508)
2025-03-18 11:24:29 +05:30
ruthra kumar
e6dd3f3e64 fix: set correct currency for offset account gl entries
(cherry picked from commit c32e11e69d)
2025-03-18 05:45:13 +00:00
ruthra kumar
ec43ca97cb test: report ouput on foreign currency PI
(cherry picked from commit e80129627a)
2025-03-18 05:30:10 +00:00
ruthra kumar
3e2749d6d5 fix: use base currency total
(cherry picked from commit 46f4babcd0)
2025-03-18 05:30:09 +00:00
mergify[bot]
01bab8f22b perf: faster count estimation (backport #46550) (#46551)
perf: faster count estimation (#46550)

These count queries themselves take quite a long time. `estimate_count`
uses info_schema stats to guess the time.

Co-authored-by: Nabin Hait <nabinhait@gmail.com>
(cherry picked from commit e47a87839b)

Co-authored-by: Ankush Menat <ankush@frappe.io>
2025-03-17 21:23:30 +05:30
Ejaaz Khan
972c96b682 Merge pull request #46565 from frappe/mergify/bp/version-15-hotfix/pr-46564
refactor: remove default print format from sales invoice (backport #46564)
2025-03-17 20:52:46 +05:30
Ejaaz Khan
7cfd7e6539 refactor: remove default print format from sales invoice
(cherry picked from commit f10d1f2b1f)
2025-03-17 14:38:43 +00:00
ruthra kumar
bcd9fd090d Merge pull request #46562 from frappe/mergify/bp/version-15-hotfix/pr-46557
fix(Transaction Deletion Record): sql syntax error while deleting lead address (backport #46557)
2025-03-17 17:00:37 +05:30
venkat102
ea68caec7d fix(Transaction Deletion Record): sql syntax error while fetching lead address
(cherry picked from commit af0d6eeae8)
2025-03-17 11:09:38 +00:00
Rohit Waghchaure
34d6e4bdaa fix: performance issue for item list view
(cherry picked from commit d758fde881)

# Conflicts:
#	erpnext/stock/doctype/item_default/item_default.json
2025-03-17 11:08:38 +00:00
rohitwaghchaure
c7b8514c24 Merge pull request #46549 from frappe/mergify/bp/version-15-hotfix/pr-46504
fix: dashboard link for QC from PR (backport #46504)
2025-03-17 16:37:21 +05:30
Rohit Waghchaure
46b6e621c2 fix: Debit and Credit not equal for Purchase Invoice
(cherry picked from commit ecb31b7c9f)
2025-03-17 11:07:17 +00:00
Rohit Waghchaure
59c653ef3f fix: not able to select the item in the BOM
(cherry picked from commit 96d0cd23f1)
2025-03-17 11:07:16 +00:00
Mihir Kandoi
d071a6c900 fix: incorrect production item and bom no in job card 2025-03-17 16:06:54 +05:30
ruthra kumar
61e126901e Merge pull request #46523 from frappe/revert-46475-mergify/bp/version-15-hotfix/pr-46417
Revert "fix: error when creating delivery note from pick list (backport #46417)"
2025-03-17 15:15:10 +05:30
Rohit Waghchaure
426222d8e0 fix: dashboard link for QC from PR
(cherry picked from commit 551f89f14b)
2025-03-17 04:36:59 +00:00
Sagar Vora
ad24867699 Merge pull request #46534 from frappe/mergify/bp/version-15-hotfix/pr-46533
fix: exclude current doc when checking for duplicate (backport #46533)
2025-03-15 00:37:55 +05:30
Sagar Vora
b638aed758 fix: exclude current doc when checking for duplicate
(cherry picked from commit d8ef5e4d58)
2025-03-14 18:37:47 +00:00
Shariq Ansari
1a9873bc55 Merge pull request #46530 from frappe/mergify/bp/version-15-hotfix/pr-46529
fix: also consider CRM Deal as party type for ERPNext CRM Integration (backport #46529)
2025-03-14 16:07:27 +05:30
Shariq Ansari
65a80cffe7 fix: also consider CRM Deal as party type for ERPNext CRM Integration
(cherry picked from commit 04edbf7efe)
2025-03-14 10:34:11 +00:00
Mihir Kandoi
18e29de0c8 Merge pull request #46527 from frappe/mergify/bp/version-15-hotfix/pr-46513 2025-03-14 13:27:30 +05:30
Mihir Kandoi
e2418101ab fix: get bom_no from sales order item and material request item
(cherry picked from commit ac354505ef)
2025-03-14 07:36:47 +00:00
Mihir Kandoi
62c9181651 Merge pull request #46525 from frappe/mergify/bp/version-15-hotfix/pr-46514
fix: UOM conversion error when creating pick list from material trans… (backport #46514)
2025-03-14 13:04:43 +05:30
Mihir Kandoi
d0008ac6df Merge pull request #46524 from frappe/mergify/bp/version-15-hotfix/pr-46512
fix: hide subcontracted qty field if PO is not subcontracted (backport #46512)
2025-03-14 13:04:10 +05:30
Mihir Kandoi
be3e083e7d fix: wrong field mapping
(cherry picked from commit 8411e2e01f)
2025-03-14 07:13:46 +00:00
Mihir Kandoi
2f3dcc2137 fix: UOM conversion error when creating pick list from material transfer request
(cherry picked from commit 840ea070a9)
2025-03-14 07:13:46 +00:00
Mihir Kandoi
62feec5cc3 fix: hide subcontracted qty field if PO is not subcontracted
(cherry picked from commit 6e8521d761)
2025-03-14 07:12:44 +00:00
Nabin Hait
0852533751 Revert "fix: error when creating delivery note from pick list (backport #46417)" 2025-03-14 12:33:37 +05:30
ruthra kumar
99f59c0410 Merge pull request #46521 from frappe/mergify/bp/version-15-hotfix/pr-46497
fix: use `party` explicitly instead of party_field (backport #46497)
2025-03-14 11:08:05 +05:30
Sanket322
5dd5784716 fix: use party explicitly
(cherry picked from commit 5057e3fe30)
2025-03-14 04:52:33 +00:00
ruthra kumar
5ad3e5b5c8 Merge pull request #46520 from frappe/mergify/bp/version-15-hotfix/pr-46488
refactor: replace get_list with get_all for dynamic link child access (backport #46488)
2025-03-14 10:11:05 +05:30
Sugesh393
7fb26f802c refactor: replace get_list with get_all for dynamic link child access
(cherry picked from commit 8f7f0b81f6)
2025-03-14 04:22:25 +00:00
ruthra kumar
27d6659962 Merge pull request #46480 from frappe/mergify/bp/version-15-hotfix/pr-46473
fix: use shipping_address_name for address validation in sales invoice (backport #46473)
2025-03-14 09:50:37 +05:30
ruthra kumar
3737b4a300 refactor(test): unset billing address 2025-03-14 09:29:43 +05:30
ruthra kumar
1065e483b2 Merge pull request #46510 from aerele/fix/item-stock-difference-account
fix: set stock adjustment account in difference account (backport #45606)
2025-03-14 09:23:46 +05:30
Bhavan23
6202e302b1 fix: set stock adjustment account in difference account 2025-03-13 16:45:18 +05:30
mergify[bot]
2a788a4fb1 refactor: print receipt on order complete on pos (backport #46501) (#46507)
* refactor: print receipt on order complete on pos (#46501)

(cherry picked from commit 0552209310)

# Conflicts:
#	erpnext/selling/page/point_of_sale/pos_past_order_summary.js

* chore: resolve conflict

---------

Co-authored-by: Diptanil Saha <diptanil@frappe.io>
2025-03-13 14:30:38 +05:30
mergify[bot]
32335da839 fix: add parenttype condition to payment schedule query in accounts receivable report (backport #46370) (#46499)
Fix: add parenttype condition to payment schedule query in accounts receivable report (#46370)

fix: add parenttype condition to payment schedule query in accounts receivable report
(cherry picked from commit f311a0fc1c)

Co-authored-by: Shanuka Hewage <89955436+Shanuka-98@users.noreply.github.com>
2025-03-13 12:03:46 +05:30
ruthra kumar
c47cc0572b Merge pull request #46493 from frappe/mergify/bp/version-15-hotfix/pr-46492
fix: using `in` for lookup in list instead of directly assigning (backport #46492)
2025-03-13 08:41:22 +05:30
ruthra kumar
1ec971f805 Merge pull request #46496 from frappe/mergify/bp/version-15/pr-46423
Revert "fix: Show Credit Note amount in credit note column" (backport #46423)
2025-03-13 08:20:53 +05:30
ruthra kumar
a6e92d7d16 Merge pull request #46495 from frappe/mergify/bp/version-15-hotfix/pr-46423
Revert "fix: Show Credit Note amount in credit note column" (backport #46423)
2025-03-13 08:12:37 +05:30
ruthra kumar
4d7071299e Revert "fix: Show Credit Note amount in credit note column"
(cherry picked from commit 5a9767ca67)
2025-03-13 02:35:11 +00:00
ruthra kumar
0223651b5b Revert "fix: Show Credit Note amount in credit note column"
(cherry picked from commit 5a9767ca67)
2025-03-13 02:28:08 +00:00
Sanket Shah
950656d6f7 fix: using in for lookup in list instead of directly assigning (#46492)
fix: using in for lookup in list instead of assigning

Co-authored-by: Sanket322 <shahsanket322003.com>
(cherry picked from commit 38955af802)
2025-03-12 17:08:05 +00:00
Frappe PR Bot
08f47b626c chore(release): Bumped to Version 15.54.4
## [15.54.4](https://github.com/frappe/erpnext/compare/v15.54.3...v15.54.4) (2025-03-12)

### Bug Fixes

* `base_net_rate` Required to Check Valid Range (backport [#46332](https://github.com/frappe/erpnext/issues/46332)) ([#46382](https://github.com/frappe/erpnext/issues/46382)) ([877d5bd](877d5bd3aa))
* **account:** update account number from parent company ([428aedc](428aedc29c))
* Allow rename prospect doctype ([#46352](https://github.com/frappe/erpnext/issues/46352)) ([de46165](de46165768))
* auto email report creation ([#46343](https://github.com/frappe/erpnext/issues/46343)) ([5cc251a](5cc251a172))
* backport translations from develop ([#46428](https://github.com/frappe/erpnext/issues/46428)) ([9c70376](9c703765a1))
* calculate due date based on payment term (backport [#46416](https://github.com/frappe/erpnext/issues/46416)) ([#46479](https://github.com/frappe/erpnext/issues/46479)) ([7f14744](7f147446df))
* change fieldname for cash_flow to export (backport [#46353](https://github.com/frappe/erpnext/issues/46353)) ([#46366](https://github.com/frappe/erpnext/issues/46366)) ([23c4252](23c4252b9b))
* check if set_landed_cost_based_on_purchase_invoice_rate is enabled before running patch ([7047fe2](7047fe2681))
* clear cashe on employee hierarchy change to reflect updated permissions ([4dfdb2b](4dfdb2b0a1))
* consider account freeze date in recalculate_amount_difference_field patch ([8b67527](8b67527900))
* consider stock freeze date in recalculate_amount_difference_field patch ([8264d42](8264d42cd9))
* credit note creation during pos invoice consolidation (backport [#46277](https://github.com/frappe/erpnext/issues/46277)) ([#46469](https://github.com/frappe/erpnext/issues/46469)) ([a4b8b4c](a4b8b4c771))
* do not recalculate qty for batch items during reposting ([bac36f3](bac36f342d))
* doctype name ([1dcbdf3](1dcbdf3257))
* enable no copy for serial no field ([3f9df2f](3f9df2fb2d))
* error in production analytics report ([db6ae61](db6ae61935))
* error when creating delivery note from pick list ([#46417](https://github.com/frappe/erpnext/issues/46417)) ([0b92101](0b921016ff))
* filter batches that going to be zero ([ac97489](ac97489a32))
* incorrect category in list ([002685f](002685fc89))
* make 'company_tax_id' and 'company_fiscal_code' as mandatory ([229f4d3](229f4d3d92))
* not able to save work order with alternative item ([9554a49](9554a49bbd))
* **payment entry:** fetch default bank account based on company (backport [#46379](https://github.com/frappe/erpnext/issues/46379)) ([#46471](https://github.com/frappe/erpnext/issues/46471)) ([1371199](13711993fe))
* pricing rule not ignored in Sales Order ([#46248](https://github.com/frappe/erpnext/issues/46248)) ([8def42f](8def42f751))
* rare precision issue preventing submission of subcontracting order ([6419d02](6419d020a1))
* recalculate_amount_difference_field patch ([f247f02](f247f02e49))
* remove no copy for serial no field of purchase receipt item ([baa564f](baa564fc94))
* rename sla fields patch ([73f11cf](73f11cf19e))
* rename sla fields patch ([#46465](https://github.com/frappe/erpnext/issues/46465)) ([5edbd88](5edbd8851a))
* rename_sla_fields patch ([7bc7557](7bc7557018))
* run bank reconciliation as a background job to prevent request timeout ([739cd18](739cd18604))
* set correct account currency for deferred expence account in PI ([f96848a](f96848a3b9))
* show remaining qty on 'Complete Job' button instead of full qty ([79e6550](79e6550321))
* sla fields patch ([0d044bc](0d044bc5bb))
* stock balance in and out value ([c2001e9](c2001e9c67))
* **test:** incorrect transaction exchange rate in test case ([b76c968](b76c96820e))
* typo in sales_invoice_print ([b610621](b6106212c1))
* uom reverts to default upon selecting do not explode ([#45693](https://github.com/frappe/erpnext/issues/45693)) ([6b1d209](6b1d20970e))
* validate accounting dimension company in Journal Entry & Stock Entry (backport [#46204](https://github.com/frappe/erpnext/issues/46204)) ([#46369](https://github.com/frappe/erpnext/issues/46369)) ([c816f9b](c816f9bd0a))
* validate last_gl_update exists before comparing (backport [#46464](https://github.com/frappe/erpnext/issues/46464)) ([#46468](https://github.com/frappe/erpnext/issues/46468)) ([3cef94e](3cef94e2ed))
* validations and account type filter for `Tax Withholding Category` ([#46207](https://github.com/frappe/erpnext/issues/46207)) ([cc30a01](cc30a01898))
2025-03-12 14:37:29 +00:00
ruthra kumar
0283f7526c Merge pull request #46444 from frappe/version-15-hotfix
chore: release v15
2025-03-12 20:05:56 +05:30
ruthra kumar
3ad451dd6e Merge branch 'version-15' into version-15-hotfix 2025-03-12 19:48:08 +05:30
rohitwaghchaure
9e409bde2e Merge pull request #46486 from frappe/st33357
fix: enable no copy for serial no field
2025-03-12 19:39:32 +05:30
ruthra kumar
8459166323 Merge pull request #46482 from frappe/mergify/bp/version-15-hotfix/pr-46207
fix: validations and account type filter for `Tax Withholding Category` (backport #46207)
2025-03-12 17:46:04 +05:30
ruthra kumar
e1328de712 Merge pull request #46487 from frappe/mergify/bp/version-15-hotfix/pr-46251
fix(bank-reconciliation): run bank reconciliation as a background job (backport #46251)
2025-03-12 17:45:45 +05:30
mergify[bot]
d3a2350b3e fix(invoice):validate return invoice qty (backport #46451) (#46481)
fix(invoice):validate return invoice qty (#46451)

* fix(invoice): validate return quantity when update stock is unchecked

* test: add unit test for validating fully returned invoice quantity

(cherry picked from commit ba96c86576)

Co-authored-by: Bhavansathru <122002510+Bhavan23@users.noreply.github.com>
2025-03-12 17:23:26 +05:30
Bhavan23
739cd18604 fix: run bank reconciliation as a background job to prevent request timeout
(cherry picked from commit a29c6a5aea)
2025-03-12 11:52:26 +00:00
ruthra kumar
e61cc9b12e Merge pull request #46483 from frappe/mergify/bp/version-15-hotfix/pr-46248
fix: pricing rule not ignored in Sales Order (backport #46248)
2025-03-12 17:13:13 +05:30
Mihir Kandoi
baa564fc94 fix: remove no copy for serial no field of purchase receipt item 2025-03-12 17:11:14 +05:30
rohitwaghchaure
a55ec56fbf Merge pull request #46484 from frappe/45440
fix: show remaining qty on 'Complete Job' button instead of full qty
2025-03-12 16:44:57 +05:30
Mihir Kandoi
3f9df2fb2d fix: enable no copy for serial no field 2025-03-12 16:35:50 +05:30
mergify[bot]
7f147446df fix: calculate due date based on payment term (backport #46416) (#46479)
fix: calculate due date based on payment term (#46416)

(cherry picked from commit 9e808c832f)

Co-authored-by: Sudharsanan Ashok <135326972+Sudharsanan11@users.noreply.github.com>
2025-03-12 16:30:14 +05:30
Sugesh G
8def42f751 fix: pricing rule not ignored in Sales Order (#46248)
* fix: pricing rule not ignored in Sales Order

* test: update parameter do_not_submit to do_not_save

(cherry picked from commit f8c659d8d5)
2025-03-12 10:58:47 +00:00
Mihir Kandoi
79e6550321 fix: show remaining qty on 'Complete Job' button instead of full qty 2025-03-12 16:27:33 +05:30
Priyansh Shah
cc30a01898 fix: validations and account type filter for Tax Withholding Category (#46207)
fix: validations and account type filter for tax withholding category
(cherry picked from commit d371236684)
2025-03-12 10:52:32 +00:00
Sugesh G
38dabdf584 fix: use shipping_address_name for address validation in sales invoice (#46473)
* fix: validate address and contact related to party

* fix: solve unboundlocal error

* refactor: improve variable scope

* refactor: translatable strings

* fix: use shipping_address_name for address validation in sales invoice

* test: add new unit test for address and contact validation

* chore: to avoid keyerror

---------

Co-authored-by: ruthra kumar <ruthra@erpnext.com>
(cherry picked from commit 0bdb81db53)
2025-03-12 10:44:37 +00:00
Ninad Parikh
877d5bd3aa fix: base_net_rate Required to Check Valid Range (backport #46332) (#46382)
fix: `base_net_rate` required to check valid range
2025-03-12 16:12:44 +05:30
Mihir Kandoi
0b53bd3e9a Merge pull request #46475 from frappe/mergify/bp/version-15-hotfix/pr-46417
fix: error when creating delivery note from pick list (backport #46417)
2025-03-12 16:09:50 +05:30
Mihir Kandoi
3606fe8fba Merge pull request #46467 from frappe/mergify/bp/version-15-hotfix/pr-46465
fix: rename sla fields patch (backport #46465)
2025-03-12 16:09:37 +05:30
Mihir Kandoi
0b921016ff fix: error when creating delivery note from pick list (#46417)
(cherry picked from commit 67e9389a02)
2025-03-12 10:00:53 +00:00
rohitwaghchaure
4d49608a68 Merge pull request #46474 from frappe/mergify/bp/version-15-hotfix/pr-46470
fix: do not recalculate qty for batch items during reposting (backport #46470)
2025-03-12 12:39:06 +05:30
Rohit Waghchaure
bac36f342d fix: do not recalculate qty for batch items during reposting
(cherry picked from commit 0753c018d2)
2025-03-12 06:48:00 +00:00
mergify[bot]
a4b8b4c771 fix: credit note creation during pos invoice consolidation (backport #46277) (#46469)
* fix: credit note creation during pos invoice consolidation (#46277)

* fix: credit note creation during pos invoice consolidation

* fix: added check to skip merging empty list of return pos invoices

* fix: sql query

* fix: using return invoice name instead of return invoice object

* fix: added pos invoice field in sales invoice item

(cherry picked from commit 8ba4ac3b86)

# Conflicts:
#	erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json

* chore: resolve conflict

---------

Co-authored-by: Diptanil Saha <diptanil@frappe.io>
2025-03-12 11:41:41 +05:30
mergify[bot]
3cef94e2ed fix: validate last_gl_update exists before comparing (backport #46464) (#46468)
fix: validate last_gl_update exists before comparing (#46464)

(cherry picked from commit 0a5ca0c35f)

Co-authored-by: Dany Robert <rtdany10@gmail.com>
2025-03-12 11:05:24 +05:30
mergify[bot]
13711993fe fix(payment entry): fetch default bank account based on company (backport #46379) (#46471)
fix(payment entry): fetch default bank account based on company (#46379)

(cherry picked from commit b72f6f5a3d)

Co-authored-by: Venkatesh <47534423+venkat102@users.noreply.github.com>
2025-03-12 11:05:08 +05:30
Nabin Hait
24678b0e24 chore: conflicts 2025-03-12 10:38:26 +05:30
Mihir Kandoi
5edbd8851a fix: rename sla fields patch (#46465)
* fix: rename sla fields patch

* fix: rerun patch

(cherry picked from commit 8bce42e633)

# Conflicts:
#	erpnext/patches.txt
2025-03-12 05:04:52 +00:00
rohitwaghchaure
6582e4c5f9 Merge pull request #46462 from frappe/mergify/bp/version-15-hotfix/pr-46455
fix: error in production analytics report (backport #46455)
2025-03-12 09:50:35 +05:30
rohitwaghchaure
fd1c1ba35e Merge pull request #46461 from frappe/mergify/bp/version-15-hotfix/pr-46460
fix: rename sla fields patch (backport #46460)
2025-03-12 09:49:46 +05:30
Mihir Kandoi
db6ae61935 fix: error in production analytics report
(cherry picked from commit 03e66468f6)
2025-03-11 19:00:35 +00:00
Mihir Kandoi
73f11cf19e fix: rename sla fields patch
(cherry picked from commit b6c18849c5)
2025-03-11 18:57:17 +00:00
rohitwaghchaure
8f7dc827ea Merge pull request #46459 from frappe/mergify/bp/version-15-hotfix/pr-46452
fix: sla fields patch (backport #46452)
2025-03-12 00:01:35 +05:30
Mihir Kandoi
0d044bc5bb fix: sla fields patch
(cherry picked from commit d653899372)
2025-03-11 18:08:24 +00:00
rohitwaghchaure
14ee2d239a Merge pull request #46441 from frappe/mergify/bp/version-15-hotfix/pr-46436
fix: filter batches that going to be zero (backport #46436)
2025-03-11 23:38:21 +05:30
Raffael Meyer
fc8eeaf4f6 Merge pull request #46457 from frappe/mergify/bp/version-15-hotfix/pr-46453
ci: ignore PRs labeled with "skip-release-notes" when generating release notes (backport #46453)
2025-03-11 17:51:58 +01:00
barredterra
aad8c88532 ci: ignore PRs labeled with "skip-release-notes" when generating release notes
(cherry picked from commit 57007bf937)
2025-03-11 16:35:20 +00:00
ruthra kumar
e783536ba0 Merge pull request #46450 from frappe/mergify/bp/version-15-hotfix/pr-46398
chore: rename print and stationery account (backport #46398)
2025-03-11 18:12:19 +05:30
chethank1407
ee3feba386 chore: rename print and stationery account
(cherry picked from commit 615997b774)
2025-03-11 12:03:42 +00:00
ruthra kumar
cb9be11448 Merge pull request #46447 from frappe/mergify/bp/version-15-hotfix/pr-46344
fix: make 'company_tax_id' and 'company_fiscal_code' as mandatory (backport #46344)
2025-03-11 17:31:19 +05:30
ruthra kumar
31dc6021e2 chore: translatable strings
(cherry picked from commit 121798ba85)
2025-03-11 11:42:30 +00:00
Bhavan23
229f4d3d92 fix: make 'company_tax_id' and 'company_fiscal_code' as mandatory
(cherry picked from commit abd044eb0d)
2025-03-11 11:42:19 +00:00
ruthra kumar
c25862a85f Merge pull request #46446 from frappe/mergify/bp/version-15-hotfix/pr-45818
fix: set correct account currency for deferred expense account (backport #45818)
2025-03-11 16:50:55 +05:30
vishakhdesai
f96848a3b9 fix: set correct account currency for deferred expence account in PI
(cherry picked from commit 398083853c)
2025-03-11 11:06:14 +00:00
Rohit Waghchaure
ac97489a32 fix: filter batches that going to be zero
(cherry picked from commit aba512c1c6)
2025-03-11 08:02:49 +00:00
ruthra kumar
02ff406b7c Merge pull request #46439 from frappe/mergify/bp/version-15-hotfix/pr-46372
fix(account): update account number from parent company (backport #46372)
2025-03-11 11:19:33 +05:30
venkat102
428aedc29c fix(account): update account number from parent company
(cherry picked from commit 4a4894bc01)
2025-03-11 05:32:15 +00:00
ruthra kumar
6af24dca6e Merge pull request #46432 from frappe/mergify/bp/version-15-hotfix/pr-46427
fix: not able to save work order with alternative item (backport #46414) (backport #46427)
2025-03-11 11:02:04 +05:30
ruthra kumar
8980eb9b9d Merge pull request #46437 from frappe/mergify/bp/version-15-hotfix/pr-46426
fix: clear cashe on employee hierarchy change (backport #46426)
2025-03-11 10:58:50 +05:30
Asmita Hase
4dfdb2b0a1 fix: clear cashe on employee hierarchy change to reflect updated permissions
(cherry picked from commit 6789578b27)
2025-03-11 05:13:04 +00:00
Rohit Waghchaure
9554a49bbd fix: not able to save work order with alternative item
(cherry picked from commit 6ca1f9bc73)
(cherry picked from commit ac7fc608aa)
2025-03-10 17:44:57 +00:00
rohitwaghchaure
5b69445294 Merge pull request #46420 from frappe/mergify/bp/version-15-hotfix/pr-46418
fix: stock balance in and out value (backport #46418)
2025-03-10 23:13:37 +05:30
Raffael Meyer
9c703765a1 fix: backport translations from develop (#46428) 2025-03-10 14:32:19 +01:00
rohitwaghchaure
043539fcdb chore: fix conflicts 2025-03-10 17:37:29 +05:30
ruthra kumar
54a76d8932 Merge pull request #46425 from frappe/mergify/bp/version-15-hotfix/pr-46407
fix: typo in sales_invoice_print (backport #46407)
2025-03-10 16:55:28 +05:30
mahsem
b6106212c1 fix: typo in sales_invoice_print
(cherry picked from commit f7bcae83e4)
2025-03-10 11:18:23 +00:00
Rohit Waghchaure
c2001e9c67 fix: stock balance in and out value
(cherry picked from commit e917bd5334)

# Conflicts:
#	erpnext/stock/report/stock_balance/stock_balance.py
2025-03-10 10:06:09 +00:00
Frappe PR Bot
47429095a2 chore(release): Bumped to Version 15.54.3
## [15.54.3](https://github.com/frappe/erpnext/compare/v15.54.2...v15.54.3) (2025-03-09)

### Bug Fixes

* consider account freeze date in recalculate_amount_difference_field patch ([34f03d6](34f03d608a))
* consider stock freeze date in recalculate_amount_difference_field patch ([a18721d](a18721d21c))
2025-03-09 11:04:11 +00:00
rohitwaghchaure
2f3f87fe7e Merge pull request #46403 from frappe/mergify/bp/version-15/pr-46402
fix: consider account freeze date in recalculate_amount_difference_fi… (backport #46395) (backport #46402)
2025-03-09 16:32:52 +05:30
Mihir Kandoi
2b4dfca3ff chore: resolve conflicts
(cherry picked from commit 985fb5dfdc)
2025-03-08 17:16:43 +00:00
Mihir Kandoi
a18721d21c fix: consider stock freeze date in recalculate_amount_difference_field patch
(cherry picked from commit cd72532789)
(cherry picked from commit 8264d42cd9)
2025-03-08 17:16:43 +00:00
Mihir Kandoi
34f03d608a fix: consider account freeze date in recalculate_amount_difference_field patch
(cherry picked from commit 696f931678)

# Conflicts:
#	erpnext/patches/v15_0/recalculate_amount_difference_field.py
(cherry picked from commit 8b67527900)
2025-03-08 17:16:43 +00:00
rohitwaghchaure
b786cd30e6 Merge pull request #46402 from frappe/mergify/bp/version-15-hotfix/pr-46395
fix: consider account freeze date in recalculate_amount_difference_fi… (backport #46395)
2025-03-08 22:45:06 +05:30
Mihir Kandoi
985fb5dfdc chore: resolve conflicts 2025-03-08 22:22:12 +05:30
Mihir Kandoi
8264d42cd9 fix: consider stock freeze date in recalculate_amount_difference_field patch
(cherry picked from commit cd72532789)
2025-03-08 16:28:33 +00:00
Mihir Kandoi
8b67527900 fix: consider account freeze date in recalculate_amount_difference_field patch
(cherry picked from commit 696f931678)

# Conflicts:
#	erpnext/patches/v15_0/recalculate_amount_difference_field.py
2025-03-08 16:28:32 +00:00
Frappe PR Bot
2ce8299bc8 chore(release): Bumped to Version 15.54.2
## [15.54.2](https://github.com/frappe/erpnext/compare/v15.54.1...v15.54.2) (2025-03-08)

### Bug Fixes

* incorrect category in list ([3bdd4ce](3bdd4ce116))
* **test:** incorrect transaction exchange rate in test case ([3015628](3015628519))
2025-03-08 07:42:44 +00:00
ruthra kumar
84b03485d6 Merge pull request #46397 from frappe/mergify/bp/version-15/pr-46064
fix: Debit and Credit mismatch on transaction currency debit and credit values (backport #46064)
2025-03-08 13:11:25 +05:30
ruthra kumar
d0b14f1907 chore: resolve conflict 2025-03-08 12:28:49 +05:30
ruthra kumar
cd1803a74d refactor: internal transfer gl
(cherry picked from commit f1d8feec15)
2025-03-08 06:56:37 +00:00
ruthra kumar
a1cf27ec17 test: assert total debit and credit for trx currency
(cherry picked from commit 55d0636123)
2025-03-08 06:56:37 +00:00
ruthra kumar
61880a311a refactor: handle rounding diff for trx currency dr and cr
(cherry picked from commit 455a55b2ce)
2025-03-08 06:56:37 +00:00
ruthra kumar
2d290b153d refactor: trx currency dr and cr for tax rows and item rows
(cherry picked from commit 4cd3f3531c)
2025-03-08 06:56:36 +00:00
ruthra kumar
cacb720556 refactor: convert tax amount using exchange rate
(cherry picked from commit 7528ef147a)
2025-03-08 06:56:36 +00:00
ruthra kumar
3bdd4ce116 fix: incorrect category in list
(cherry picked from commit 6545467aec)
2025-03-08 06:56:36 +00:00
ruthra kumar
c479998cd6 chore: typo
(cherry picked from commit bc792c61e9)
2025-03-08 06:56:36 +00:00
ruthra kumar
501e388186 refactor: isolate to specific doctypes
(cherry picked from commit b348aa3b37)
2025-03-08 06:56:35 +00:00
ruthra kumar
af45ec0d6d refactor(test): save first to let the tax table populate
(cherry picked from commit 23d465805b)
2025-03-08 06:56:35 +00:00
ruthra kumar
3015628519 fix(test): incorrect transaction exchange rate in test case
(cherry picked from commit a31770d122)
2025-03-08 06:56:35 +00:00
ruthra kumar
8b6eea6349 refactor: set transaction currency and rate before gl map
(cherry picked from commit ceca5b4c72)
2025-03-08 06:56:34 +00:00
ruthra kumar
81c29e8f8c refactor: handle payment entry
(cherry picked from commit 5c86e3ce85)
2025-03-08 06:56:34 +00:00
ruthra kumar
04758d3de3 refactor: handle Journal entries
(cherry picked from commit 9f3847c0f8)
2025-03-08 06:56:34 +00:00
ruthra kumar
615b0c40a3 refactor: move utility method to controller
(cherry picked from commit d1d06885dc)
2025-03-08 06:56:34 +00:00
ruthra kumar
231abab321 refactor: set transaction currency dr/cr in sales invoice
(cherry picked from commit 3e292ef2cb)

# Conflicts:
#	erpnext/accounts/doctype/sales_invoice/sales_invoice.py
2025-03-08 06:56:33 +00:00
ruthra kumar
fff3b1e84e refactor: handle stocked items
(cherry picked from commit ee93ed8c97)
2025-03-08 06:56:33 +00:00
ruthra kumar
5299a1032b refactor: handle stocked items
(cherry picked from commit 7ff3977394)
2025-03-08 06:56:33 +00:00
ruthra kumar
1e5fbc0a48 refactor: set tr currency dr & cr directly on parent document
(cherry picked from commit e9af567033)
2025-03-08 06:56:32 +00:00
ruthra kumar
5c47c35a0f refactor: use highest precision for storing exc rate
(cherry picked from commit b115bf2e2a)
2025-03-08 06:56:32 +00:00
ruthra kumar
2bf910a786 Merge pull request #46396 from frappe/mergify/bp/version-15-hotfix/pr-46064
fix: Debit and Credit mismatch on transaction currency debit and credit values (backport #46064)
2025-03-08 12:25:57 +05:30
ruthra kumar
0b8673777a chore: resolve conflict 2025-03-08 12:11:54 +05:30
ruthra kumar
8f4c1e7169 refactor: internal transfer gl
(cherry picked from commit f1d8feec15)
2025-03-08 06:36:37 +00:00
ruthra kumar
f303245fae test: assert total debit and credit for trx currency
(cherry picked from commit 55d0636123)
2025-03-08 06:36:37 +00:00
ruthra kumar
cd21e5c652 refactor: handle rounding diff for trx currency dr and cr
(cherry picked from commit 455a55b2ce)
2025-03-08 06:36:37 +00:00
ruthra kumar
57e0f73595 refactor: trx currency dr and cr for tax rows and item rows
(cherry picked from commit 4cd3f3531c)
2025-03-08 06:36:37 +00:00
ruthra kumar
2c73e31742 refactor: convert tax amount using exchange rate
(cherry picked from commit 7528ef147a)
2025-03-08 06:36:36 +00:00
ruthra kumar
002685fc89 fix: incorrect category in list
(cherry picked from commit 6545467aec)
2025-03-08 06:36:36 +00:00
ruthra kumar
38a3a43ba5 chore: typo
(cherry picked from commit bc792c61e9)
2025-03-08 06:36:36 +00:00
ruthra kumar
07f938cc10 refactor: isolate to specific doctypes
(cherry picked from commit b348aa3b37)
2025-03-08 06:36:35 +00:00
ruthra kumar
5c013172f9 refactor(test): save first to let the tax table populate
(cherry picked from commit 23d465805b)
2025-03-08 06:36:35 +00:00
ruthra kumar
b76c96820e fix(test): incorrect transaction exchange rate in test case
(cherry picked from commit a31770d122)
2025-03-08 06:36:35 +00:00
ruthra kumar
1d56931050 refactor: set transaction currency and rate before gl map
(cherry picked from commit ceca5b4c72)
2025-03-08 06:36:34 +00:00
ruthra kumar
66dc79ceb5 refactor: handle payment entry
(cherry picked from commit 5c86e3ce85)
2025-03-08 06:36:34 +00:00
ruthra kumar
00cbc89b5f refactor: handle Journal entries
(cherry picked from commit 9f3847c0f8)
2025-03-08 06:36:33 +00:00
ruthra kumar
d7baa451e3 refactor: move utility method to controller
(cherry picked from commit d1d06885dc)
2025-03-08 06:36:33 +00:00
ruthra kumar
e0b5386bf0 refactor: set transaction currency dr/cr in sales invoice
(cherry picked from commit 3e292ef2cb)

# Conflicts:
#	erpnext/accounts/doctype/sales_invoice/sales_invoice.py
2025-03-08 06:36:33 +00:00
ruthra kumar
133dca1824 refactor: handle stocked items
(cherry picked from commit ee93ed8c97)
2025-03-08 06:36:32 +00:00
ruthra kumar
eb0df50f1b refactor: handle stocked items
(cherry picked from commit 7ff3977394)
2025-03-08 06:36:32 +00:00
ruthra kumar
5761cfb3d5 refactor: set tr currency dr & cr directly on parent document
(cherry picked from commit e9af567033)
2025-03-08 06:36:32 +00:00
ruthra kumar
568b582b6a refactor: use highest precision for storing exc rate
(cherry picked from commit b115bf2e2a)
2025-03-08 06:36:31 +00:00
Shariq Ansari
d115c1c156 Merge pull request #46365 from frappe/mergify/bp/version-15-hotfix/pr-46352
fix: Allow rename prospect doctype (backport #46352)
2025-03-07 17:12:22 +05:30
Nabin Hait
4e688778dc chore: linter issue 2025-03-07 10:28:52 +05:30
Mihir Kandoi
b5890c1d55 Merge pull request #46376 from frappe/mergify/bp/version-15-hotfix/pr-46374 2025-03-06 23:00:13 +05:30
Mihir Kandoi
6419d020a1 fix: rare precision issue preventing submission of subcontracting order
(cherry picked from commit 33b71544db)
2025-03-06 16:46:04 +00:00
Nabin Hait
60364f6dc9 chore: conflicts 2025-03-06 18:14:09 +05:30
mergify[bot]
23c4252b9b fix: change fieldname for cash_flow to export (backport #46353) (#46366)
fix: change fieldname for cash_flow to export (#46353)

fix: change fieldname for cash_flow

Co-authored-by: Sanket322 <shahsanket322003.com>
(cherry picked from commit 606dcb0ad1)

Co-authored-by: Sanket Shah <113279972+Sanket322@users.noreply.github.com>
2025-03-06 18:12:31 +05:30
mergify[bot]
c816f9bd0a fix: validate accounting dimension company in Journal Entry & Stock Entry (backport #46204) (#46369)
fix: validate accounting dimension company in Journal Entry & Stock Entry (#46204)

* fix: validate accounting dimension company in journal entry and stock entry

* test: update test cases to validate company-based accounting dimension

* fix(test): ensure 'Pick List' company matches 'Delivery Note' to prevent test failures

* chore: remove redundant lines of code

(cherry picked from commit 7b6ebad9e6)

Co-authored-by: Bhavansathru <122002510+Bhavan23@users.noreply.github.com>
2025-03-06 18:12:06 +05:30
Shariq Ansari
de46165768 fix: Allow rename prospect doctype (#46352)
fix: allow rename prospect doctype
(cherry picked from commit 884709deb8)

# Conflicts:
#	erpnext/crm/doctype/prospect/prospect.json
2025-03-06 11:50:08 +00:00
Justine Jay
5cc251a172 fix: auto email report creation (#46343)
* fix(financial_statements): mandatory based on filter_based_on value

* fix(financial_statements.js): include options for multiselect
2025-03-06 17:18:26 +05:30
Frappe PR Bot
7c8b34fd8f chore(release): Bumped to Version 15.54.1
## [15.54.1](https://github.com/frappe/erpnext/compare/v15.54.0...v15.54.1) (2025-03-06)

### Bug Fixes

* check if set_landed_cost_based_on_purchase_invoice_rate is enabled before running patch ([12bf31d](12bf31df87))
* recalculate_amount_difference_field patch ([041335f](041335f318))
* rename_sla_fields patch ([bb553c2](bb553c27ab))
2025-03-06 11:05:55 +00:00
rohitwaghchaure
83320c97fa Merge pull request #46360 from frappe/mergify/bp/version-15/pr-46357
fix: rename_sla_fields patch (backport #46355) (backport #46357)
2025-03-06 16:34:33 +05:30
rohitwaghchaure
b004865240 Merge pull request #46362 from frappe/mergify/bp/version-15/pr-46358
fix: recalculate_amount_difference_field patch (backport #46354) (backport #46358)
2025-03-06 16:34:20 +05:30
Mihir Kandoi
525780645a chore: resolve conflicts
(cherry picked from commit 8e65b0ec0c)
2025-03-06 10:42:01 +00:00
Mihir Kandoi
12bf31df87 fix: check if set_landed_cost_based_on_purchase_invoice_rate is enabled before running patch
(cherry picked from commit 95d1976931)

# Conflicts:
#	erpnext/patches/v15_0/recalculate_amount_difference_field.py
(cherry picked from commit 7047fe2681)
2025-03-06 10:42:01 +00:00
Mihir Kandoi
041335f318 fix: recalculate_amount_difference_field patch
(cherry picked from commit 0492b941ff)

# Conflicts:
#	erpnext/patches/v15_0/recalculate_amount_difference_field.py
(cherry picked from commit f247f02e49)
2025-03-06 10:42:00 +00:00
rohitwaghchaure
9c9c8c9356 Merge pull request #46358 from frappe/mergify/bp/version-15-hotfix/pr-46354
fix: recalculate_amount_difference_field patch (backport #46354)
2025-03-06 14:53:08 +05:30
Mihir Kandoi
8e65b0ec0c chore: resolve conflicts 2025-03-06 14:13:55 +05:30
Mihir Kandoi
bb553c27ab fix: rename_sla_fields patch
(cherry picked from commit e8d4a487c6)
(cherry picked from commit 7bc7557018)
2025-03-06 08:20:30 +00:00
rohitwaghchaure
7080e1422d Merge pull request #46357 from frappe/mergify/bp/version-15-hotfix/pr-46355
fix: rename_sla_fields patch (backport #46355)
2025-03-06 13:48:54 +05:30
Mihir Kandoi
7047fe2681 fix: check if set_landed_cost_based_on_purchase_invoice_rate is enabled before running patch
(cherry picked from commit 95d1976931)

# Conflicts:
#	erpnext/patches/v15_0/recalculate_amount_difference_field.py
2025-03-06 07:58:38 +00:00
Mihir Kandoi
f247f02e49 fix: recalculate_amount_difference_field patch
(cherry picked from commit 0492b941ff)

# Conflicts:
#	erpnext/patches/v15_0/recalculate_amount_difference_field.py
2025-03-06 07:58:37 +00:00
Mihir Kandoi
7bc7557018 fix: rename_sla_fields patch
(cherry picked from commit e8d4a487c6)
2025-03-06 07:49:12 +00:00
rohitwaghchaure
e72264f448 Merge pull request #46346 from frappe/mergify/bp/version-15-hotfix/pr-46339
fix: doctype name (backport #46339)
2025-03-05 21:44:40 +05:30
Rohit Waghchaure
1dcbdf3257 fix: doctype name
(cherry picked from commit d039310d80)
2025-03-05 15:48:13 +00:00
Mihir Kandoi
5d6730a059 Merge pull request #46345 from frappe/mergify/bp/version-15-hotfix/pr-45693
fix: uom reverts to default upon selecting do not explode (backport #45693)
2025-03-05 21:09:04 +05:30
Mihir Kandoi
6b1d20970e fix: uom reverts to default upon selecting do not explode (#45693)
* fix: uom reverts to default upon selecting do not explode

* fix: logical error failing tests

(cherry picked from commit 58ed697ba5)
2025-03-05 15:21:58 +00:00
Frappe PR Bot
528107e224 chore(release): Bumped to Version 15.54.0
# [15.54.0](https://github.com/frappe/erpnext/compare/v15.53.4...v15.54.0) (2025-03-05)

### Bug Fixes

* Accounting Period validation throwing for different companies ([6df9cf3](6df9cf327d))
* Add company filter at get_invoice method (backport [#46238](https://github.com/frappe/erpnext/issues/46238)) ([#46299](https://github.com/frappe/erpnext/issues/46299)) ([4f80ddd](4f80ddd834))
* Add permission check in POS's `Toggle Recent Orders` (backport [#46010](https://github.com/frappe/erpnext/issues/46010)) ([#46274](https://github.com/frappe/erpnext/issues/46274)) ([7759775](7759775ee6))
* adding cost center on pos invoice items while applying product discount (backport [#46082](https://github.com/frappe/erpnext/issues/46082)) ([#46322](https://github.com/frappe/erpnext/issues/46322)) ([9a433a6](9a433a6750))
* **asset depreciation schedules:** enable auto commit ([899e468](899e468f6a))
* auto allocation for negative amount outstanding for Customers in Payment Entry ([78a329e](78a329e573))
* Batch Price gets updated only if it is a billed item ([dbd47df](dbd47dff98))
* Batch Price gets updated only if it is a billed item ([8ed512f](8ed512f6c6))
* change voucher_type and voucher_no field type to data ([3a03865](3a03865a8f))
* Close and Reopen buttons dissapear after saving changes ([#46048](https://github.com/frappe/erpnext/issues/46048)) ([506dd3c](506dd3c6b9))
* consider journal entry and return invoice in paid_amount calculation (backport [#46129](https://github.com/frappe/erpnext/issues/46129)) ([#46319](https://github.com/frappe/erpnext/issues/46319)) ([836fd8f](836fd8fbc4))
* consolidate gl entries by project in General Ledger Report (backport [#46314](https://github.com/frappe/erpnext/issues/46314)) ([#46321](https://github.com/frappe/erpnext/issues/46321)) ([6aa8803](6aa8803068))
* Convert tuple of tuples to list of dicts for dot notation access ([#46062](https://github.com/frappe/erpnext/issues/46062)) ([ef19551](ef195513d0))
* delivery note from sales order uom conversion mistake ([d10add4](d10add4b1e))
* depreciation and balances report correction (backport [#46259](https://github.com/frappe/erpnext/issues/46259)) ([#46305](https://github.com/frappe/erpnext/issues/46305)) ([087dde5](087dde5873))
* discount accounting for v15 ([f609012](f609012f02))
* do not include opening invoices in billed items to be received report ([eee500f](eee500f20e))
* don't allow renaming account while system is actively in use (backport [#46176](https://github.com/frappe/erpnext/issues/46176)) ([#46210](https://github.com/frappe/erpnext/issues/46210)) ([faee8d6](faee8d6c5e))
* dont update rate of free item when batch is updated ([9e649d8](9e649d8522))
* error ([61d5680](61d5680c8d))
* exclude already consumed purchase receipt items from asset capitalization (backport [#46329](https://github.com/frappe/erpnext/issues/46329)) ([#46336](https://github.com/frappe/erpnext/issues/46336)) ([6c1ceff](6c1ceff8ee))
* exclude cancelled gl entries ([5e08386](5e083861a4))
* fiscal year error ([7b13d8c](7b13d8cd98))
* fixing test case ([9f4311e](9f4311e7fb))
* if invoice is return then add amount in proper column ([0a65217](0a65217423))
* Include additional account types for Expense Account in LCV (backport [#46206](https://github.com/frappe/erpnext/issues/46206)) ([#46296](https://github.com/frappe/erpnext/issues/46296)) ([88234bb](88234bbf9a))
* incorrect batch picked ([e94f0b1](e94f0b1cca))
* incorrect batch picked in the pick list (backport [#45761](https://github.com/frappe/erpnext/issues/45761)) ([#46315](https://github.com/frappe/erpnext/issues/46315)) ([5a3073c](5a3073c4c1))
* incorrectly billed amount in the purchase receipt ([c247cf8](c247cf888b))
* Naming of Purchase Amount (backport [#46051](https://github.com/frappe/erpnext/issues/46051)) ([#46324](https://github.com/frappe/erpnext/issues/46324)) ([aaf35c5](aaf35c5df9))
* only include submitted docs for internal received quantity validation (backport [#46262](https://github.com/frappe/erpnext/issues/46262)) ([#46304](https://github.com/frappe/erpnext/issues/46304)) ([5ae9faa](5ae9faab91))
* patch ([5e06e4a](5e06e4acce))
* patch ([8f2fdca](8f2fdcae88))
* patch path ([af49f5a](af49f5a8af))
* **patch:** Ensure SLE indexes (backport [#46131](https://github.com/frappe/erpnext/issues/46131)) ([#46135](https://github.com/frappe/erpnext/issues/46135)) ([f3cafef](f3cafef6a7))
* payment entry exchange gain loss issue ([3fb9033](3fb9033fb7))
* pos item detail serial no field (backport [#46211](https://github.com/frappe/erpnext/issues/46211)) ([#46212](https://github.com/frappe/erpnext/issues/46212)) ([de0dfbc](de0dfbca9a))
* pos item selection using serial no (backport [#46200](https://github.com/frappe/erpnext/issues/46200)) ([#46203](https://github.com/frappe/erpnext/issues/46203)) ([0f263bc](0f263bcff2))
* **pos:** get parent item group without user permission ([#46020](https://github.com/frappe/erpnext/issues/46020)) ([29f3aac](29f3aac925))
* production analytics report ([5668795](5668795884))
* rate changing on the deliver note ([75bc68b](75bc68b863))
* rearrange stock settings fields ([87703c6](87703c6511))
* removed mandatory property for the cost center field ([a94292a](a94292a69f))
* rename some sla fields ([c5717b9](c5717b983d))
* replacing serial and batch bundle on pos with auto fetch serial nos (backport [#46236](https://github.com/frappe/erpnext/issues/46236)) ([#46337](https://github.com/frappe/erpnext/issues/46337)) ([1e85f69](1e85f69072))
* **report:** allow `Closed` purchase orders to be visible ([20c4487](20c4487853))
* **report:** allow `Closed` sales orders to be visible ([8799af9](8799af9747))
* **report:** filter sales / purchase orders based on date filters ([2221bf1](2221bf1cba))
* revamp logic (split parent and child) ([7437cea](7437cea458))
* revert last commit ([a09c57f](a09c57f0d1))
* set landed cost based on purchase invoice rate ([fdaf5fa](fdaf5fafda))
* set taxes before calculating taxes and totals ([90dea42](90dea426d8))
* source warehouse not fetched in bom creator ([6157fed](6157fed71c))
* stock qty not recalculate on changing of the qty ([331798b](331798babc))
* stock reservation issue while making Purchase Invoice ([8bd7195](8bd71954f3))
* syntax error ([1790bcc](1790bcc6d1))
* syntax error ([bd48d39](bd48d391e4))
* syntax error ([cc535b7](cc535b7636))
* test case for debit note ([a8b31df](a8b31df65d))
* tests ([46b0734](46b0734d6f))
* tests ([d413039](d41303961c))
* translation DE ([ddcf79d](ddcf79da1d))
* use else instead of unnecessary elif ([6f760d1](6f760d197d))
* use valuation method from settings in stock ageing report (backport [#46068](https://github.com/frappe/erpnext/issues/46068)) ([#46297](https://github.com/frappe/erpnext/issues/46297)) ([d02d005](d02d005913))
* use value from currency exchange when exchange api is disabled (backport [#46137](https://github.com/frappe/erpnext/issues/46137)) ([#46309](https://github.com/frappe/erpnext/issues/46309)) ([ccc0358](ccc0358db6))
* **workspace:** enable is_query_report on purchase reports (backport [#46249](https://github.com/frappe/erpnext/issues/46249)) ([#46306](https://github.com/frappe/erpnext/issues/46306)) ([363129b](363129bcd4))
* Wrong Overdue Status in Sales Invoices (Floating-point arithmetic) (backport [#46146](https://github.com/frappe/erpnext/issues/46146)) ([#46310](https://github.com/frappe/erpnext/issues/46310)) ([1ff0858](1ff085876e))

### Features

* add new Closed and Stopped rows ([7749814](7749814571))
* add total weight in shipment ([#46049](https://github.com/frappe/erpnext/issues/46049)) ([171df3a](171df3aba5))
* create sales invoice print format ([#45403](https://github.com/frappe/erpnext/issues/45403)) ([1a382eb](1a382ebe86))
* **received items to be billed:** add company and date filters (backport [#46271](https://github.com/frappe/erpnext/issues/46271)) ([#46302](https://github.com/frappe/erpnext/issues/46302)) ([400f4f3](400f4f32ad))
* **Sales Invoice:** add items row via "Fetch Timesheet" (backport [#46071](https://github.com/frappe/erpnext/issues/46071)) ([#46311](https://github.com/frappe/erpnext/issues/46311)) ([1c6e464](1c6e4649bd))

### Performance Improvements

* don't track seen for POS Invoice (backport [#46187](https://github.com/frappe/erpnext/issues/46187)) ([#46189](https://github.com/frappe/erpnext/issues/46189)) ([41ab7f3](41ab7f3f7c))
* patch ([ee41e55](ee41e55343))
* replace if function in query ([d0b8e0d](d0b8e0da8d))
2025-03-05 13:31:02 +00:00
ruthra kumar
86b917b04c Merge pull request #46263 from frappe/version-15-hotfix
chore: release v15
2025-03-05 18:59:38 +05:30
ruthra kumar
9875489758 Merge pull request #46340 from frappe/mergify/bp/version-15-hotfix/pr-46020
fix(pos): get parent item group without user permission (backport #46020)
2025-03-05 18:40:04 +05:30
ruthra kumar
939cf321f7 Merge pull request #46338 from frappe/mergify/bp/version-15-hotfix/pr-45403
feat: create sales invoice print format (backport #45403)
2025-03-05 18:39:43 +05:30
Sugesh G
29f3aac925 fix(pos): get parent item group without user permission (#46020)
* fix(pos): get parent item group without user permission

* feat: add item group filter based on user permission

---------

Co-authored-by: venkat102 <venkatesharunachalam659@gmail.com>
(cherry picked from commit 8caf7f275e)
2025-03-05 12:42:03 +00:00
Ejaaz Khan
1a382ebe86 feat: create sales invoice print format (#45403)
* feat: create sales invoice print format

* fix: linter issue

* style: remove border from table

* refactor: change label to uppercase and show taxes

* refactor: format date and add translation on label

* refactor: remove default header and format labels

* refactor: change label style and small fix

* chore: Qty in title case

---------

Co-authored-by: Nabin Hait <nabinhait@gmail.com>
(cherry picked from commit 38aa7cab8a)
2025-03-05 12:38:03 +00:00
mergify[bot]
6c1ceff8ee fix: exclude already consumed purchase receipt items from asset capitalization (backport #46329) (#46336)
* fix: exclude already consumed purchase receipt items from asset capitalization (#46329)

* feat: link purchase receipt row item to capitalization

* fix: avoid fetching already consumed stock and asset items during capitalization

* fix(patch): added patch to link purchase receipt item to stock item child table

* fix: added nosemgrep

* refactor: rename  to

(cherry picked from commit f50d479bfd)

# Conflicts:
#	erpnext/assets/doctype/asset_capitalization_stock_item/asset_capitalization_stock_item.json
#	erpnext/patches.txt

* fix: resolved conflicts

* fix: resolved conflicts

---------

Co-authored-by: Khushi Rawat <142375893+khushi8112@users.noreply.github.com>
2025-03-05 18:07:14 +05:30
mergify[bot]
1e85f69072 fix: replacing serial and batch bundle on pos with auto fetch serial nos (backport #46236) (#46337)
fix: replacing serial and batch bundle on pos with auto fetch serial nos (#46236)

* fix: replacing serial and batch bundle on pos with auto fetch serial nos

* fix: reserved serial no

added a check to look for serial no in reserved serial nos list before removing it as there might be a situation where an item is returned which was already consolidated.

(cherry picked from commit 35512d40bb)

Co-authored-by: Diptanil Saha <diptanil@frappe.io>
2025-03-05 18:00:31 +05:30
rohitwaghchaure
1992c2639c Merge pull request #46333 from frappe/mergify/bp/version-15-hotfix/pr-46330
fix: Accounting Period validation throwing for different companies (backport #46330)
2025-03-05 17:03:24 +05:30
Mihir Kandoi
8f278ab7c7 Merge pull request #46317 from frappe/mergify/bp/version-15-hotfix/pr-45947
fix: set landed cost based on purchase invoice rate (backport #45947)
2025-03-05 16:58:41 +05:30
Mihir Kandoi
7a33bf41d8 Merge pull request #46331 from frappe/mergify/bp/version-15-hotfix/pr-46313
fix: production analytics report (backport #46313)
2025-03-05 16:45:33 +05:30
Rohit Waghchaure
6df9cf327d fix: Accounting Period validation throwing for different companies
(cherry picked from commit b1508efca2)
2025-03-05 11:11:04 +00:00
Mihir Kandoi
5e06e4acce fix: patch 2025-03-05 16:32:26 +05:30
Mihir Kandoi
7749814571 feat: add new Closed and Stopped rows
(cherry picked from commit 6cc3d67835)
2025-03-05 10:54:36 +00:00
Mihir Kandoi
6f760d197d fix: use else instead of unnecessary elif
(cherry picked from commit 961258a4ce)
2025-03-05 10:54:36 +00:00
Mihir Kandoi
5668795884 fix: production analytics report
(cherry picked from commit 772e9ecfaa)
2025-03-05 10:54:36 +00:00
mergify[bot]
aaf35c5df9 fix: Naming of Purchase Amount (backport #46051) (#46324)
fix: Naming of Purchase Amount (#46051)

* fix: Naming of Purchase Amount

* fix: linters

(cherry picked from commit 104f60cc57)

Co-authored-by: 0xD0M1M0 <76812428+0xD0M1M0@users.noreply.github.com>
2025-03-05 16:18:50 +05:30
mergify[bot]
6aa8803068 fix: consolidate gl entries by project in General Ledger Report (backport #46314) (#46321)
fix: consolidate gl entries by project in General Ledger Report (#46314)

(cherry picked from commit 1f685efcaf)

Co-authored-by: Lakshit Jain <108322669+ljain112@users.noreply.github.com>
2025-03-05 16:18:42 +05:30
Ben Kebdani
506dd3c6b9 fix: Close and Reopen buttons dissapear after saving changes (#46048)
* fix: Close and Reopen buttons dissapear after saving changes

* style: linter issue

---------

Co-authored-by: Nabin Hait <nabinhait@gmail.com>
2025-03-05 15:34:55 +05:30
mergify[bot]
9a433a6750 fix: adding cost center on pos invoice items while applying product discount (backport #46082) (#46322)
fix: adding cost center on pos invoice items while applying product discount (#46082)

(cherry picked from commit 926e4ecc4f)

Co-authored-by: Diptanil Saha <diptanil@frappe.io>
2025-03-05 15:22:46 +05:30
mergify[bot]
e3ce17bd6e fix:[regional] Italian einvoice xml generated with wrong prices (#40254) (backport #45840) (#46318)
Merge pull request #45840 from gms-electronics/40254-italian-einvoice

fix:[regional] Italian einvoice xml generated with wrong prices (#40254)
(cherry picked from commit c5f90c823d)

Co-authored-by: Fab <fabian.thobe@mwv.vc>
2025-03-05 15:19:41 +05:30
mergify[bot]
836fd8fbc4 fix: consider journal entry and return invoice in paid_amount calculation (backport #46129) (#46319)
fix: consider journal entry and return invoice in paid_amount calculation (#46129)

* fix: consider journal entry and return invoice in paid_amount calculation

* test: add new unit test to consider journal entry and return invoice in paid_amount calculation

(cherry picked from commit 425fb12e91)

Co-authored-by: Sugesh G <73237300+Sugesh393@users.noreply.github.com>
2025-03-05 15:07:36 +05:30
Mihir Kandoi
fe8c9a3605 chore: resolve conflicts 2025-03-05 14:54:40 +05:30
Mihir Kandoi
941d67a0b6 chore: resolve conflicts 2025-03-05 14:48:41 +05:30
mergify[bot]
5a3073c4c1 fix: incorrect batch picked in the pick list (backport #45761) (#46315)
fix: incorrect batch picked in the pick list

(cherry picked from commit e1b7688a17)

Co-authored-by: Rohit Waghchaure <rohitw1991@gmail.com>
2025-03-05 14:48:01 +05:30
Mihir Kandoi
8f2fdcae88 fix: patch
(cherry picked from commit 1230127d24)

# Conflicts:
#	erpnext/patches.txt
2025-03-05 09:02:36 +00:00
Mihir Kandoi
a09c57f0d1 fix: revert last commit
(cherry picked from commit 154e9813c4)

# Conflicts:
#	erpnext/patches.txt
2025-03-05 09:02:35 +00:00
Mihir Kandoi
7b13d8cd98 fix: fiscal year error
(cherry picked from commit 7cf8e498c4)
2025-03-05 09:02:34 +00:00
Mihir Kandoi
ee41e55343 perf: patch
(cherry picked from commit a41024813b)
2025-03-05 09:02:34 +00:00
Mihir Kandoi
fdaf5fafda fix: set landed cost based on purchase invoice rate
(cherry picked from commit 17d415b105)

# Conflicts:
#	erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
#	erpnext/patches.txt
#	erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json
2025-03-05 09:02:34 +00:00
rohitwaghchaure
c85fd36960 Merge pull request #46308 from frappe/mergify/bp/version-15-hotfix/pr-45987
fix: rename some sla fields (backport #45987)
2025-03-05 14:30:54 +05:30
rohitwaghchaure
a4e5a46566 Merge pull request #46298 from frappe/mergify/bp/version-15-hotfix/pr-46046
perf: optimize query in project.py (backport #46046)
2025-03-05 14:30:26 +05:30
ruthra kumar
3c39888227 Merge pull request #46069 from frappe/mergify/bp/version-15-hotfix/pr-46049
feat: add total weight in shipment (backport #46049)
2025-03-05 14:23:49 +05:30
mergify[bot]
d5f07f06c7 refactor: rename subcontracting fields (backport #46226) (#46301)
* refactor: rename subcontracting fields

(cherry picked from commit b4f65154f5)

# Conflicts:
#	erpnext/subcontracting/doctype/subcontracting_order_item/subcontracting_order_item.json

* chore: resolve conflicts

---------

Co-authored-by: Mihir Kandoi <kandoimihir@gmail.com>
2025-03-05 14:08:10 +05:30
mergify[bot]
ccc0358db6 fix: use value from currency exchange when exchange api is disabled (backport #46137) (#46309)
fix: use value from currency exchange when exchange api is disabled (#46137)

(cherry picked from commit 2d26bff870)

Co-authored-by: Venkatesh <47534423+venkat102@users.noreply.github.com>
2025-03-05 14:07:12 +05:30
mergify[bot]
1ff085876e fix: Wrong Overdue Status in Sales Invoices (Floating-point arithmetic) (backport #46146) (#46310)
fix: Wrong Overdue Status in Sales Invoices (Floating-point arithmetic) (#46146)

* fix: Wrong Overdue Status in Sales Invoices (Floating-point arithmetic)

* style: after run pre-commit

(cherry picked from commit 89bcdd6fa5)

Co-authored-by: Diógenes Souza <103958767+devdiogenes@users.noreply.github.com>
2025-03-05 14:07:03 +05:30
mergify[bot]
1c6e4649bd feat(Sales Invoice): add items row via "Fetch Timesheet" (backport #46071) (#46311)
feat(Sales Invoice): add items row via "Fetch Timesheet" (#46071)

(cherry picked from commit 94547188bf)

Co-authored-by: Raffael Meyer <14891507+barredterra@users.noreply.github.com>
2025-03-05 14:06:55 +05:30
Mihir Kandoi
e4e1be568b Merge branch 'version-15-hotfix' into mergify/bp/version-15-hotfix/pr-45987 2025-03-05 13:59:59 +05:30
Mihir Kandoi
01db730714 Merge pull request #46300 from frappe/mergify/bp/version-15-hotfix/pr-46258
fix: delivery note from sales order uom conversion mistake (backport #46258)
2025-03-05 13:59:14 +05:30
ruthra kumar
dbcffa7ea4 Merge pull request #46235 from frappe/mergify/bp/version-15-hotfix/pr-46223
fix: dont update rate of free item when batch is updated (backport #46223)
2025-03-05 13:57:23 +05:30
ruthra kumar
36fa6bf15c chore: resolve conflict 2025-03-05 13:55:50 +05:30
mergify[bot]
4f80ddd834 fix: Add company filter at get_invoice method (backport #46238) (#46299)
fix: Add company filter at get_invoice method (#46238)

(cherry picked from commit a8d1cbc1c3)

Co-authored-by: Kunhi <kunhimohamed6@gmail.com>
2025-03-05 13:12:20 +05:30
mergify[bot]
400f4f32ad feat(received items to be billed): add company and date filters (backport #46271) (#46302)
feat(received items to be billed): add company and date filters (#46271)

* feat(received items to be billed): add company and date filters

* feat(delivered to be billed): add company and date filters

* feat: add company and date conditions

* chore: remove debugger

(cherry picked from commit 6117706ab5)

Co-authored-by: Sudharsanan Ashok <135326972+Sudharsanan11@users.noreply.github.com>
2025-03-05 13:12:09 +05:30
mergify[bot]
363129bcd4 fix(workspace): enable is_query_report on purchase reports (backport #46249) (#46306)
fix(workspace): enable is_query_report on purchase reports (#46249)

* fix(workspace): enable is_query_report on purchase reports

* fix: resolved conflict

---------

Co-authored-by: venkat102 <venkatesharunachalam659@gmail.com>
(cherry picked from commit 5513e24b00)

Co-authored-by: Nabin Hait <nabinhait@gmail.com>
2025-03-05 13:11:53 +05:30
mergify[bot]
087dde5873 fix: depreciation and balances report correction (backport #46259) (#46305)
fix: depreciation and balances report correction (#46259)

(cherry picked from commit 4a542b22a4)

Co-authored-by: Khushi Rawat <142375893+khushi8112@users.noreply.github.com>
2025-03-05 13:11:45 +05:30
mergify[bot]
5ae9faab91 fix: only include submitted docs for internal received quantity validation (backport #46262) (#46304)
fix: only include submitted docs for internal received quantity validation (#46262)

(cherry picked from commit 88fcdbb81e)

Co-authored-by: Lakshit Jain <108322669+ljain112@users.noreply.github.com>
2025-03-05 13:11:34 +05:30
Mihir Kandoi
446a8fe096 chore: resolve conflicts 2025-03-05 13:08:47 +05:30
Mihir Kandoi
0b50f1a9c3 chore: fix pre-commit/linter error 2025-03-05 12:57:53 +05:30
Mihir Kandoi
f29c43811c chore: resolve conflicts 2025-03-05 12:55:10 +05:30
Mihir Kandoi
e4fbd22173 Merge branch 'version-15-hotfix' into mergify/bp/version-15-hotfix/pr-46223 2025-03-05 12:51:01 +05:30
Mihir Kandoi
6b56724436 chore: resolve conflicts 2025-03-05 12:46:52 +05:30
Mihir Kandoi
af49f5a8af fix: patch path
(cherry picked from commit dcec446e55)

# Conflicts:
#	erpnext/patches.txt
2025-03-05 07:16:48 +00:00
Mihir Kandoi
46b0734d6f fix: tests
(cherry picked from commit 019303dd12)

# Conflicts:
#	erpnext/support/doctype/issue/issue.json
2025-03-05 07:16:47 +00:00
Mihir Kandoi
d41303961c fix: tests
(cherry picked from commit 1b831e9abd)
2025-03-05 07:16:47 +00:00
Mihir Kandoi
c5717b983d fix: rename some sla fields
(cherry picked from commit baa0dd1235)

# Conflicts:
#	erpnext/patches.txt
2025-03-05 07:16:46 +00:00
mergify[bot]
d02d005913 fix: use valuation method from settings in stock ageing report (backport #46068) (#46297)
fix: use valuation method from settings in stock ageing report

(cherry picked from commit da09c278c8)

Co-authored-by: Mihir Kandoi <kandoimihir@gmail.com>
2025-03-05 12:40:13 +05:30
Mihir Kandoi
d10add4b1e fix: delivery note from sales order uom conversion mistake
(cherry picked from commit 49a43d355d)

# Conflicts:
#	erpnext/selling/doctype/sales_order/sales_order.py
2025-03-05 06:52:07 +00:00
mergify[bot]
88234bbf9a fix: Include additional account types for Expense Account in LCV (backport #46206) (#46296)
fix: Include additional account types for Expense Account in LCV (#46206)

fix: additional account types in filters for the Expense account selection
(cherry picked from commit 59e99f167d)

Co-authored-by: Priyansh Shah <108476017+priyanshshah2442@users.noreply.github.com>
2025-03-05 12:19:31 +05:30
Mihir Kandoi
d8a1d0e908 test: added test
(cherry picked from commit 6073f5a6f9)
2025-03-05 06:41:09 +00:00
Mihir Kandoi
7437cea458 fix: revamp logic (split parent and child)
(cherry picked from commit f7594e2ff9)
2025-03-05 06:41:08 +00:00
Mihir Kandoi
1790bcc6d1 fix: syntax error
(cherry picked from commit 2f1e253e19)
2025-03-05 06:41:08 +00:00
Mihir Kandoi
d0b8e0da8d perf: replace if function in query
(cherry picked from commit 5e66231ca4)
2025-03-05 06:41:08 +00:00
rohitwaghchaure
ab4b1d4356 Merge pull request #46019 from frappe/st30783
fix: source warehouse not fetched in bom creator
2025-03-05 12:06:31 +05:30
mergify[bot]
7759775ee6 fix: Add permission check in POS's Toggle Recent Orders (backport #46010) (#46274)
fix: use get_list to check permissions

(cherry picked from commit a08bc6b913)

Co-authored-by: Sanket322 <shahsanket322003.com>
2025-03-05 12:04:17 +05:30
mergify[bot]
1b00de1815 chore: erpnext.com -> frappe.io/erpnext (backport #46288) (#46290)
* chore: erpnext.com -> frappe.io/erpnext (#46288)

(cherry picked from commit 41fe30ea6e)

# Conflicts:
#	README.md

* Update README.md

---------

Co-authored-by: Ankush Menat <ankush@frappe.io>
2025-03-05 11:35:52 +05:30
mergify[bot]
41ab7f3f7c perf: don't track seen for POS Invoice (backport #46187) (#46189)
* perf: don't track seen for POS Invoice (#46187)

This is a moving doctype. Do people even browse the list view?

It doesn't make much sense, either. POS INvoices are rarely "reviewed" by multiple users.

(cherry picked from commit ded0aab680)

# Conflicts:
#	erpnext/accounts/doctype/pos_invoice/pos_invoice.json

* chore: conflicts

---------

Co-authored-by: Ankush Menat <ankush@frappe.io>
2025-03-05 11:28:22 +05:30
ruthra kumar
5049f80b7f Merge pull request #46278 from mhh008/version-15-hotfix
fix-de-transaltion
2025-03-05 11:01:42 +05:30
rohitwaghchaure
d650b23722 Merge pull request #46282 from frappe/mergify/bp/version-15-hotfix/pr-46279
fix: rate changing on the deliver note (backport #46279)
2025-03-04 23:24:30 +05:30
Rohit Waghchaure
75bc68b863 fix: rate changing on the deliver note
(cherry picked from commit 6f40849d55)
2025-03-04 16:12:37 +00:00
rohitwaghchaure
f37fe1781a Merge pull request #46280 from frappe/mergify/bp/version-15-hotfix/pr-46208
fix: stock reservation issue while making Purchase Invoice (backport #46208)
2025-03-04 21:41:53 +05:30
Rohit Waghchaure
8bd71954f3 fix: stock reservation issue while making Purchase Invoice
(cherry picked from commit 64985bffe0)
2025-03-04 14:41:41 +00:00
Lakshit Jain
0f86ed28bc Merge pull request #46276 from frappe/mergify/bp/version-15-hotfix/pr-46039
fix: Ensure new line is added regardless of postal code presence (backport #46039)
2025-03-04 19:14:17 +05:30
mhh008
ddcf79da1d fix: translation DE 2025-03-04 13:56:19 +01:00
Lakshit Jain
b5fcd682a6 Merge pull request #46268 from frappe/mergify/bp/version-15-hotfix/pr-45896
fix: auto allocation for negative amount outstanding for Customers in Payment Entry (backport #45896)
2025-03-04 18:17:15 +05:30
Lakshit Jain
29405498bd Merge pull request #46270 from frappe/mergify/bp/version-15-hotfix/pr-46260
fix: do not include opening invoices in billed items to be received report (backport #46260)
2025-03-04 18:16:42 +05:30
Sanket322
1630979f05 refactor: add new line ragardless of postal code
(cherry picked from commit 746adfd057)
2025-03-04 12:36:40 +00:00
Smit Vora
6ab7d98681 Merge pull request #46139 from frappe/mergify/bp/version-15-hotfix/pr-46117
fix(report): Allow `Closed` Purchase Orders to be Visible in Purchase Order Analysis Report (backport #46117)
2025-03-04 18:03:47 +05:30
ljain112
eee500f20e fix: do not include opening invoices in billed items to be received report
(cherry picked from commit c1ddf444c6)
2025-03-04 11:24:24 +00:00
ljain112
78a329e573 fix: auto allocation for negative amount outstanding for Customers in Payment Entry
(cherry picked from commit 6275b44a0b)
2025-03-04 11:20:12 +00:00
Smit Vora
83dcbec86a chore: resolve conflicts 2025-03-04 16:43:55 +05:30
Smit Vora
5b6ed1d077 Merge pull request #46253 from frappe/mergify/bp/version-15-hotfix/pr-46062
fix: Convert tuple of tuples to list of dicts for dot notation access (backport #46062)
2025-03-04 16:39:16 +05:30
Smit Vora
284c93ecc2 Merge pull request #46246 from frappe/mergify/bp/version-15-hotfix/pr-46192
fix: Exclude Cancelled GL Entries (backport #46192)
2025-03-04 16:38:38 +05:30
Smit Vora
33051ec17e Merge pull request #46245 from frappe/mergify/bp/version-15-hotfix/pr-45972
fix: Set Taxes Before Calculating Taxes and Totals (backport #45972)
2025-03-04 16:38:24 +05:30
ruthra kumar
9e54e2ea58 Merge pull request #46266 from frappe/mergify/bp/version-15-hotfix/pr-45751
fix: change voucher_type and voucher_name field type to data (backport #45751)
2025-03-04 16:12:40 +05:30
ruthra kumar
c09c4cc243 Merge pull request #46252 from frappe/mergify/bp/version-15-hotfix/pr-46070
fix: Batch Price gets updated only if it is a billed item (backport #46070)
2025-03-04 15:49:25 +05:30
ruthra kumar
489efda985 chore: resolve conflict 2025-03-04 15:47:03 +05:30
Sugesh393
3a03865a8f fix: change voucher_type and voucher_no field type to data
(cherry picked from commit f8ab021920)

# Conflicts:
#	erpnext/accounts/doctype/tax_withheld_vouchers/tax_withheld_vouchers.json
2025-03-04 10:10:54 +00:00
ruthra kumar
854632dd51 chore: resolve conflict 2025-03-04 15:03:03 +05:30
ruthra kumar
ef44ad79a0 Merge pull request #46261 from frappe/mergify/bp/version-15-hotfix/pr-46172
fix: Show Credit Note amount in credit note column (backport #46172)
2025-03-04 15:00:15 +05:30
Sanket322
a8b31df65d fix: test case for debit note
(cherry picked from commit 6719bbeb10)
2025-03-04 07:58:31 +00:00
Sanket322
9f4311e7fb fix: fixing test case
(cherry picked from commit 9b2b477ae0)
2025-03-04 07:58:31 +00:00
Sanket322
0a65217423 fix: if invoice is return then add amount in proper column
(cherry picked from commit ccb4bdbe4c)
2025-03-04 07:58:30 +00:00
Sanket Shah
ef195513d0 fix: Convert tuple of tuples to list of dicts for dot notation access (#46062)
fix: use as_dict to convert tuples into list of dict

Co-authored-by: Sanket322 <shahsanket322003.com>
(cherry picked from commit e4b0ab6656)
2025-03-03 16:09:45 +00:00
mergify[bot]
f3cafef6a7 fix(patch): Ensure SLE indexes (backport #46131) (#46135)
* fix(patch): Ensure SLE indexes (#46131)

Because of the way this change was pushed in parts, some sites don't see
this as "update" and don't have the new indexes.

(cherry picked from commit f62aa8fc57)

# Conflicts:
#	erpnext/patches.txt

* fix: resolved conflict

---------

Co-authored-by: Ankush Menat <ankush@frappe.io>
Co-authored-by: Nabin Hait <nabinhait@gmail.com>
2025-03-03 21:37:02 +05:30
ruthra kumar
6762dc3392 chore: linter fix
(cherry picked from commit 0a2193e458)

# Conflicts:
#	erpnext/stock/get_item_details.py
2025-03-03 14:27:25 +00:00
Nirmalrajaa K
dbd47dff98 fix: Batch Price gets updated only if it is a billed item
(cherry picked from commit 1a56b83054)

# Conflicts:
#	erpnext/stock/get_item_details.py
2025-03-03 14:27:25 +00:00
Nirmalrajaa K
8ed512f6c6 fix: Batch Price gets updated only if it is a billed item
(cherry picked from commit 9597b1a69e)

# Conflicts:
#	erpnext/stock/get_item_details.py
2025-03-03 14:27:25 +00:00
Marica
3a6ef2564e Merge pull request #46073 from 0xD0M1M0/fix-discount-accounting-v15
fix: discount accounting for v15
2025-03-03 19:46:51 +05:30
Smit Vora
35df539da3 chore: fix linters 2025-03-03 17:02:15 +05:30
Ninad1306
5e083861a4 fix: exclude cancelled gl entries
(cherry picked from commit 3251a331dd)
2025-03-03 11:28:57 +00:00
Ninad1306
41e9a10ab4 test: validate fetching of taxes based on taxes and charges template
(cherry picked from commit 196ef7ac4e)
2025-03-03 11:27:45 +00:00
Ninad1306
90dea426d8 fix: set taxes before calculating taxes and totals
(cherry picked from commit 0fd0695bbb)
2025-03-03 11:27:45 +00:00
Mihir Kandoi
bd48d391e4 fix: syntax error 2025-03-03 16:40:19 +05:30
rohitwaghchaure
9082ff6aa9 Merge pull request #46242 from frappe/mergify/bp/version-15-hotfix/pr-46239
fix: incorrectly billed amount in the purchase receipt (backport #46239)
2025-03-03 16:16:09 +05:30
rohitwaghchaure
ba0ce267c2 Merge pull request #46243 from frappe/mergify/bp/version-15-hotfix/pr-46231
fix: incorrect batch picked (backport #46231)
2025-03-03 16:15:43 +05:30
Mihir Kandoi
cc535b7636 fix: syntax error 2025-03-03 15:27:35 +05:30
Mihir Kandoi
81c7b8c273 chore: resolve conflicts 2025-03-03 15:05:44 +05:30
Rohit Waghchaure
e94f0b1cca fix: incorrect batch picked
(cherry picked from commit d2564cad68)
2025-03-03 09:24:24 +00:00
Rohit Waghchaure
c247cf888b fix: incorrectly billed amount in the purchase receipt
(cherry picked from commit a5271fdb2e)
2025-03-03 09:15:48 +00:00
Khushi Rawat
7409c140d4 Merge pull request #46237 from frappe/mergify/bp/version-15-hotfix/pr-46201
fix(asset depreciation schedules): enable auto commit (backport #46201)
2025-03-03 14:04:39 +05:30
Mihir Kandoi
7f4d553201 chore: resolve conflicts 2025-03-03 12:28:06 +05:30
venkat102
899e468f6a fix(asset depreciation schedules): enable auto commit
(cherry picked from commit a4b24f7451)
2025-03-03 06:42:02 +00:00
mergify[bot]
faee8d6c5e fix: don't allow renaming account while system is actively in use (backport #46176) (#46210)
fix: don't allow renaming account while system is actively in use (#46176)

(cherry picked from commit 999f1cf96d)

Co-authored-by: Ankush Menat <ankush@frappe.io>
2025-03-03 11:16:37 +05:30
Frappe PR Bot
171f966421 chore(release): Bumped to Version 15.53.4
## [15.53.4](https://github.com/frappe/erpnext/compare/v15.53.3...v15.53.4) (2025-03-03)

### Bug Fixes

* removed mandatory property for the cost center field ([8eddc09](8eddc09bba))
2025-03-03 05:12:02 +00:00
rohitwaghchaure
3f76a413f8 Merge pull request #46205 from frappe/mergify/bp/version-15/pr-46186
fix: removed mandatory property for the cost center field (backport #46186)
2025-03-03 10:40:35 +05:30
Mihir Kandoi
61d5680c8d fix: error
(cherry picked from commit 7c9c0c7776)

# Conflicts:
#	erpnext/stock/get_item_details.py
2025-03-03 04:46:28 +00:00
Mihir Kandoi
9e649d8522 fix: dont update rate of free item when batch is updated
(cherry picked from commit a3596f717b)

# Conflicts:
#	erpnext/stock/get_item_details.py
2025-03-03 04:46:28 +00:00
rohitwaghchaure
c0f736736e Merge pull request #46217 from frappe/mergify/bp/version-15-hotfix/pr-46202
fix: rearrange stock settings fields (backport #46202)
2025-03-03 10:15:36 +05:30
Frappe PR Bot
bcd02df6fd chore(release): Bumped to Version 15.53.3
## [15.53.3](https://github.com/frappe/erpnext/compare/v15.53.2...v15.53.3) (2025-03-03)

### Bug Fixes

* stock qty not recalculate on changing of the qty ([9186f13](9186f13458))
2025-03-03 04:02:37 +00:00
rohitwaghchaure
7a71c24d5c Merge pull request #46232 from frappe/mergify/bp/version-15/pr-46224
fix: stock qty not recalculate on changing of the qty (backport #46219) (backport #46224)
2025-03-03 09:31:16 +05:30
Rohit Waghchaure
9186f13458 fix: stock qty not recalculate on changing of the qty
(cherry picked from commit 464e3339fe)
(cherry picked from commit 331798babc)
2025-03-03 03:57:22 +00:00
rohitwaghchaure
c48e157a25 Merge pull request #46224 from frappe/mergify/bp/version-15-hotfix/pr-46219
fix: stock qty not recalculate on changing of the qty (backport #46219)
2025-03-03 08:24:05 +05:30
mergify[bot]
84ca0ada1b refactor: using function to unset grand total to default mode of payment in pos (backport #46228) (#46229)
refactor: using function to unset grand total to default mode of payment in pos (#46228)

(cherry picked from commit 62c3915ecb)

Co-authored-by: Diptanil Saha <diptanil@frappe.io>
2025-03-03 01:59:13 +05:30
Rohit Waghchaure
331798babc fix: stock qty not recalculate on changing of the qty
(cherry picked from commit 464e3339fe)
2025-03-02 06:46:56 +00:00
rohitwaghchaure
93fed0ce86 chore: fix conflicts 2025-03-01 12:53:44 +05:30
Rohit Waghchaure
87703c6511 fix: rearrange stock settings fields
(cherry picked from commit 93f461c6f3)

# Conflicts:
#	erpnext/stock/doctype/stock_settings/stock_settings.json
2025-03-01 06:57:35 +00:00
mergify[bot]
de0dfbca9a fix: pos item detail serial no field (backport #46211) (#46212)
fix: pos item detail serial no field (#46211)

(cherry picked from commit d2fad44e89)

Co-authored-by: Diptanil Saha <diptanil@frappe.io>
2025-02-28 23:24:49 +05:30
Rohit Waghchaure
8eddc09bba fix: removed mandatory property for the cost center field
(cherry picked from commit 079cf772aa)
2025-02-28 10:25:50 +00:00
mergify[bot]
0f263bcff2 fix: pos item selection using serial no (backport #46200) (#46203)
fix: pos item selection using serial no (#46200)

(cherry picked from commit 8fb09decd2)

Co-authored-by: Diptanil Saha <diptanil@frappe.io>
2025-02-28 15:43:59 +05:30
ruthra kumar
a9b2f4885e Merge pull request #46197 from frappe/mergify/bp/version-15-hotfix/pr-46186
fix: removed mandatory property for the cost center field (backport #46186)
2025-02-28 13:56:09 +05:30
Rohit Waghchaure
a94292a69f fix: removed mandatory property for the cost center field
(cherry picked from commit 079cf772aa)
2025-02-28 08:03:51 +00:00
Sagar Vora
5b072c88a6 Merge pull request #46191 from frappe/mergify/bp/version-15-hotfix/pr-46177
fix: Payment Entry fixes (backport #46177)
2025-02-28 10:44:00 +05:30
vishakhdesai
3fb9033fb7 fix: payment entry exchange gain loss issue
(cherry picked from commit 2dbef23244)
2025-02-28 05:13:43 +00:00
Frappe PR Bot
d9c1b58fc3 chore(release): Bumped to Version 15.53.2
## [15.53.2](https://github.com/frappe/erpnext/compare/v15.53.1...v15.53.2) (2025-02-26)

### Bug Fixes

* check value as int ([97d3e86](97d3e8648b))
* enable fetch_timesheet_in_sales_invoice in test ([feb64cb](feb64cb9b5))
* incorrect stock value difference for adjustment entry ([96d44e3](96d44e362d))
* inventory dimension for maintence visit ([ec3b281](ec3b281a3b))
* no permission to get project settings in sales invoice ([b8281c3](b8281c34e2))
* pos opening entry dialog not saving on change data (backport [#46066](https://github.com/frappe/erpnext/issues/46066)) ([#46067](https://github.com/frappe/erpnext/issues/46067)) ([0ae2d61](0ae2d61974))
* **project settings:** add checkbox to auto fetch timesheet in sales invoice ([b3c1df8](b3c1df8561))
* **sales invoice:** check fetch_timesheet_in_sales_invoice enabled before fetching the timesheet ([b1095bb](b1095bb91b))
* valuation rate for batch ([c72dab4](c72dab49f4))
2025-02-26 12:58:53 +00:00
ruthra kumar
f93d1a2633 Merge pull request #46132 from frappe/version-15-hotfix
chore: release v15
2025-02-26 18:27:33 +05:30
ruthra kumar
bc53365620 Merge pull request #46159 from frappe/mergify/bp/version-15-hotfix/pr-46156
fix: no permission to get project settings in sales invoice (backport #46156)
2025-02-26 14:34:36 +05:30
venkat102
b8281c34e2 fix: no permission to get project settings in sales invoice
(cherry picked from commit 221f1468cb)
2025-02-26 08:22:24 +00:00
rohitwaghchaure
81ff16248e Merge pull request #46143 from frappe/mergify/bp/version-15-hotfix/pr-46097
fix: valuation rate for batch (backport #46097)
2025-02-26 10:16:10 +05:30
ruthra kumar
8bb085a055 Merge pull request #46142 from frappe/mergify/bp/version-15-hotfix/pr-45908
fix(projects settings): add checkbox to auto fetch timesheet in sales invoice (backport #45908)
2025-02-26 06:23:58 +05:30
Rohit Waghchaure
c72dab49f4 fix: valuation rate for batch
(cherry picked from commit b88305a95f)
2025-02-25 17:45:05 +00:00
ruthra kumar
feec16b682 chore: resolve conflicts 2025-02-25 22:53:14 +05:30
venkat102
feb64cb9b5 fix: enable fetch_timesheet_in_sales_invoice in test
(cherry picked from commit 5880f1d5c6)

# Conflicts:
#	erpnext/projects/doctype/timesheet/test_timesheet.py
2025-02-25 16:56:57 +00:00
venkat102
97d3e8648b fix: check value as int
(cherry picked from commit 43b13b91be)
2025-02-25 16:56:56 +00:00
venkat102
b1095bb91b fix(sales invoice): check fetch_timesheet_in_sales_invoice enabled before fetching the timesheet
(cherry picked from commit 914ad357fd)

# Conflicts:
#	erpnext/accounts/doctype/sales_invoice/sales_invoice.py
2025-02-25 16:56:56 +00:00
venkat102
b3c1df8561 fix(project settings): add checkbox to auto fetch timesheet in sales invoice
(cherry picked from commit 876082ea2f)

# Conflicts:
#	erpnext/projects/doctype/projects_settings/projects_settings.json
2025-02-25 16:56:56 +00:00
Ninad1306
2221bf1cba fix(report): filter sales / purchase orders based on date filters
(cherry picked from commit 936d7d4342)
2025-02-25 13:07:54 +00:00
Ninad1306
8799af9747 fix(report): allow Closed sales orders to be visible
(cherry picked from commit 2394e76e7d)

# Conflicts:
#	erpnext/selling/report/sales_order_analysis/sales_order_analysis.js
2025-02-25 13:07:54 +00:00
Ninad1306
20c4487853 fix(report): allow Closed purchase orders to be visible
(cherry picked from commit 3b2879d3a1)

# Conflicts:
#	erpnext/buying/report/purchase_order_analysis/purchase_order_analysis.js
2025-02-25 13:07:53 +00:00
0xD0M1M0
f609012f02 fix: discount accounting for v15 2025-02-21 22:26:39 +01:00
Ravibharathi
171df3aba5 feat: add total weight in shipment (#46049)
Co-authored-by: barredterra <14891507+barredterra@users.noreply.github.com>
(cherry picked from commit 1ec182430d)

# Conflicts:
#	erpnext/stock/doctype/shipment/shipment.json
2025-02-21 14:16:46 +00:00
mergify[bot]
0ae2d61974 fix: pos opening entry dialog not saving on change data (backport #46066) (#46067)
fix: pos opening entry dialog not saving on change data (#46066)

(cherry picked from commit 8e6959dfad)

Co-authored-by: Diptanil Saha <diptanil@frappe.io>
2025-02-21 17:53:59 +05:30
Frappe PR Bot
9e824fc4fe chore(release): Bumped to Version 15.53.1
## [15.53.1](https://github.com/frappe/erpnext/compare/v15.53.0...v15.53.1) (2025-02-21)

### Bug Fixes

* inventory dimension for maintence visit ([1d818e1](1d818e1510))
2025-02-21 10:01:58 +00:00
rohitwaghchaure
b6b47d6683 Merge pull request #46044 from frappe/mergify/bp/version-15/pr-46041
fix: inventory dimension for maintenance visit (backport #46037) (backport #46041)
2025-02-21 15:30:36 +05:30
Rohit Waghchaure
1d818e1510 fix: inventory dimension for maintence visit
(cherry picked from commit cd4ba69262)
(cherry picked from commit ec3b281a3b)
2025-02-20 07:37:38 +00:00
rohitwaghchaure
b00fa1dfee Merge pull request #46041 from frappe/mergify/bp/version-15-hotfix/pr-46037
fix: inventory dimension for maintenance visit (backport #46037)
2025-02-20 13:06:33 +05:30
Rohit Waghchaure
ec3b281a3b fix: inventory dimension for maintence visit
(cherry picked from commit cd4ba69262)
2025-02-20 06:13:19 +00:00
rohitwaghchaure
9318e4f0e8 Merge pull request #46028 from frappe/mergify/bp/version-15-hotfix/pr-46021
fix: incorrect stock value difference for adjustment entry (backport #46021)
2025-02-19 17:24:42 +05:30
Frappe PR Bot
16e8a00f45 chore(release): Bumped to Version 15.53.0
# [15.53.0](https://github.com/frappe/erpnext/compare/v15.52.0...v15.53.0) (2025-02-19)

### Bug Fixes

* add accounting dimensions section in sales order item ([b32e4da](b32e4daf2b))
* add is_new in if condition ([fc2ec7c](fc2ec7c495))
* add validate to allow equity account and party_type shareholder ([bb3eb81](bb3eb81170))
* allow scrap item with zero qty ([abe5384](abe5384449))
* auto create asset due to message error (backport [#45934](https://github.com/frappe/erpnext/issues/45934)) ([#45952](https://github.com/frappe/erpnext/issues/45952)) ([830edb8](830edb8f52))
* check if employee is currently working on another workstation ([22eaa14](22eaa14179))
* disable partial payment in pos (backport [#45752](https://github.com/frappe/erpnext/issues/45752)) ([#45945](https://github.com/frappe/erpnext/issues/45945)) ([38edc46](38edc46c46))
* do not reschedule depreciation for fully depreciated asset on scrap ([1e7c5ec](1e7c5ec0cb))
* fetch child account data for selected parent ([#45904](https://github.com/frappe/erpnext/issues/45904)) ([e36b860](e36b860a79))
* handle division by zero error (backport [#45966](https://github.com/frappe/erpnext/issues/45966)) ([#46015](https://github.com/frappe/erpnext/issues/46015)) ([15106b4](15106b49b6))
* include missing payment_gateway parameter in Payment Request URL ([18f9476](18f94765f7))
* letter head for quality inspection ([c289fef](c289fef3b5))
* link correct row item of purchase doc ([87f337b](87f337b605))
* make purchase_receipt_item and purchase_invoice_item fields of data type ([281431e](281431e041))
* millisecond issue for posting datetime ([4292365](42923656ee))
* patch for creating asset depreciation schedule records ([f043b46](f043b46696))
* pos accounting dimension fieldname error (backport [#45899](https://github.com/frappe/erpnext/issues/45899)) ([#45921](https://github.com/frappe/erpnext/issues/45921)) ([e998f06](e998f063a9))
* **pos profile:** check company while validating mandatory accounting dimension ([#45974](https://github.com/frappe/erpnext/issues/45974)) ([6a57743](6a577438aa))
* pos return validation on v15 ([#45951](https://github.com/frappe/erpnext/issues/45951)) ([dd34bbe](dd34bbe570))
* provision to enable naming series for SABB ([8fbfe14](8fbfe14c63))
* **quotation:** fetch exchange rate on currency change ([bd89c19](bd89c19c98))
* remove party type from validate ([0d21151](0d2115197e))
* remove public access to list items (backport [#45838](https://github.com/frappe/erpnext/issues/45838)) ([#46018](https://github.com/frappe/erpnext/issues/46018)) ([eead6d4](eead6d46ff))
* remove unused code ([dd5d144](dd5d144b55))
* **report:** add options to multiselectlist fields ([7e85a12](7e85a123b2))
* reset location only if there is value in row item location field ([a509568](a509568110))
* resolved conflicts ([84647a1](84647a1c73))
* round sum amount in JE auditing PF ([#45961](https://github.com/frappe/erpnext/issues/45961)) ([44e1ca9](44e1ca9d05))
* **send_message:** escape HTML in the text ([cbec989](cbec989a7c))
* serial no status for internal transfer delivery note ([2b80c00](2b80c009b3))
* set default value to 0 as per new logic ([1abe1a1](1abe1a1fd5))
* set sco_qty field of PO to non negative ([567fb8a](567fb8abd1))
* slow query ([8306d6f](8306d6fdb6))
* stock reservation for sales invoice ([1fb5586](1fb5586f56))
* stock reservation not working for sales invoice with update stock ([7d871f6](7d871f6bb5))
* tests ([f63a9db](f63a9dbf9b))
* throw correct exception ([5bccf9f](5bccf9f837))
* validate if no matching item found ([6183b38](6183b38089))
* validate payment request total of partly paid invoice ([c8881a9](c8881a9358))

### Features

* added ability to use custom html format for process statement of accounts (copy [#45746](https://github.com/frappe/erpnext/issues/45746)) ([#46012](https://github.com/frappe/erpnext/issues/46012)) ([1a4297a](1a4297ac35))
* added option to enforce free item qty in pricing rule ([8fb9228](8fb9228871))
* disable auto setting grand total to default mode of payment (backport [#45591](https://github.com/frappe/erpnext/issues/45591)) ([#45917](https://github.com/frappe/erpnext/issues/45917)) ([e271a5c](e271a5cba0))
2025-02-19 11:50:41 +00:00
ruthra kumar
2bb79c34c3 Merge pull request #45981 from frappe/version-15-hotfix
chore: release v15
2025-02-19 17:19:18 +05:30
mergify[bot]
eead6d46ff fix: remove public access to list items (backport #45838) (#46018)
fix: remove public access to list items

(cherry picked from commit 2bd596ee3d)

Co-authored-by: CaseSolved <richard@casesolved.co.uk>
2025-02-19 16:52:09 +05:30
mergify[bot]
15106b49b6 fix: handle division by zero error (backport #45966) (#46015)
fix: handle division by zero error (#45966)

Co-authored-by: Sanket322 <shahsanket322003.com>
(cherry picked from commit 24394765a6)

Co-authored-by: Sanket Shah <113279972+Sanket322@users.noreply.github.com>
2025-02-19 16:51:09 +05:30
Akhil Narang
452e4dcbad Merge pull request #46025 from frappe/mergify/bp/version-15-hotfix/pr-46003
fix(send_message): escape HTML in the text (backport #46003)
2025-02-19 16:43:06 +05:30
Rohit Waghchaure
96d44e362d fix: incorrect stock value difference for adjustment entry
(cherry picked from commit df83e427a3)
2025-02-19 11:11:15 +00:00
Khushi Rawat
5a17171bd1 Merge pull request #46013 from frappe/mergify/bp/version-15-hotfix/pr-45872
fix: enable asset value editing for duplicate item code (backport #45872)
2025-02-19 16:34:36 +05:30
Khushi Rawat
777daf6aee Merge pull request #46014 from frappe/mergify/bp/version-15-hotfix/pr-45898
fix: patch for creating asset depreciation schedule records (backport #45898)
2025-02-19 16:33:03 +05:30
ruthra kumar
9b866e8ee4 Merge pull request #46016 from frappe/mergify/bp/version-15-hotfix/pr-45974
fix(pos profile): check company while validating mandatory accounting dimension (backport #45974)
2025-02-19 16:28:42 +05:30
Akhil Narang
cbec989a7c fix(send_message): escape HTML in the text
Signed-off-by: Akhil Narang <me@akhilnarang.dev>
(cherry picked from commit 448a5db20f)
2025-02-19 10:45:49 +00:00
Khushi Rawat
dd5d144b55 fix: remove unused code 2025-02-19 16:00:31 +05:30
Mihir Kandoi
6157fed71c fix: source warehouse not fetched in bom creator 2025-02-19 15:54:31 +05:30
Khushi Rawat
9b8623dd64 chore: resolved conflicts 2025-02-19 15:50:53 +05:30
Khushi Rawat
84647a1c73 fix: resolved conflicts 2025-02-19 15:47:40 +05:30
mergify[bot]
1a4297ac35 feat: added ability to use custom html format for process statement of accounts (copy #45746) (#46012)
feat: added ability to use custom html format for process statement of accounts (#45746)

* feat: added ability to use custom print format for process statement of accounts documents.

* fix: handles missing hook issues

* chore: linter changes

---------

Co-authored-by: Boy4099 <mashtawayne4099@gmail.com>
Co-authored-by: ruthra kumar <ruthra@erpnext.com>
(cherry picked from commit a0cd08e9ea)

Co-authored-by: Steve Wilson <stevew9009@gmail.com>
2025-02-19 15:45:10 +05:30
Ejaaz Khan
236b502155 Merge pull request #46017 from frappe/mergify/bp/version-15-hotfix/pr-45961
fix: round sum amount in JE auditing PF (backport #45961)
2025-02-19 15:43:57 +05:30
mergify[bot]
830edb8f52 fix: auto create asset due to message error (backport #45934) (#45952)
fix: auto create asset due to message error (#45934)

* fix: auto create asset due to message error

* fix: linters

(cherry picked from commit 6f1bc5225a)

Co-authored-by: 0xD0M1M0 <76812428+0xD0M1M0@users.noreply.github.com>
2025-02-19 15:43:53 +05:30
Ejaaz Khan
44e1ca9d05 fix: round sum amount in JE auditing PF (#45961)
(cherry picked from commit 941085000a)
2025-02-19 10:11:36 +00:00
Venkatesh
6a577438aa fix(pos profile): check company while validating mandatory accounting dimension (#45974)
(cherry picked from commit 17a2f44290)
2025-02-19 10:10:20 +00:00
Nabin Hait
f043b46696 fix: patch for creating asset depreciation schedule records
(cherry picked from commit 7324dcb7c8)

# Conflicts:
#	erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py
2025-02-19 10:08:12 +00:00
Khushi Rawat
a509568110 fix: reset location only if there is value in row item location field
(cherry picked from commit 2bb79197aa)
2025-02-19 10:02:33 +00:00
Khushi Rawat
6183b38089 fix: validate if no matching item found
(cherry picked from commit 44c1425e73)
2025-02-19 10:02:33 +00:00
Khushi Rawat
87f337b605 fix: link correct row item of purchase doc
(cherry picked from commit da1b4cb9ab)
2025-02-19 10:02:33 +00:00
Khushi Rawat
281431e041 fix: make purchase_receipt_item and purchase_invoice_item fields of data type
(cherry picked from commit 8af9dcb33e)

# Conflicts:
#	erpnext/assets/doctype/asset/asset.json
2025-02-19 10:02:32 +00:00
rohitwaghchaure
be65cd4df6 Merge pull request #46005 from frappe/mergify/bp/version-15-hotfix/pr-45750
feat: added option to enforce free item qty in pricing rule (backport #45750)
2025-02-19 15:09:51 +05:30
Khushi Rawat
965dbb6d2b Merge pull request #46006 from frappe/mergify/bp/version-15-hotfix/pr-45895
fix: do not reschedule depreciation for fully depreciated asset on scrap (backport #45895)
2025-02-19 14:24:55 +05:30
ruthra kumar
07d4725810 Merge pull request #46008 from frappe/mergify/bp/version-15-hotfix/pr-45904
fix: fetch child account data for selected parent (backport #45904)
2025-02-19 14:21:48 +05:30
Bhavansathru
e36b860a79 fix: fetch child account data for selected parent (#45904)
* fix: fetch child account data for selected parent

* fix: change reference name

---------

Co-authored-by: venkat102 <venkatesharunachalam659@gmail.com>
(cherry picked from commit 73e82b7afa)
2025-02-19 08:28:59 +00:00
Khushi Rawat
1e7c5ec0cb fix: do not reschedule depreciation for fully depreciated asset on scrap
(cherry picked from commit fd4c4f98fa)
2025-02-19 07:37:42 +00:00
Mihir Kandoi
1abe1a1fd5 fix: set default value to 0 as per new logic
(cherry picked from commit 844f1636c0)
2025-02-19 07:21:54 +00:00
Mihir Kandoi
f782900a15 refactor: rename field
(cherry picked from commit f3d598881c)
2025-02-19 07:21:54 +00:00
Mihir Kandoi
fc2ec7c495 fix: add is_new in if condition
(cherry picked from commit 4dcac56486)
2025-02-19 07:21:53 +00:00
Mihir Kandoi
ad11208109 test: added test
(cherry picked from commit ac3259b8f1)
2025-02-19 07:21:53 +00:00
Mihir Kandoi
f63a9dbf9b fix: tests
(cherry picked from commit 366ae85d85)
2025-02-19 07:21:53 +00:00
Mihir Kandoi
8fb9228871 feat: added option to enforce free item qty in pricing rule
(cherry picked from commit 19c01b1457)
2025-02-19 07:21:53 +00:00
rohitwaghchaure
617a24d61e Merge pull request #45994 from frappe/mergify/bp/version-15-hotfix/pr-45980
fix: check if employee is currently working on another workstation (backport #45980)
2025-02-19 11:24:05 +05:30
ruthra kumar
6fad501aa0 Merge pull request #46001 from frappe/mergify/bp/version-15-hotfix/pr-45882
fix(quotation): fetch exchange rate on currency change (backport #45882)
2025-02-19 11:13:04 +05:30
venkat102
bd89c19c98 fix(quotation): fetch exchange rate on currency change
(cherry picked from commit 2f77a8bed1)
2025-02-19 05:21:57 +00:00
Mihir Kandoi
5bccf9f837 fix: throw correct exception
(cherry picked from commit 4487edb255)
2025-02-18 15:13:04 +00:00
Mihir Kandoi
22eaa14179 fix: check if employee is currently working on another workstation
(cherry picked from commit 8234e659c8)
2025-02-18 15:13:04 +00:00
rohitwaghchaure
d3d0aacd4c Merge pull request #45993 from frappe/mergify/bp/version-15-hotfix/pr-45977
fix: millisecond issue for posting datetime (backport #45977)
2025-02-18 20:31:20 +05:30
rohitwaghchaure
69f5be65f6 Merge pull request #45975 from frappe/mergify/bp/version-15-hotfix/pr-45970
fix: serial no status for internal transfer delivery note (backport #45970)
2025-02-18 20:23:20 +05:30
rohitwaghchaure
508efd1322 Merge pull request #45990 from frappe/mergify/bp/version-15-hotfix/pr-45976
fix: slow query (backport #45976)
2025-02-18 20:22:51 +05:30
rohitwaghchaure
ecc2de2709 Merge pull request #45992 from frappe/mergify/bp/version-15-hotfix/pr-45971
fix: set sco_qty field of PO to non negative (backport #45971)
2025-02-18 20:22:39 +05:30
rohitwaghchaure
2e3b19ebb2 chore: fix conflicts 2025-02-18 20:11:02 +05:30
rohitwaghchaure
050bb1eef5 chore: fix conflicts 2025-02-18 20:10:30 +05:30
Rohit Waghchaure
42923656ee fix: millisecond issue for posting datetime
(cherry picked from commit ac9e5c0163)

# Conflicts:
#	erpnext/patches.txt
#	erpnext/stock/utils.py
2025-02-18 14:39:39 +00:00
rohitwaghchaure
0acdae02c1 chore: fix conflicts 2025-02-18 20:00:08 +05:30
Mihir Kandoi
567fb8abd1 fix: set sco_qty field of PO to non negative
(cherry picked from commit dfc3dc4944)
2025-02-18 14:29:22 +00:00
Rohit Waghchaure
8306d6fdb6 fix: slow query
(cherry picked from commit 8cfab57fc8)

# Conflicts:
#	erpnext/stock/doctype/packed_item/packed_item.json
2025-02-18 14:28:19 +00:00
ruthra kumar
20709f1b3e Merge pull request #45979 from frappe/mergify/bp/version-15-hotfix/pr-45765
fix: add accounting dimensions section in sales order item (backport #45765)
2025-02-18 17:48:34 +05:30
ruthra kumar
52860cc566 chore: resolve conflict 2025-02-18 14:27:14 +05:30
Sugesh393
b32e4daf2b fix: add accounting dimensions section in sales order item
(cherry picked from commit 7d47869f4b)

# Conflicts:
#	erpnext/selling/doctype/sales_order_item/sales_order_item.json
2025-02-18 08:42:56 +00:00
Rohit Waghchaure
2b80c009b3 fix: serial no status for internal transfer delivery note
(cherry picked from commit 3333331a3d)
2025-02-18 08:22:03 +00:00
ruthra kumar
8da1348a48 Merge pull request #45973 from frappe/mergify/bp/version-15-hotfix/pr-45723
fix: validate payment request total of partly paid invoice (backport #45723)
2025-02-18 13:42:58 +05:30
Sugesh393
9a33b877f5 test: add unit test to validate payment request grand_total for partly paid invoice
(cherry picked from commit f8472c32d9)
2025-02-18 07:42:28 +00:00
Sugesh393
c8881a9358 fix: validate payment request total of partly paid invoice
(cherry picked from commit 899c18df18)
2025-02-18 07:42:28 +00:00
ruthra kumar
f6047d8491 Merge pull request #45968 from frappe/mergify/bp/version-15-hotfix/pr-45687
fix: add validation to allow equity account (backport #45687)
2025-02-18 12:12:09 +05:30
rethik
0d2115197e fix: remove party type from validate
(cherry picked from commit f82837a4a2)
2025-02-18 06:16:03 +00:00
rethik
552b5a79ce test: add unit test to validate account type and party type
(cherry picked from commit 9422ce5aee)
2025-02-18 06:16:02 +00:00
rethik
bb3eb81170 fix: add validate to allow equity account and party_type shareholder
(cherry picked from commit 2c8e3f3409)
2025-02-18 06:16:02 +00:00
rohitwaghchaure
7ab69cfe5f Merge pull request #45956 from frappe/mergify/bp/version-15-hotfix/pr-45946
fix: provision to enable naming series for SABB (backport #45946)
2025-02-18 07:44:18 +05:30
rohitwaghchaure
43d32eb10e chore: fix conflicts 2025-02-17 21:32:48 +05:30
rohitwaghchaure
697fdf5bc3 chore: fix conflicts 2025-02-17 21:30:15 +05:30
rohitwaghchaure
2f7f9c0bac chore: fix conflicts 2025-02-17 21:29:22 +05:30
Rohit Waghchaure
8fbfe14c63 fix: provision to enable naming series for SABB
(cherry picked from commit fe43975cdd)

# Conflicts:
#	erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.json
#	erpnext/stock/doctype/serial_and_batch_bundle/test_serial_and_batch_bundle.py
#	erpnext/stock/doctype/stock_settings/stock_settings.json
2025-02-17 11:31:46 +00:00
mergify[bot]
38edc46c46 fix: disable partial payment in pos (backport #45752) (#45945)
* fix: disable partial payment in pos (#45752)

* fix: disable partial payment in pos

* test: disable partial payment

* test: removed print statement

* test: using save method to auto calculate paid_amount

* test: paid_amount calculation using save method

* test: added save method to calculate paid_amount

* test: outstanding amount

* test: added test for partial payments in pos invoice

* fix: custom validation error for partial payment

* test: using partial payment validation

* fix: validate only on submit

(cherry picked from commit d94802067b)

# Conflicts:
#	erpnext/accounts/doctype/pos_closing_entry/test_pos_closing_entry.py
#	erpnext/accounts/doctype/pos_invoice_merge_log/test_pos_invoice_merge_log.py

* chore: resolve conflict

* chore: resolve conflict

* chore: resolve linter issue

* test: fixed failing test

---------

Co-authored-by: Diptanil Saha <diptanil@frappe.io>
2025-02-17 17:01:34 +05:30
Diptanil Saha
dd34bbe570 fix: pos return validation on v15 (#45951) 2025-02-17 16:03:19 +05:30
rohitwaghchaure
11622f81f3 Merge pull request #45943 from frappe/mergify/bp/version-15-hotfix/pr-45941
fix: letter head for quality inspection (backport #45941)
2025-02-17 14:42:56 +05:30
mergify[bot]
e998f063a9 fix: pos accounting dimension fieldname error (backport #45899) (#45921)
* fix: pos accounting dimension fieldname error (#45899)

* fix: pos accounting dimension fieldname error

* fix: method to get enabled accounting dimensions

* fix: fetch enabled accounting dimensions

* fix: clear flags for accounting_dimensions_details on_update

* refactor: validation for doctype

* fix: using get_checks_for_pl_and_bs_accounts for accounting dimensions

(cherry picked from commit 60a5f4f30d)

# Conflicts:
#	erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py

* chore: resolve conflict

* chore: resolve linter issue

* fix: resolve linter issue

* chore: resolve linter issue

* chore: resolve linter issue

* chore: resolve linter issue

---------

Co-authored-by: Diptanil Saha <diptanil@frappe.io>
2025-02-17 14:13:34 +05:30
Rohit Waghchaure
c289fef3b5 fix: letter head for quality inspection
(cherry picked from commit cdd41373b6)
2025-02-17 08:28:52 +00:00
rohitwaghchaure
f8839957da Merge pull request #45913 from frappe/mergify/bp/version-15-hotfix/pr-45903
fix: allow scrap item with zero qty (backport #45903)
2025-02-16 13:28:00 +05:30
mergify[bot]
e271a5cba0 feat: disable auto setting grand total to default mode of payment (backport #45591) (#45917)
feat: disable auto setting grand total to default mode of payment (#45591)

(cherry picked from commit f0a6399056)

Co-authored-by: Diptanil Saha <diptanil@frappe.io>
2025-02-14 17:34:37 +05:30
ruthra kumar
a486e2962e Merge pull request #45919 from frappe/mergify/bp/version-15-hotfix/pr-45912
fix: include missing payment_gateway parameter in Payment Request URL (backport #45912)
2025-02-14 17:13:29 +05:30
Navin-S-R
18f94765f7 fix: include missing payment_gateway parameter in Payment Request URL
(cherry picked from commit dbac8cfc94)
2025-02-14 11:20:17 +00:00
Rohit Waghchaure
abe5384449 fix: allow scrap item with zero qty
(cherry picked from commit 706cb64279)
2025-02-14 09:47:30 +00:00
rohitwaghchaure
698b7a9d00 Merge pull request #45764 from frappe/mergify/bp/version-15-hotfix/pr-45763
fix: stock reservation not working for sales invoice with update stock (backport #45763)
2025-02-14 15:16:11 +05:30
rohitwaghchaure
52761affe2 chore: fix test case 2025-02-13 16:32:56 +05:30
Rohit Waghchaure
1fb5586f56 fix: stock reservation for sales invoice 2025-02-13 16:04:05 +05:30
ruthra kumar
ef2cddd338 Merge pull request #45894 from frappe/mergify/bp/version-15-hotfix/pr-45804
fix(report): add options to multiselectlist fields (backport #45804)
2025-02-13 14:26:31 +05:30
ruthra kumar
dbe14d6fe4 chore: resolve conflicts 2025-02-13 14:23:46 +05:30
venkat102
7e85a123b2 fix(report): add options to multiselectlist fields
(cherry picked from commit 8785342fce)

# Conflicts:
#	erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.js
#	erpnext/accounts/report/supplier_ledger_summary/supplier_ledger_summary.js
2025-02-13 08:47:15 +00:00
Frappe PR Bot
ce90d427e8 chore(release): Bumped to Version 15.52.0
# [15.52.0](https://github.com/frappe/erpnext/compare/v15.51.2...v15.52.0) (2025-02-12)

### Bug Fixes

* '0' rate LDC's Invoice net totals should be ignored ([96c19cd](96c19cd990))
* add allow_on_submit for party_balance, paid_from_account_balance and paid_to_account_balance ([086c36f](086c36fca6))
* add precision in serial_batch_bundle.py ([a85f6f5](a85f6f54fe))
* add total row in non_grouped_invoices ([e432ae9](e432ae98a9))
* added validation for required invoice_fields in POS (backport [#45780](https://github.com/frappe/erpnext/issues/45780)) ([#45868](https://github.com/frappe/erpnext/issues/45868)) ([4f9a7f5](4f9a7f5065))
* Attibute error `selling_price_list` ([6dc99f9](6dc99f95c0))
* changed naming series to random for SABB ([48a4eff](48a4effdb6))
* check_item_quality_inspection is not whitelisted ([0a4a093](0a4a09352a))
* correct amount in transaction currency for reverse gl entries (backport [#45794](https://github.com/frappe/erpnext/issues/45794)) ([#45849](https://github.com/frappe/erpnext/issues/45849)) ([b06bd82](b06bd825c1))
* correct amt in account currency for lcv with manually distributed charges. (backport [#45532](https://github.com/frappe/erpnext/issues/45532)) ([#45864](https://github.com/frappe/erpnext/issues/45864)) ([179cb1e](179cb1e6e5))
* correct pay amount in portal pages ([3ada520](3ada520618))
* create job card with wip warehouse set to source warehouse if material transfer to wip warehouse is skipped in work order ([9d6f318](9d6f3180d4))
* do not allow "Finance Book" in Accounting Dimensions (backport [#45696](https://github.com/frappe/erpnext/issues/45696)) ([#45856](https://github.com/frappe/erpnext/issues/45856)) ([0954aca](0954aca758))
* do not validate party against  Receivable and Payable account for cancelled gl entries ([6d777cd](6d777cdc68))
* dont update rate of free item on save ([1d3da4d](1d3da4d49a))
* handle response when json is None ([eeb322b](eeb322bd0e))
* map project from rfq to supplier quotation (backport [#45745](https://github.com/frappe/erpnext/issues/45745)) ([#45828](https://github.com/frappe/erpnext/issues/45828)) ([b112d88](b112d88767))
* not able to select the item in the sales invoice ([a649001](a649001886))
* Party name in Supplier Portal for Purchase Order (backport [#45772](https://github.com/frappe/erpnext/issues/45772)) ([#45858](https://github.com/frappe/erpnext/issues/45858)) ([435c354](435c35414f))
* pos numpad editable action buttons (backport [#45823](https://github.com/frappe/erpnext/issues/45823)) ([#45826](https://github.com/frappe/erpnext/issues/45826)) ([035758f](035758f47d))
* possible model sync issue ([ea01fa1](ea01fa135e))
* **regional:** removed payment schedule validation in sales invoice for italy (backport [#45852](https://github.com/frappe/erpnext/issues/45852)) ([#45854](https://github.com/frappe/erpnext/issues/45854)) ([2e9e355](2e9e355329))
* remove serial no if qty is zero ([1359a77](1359a77e72))
* skip warning for free items ([2adab1d](2adab1d36f))
* stock reco current valuation rate ([3b7c38d](3b7c38da10))
* the project document timed out while opening ([28cbce4](28cbce4356))
* unable to remove image from employee ([e3cceb8](e3cceb894b))
* update ctx to args ([d4bc3d1](d4bc3d182f))

### Features

* add repost accounting ledger entry for payment entry ([757dd3f](757dd3f0b6))
2025-02-12 12:09:09 +00:00
ruthra kumar
0eb4556c83 Merge pull request #45860 from frappe/version-15-hotfix
chore: release v15
2025-02-12 17:37:43 +05:30
rohitwaghchaure
45fa2eb542 Merge pull request #45884 from frappe/mergify/bp/version-15-hotfix/pr-45786
fix: skip warning for free items (backport #45786)
2025-02-12 15:16:29 +05:30
barredterra
2adab1d36f fix: skip warning for free items
(cherry picked from commit 772776ad8a)
2025-02-12 09:20:15 +00:00
rohitwaghchaure
162d1ba472 chore: fix test case 2025-02-12 14:32:06 +05:30
rohitwaghchaure
4889950a9e chore: fix conflicts 2025-02-12 14:32:05 +05:30
Rohit Waghchaure
7d871f6bb5 fix: stock reservation not working for sales invoice with update stock
(cherry picked from commit 0c9d0ea1f4)

# Conflicts:
#	erpnext/selling/doctype/sales_order/test_sales_order.py
2025-02-12 14:32:05 +05:30
rohitwaghchaure
70bac1ab17 Merge pull request #45748 from frappe/mergify/bp/version-15-hotfix/pr-45739
fix: create job card with wip warehouse set to source warehouse if material transfer to wip warehouse is skipped in work order (backport #45739)
2025-02-12 13:00:19 +05:30
rohitwaghchaure
0caaff0758 Merge pull request #45880 from frappe/mergify/bp/version-15-hotfix/pr-45879
fix: changed naming series to random for SABB (backport #45879)
2025-02-12 10:53:47 +05:30
rohitwaghchaure
4094fbd6c5 chore: fix conflicts 2025-02-12 10:21:44 +05:30
Rohit Waghchaure
48a4effdb6 fix: changed naming series to random for SABB
(cherry picked from commit a007dc285d)

# Conflicts:
#	erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.json
2025-02-12 04:50:41 +00:00
rohitwaghchaure
68ea528841 Merge pull request #45877 from frappe/mergify/bp/version-15-hotfix/pr-45875
fix: add precision in serial_batch_bundle.py (backport #45875)
2025-02-12 09:25:31 +05:30
rohitwaghchaure
4aa7666e46 Merge pull request #45878 from frappe/mergify/bp/version-15-hotfix/pr-45865
fix: dont update rate of free item on save (backport #45865)
2025-02-12 09:25:08 +05:30
Mihir Kandoi
1d3da4d49a fix: dont update rate of free item on save
(cherry picked from commit 6591e76a63)
2025-02-12 03:13:41 +00:00
Mihir Kandoi
a85f6f54fe fix: add precision in serial_batch_bundle.py
(cherry picked from commit 4bf85d1a5a)
2025-02-12 03:06:27 +00:00
rohitwaghchaure
da08b4eeb9 Merge pull request #45870 from frappe/mergify/bp/version-15-hotfix/pr-45869
fix: stock reco current valuation rate (backport #45869)
2025-02-11 18:38:12 +05:30
rohitwaghchaure
b4f291d0ae Merge pull request #45871 from frappe/mergify/bp/version-15-hotfix/pr-45862
fix: remove serial no if qty is zero (backport #45862)
2025-02-11 18:21:21 +05:30
mergify[bot]
4f9a7f5065 fix: added validation for required invoice_fields in POS (backport #45780) (#45868)
* fix: added validation for required invoice_fields in POS (#45780)

fix: added missing validation for required invoice_fields
(cherry picked from commit b95b13ecd8)

# Conflicts:
#	erpnext/selling/page/point_of_sale/pos_payment.js

* fix: resolved merge conflict

---------

Co-authored-by: Diptanil Saha <diptanil@frappe.io>
2025-02-11 17:55:07 +05:30
Rohit Waghchaure
1359a77e72 fix: remove serial no if qty is zero
(cherry picked from commit 3a4ae8c463)
2025-02-11 11:28:16 +00:00
Rohit Waghchaure
3b7c38da10 fix: stock reco current valuation rate
(cherry picked from commit 8d8f3afb39)
2025-02-11 11:24:14 +00:00
mergify[bot]
179cb1e6e5 fix: correct amt in account currency for lcv with manually distributed charges. (backport #45532) (#45864)
fix: correct amt in account currency for lcv with manually distributed charges.

(cherry picked from commit db38e7bf5a)

Co-authored-by: ljain112 <ljain112@gmail.com>
2025-02-11 16:05:42 +05:30
mergify[bot]
435c35414f fix: Party name in Supplier Portal for Purchase Order (backport #45772) (#45858)
fix: Party name in Supplier Portal for Purchase Order

(cherry picked from commit fc8663421b)

Co-authored-by: ljain112 <ljain112@gmail.com>
2025-02-11 15:42:45 +05:30
mergify[bot]
0954aca758 fix: do not allow "Finance Book" in Accounting Dimensions (backport #45696) (#45856)
fix: do not allow "Finance Book" in Accounting Dimensions

(cherry picked from commit a44be73a98)

Co-authored-by: ljain112 <ljain112@gmail.com>
2025-02-11 15:42:36 +05:30
mergify[bot]
2e9e355329 fix(regional): removed payment schedule validation in sales invoice for italy (backport #45852) (#45854)
fix(regional): removed payment schedule validation in sales invoice for italy (#45852)

(cherry picked from commit 494310293c)

Co-authored-by: Lakshit Jain <108322669+ljain112@users.noreply.github.com>
2025-02-11 15:41:30 +05:30
Smit Vora
6b8826f234 Merge pull request #45773 from ljain112/fix-portalpay
fix: correct pay amount in portal pages
2025-02-11 14:59:03 +05:30
mergify[bot]
b112d88767 fix: map project from rfq to supplier quotation (backport #45745) (#45828)
* fix: map project from rfq to supplier quotation

(cherry picked from commit d0479036bb)

* fix: add project field map from mr to rfq

(cherry picked from commit 8fa39bec61)

---------

Co-authored-by: HenningWendtland <156231187+HenningWendtland@users.noreply.github.com>
2025-02-11 14:52:13 +05:30
mergify[bot]
b06bd825c1 fix: correct amount in transaction currency for reverse gl entries (backport #45794) (#45849)
fix: correct amount in tansaction currency for reverse gl entries

(cherry picked from commit 6077c248b0)

Co-authored-by: ljain112 <ljain112@gmail.com>
2025-02-11 14:49:27 +05:30
ruthra kumar
b084433158 Merge pull request #45847 from frappe/mergify/bp/version-15-hotfix/pr-45792
fix: do not validate party against Receivable and Payable account for cancelled gl entries (backport #45792)
2025-02-11 12:53:29 +05:30
ljain112
6d777cdc68 fix: do not validate party against Receivable and Payable account for cancelled gl entries
(cherry picked from commit 0809e00455)
2025-02-11 06:44:50 +00:00
ruthra kumar
ebce6be23f Merge pull request #45844 from frappe/mergify/bp/version-15-hotfix/pr-45781
fix: Added Total Row for `Gross Profit` Report in Non-Grouped Invoices (backport #45781)
2025-02-11 12:01:11 +05:30
Sanket322
e432ae98a9 fix: add total row in non_grouped_invoices
(cherry picked from commit 2d32ddacc3)
2025-02-11 04:51:47 +00:00
ruthra kumar
09114e6a7b Merge pull request #45842 from frappe/mergify/bp/version-15-hotfix/pr-45832
fix: possible model sync issue (backport #45832)
2025-02-11 10:20:21 +05:30
ruthra kumar
ea01fa135e fix: possible model sync issue
(cherry picked from commit 0069581aa3)
2025-02-11 04:25:34 +00:00
Frappe PR Bot
b0c9fbe9fc chore(release): Bumped to Version 15.51.2
## [15.51.2](https://github.com/frappe/erpnext/compare/v15.51.1...v15.51.2) (2025-02-10)

### Bug Fixes

* Attibute error `selling_price_list` ([e8fd2ee](e8fd2eeaa2))
* check_item_quality_inspection is not whitelisted ([d0dbfa1](d0dbfa1cbd))
2025-02-10 16:28:24 +00:00
rohitwaghchaure
0758192c53 Merge pull request #45836 from frappe/mergify/bp/version-15/pr-45835
fix: check_item_quality_inspection is not whitelisted (backport #45835)
2025-02-10 21:56:59 +05:30
rohitwaghchaure
d2cb659220 Merge pull request #45834 from frappe/mergify/bp/version-15/pr-45822
fix: AttributeError in `get_item_details` when selecting/scanning batch in Delivery Note (backport #45774) (backport #45822)
2025-02-10 21:56:40 +05:30
Rohit Waghchaure
d0dbfa1cbd fix: check_item_quality_inspection is not whitelisted
(cherry picked from commit 0a4a09352a)
2025-02-10 15:46:46 +00:00
rohitwaghchaure
b9b2fc5773 Merge pull request #45835 from rohitwaghchaure/fixed-support-31452
fix: check_item_quality_inspection is not whitelisted
2025-02-10 21:15:27 +05:30
Rohit Waghchaure
0a4a09352a fix: check_item_quality_inspection is not whitelisted 2025-02-10 19:09:02 +05:30
DaizyModi
e8fd2eeaa2 fix: Attibute error selling_price_list
(cherry picked from commit 820b32eb8a)
(cherry picked from commit 6dc99f95c0)
2025-02-10 13:34:14 +00:00
rohitwaghchaure
51545234d3 Merge pull request #45822 from frappe/mergify/bp/version-15-hotfix/pr-45774
fix: AttributeError in `get_item_details` when selecting/scanning batch in Delivery Note (backport #45774)
2025-02-10 19:02:51 +05:30
mergify[bot]
035758f47d fix: pos numpad editable action buttons (backport #45823) (#45826)
fix: pos numpad editable action buttons (#45823)

(cherry picked from commit 0b9c28620f)

Co-authored-by: Diptanil Saha <diptanil@frappe.io>
2025-02-10 16:28:59 +05:30
DaizyModi
6dc99f95c0 fix: Attibute error selling_price_list
(cherry picked from commit 820b32eb8a)
2025-02-10 10:19:49 +00:00
ruthra kumar
f440795809 Merge pull request #45816 from frappe/mergify/bp/version-15-hotfix/pr-45747
fix: Handle Empty JSON in Report Parsing (backport #45747)
2025-02-10 12:10:43 +05:30
Sanket322
eeb322bd0e fix: handle response when json is None
(cherry picked from commit 133e0417b8)
2025-02-10 06:12:45 +00:00
ruthra kumar
9a5aa8eeb9 Merge pull request #45813 from frappe/mergify/bp/version-15-hotfix/pr-45793
fix: unable to remove image from employee (backport #45793)
2025-02-10 11:01:00 +05:30
ruthra kumar
1f967f7e9d Merge pull request #45814 from frappe/mergify/bp/version-15-hotfix/pr-45762
refactor: set received and paid amount based on each other, if unset (backport #45762)
2025-02-10 11:00:48 +05:30
rohitwaghchaure
3c386c2062 Merge pull request #45811 from frappe/mergify/bp/version-15-hotfix/pr-45810
fix: not able to select the item in the sales invoice (backport #45810)
2025-02-10 10:41:31 +05:30
ruthra kumar
1d6c50c9a1 chore: resolve conflict 2025-02-10 10:38:18 +05:30
ruthra kumar
e589c5b6ef refactor: set paid amount based on received amount if unset
(cherry picked from commit 99e721e622)
2025-02-10 05:08:05 +00:00
ruthra kumar
6638b391ff refactor: set received amount based on paid amount
(cherry picked from commit 5ff540bd82)
2025-02-10 05:08:05 +00:00
Asmita Hase
e3cceb894b fix: unable to remove image from employee
fix: employee image disappears when newly created user_id is linked to employee

(cherry picked from commit 0207d2d7b6)

# Conflicts:
#	erpnext/setup/doctype/employee/employee.json
2025-02-10 05:03:12 +00:00
Rohit Waghchaure
a649001886 fix: not able to select the item in the sales invoice
(cherry picked from commit 35388e7a04)
2025-02-10 04:39:40 +00:00
rohitwaghchaure
39e3746a62 Merge pull request #45775 from frappe/mergify/bp/version-15-hotfix/pr-45767
fix: the project document timed out while opening (backport #45767)
2025-02-10 10:09:38 +05:30
Frappe PR Bot
8c57e9f8c8 chore(release): Bumped to Version 15.51.1
## [15.51.1](https://github.com/frappe/erpnext/compare/v15.51.0...v15.51.1) (2025-02-07)

### Bug Fixes

* update ctx to args ([13bebe7](13bebe71b0))
2025-02-07 14:22:13 +00:00
ruthra kumar
5f62fc5a99 Merge pull request #45795 from frappe/mergify/bp/version-15/pr-45770
Fix: Update `ctx` to `args` for compatibility. (backport #45770)
2025-02-07 19:50:45 +05:30
Sanket322
13bebe71b0 fix: update ctx to args
(cherry picked from commit d4bc3d182f)
2025-02-07 14:14:41 +00:00
ruthra kumar
9702a192d7 Merge pull request #45770 from Sanket322/update_ctx_to_args
Fix: Update `ctx` to `args` for compatibility.
2025-02-07 19:43:53 +05:30
ruthra kumar
a051ddee6d Merge pull request #45788 from frappe/mergify/bp/version-15-hotfix/pr-45640
feat: add repost accounting ledger entry for payment entry (backport #45640)
2025-02-07 17:15:33 +05:30
ruthra kumar
be09700d8b Merge pull request #45789 from frappe/mergify/bp/version-15-hotfix/pr-45644
fix: add allow_on_submit for party_balance, paid_from_account_balance and paid_to_account_balance (backport #45644)
2025-02-07 17:15:22 +05:30
l0gesh29
757dd3f0b6 feat: add repost accounting ledger entry for payment entry
(cherry picked from commit 5676d60ed3)
2025-02-07 10:41:54 +00:00
Sugesh393
086c36fca6 fix: add allow_on_submit for party_balance, paid_from_account_balance and paid_to_account_balance
(cherry picked from commit 707c01487e)
2025-02-07 10:41:54 +00:00
ruthra kumar
a7d32b580f Merge pull request #45784 from frappe/mergify/bp/version-15-hotfix/pr-45639
fix: '0' rate LDC's Invoice net totals should be ignored (backport #45639)
2025-02-07 13:43:58 +05:30
ruthra kumar
43d75b96c6 chore: resolve conflict 2025-02-07 13:18:42 +05:30
ruthra kumar
3734289983 test: ldc @ 0 rate
(cherry picked from commit 0cdd346f8f)

# Conflicts:
#	erpnext/accounts/doctype/tax_withholding_category/test_tax_withholding_category.py
2025-02-07 07:44:11 +00:00
ruthra kumar
96c19cd990 fix: '0' rate LDC's Invoice net totals should be ignored
(cherry picked from commit 325c4e3536)
2025-02-07 07:44:11 +00:00
rohitwaghchaure
08a6f4e6d3 chore: fix conflicts 2025-02-06 22:09:44 +05:30
Rohit Waghchaure
28cbce4356 fix: the project document timed out while opening
(cherry picked from commit 33d03b1542)

# Conflicts:
#	erpnext/selling/doctype/sales_order/sales_order.json
2025-02-06 16:38:46 +00:00
ljain112
3ada520618 fix: correct pay amount in portal pages 2025-02-06 18:56:29 +05:30
Sanket322
d4bc3d182f fix: update ctx to args 2025-02-06 17:55:37 +05:30
Mihir Kandoi
4196986273 chore: resolve conflicts 2025-02-05 17:59:34 +05:30
Mihir Kandoi
9d6f3180d4 fix: create job card with wip warehouse set to source warehouse if material transfer to wip warehouse is skipped in work order
(cherry picked from commit 723e902470)

# Conflicts:
#	erpnext/manufacturing/doctype/work_order/work_order.py
2025-02-05 12:19:49 +00:00
Frappe PR Bot
b1161f446f chore(release): Bumped to Version 15.51.0
# [15.51.0](https://github.com/frappe/erpnext/compare/v15.50.1...v15.51.0) (2025-02-05)

### Bug Fixes

* actual qty showing blank for sub-assembly items ([d0748b1](d0748b1b67))
* added correct options for incoming_rate field of delivery note item ([cfc5007](cfc50073ed))
* allow multiple email ids ([2a25302](2a25302c35))
* attribute 'msgbox' not found in sales invoice.js ([f6b4984](f6b49845e2))
* bind this to function ([c0b32c4](c0b32c446b))
* check billing address ([44d9fb7](44d9fb7a69))
* closing stock balance report not generating ([47d1c3b](47d1c3b5a3))
* conflicts ([4aa072a](4aa072a8eb))
* consider process_loss_qty in work order ([1522d76](1522d76a3b))
* copy correct uom from devliery note when creating packing list ([f9794e5](f9794e5b44))
* correct error message in payment entry ([6ea5307](6ea5307b0e))
* default payment terms template selected while duplicating ([ca4bb96](ca4bb96fb4))
* Do not check for cancelled invoices ([84638f5](84638f58fd))
* Do not check for cancelled invoices ([b612ab5](b612ab5823))
* fetch rate from item price list when document is saved ([b140ce7](b140ce71d7))
* filter the item tax template using the input text ([8ea9a9e](8ea9a9e467))
* Gross Profit Report with Correct Totals and Gross Margin (backport [#45548](https://github.com/frappe/erpnext/issues/45548)) ([#45598](https://github.com/frappe/erpnext/issues/45598)) ([6301b32](6301b321d8))
* handling company in bank reconciliation tool ([#45582](https://github.com/frappe/erpnext/issues/45582)) ([aa27e19](aa27e19a58))
* ignore expired batch for pick list ([786db3d](786db3d0fa))
* loading print receipt only at order complete (backport [#45627](https://github.com/frappe/erpnext/issues/45627)) ([#45628](https://github.com/frappe/erpnext/issues/45628)) ([72868ee](72868eee04))
* logical error failing tests ([6a03f99](6a03f99546))
* not able to make manufacturing entry for alternate items ([eef2f3c](eef2f3c5d4))
* only system manager was able to create customer & prospect ([6149306](6149306b78))
* payment schedule table is empty while duplicating record ([c523625](c52362531c))
* point of sale padding (backport [#45697](https://github.com/frappe/erpnext/issues/45697)) ([#45699](https://github.com/frappe/erpnext/issues/45699)) ([b915e7f](b915e7f637))
* pos payment cash shortcut decimal (backport [#45702](https://github.com/frappe/erpnext/issues/45702)) ([#45705](https://github.com/frappe/erpnext/issues/45705)) ([6113cc1](6113cc1e43))
* pos print receipt on submit (backport [#45632](https://github.com/frappe/erpnext/issues/45632)) ([#45633](https://github.com/frappe/erpnext/issues/45633)) ([676dde5](676dde59c2))
* **pos:** add item in the existing item row when discount is applied ([0b54cb9](0b54cb9a7c))
* posting_date to posting_datetime in stock related queries ([cd5174e](cd5174e423))
* remove tds account in taxes table on change of Tax Withholding Category ([1ad16c3](1ad16c368e))
* removed unused field ([9a27d3c](9a27d3cedc))
* renamed Commments Tab to Notes tab in Lead doctype ([86edcfc](86edcfc1fd))
* reposting issue with s3 backup ([73c1bf9](73c1bf972e))
* resolved conflicts ([223fe62](223fe62638))
* respect user set account if not advance account for getting outstanding invoices in payment entry ([8108d7f](8108d7fdba))
* semgrep ([401fd7f](401fd7fca7))
* set asset value correctly after cancelling value adjustment ([7f7f403](7f7f403f5b))
* show only items with inspection enabled on create QI dialog ([34f8a37](34f8a370d1))
* slow SABB query ([7931c2d](7931c2d182))
* subcontracting valiation precision issue ([5319683](5319683dbf))
* track employee changes ([#45674](https://github.com/frappe/erpnext/issues/45674)) ([cf98ebf](cf98ebf7fe))
* validation message ([4742211](47422111b4))
* validation to prevent submission if the SABB is not linked to a stock transaction ([24a6f61](24a6f611d8))

### Features

* account heads changed along with journal entry type and descrip… ([#42845](https://github.com/frappe/erpnext/issues/42845)) ([bbecd36](bbecd36a5d))
* report to find incorrect SABB ([a948f2e](a948f2e095))
* set bank account of company to default company bank account from masters ([b840271](b840271d2a))

### Performance Improvements

* stock entry with batch (backport [#45486](https://github.com/frappe/erpnext/issues/45486)) ([#45602](https://github.com/frappe/erpnext/issues/45602)) ([8b75401](8b75401db9))
2025-02-05 12:08:00 +00:00
ruthra kumar
b8485e1d28 Merge pull request #45703 from frappe/version-15-hotfix
chore: release v15
2025-02-05 17:36:41 +05:30
ruthra kumar
e422ae16e5 Merge pull request #45743 from frappe/mergify/bp/version-15-hotfix/pr-45604
fix: filter the item tax template using the input text (backport #45604)
2025-02-05 17:13:07 +05:30
rohitwaghchaure
dcdd8e9824 Merge pull request #45742 from frappe/mergify/bp/version-15-hotfix/pr-45734
fix: added correct options for incoming_rate field of delivery note item (backport #45734)
2025-02-05 17:08:16 +05:30
rohitwaghchaure
9d98d0efc8 Merge pull request #45744 from frappe/mergify/bp/version-15-hotfix/pr-45741
fix: removed unused field (backport #45741)
2025-02-05 17:07:46 +05:30
rohitwaghchaure
af60368e54 Merge pull request #45740 from frappe/mergify/bp/version-15-hotfix/pr-45692
fix: fetch rate from item price list when document is saved (backport #45692)
2025-02-05 16:42:00 +05:30
rohitwaghchaure
ab37e5754b chore: fix conflicts 2025-02-05 16:40:20 +05:30
Rohit Waghchaure
9a27d3cedc fix: removed unused field
(cherry picked from commit 2d7a576da5)
2025-02-05 11:09:40 +00:00
ruthra kumar
0b591ba7eb chore: resolve conflicts 2025-02-05 16:37:09 +05:30
Bhavan23
8ea9a9e467 fix: filter the item tax template using the input text
(cherry picked from commit 4dd37ba033)

# Conflicts:
#	erpnext/controllers/queries.py
2025-02-05 11:01:21 +00:00
Mihir Kandoi
cfc50073ed fix: added correct options for incoming_rate field of delivery note item
(cherry picked from commit 417bf49a8d)

# Conflicts:
#	erpnext/stock/doctype/delivery_note_item/delivery_note_item.json
2025-02-05 10:48:01 +00:00
Mihir Kandoi
25075e5981 test: added test
(cherry picked from commit 07adfadd58)
2025-02-05 10:23:26 +00:00
Mihir Kandoi
6a03f99546 fix: logical error failing tests
(cherry picked from commit fee318a275)
2025-02-05 10:23:26 +00:00
Mihir Kandoi
b140ce71d7 fix: fetch rate from item price list when document is saved
(cherry picked from commit 1e4b9fbdf0)
2025-02-05 10:23:26 +00:00
Khushi Rawat
f72d4b6984 Merge pull request #45738 from frappe/mergify/bp/version-15-hotfix/pr-45735
fix: set asset value correctly after cancelling value adjustment (backport #45735)
2025-02-05 15:51:11 +05:30
ruthra kumar
d86f7839ab Merge pull request #45737 from frappe/mergify/bp/version-15-hotfix/pr-45717
fix(Purchase Invoice): default payment terms template selected while duplicating (backport #45717)
2025-02-05 15:30:48 +05:30
Khushi Rawat
7f7f403f5b fix: set asset value correctly after cancelling value adjustment
(cherry picked from commit fee3846144)
2025-02-05 09:56:11 +00:00
Ejaaz Khan
df0ca2d198 refactor: remove log
(cherry picked from commit bfc01441a0)
2025-02-05 09:47:59 +00:00
Ejaaz Khan
c52362531c fix: payment schedule table is empty while duplicating record
(cherry picked from commit fb3f08a441)
2025-02-05 09:47:59 +00:00
Ejaaz Khan
ca4bb96fb4 fix: default payment terms template selected while duplicating
(cherry picked from commit 18127603fe)
2025-02-05 09:47:59 +00:00
Khushi Rawat
50d10d5c8d Merge pull request #45733 from frappe/mergify/bp/version-15-hotfix/pr-42845
feat: account heads changed along with journal entry type and descrip… (backport #42845)
2025-02-05 15:03:27 +05:30
Khushi Rawat
4aa072a8eb fix: conflicts 2025-02-05 14:44:39 +05:30
Khushi Rawat
223fe62638 fix: resolved conflicts 2025-02-05 14:43:24 +05:30
rahulgupta8848
bbecd36a5d feat: account heads changed along with journal entry type and descrip… (#42845)
* feat: account heads changed along with journal entry type and description

* feat: added patch for difference_amount for asset value adjustment and refactor

---------

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

# Conflicts:
#	erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.json
#	erpnext/patches.txt
2025-02-05 09:09:49 +00:00
ruthra kumar
9f28993575 Merge pull request #45732 from frappe/mergify/bp/version-15-hotfix/pr-45590
fix: remove tds account in taxes table on change of Tax Withholding C… (backport #45590)
2025-02-05 14:28:07 +05:30
l0gesh29
1ad16c368e fix: remove tds account in taxes table on change of Tax Withholding Category
(cherry picked from commit 79b5a3e1dd)
2025-02-05 08:39:21 +00:00
ruthra kumar
c1002d3787 Merge pull request #45728 from frappe/mergify/bp/version-15-hotfix/pr-45686
fix: allow multiple email ids (backport #45686)
2025-02-05 14:08:48 +05:30
ruthra kumar
8ad32c4593 Merge pull request #45731 from frappe/mergify/bp/version-15-hotfix/pr-45447
fix(pos): add item in the existing item row when discount is applied (backport #45447)
2025-02-05 14:04:09 +05:30
venkat102
0b54cb9a7c fix(pos): add item in the existing item row when discount is applied
(cherry picked from commit bee2c04d0b)
2025-02-05 08:30:27 +00:00
Sudharsanan11
44d9fb7a69 fix: check billing address
(cherry picked from commit 9950e4aa0c)
2025-02-05 08:19:58 +00:00
Sudharsanan11
2a25302c35 fix: allow multiple email ids
(cherry picked from commit 423decb93c)
2025-02-05 08:19:58 +00:00
ruthra kumar
0cac9e9b9a Merge pull request #45727 from frappe/mergify/bp/version-15-hotfix/pr-45610
fix: respect user set account if not advance account for getting outsanding invoices in payment entry (backport #45610)
2025-02-05 13:40:05 +05:30
rohitwaghchaure
efa7602fae Merge pull request #45718 from frappe/mergify/bp/version-15-hotfix/pr-45710
fix: show only items with inspection enabled on create QI dialog (backport #45710)
2025-02-05 13:05:16 +05:30
ruthra kumar
b926b49afa chore: fix typo
(cherry picked from commit 85378f9d1a)
2025-02-05 06:40:22 +00:00
ljain112
8108d7fdba fix: respect user set account if not advance account for getting outstanding invoices in payment entry
(cherry picked from commit 9faf78d3e5)
2025-02-05 06:40:22 +00:00
Mihir Kandoi
3689a2deae chore: resolve conflicts 2025-02-05 12:00:01 +05:30
ruthra kumar
5a7b901327 Merge pull request #45719 from frappe/mergify/bp/version-15-hotfix/pr-45678
fix: copy correct uom from delivery note when creating packing list (backport #45678)
2025-02-05 10:38:13 +05:30
rohitwaghchaure
51b03d40aa Merge pull request #45721 from rohitwaghchaure/fixed-support-30732
fix: closing stock balance report not generating
2025-02-05 08:45:00 +05:30
Rohit Waghchaure
47d1c3b5a3 fix: closing stock balance report not generating 2025-02-05 05:29:23 +05:30
Mihir Kandoi
f9794e5b44 fix: copy correct uom from devliery note when creating packing list
(cherry picked from commit 3cdaa80526)
2025-02-04 19:06:15 +00:00
Mihir Kandoi
401fd7fca7 fix: semgrep
(cherry picked from commit ffd10d1fe9)
2025-02-04 19:04:57 +00:00
Mihir Kandoi
34f8a370d1 fix: show only items with inspection enabled on create QI dialog
(cherry picked from commit c92ec312b9)

# Conflicts:
#	erpnext/controllers/stock_controller.py
2025-02-04 19:04:57 +00:00
ruthra kumar
ac960d26e8 Merge pull request #45711 from frappe/mergify/bp/version-15-hotfix/pr-45582
fix: handling company in bank reconciliation tool (backport #45582)
2025-02-04 17:32:42 +05:30
Aayush Dalal
aa27e19a58 fix: handling company in bank reconciliation tool (#45582)
Co-authored-by: Raffael Meyer <14891507+barredterra@users.noreply.github.com>
(cherry picked from commit d1c927530e)
2025-02-04 11:45:01 +00:00
rohitwaghchaure
1ed52c3b41 Merge pull request #45708 from frappe/mergify/bp/version-15-hotfix/pr-45701
fix: subcontracting validation precision issue (backport #45701)
2025-02-04 15:56:44 +05:30
Frappe PR Bot
fea51b7086 chore(release): Bumped to Version 15.50.1
## [15.50.1](https://github.com/frappe/erpnext/compare/v15.50.0...v15.50.1) (2025-02-04)

### Bug Fixes

* not able to make manufacturing entry for alternate items ([32bfc2f](32bfc2f555))
2025-02-04 10:23:41 +00:00
rohitwaghchaure
49192d90d0 Merge pull request #45707 from frappe/mergify/bp/version-15/pr-45647
fix: not able to make manufacturing entry for alternate items (backport #45646) (backport #45647)
2025-02-04 15:52:11 +05:30
rohitwaghchaure
f9af53cd87 Merge pull request #45706 from frappe/mergify/bp/version-15-hotfix/pr-45698
feat: report to find incorrect SABB (backport #45698)
2025-02-04 15:45:40 +05:30
Mihir Kandoi
5319683dbf fix: subcontracting valiation precision issue
(cherry picked from commit 8720d412bd)
2025-02-04 09:54:08 +00:00
Rohit Waghchaure
32bfc2f555 fix: not able to make manufacturing entry for alternate items
(cherry picked from commit 1607aa1a44)
(cherry picked from commit eef2f3c5d4)
2025-02-04 09:52:11 +00:00
Rohit Waghchaure
a948f2e095 feat: report to find incorrect SABB
(cherry picked from commit 7e24395e00)
2025-02-04 09:47:04 +00:00
mergify[bot]
6113cc1e43 fix: pos payment cash shortcut decimal (backport #45702) (#45705)
fix: pos payment cash shortcut decimal (#45702)

(cherry picked from commit a20116816e)

Co-authored-by: Diptanil Saha <diptanil@frappe.io>
2025-02-04 15:14:08 +05:30
mergify[bot]
b915e7f637 fix: point of sale padding (backport #45697) (#45699)
fix: point of sale padding (#45697)

(cherry picked from commit 51a65899ec)

Co-authored-by: Diptanil Saha <diptanil@frappe.io>
2025-02-04 14:02:38 +05:30
Shariq Ansari
0d03e03925 Merge pull request #45695 from frappe/mergify/bp/version-15-hotfix/pr-45694
fix: only system manager was able to create customer & prospect (backport #45694)
2025-02-04 12:48:50 +05:30
Shariq Ansari
6149306b78 fix: only system manager was able to create customer & prospect
(cherry picked from commit 716edeb465)
2025-02-04 06:41:09 +00:00
rohitwaghchaure
a0523c7956 Merge pull request #45690 from frappe/mergify/bp/version-15-hotfix/pr-45680
fix: slow SABB query (backport #45680)
2025-02-03 23:10:46 +05:30
Rohit Waghchaure
7931c2d182 fix: slow SABB query
(cherry picked from commit 81978a0bd8)
2025-02-03 17:02:03 +00:00
rohitwaghchaure
7658053dbd Merge pull request #45665 from frappe/mergify/bp/version-15-hotfix/pr-45648
fix: consider process_loss_qty in work order (backport #45648)
2025-02-03 20:57:01 +05:30
ruthra kumar
1b85cdcf48 Merge pull request #45677 from frappe/mergify/bp/version-15-hotfix/pr-45674
fix: track employee changes (backport #45674)
2025-02-03 15:27:03 +05:30
ruthra kumar
16a80cc04a Merge pull request #45675 from frappe/mergify/bp/version-15-hotfix/pr-45631
fix: Do not check for cancelled invoices (backport #45631)
2025-02-03 14:32:00 +05:30
Ankush Menat
cf98ebf7fe fix: track employee changes (#45674)
closes https://github.com/frappe/erpnext/issues/45571

(cherry picked from commit 827afbfa2e)
2025-02-03 08:52:45 +00:00
Deepesh Garg
84638f58fd fix: Do not check for cancelled invoices
(cherry picked from commit 2c94867b0e)
2025-02-03 08:42:28 +00:00
Deepesh Garg
b612ab5823 fix: Do not check for cancelled invoices
(cherry picked from commit 701fc02050)
2025-02-03 08:42:27 +00:00
ruthra kumar
0d94eba021 Merge pull request #45669 from frappe/mergify/bp/version-15-hotfix/pr-45619
feat: set bank account of company to default company bank account fro… (backport #45619)
2025-02-03 14:05:23 +05:30
Shariq Ansari
7d95113499 Merge pull request #45673 from frappe/mergify/bp/version-15-hotfix/pr-45637
fix: renamed Comments Tab to Notes tab in Lead doctype (backport #45637)
2025-02-03 13:27:26 +05:30
Shariq Ansari
afd2529c2a chore: resolved conflict 2025-02-03 13:26:33 +05:30
Shariq Ansari
86edcfc1fd fix: renamed Commments Tab to Notes tab in Lead doctype
(cherry picked from commit 018df3135a)

# Conflicts:
#	erpnext/crm/doctype/lead/lead.json
2025-02-03 07:53:32 +00:00
Mihir Kandoi
b840271d2a feat: set bank account of company to default company bank account from masters
(cherry picked from commit ce7702cc19)
2025-02-03 06:31:55 +00:00
rohitwaghchaure
55ac00a510 Merge pull request #45667 from frappe/mergify/bp/version-15-hotfix/pr-45621
fix: delivered button of purchase order (backport #45621)
2025-02-03 11:58:35 +05:30
Mihir Kandoi
c0b32c446b fix: bind this to function
(cherry picked from commit 41649cf52d)
2025-02-03 06:22:47 +00:00
Mihir Kandoi
1522d76a3b fix: consider process_loss_qty in work order
(cherry picked from commit 95fda47b6c)
2025-02-03 06:21:40 +00:00
rohitwaghchaure
83e676f128 Merge pull request #45647 from frappe/mergify/bp/version-15-hotfix/pr-45646
fix: not able to make manufacturing entry for alternate items (backport #45646)
2025-02-03 11:48:03 +05:30
Rohit Waghchaure
eef2f3c5d4 fix: not able to make manufacturing entry for alternate items
(cherry picked from commit 1607aa1a44)
2025-01-31 18:18:37 +00:00
rohitwaghchaure
821cc215e3 Merge pull request #45645 from frappe/mergify/bp/version-15-hotfix/pr-45642
fix: actual qty showing blank for sub-assembly items (backport #45642)
2025-01-31 23:22:09 +05:30
rohitwaghchaure
3e09abc495 Merge pull request #45617 from rtdany10/expired-batch-pick
fix: ignore expired batch for pick list
2025-01-31 22:49:34 +05:30
Rohit Waghchaure
d0748b1b67 fix: actual qty showing blank for sub-assembly items
(cherry picked from commit 5be2e71a35)
2025-01-31 17:09:00 +00:00
rohitwaghchaure
7fc70e3f20 Merge pull request #45638 from frappe/mergify/bp/version-15-hotfix/pr-45626
fix: validation to prevent submission, if the SABB is not linked to a stock transaction (backport #45626)
2025-01-31 15:21:43 +05:30
Rohit Waghchaure
24a6f611d8 fix: validation to prevent submission if the SABB is not linked to a stock transaction
(cherry picked from commit f976115a2b)
2025-01-31 09:14:53 +00:00
ruthra kumar
4b91b7691a Merge pull request #45636 from frappe/mergify/bp/version-15-hotfix/pr-45615
fix: correct error message in payment entry (backport #45615)
2025-01-31 14:18:59 +05:30
ljain112
6ea5307b0e fix: correct error message in payment entry
(cherry picked from commit 592704cfd0)
2025-01-31 07:27:37 +00:00
rohitwaghchaure
d65101a5f2 Merge pull request #45634 from frappe/mergify/bp/version-15-hotfix/pr-45629
fix: attribute 'msgbox' not found in sales invoice.js (backport #45629)
2025-01-31 12:11:28 +05:30
rohitwaghchaure
bd8e4eeddc chore: fix conflicts 2025-01-31 12:09:50 +05:30
Mihir Kandoi
f6b49845e2 fix: attribute 'msgbox' not found in sales invoice.js
(cherry picked from commit 5643385c22)

# Conflicts:
#	erpnext/accounts/doctype/sales_invoice/sales_invoice.js
2025-01-31 06:34:32 +00:00
mergify[bot]
676dde59c2 fix: pos print receipt on submit (backport #45632) (#45633)
fix: pos print receipt on submit (#45632)

(cherry picked from commit fe51535392)

Co-authored-by: Diptanil Saha <diptanil@frappe.io>
2025-01-31 12:02:47 +05:30
mergify[bot]
72868eee04 fix: loading print receipt only at order complete (backport #45627) (#45628)
fix: loading print receipt only at order complete (#45627)

(cherry picked from commit 5a1851dfe3)

Co-authored-by: Diptanil Saha <diptanil@frappe.io>
2025-01-31 11:19:23 +05:30
rohitwaghchaure
04c1fc71dd Merge pull request #45614 from frappe/mergify/bp/version-15-hotfix/pr-45612
fix: posting_date to posting_datetime in stock related queries (backport #45612)
2025-01-30 21:19:19 +05:30
Dany Robert
786db3d0fa fix: ignore expired batch for pick list 2025-01-30 19:34:06 +05:30
Rohit Waghchaure
cd5174e423 fix: posting_date to posting_datetime in stock related queries
(cherry picked from commit e61ab48145)
2025-01-30 11:36:10 +00:00
rohitwaghchaure
20d5a79839 Merge pull request #45613 from frappe/mergify/bp/version-15-hotfix/pr-45609
fix: reposting issue with s3 backup (backport #45609)
2025-01-30 17:05:16 +05:30
Rohit Waghchaure
73c1bf972e fix: reposting issue with s3 backup
(cherry picked from commit 6b454ca9a7)
2025-01-30 10:29:54 +00:00
mergify[bot]
6301b321d8 fix: Gross Profit Report with Correct Totals and Gross Margin (backport #45548) (#45598)
fix: Gross Profit Report with Correct Totals and Gross Margin (#45548)

Co-authored-by: Sanket322 <shahsanket322003.com>
(cherry picked from commit aaf720ab61)

Co-authored-by: Sanket Shah <113279972+Sanket322@users.noreply.github.com>
2025-01-30 11:21:52 +05:30
mergify[bot]
8b75401db9 perf: stock entry with batch (backport #45486) (#45602)
perf: stock entry with batch

(cherry picked from commit 0b1b964b77)

Co-authored-by: Rohit Waghchaure <rohitw1991@gmail.com>
2025-01-30 11:21:20 +05:30
rohitwaghchaure
b5856d4f1f Merge pull request #45601 from frappe/mergify/bp/version-15-hotfix/pr-45600
fix: validation message (backport #45600)
2025-01-29 20:48:56 +05:30
Rohit Waghchaure
47422111b4 fix: validation message
(cherry picked from commit 4c8dff942d)
2025-01-29 15:12:39 +00:00
Frappe PR Bot
c5cd0fcd29 chore(release): Bumped to Version 15.50.0
# [15.50.0](https://github.com/frappe/erpnext/compare/v15.49.3...v15.50.0) (2025-01-29)

### Bug Fixes

* add condition to check if item is delivered by supplier in make_purchase_order_for_default_supplier() (backport [#45370](https://github.com/frappe/erpnext/issues/45370)) ([#45410](https://github.com/frappe/erpnext/issues/45410)) ([5d7d3d8](5d7d3d8c19))
* add multiple item issue in stock entry (backport [#45544](https://github.com/frappe/erpnext/issues/45544)) ([#45580](https://github.com/frappe/erpnext/issues/45580)) ([8b0efab](8b0efab13e))
* added debounce to prevent multiple clicks (backport [#45369](https://github.com/frappe/erpnext/issues/45369)) ([#45376](https://github.com/frappe/erpnext/issues/45376)) ([bdc65da](bdc65daadd))
* added item_group filter in item_code field in stock balance report (backport [#45340](https://github.com/frappe/erpnext/issues/45340)) ([#45389](https://github.com/frappe/erpnext/issues/45389)) ([412e22f](412e22fb4e))
* allow to fix negative stock for batch using stock reco ([69c5695](69c5695f6e))
* batch qty calculation (backport [#45367](https://github.com/frappe/erpnext/issues/45367)) ([#45388](https://github.com/frappe/erpnext/issues/45388)) ([767529f](767529f0ec))
* Correct Party Bank Account mapping in `Payment Entry` ([4a390ae](4a390ae3de))
* currency decimal on POS Past Order List (backport [#45524](https://github.com/frappe/erpnext/issues/45524)) ([#45527](https://github.com/frappe/erpnext/issues/45527)) ([ff46ae5](ff46ae5bc1))
* disable load_after_mapping when purchase order created from sales order (backport [#45405](https://github.com/frappe/erpnext/issues/45405)) ([#45429](https://github.com/frappe/erpnext/issues/45429)) ([ae5ce97](ae5ce97fd0))
* Do no query GLs if no PCVs are posted ([ad06652](ad06652ed5))
* do not allow to manually submit the SABB ([2b16eb5](2b16eb5381))
* do not check budget during reposting ([#45432](https://github.com/frappe/erpnext/issues/45432)) ([f2b946d](f2b946d325))
* don't update party-type on change of cost center in Journal Entry ([#45291](https://github.com/frappe/erpnext/issues/45291)) ([fb75180](fb75180a7d))
* existing logical error ([6c4655d](6c4655dd72))
* fix creating documents from sales invoice (backport [#45346](https://github.com/frappe/erpnext/issues/45346)) ([#45408](https://github.com/frappe/erpnext/issues/45408)) ([73a21c2](73a21c294c))
* get stock balance filtered by company for validating stock value in jv (backport [#45549](https://github.com/frappe/erpnext/issues/45549)) ([#45578](https://github.com/frappe/erpnext/issues/45578)) ([ef2f411](ef2f4118d9))
* import ([d74c498](d74c498efe))
* import 2 ([b59d253](b59d253d93))
* JobCardTimeLog' object has no attribute 'remaining_time_in_mins' ([ef15429](ef15429d98))
* logical error in where condition of qb query ([c102e51](c102e51eb1))
* **material request:** mapping Sales Order Item Delivery Date to Mate… (backport [#45227](https://github.com/frappe/erpnext/issues/45227)) ([#45424](https://github.com/frappe/erpnext/issues/45424)) ([52fdc7c](52fdc7cecd))
* merge conflict ([57f79a2](57f79a2240))
* **payment entry:** get amount in transaction currency ([b37602c](b37602c716))
* postal_code_move_and_fixes ([0e088dd](0e088dde36))
* precision issue causing incorrect status ([46a2b7a](46a2b7a07e))
* precision issue in stock entry ([fe5e42d](fe5e42d2dc))
* **query:** remove duplicate docstatus condition ([#45586](https://github.com/frappe/erpnext/issues/45586)) ([2d2f30e](2d2f30e6cf))
* remove applied pricing rule ([4e347d8](4e347d835e))
* remove unnecessary auth from plaid connector (backport [#44305](https://github.com/frappe/erpnext/issues/44305)) ([#45421](https://github.com/frappe/erpnext/issues/45421)) ([d9b342f](d9b342f257))
* removed field not present in v15 ([1be1981](1be19819fb))
* resolved pos return setting to default mode of payment instead of user selection (backport [#45377](https://github.com/frappe/erpnext/issues/45377)) ([#45419](https://github.com/frappe/erpnext/issues/45419)) ([224a925](224a92587d))
* return qty error due to precision (backport [#45536](https://github.com/frappe/erpnext/issues/45536)) ([#45581](https://github.com/frappe/erpnext/issues/45581)) ([a2ffdc7](a2ffdc7805))
* secure bulk transaction (backport [#45386](https://github.com/frappe/erpnext/issues/45386)) ([#45426](https://github.com/frappe/erpnext/issues/45426)) ([f9d9672](f9d96726f0))
* set company related values ([1498275](149827562b))
* set expense_account and cost_center based on company in stock entry (backport [#45159](https://github.com/frappe/erpnext/issues/45159)) ([#45416](https://github.com/frappe/erpnext/issues/45416)) ([3eb28bb](3eb28bb0e0))
* set party_account_currency for pos_invoice returns ([172fdad](172fdad244))
* set preferred email in Employee via backend controller (backport [#45320](https://github.com/frappe/erpnext/issues/45320)) ([#45379](https://github.com/frappe/erpnext/issues/45379)) ([f8099a6](f8099a6847))
* Set right party name in bank transaction ([86f4bf6](86f4bf6e01))
* show payment entries in Tax Withheld Vouchers ([28bb9c3](28bb9c39e8))
* System was allowing to save payment schedule amount less than grand total (backport [#45322](https://github.com/frappe/erpnext/issues/45322)) ([#45381](https://github.com/frappe/erpnext/issues/45381)) ([2403cdc](2403cdc4d7))
* update fields on change of item code In `Update Items` of `Sales Order` ([#45125](https://github.com/frappe/erpnext/issues/45125)) ([f60a3bc](f60a3bcedf))
* update voucher outstanding from payment ledger ([e385594](e3855949e1))
* Use `process.extract` to get the corresponding party doc name of the result ([153e961](153e961df7))
* use frappe.datetime.str_to_user (backport [#45216](https://github.com/frappe/erpnext/issues/45216)) ([#45417](https://github.com/frappe/erpnext/issues/45417)) ([6c10393](6c10393164))
* use user defined discount amount or default ([e73aab0](e73aab0df5))
* validate items against selling settings (backport [#45288](https://github.com/frappe/erpnext/issues/45288)) ([#45431](https://github.com/frappe/erpnext/issues/45431)) ([7ff7ec7](7ff7ec7929))
* validate non-stock item for exchange loss/gain (backport [#45306](https://github.com/frappe/erpnext/issues/45306)) ([#45380](https://github.com/frappe/erpnext/issues/45380)) ([4e367de](4e367dedec))
* valuation for batch (backport [#45335](https://github.com/frappe/erpnext/issues/45335)) ([#45420](https://github.com/frappe/erpnext/issues/45420)) ([dec0cae](dec0caeac5))
* variable names ([8f73978](8f73978a26))
* Wrong `bank_ac_no` filter + simplify convoluted logic ([60feb7c](60feb7cbd4))

### Features

* Add chart of accounts for Switzerland ([de43c12](de43c123e2))
* add company level validation for accounting dimension ([8f0d270](8f0d270746))
* Add corrective job card operating cost as additional costs in stock entry ([efc7b9a](efc7b9ac56))
* full screen on pos (backport [#45404](https://github.com/frappe/erpnext/issues/45404)) ([#45418](https://github.com/frappe/erpnext/issues/45418)) ([aca8d66](aca8d663dd))
* pos configuration for print receipt on complete order ([#45392](https://github.com/frappe/erpnext/issues/45392)) ([b9b4f63](b9b4f6316d))
* **Sales Invoice:** allow linking to project without adding timesheets (backport [#44295](https://github.com/frappe/erpnext/issues/44295)) ([#45528](https://github.com/frappe/erpnext/issues/45528)) ([2c2a25a](2c2a25ab16))
* **translations:** add Bengali translations for signature and client details ([4952733](495273365b))
* **UX:** scroll to required field (backport [#44367](https://github.com/frappe/erpnext/issues/44367)) ([#45433](https://github.com/frappe/erpnext/issues/45433)) ([692a448](692a44816f))

### Performance Improvements

* optimize DB calls with frappe.get_all (backport [#45289](https://github.com/frappe/erpnext/issues/45289)) ([#45391](https://github.com/frappe/erpnext/issues/45391)) ([04f5a72](04f5a72e08))

### Reverts

* Revert "feat(Sales Invoice): allow linking to project without adding timesheets (backport [#44295](https://github.com/frappe/erpnext/issues/44295))" ([#45531](https://github.com/frappe/erpnext/issues/45531)) ([b004855](b004855e7c))
2025-01-29 11:28:47 +00:00
ruthra kumar
cae8cee398 Merge pull request #45566 from frappe/version-15-hotfix
chore: release v15
2025-01-29 16:57:29 +05:30
rohitwaghchaure
cc96145ac9 Merge pull request #45595 from rohitwaghchaure/fixed-support-29212
fix: do not allow to manually submit the SABB
2025-01-29 16:38:19 +05:30
Rohit Waghchaure
2b16eb5381 fix: do not allow to manually submit the SABB 2025-01-29 16:36:17 +05:30
ruthra kumar
97d9030f26 Merge pull request #45594 from frappe/mergify/bp/version-15-hotfix/pr-45569
fix: update voucher outstanding from payment ledger (backport #45569)
2025-01-29 16:30:52 +05:30
ruthra kumar
156dcf535d Merge pull request #45592 from frappe/mergify/bp/version-15-hotfix/pr-45586
fix(query): remove duplicate docstatus condition (backport #45586)
2025-01-29 16:19:25 +05:30
ljain112
e3855949e1 fix: update voucher outstanding from payment ledger
(cherry picked from commit dd77070351)
2025-01-29 10:42:27 +00:00
Safvan Huzain
2d2f30e6cf fix(query): remove duplicate docstatus condition (#45586)
fix: remove duplicate docstatus condition in query
(cherry picked from commit 3f2e93dcb6)
2025-01-29 10:29:11 +00:00
ruthra kumar
3117052779 Merge pull request #45589 from frappe/mergify/bp/version-15-hotfix/pr-45441
fix: show payment entries in tax withheld vouchers (backport #45441)
2025-01-29 15:53:46 +05:30
ruthra kumar
eac5c91c8f Merge pull request #45588 from frappe/mergify/bp/version-15-hotfix/pr-45585
refactor: auto add taxes from template (backport #45585)
2025-01-29 15:50:05 +05:30
mergify[bot]
ef2f4118d9 fix: get stock balance filtered by company for validating stock value in jv (backport #45549) (#45578)
* fix: get stock balance filtered by company for validating stock value in jv (#45549)

* fix: get stock balance filtered by company for validating stock value in jv

* test: error is raised  on validate

(cherry picked from commit 9f20854bd9)

* fix: correct args for test case function

---------

Co-authored-by: Lakshit Jain <108322669+ljain112@users.noreply.github.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Co-authored-by: ljain112 <ljain112@gmail.com>
2025-01-29 15:39:30 +05:30
ljain112
8f73978a26 fix: variable names
(cherry picked from commit d97e78e5d3)
2025-01-29 10:06:33 +00:00
ljain112
28bb9c39e8 fix: show payment entries in Tax Withheld Vouchers
(cherry picked from commit 55733d4f18)
2025-01-29 10:06:33 +00:00
ruthra kumar
aef6b62f7d refactor: auto add taxes from template
(cherry picked from commit d1086722bf)
2025-01-29 09:59:20 +00:00
mergify[bot]
a2ffdc7805 fix: return qty error due to precision (backport #45536) (#45581)
fix: return qty error due to precision

(cherry picked from commit 3078578692)

Co-authored-by: Dany Robert <danyrt@wahni.com>
2025-01-29 12:46:44 +05:30
mergify[bot]
8b0efab13e fix: add multiple item issue in stock entry (backport #45544) (#45580)
fix: add multiple item issue in stock entry (#45544)

(cherry picked from commit 5a023dc8d4)

Co-authored-by: Ejaaz Khan <67804911+iamejaaz@users.noreply.github.com>
2025-01-29 12:45:34 +05:30
Mihir Kandoi
6323e641f6 Merge pull request #45542 from frappe/mergify/bp/version-15-hotfix/pr-45282 2025-01-28 18:36:59 +05:30
Mihir Kandoi
6c4655dd72 fix: existing logical error 2025-01-28 16:56:05 +05:30
ruthra kumar
33b5be03a8 Merge pull request #45563 from frappe/mergify/bp/version-15-hotfix/pr-45452
fix(payment entry): get amount in transaction currency (backport #45452)
2025-01-28 14:56:51 +05:30
venkat102
b37602c716 fix(payment entry): get amount in transaction currency
(cherry picked from commit af97f42429)
2025-01-28 09:04:35 +00:00
ruthra kumar
75a4c31948 Merge pull request #45558 from frappe/mergify/bp/version-15-hotfix/pr-45551
feat: Add chart of accounts for Switzerland (backport #45551)
2025-01-28 11:59:40 +05:30
ruthra kumar
eef907a275 chore: rename json to standard name format 2025-01-28 11:41:36 +05:30
eagleautomate
de43c123e2 feat: Add chart of accounts for Switzerland
240812 Schulkontenrahmen VEB - DE

(cherry picked from commit 2c644ec2ef)
2025-01-28 06:04:37 +00:00
ruthra kumar
0576c5c37f Merge pull request #45557 from frappe/mergify/bp/version-15-hotfix/pr-45125
fix: update fields on change of item code In `Update Items` of `Sales Order` (backport #45125)
2025-01-28 11:32:18 +05:30
Sanket Shah
f60a3bcedf fix: update fields on change of item code In Update Items of Sales Order (#45125)
* fix: update fields on change of item code

* fix: minor update

* fix: set the new values always

* Revert "fix: set the new values always"

This reverts commit 44daa0a641.

---------

Co-authored-by: Sanket322 <shahsanket322003.com>
Co-authored-by: ruthra kumar <ruthra@erpnext.com>
(cherry picked from commit 9933d3c8ff)
2025-01-28 05:58:28 +00:00
Mihir Kandoi
1be19819fb fix: removed field not present in v15 2025-01-28 10:09:31 +05:30
Mihir Kandoi
b59d253d93 fix: import 2 2025-01-27 22:55:33 +05:30
Mihir Kandoi
d74c498efe fix: import 2025-01-27 22:17:13 +05:30
Mihir Kandoi
57f79a2240 fix: merge conflict 2025-01-27 22:01:13 +05:30
Raffael Meyer
fb1ea9524b chore: bump actions/cache to v4 (#45541) 2025-01-27 13:29:51 +01:00
ruthra kumar
8d30b4d14e Merge pull request #45539 from frappe/mergify/bp/version-15-hotfix/pr-45345
fix:  maintain existing discounts in get_pricing_rule_for_item (backport #45345)
2025-01-27 17:35:27 +05:30
Mihir Kandoi
c102e51eb1 fix: logical error in where condition of qb query
(cherry picked from commit 47f8a86003)

# Conflicts:
#	erpnext/stock/doctype/landed_cost_taxes_and_charges/landed_cost_taxes_and_charges.json
2025-01-27 12:03:40 +00:00
Mihir Kandoi
d6e0c6c969 refactor: added condition which checks for corrective operation setting
(cherry picked from commit 063a205e5a)
2025-01-27 12:03:39 +00:00
Mihir Kandoi
5c9ac27478 test: Added test for new feature
(cherry picked from commit 4fb48b7f22)
2025-01-27 12:03:39 +00:00
Mihir Kandoi
efc7b9ac56 feat: Add corrective job card operating cost as additional costs in stock entry
(cherry picked from commit 2bf10f68a8)

# Conflicts:
#	erpnext/manufacturing/doctype/job_card/job_card.py
2025-01-27 12:03:38 +00:00
ruthra kumar
2c3e765896 Merge pull request #45534 from frappe/mergify/bp/version-15-hotfix/pr-45302
feat: add company level validation for accounting dimension (backport #45302)
2025-01-27 16:09:32 +05:30
Sanket322
4e347d835e fix: remove applied pricing rule
(cherry picked from commit 50223c6bec)
2025-01-27 10:32:53 +00:00
Sanket322
e73aab0df5 fix: use user defined discount amount or default
(cherry picked from commit e2a32b7257)
2025-01-27 10:32:53 +00:00
ruthra kumar
bcd3351999 refactor(test): update test data 2025-01-27 15:46:39 +05:30
Sugesh393
67e45cf002 chore: update variable names for improved readability
(cherry picked from commit 36bae55299)
2025-01-27 15:18:24 +05:30
Sugesh393
149827562b fix: set company related values
(cherry picked from commit 454067198e)
2025-01-27 15:18:19 +05:30
Sugesh393
fac4e99b0e test: add new unit test for company validation in accounting dimension
(cherry picked from commit c94091d68f)
2025-01-27 09:25:02 +00:00
Sugesh393
8f0d270746 feat: add company level validation for accounting dimension
(cherry picked from commit 60efd3e219)
2025-01-27 09:25:01 +00:00
ruthra kumar
a718737931 Merge pull request #45530 from frappe/mergify/bp/version-15-hotfix/pr-45284
fix: set party_account_currency for pos_invoice returns (backport #45284)
2025-01-27 14:54:11 +05:30
Nabin Hait
b004855e7c Revert "feat(Sales Invoice): allow linking to project without adding timesheets (backport #44295)" (#45531)
Revert "feat(Sales Invoice): allow linking to project without adding timeshee…"

This reverts commit 2c2a25ab16.
2025-01-27 14:31:44 +05:30
Sugesh393
6a382f1430 test: add new unit test to check payments amount of pos_invoice returns
(cherry picked from commit 484ecf2479)
2025-01-27 08:58:58 +00:00
Sugesh393
172fdad244 fix: set party_account_currency for pos_invoice returns
(cherry picked from commit 2af6fca7fa)
2025-01-27 08:58:58 +00:00
mergify[bot]
2c2a25ab16 feat(Sales Invoice): allow linking to project without adding timesheets (backport #44295) (#45528)
feat(Sales Invoice): allow linking to project without adding timesheets (#44295)

* feat(Sales Invoice): allow linking to project without adding timesheets

* test: add timesheet data

(cherry picked from commit 11f65f20a0)

Co-authored-by: Raffael Meyer <14891507+barredterra@users.noreply.github.com>
2025-01-27 14:26:19 +05:30
mergify[bot]
ff46ae5bc1 fix: currency decimal on POS Past Order List (backport #45524) (#45527)
fix: currency decimal on POS Past Order List (#45524)

* fix: currency decimal on POS

* fix: removed precision

(cherry picked from commit 2ac8c92e7f)

Co-authored-by: Diptanil Saha <diptanil@frappe.io>
2025-01-27 13:21:40 +05:30
mergify[bot]
692a44816f feat(UX): scroll to required field (backport #44367) (#45433)
feat(UX): scroll to required field (#44367)

(cherry picked from commit 4008ca5ddd)

Co-authored-by: Raffael Meyer <14891507+barredterra@users.noreply.github.com>
2025-01-26 12:14:44 +05:30
rohitwaghchaure
f3b8d6867b Merge pull request #45448 from frappe/mergify/bp/version-15-hotfix/pr-45443
fix: allow to fix negative stock for batch using stock reco (backport #45443)
2025-01-25 15:21:16 +05:30
Rohit Waghchaure
69c5695f6e fix: allow to fix negative stock for batch using stock reco
(cherry picked from commit 2e8cde3378)
2025-01-25 09:34:11 +00:00
mergify[bot]
f9d96726f0 fix: secure bulk transaction (backport #45386) (#45426)
Co-authored-by: Raffael Meyer <14891507+barredterra@users.noreply.github.com>
fix: secure bulk transaction (#45386)
2025-01-24 17:18:50 +01:00
rohitwaghchaure
4aa92572ef Merge pull request #45438 from frappe/mergify/bp/version-15-hotfix/pr-45432
fix: do not check budget during reposting (backport #45432)
2025-01-24 20:09:22 +05:30
rohitwaghchaure
f2b946d325 fix: do not check budget during reposting (#45432)
(cherry picked from commit 53704b98b5)
2025-01-24 12:02:13 +00:00
rohitwaghchaure
13c7fceb91 Merge pull request #45435 from frappe/mergify/bp/version-15-hotfix/pr-45423
fix: precision issue in stock entry (backport #45423)
2025-01-24 17:25:43 +05:30
Rohit Waghchaure
fe5e42d2dc fix: precision issue in stock entry
(cherry picked from commit 9f3b8520fe)
2025-01-24 11:38:02 +00:00
mergify[bot]
7ff7ec7929 fix: validate items against selling settings (backport #45288) (#45431)
fix: validate items against selling settings (#45288)

fix: validate_for_duplicate_items

Co-authored-by: Sanket322 <shahsanket322003.com>
(cherry picked from commit d862e9b771)

Co-authored-by: Sanket Shah <113279972+Sanket322@users.noreply.github.com>
2025-01-24 16:37:36 +05:30
mergify[bot]
ae5ce97fd0 fix: disable load_after_mapping when purchase order created from sales order (backport #45405) (#45429)
fix: disable load_after_mapping when purchase order created from sales order (#45405)

(cherry picked from commit 97acbb3134)

Co-authored-by: Venkatesh <47534423+venkat102@users.noreply.github.com>
2025-01-24 15:23:27 +05:30
mergify[bot]
52fdc7cecd fix(material request): mapping Sales Order Item Delivery Date to Mate… (backport #45227) (#45424)
fix(material request): mapping Sales Order Item Delivery Date to Mate… (#45227)

* fix(material request): mapping Sales Order Item Delivery Date to Material Request Item Required By

as mentioned in https://discuss.frappe.io/t/item-delivery-date-on-sales-order-is-not-transferred-to-material-request-item-required-by-date/140479
fixing
When you create a Material Request directly on the Sales Order via → Create → Material Request, Delivery Date on Sales Order Item is not transferred to Material Request Item Required By date.

* fix(linters): meaningless linters formatting message applied

In order to pass the linters test which I find meaningless as it asks for the comma after the last item in a dictionary data type

* fix(linters): formatting code for linters pass

Linters formatting applied

(cherry picked from commit 42edb9f5b1)

Co-authored-by: Tufan Kaynak <31142607+toofun666@users.noreply.github.com>
2025-01-24 14:46:47 +05:30
mergify[bot]
d9b342f257 fix: remove unnecessary auth from plaid connector (backport #44305) (#45421)
fix: remove unnecessary auth from plaid connector (#44305)

(cherry picked from commit e82911041d)

Co-authored-by: Martin Luessi <mluessi@gmail.com>
2025-01-24 14:18:04 +05:30
mergify[bot]
dec0caeac5 fix: valuation for batch (backport #45335) (#45420)
* fix: valuation for batch

(cherry picked from commit 5088d8576f)

# Conflicts:
#	erpnext/stock/deprecated_serial_batch.py

* fix: version

(cherry picked from commit 8028dd2683)

# Conflicts:
#	.github/workflows/server-tests-mariadb.yml

* chore: fix conflicts

* chore: fix conflicts

* chore: fix conflicts

---------

Co-authored-by: Rohit Waghchaure <rohitw1991@gmail.com>
2025-01-24 13:13:57 +05:30
mergify[bot]
224a92587d fix: resolved pos return setting to default mode of payment instead of user selection (backport #45377) (#45419)
fix: resolved pos return setting to default mode of payment instead of user selection (#45377)

* fix: resolved pos return setting to default mode of payment instead of user selection

* refactor: removed console log statement

* refactor: moved get_payment_data to sales_and_purchase_return.py

(cherry picked from commit 54d234e05d)

Co-authored-by: Diptanil Saha <diptanil@frappe.io>
2025-01-24 13:13:15 +05:30
mergify[bot]
aca8d663dd feat: full screen on pos (backport #45404) (#45418)
feat: full screen on pos (#45404)

* feat: full screen on pos

* refactor: variables for label

* fix: refactor and handled button label change

* refactor: rename enable fullscreen label

(cherry picked from commit 78c7c1c631)

Co-authored-by: Diptanil Saha <diptanil@frappe.io>
2025-01-24 12:40:25 +05:30
mergify[bot]
6c10393164 fix: use frappe.datetime.str_to_user (backport #45216) (#45417)
fix: use frappe.datetime.str_to_user (#45216)

* fix: default_datetime_format

* fix: add_format_datetime

* fix: update to str_to_user  in point_of_sale/pos_controller.js

Co-authored-by: Raffael Meyer <14891507+barredterra@users.noreply.github.com>

* fix: convert_to_str_to_user

* fix: linters

* fix: whitespace

---------

Co-authored-by: Raffael Meyer <14891507+barredterra@users.noreply.github.com>
(cherry picked from commit cd3f03696e)

Co-authored-by: mahsem <137205921+mahsem@users.noreply.github.com>
2025-01-24 12:19:02 +05:30
mergify[bot]
3eb28bb0e0 fix: set expense_account and cost_center based on company in stock entry (backport #45159) (#45416)
fix: set expense_account and cost_center based on company in stock entry (#45159)

* fix: set expense_account and cost_center based on company in stock entry

* fix: remove is_perpetual_inventory_enabled validation for cost_center

(cherry picked from commit 6ec18fb40d)

Co-authored-by: Sugesh G <73237300+Sugesh393@users.noreply.github.com>
2025-01-24 12:17:08 +05:30
Frappe PR Bot
de09da31bc chore(release): Bumped to Version 15.49.3
## [15.49.3](https://github.com/frappe/erpnext/compare/v15.49.2...v15.49.3) (2025-01-24)

### Bug Fixes

* decorator and merge conflicts ([2f60f23](2f60f235a8))
2025-01-24 05:14:20 +00:00
ruthra kumar
835abfd88e Merge pull request #45406 from frappe/auto-match-fix
fix: Wrong bank_ac_no filter + simplify logic in automatch
2025-01-24 10:43:13 +05:30
ruthra kumar
fd427ad2ef Merge pull request #45413 from frappe/mergify/bp/version-15/pr-44790
refactor: configurable posting date for Exc Gain / Loss journal (backport #44790)
2025-01-24 10:42:58 +05:30
ruthra kumar
2f60f235a8 fix: decorator and merge conflicts 2025-01-24 10:26:02 +05:30
ruthra kumar
1c10e4e92f refactor: support JE posting date in semi-auto reconciilation tool
(cherry picked from commit a71718883e)

# Conflicts:
#	erpnext/accounts/doctype/process_payment_reconciliation_log_allocations/process_payment_reconciliation_log_allocations.json
2025-01-24 04:50:33 +00:00
ruthra kumar
c90d33acc3 test: exc gain/loss posting date based on configuration
(cherry picked from commit 2f3281579a)
2025-01-24 04:50:32 +00:00
ruthra kumar
ccaf0d4b85 refactor: only apply configuration on normal payments
patch to update default value

(cherry picked from commit b2c3da135e)
2025-01-24 04:50:32 +00:00
ruthra kumar
d955986342 refactor: allow reconciliation date for exchange gain / loss
(cherry picked from commit 95af63e305)
2025-01-24 04:50:31 +00:00
ruthra kumar
c127cbac57 refactor: configurable posting date for Exc Gain / Loss journal
(cherry picked from commit 5257413a93)
2025-01-24 04:50:31 +00:00
ruthra kumar
c6bc5f5d7d refactor: configurable posting date for Exc Gain / Loss journal
(cherry picked from commit 3fbd2ca0d9)
2025-01-24 04:50:30 +00:00
ruthra kumar
1522600eb5 Merge pull request #45411 from frappe/mergify/bp/version-15-hotfix/pr-45291
fix: don't update party-type on change of cost center in Journal Entry (backport #45291)
2025-01-24 10:16:53 +05:30
Sanket Shah
fb75180a7d fix: don't update party-type on change of cost center in Journal Entry (#45291)
fix: don't update party-type on change of cost center

Co-authored-by: Sanket322 <shahsanket322003.com>
(cherry picked from commit 19c8708e5e)
2025-01-23 13:04:19 +00:00
mergify[bot]
5d7d3d8c19 fix: add condition to check if item is delivered by supplier in make_purchase_order_for_default_supplier() (backport #45370) (#45410)
fix: add condition to check if item is delivered by supplier in make_purchase_order_for_default_supplier() (#45370)

(cherry picked from commit 69464ab7ff)

Co-authored-by: Shanuka Hewage <89955436+Shanuka-98@users.noreply.github.com>
2025-01-23 18:18:48 +05:30
mergify[bot]
73a21c294c fix: fix creating documents from sales invoice (backport #45346) (#45408)
* fix: fix creating documents from sales invoice (#45346)

Co-authored-by: Meike Nedwidek <nedwidek@kk-software.de>
(cherry picked from commit 1758e125e0)

# Conflicts:
#	erpnext/accounts/doctype/sales_invoice/sales_invoice.js

* fix: resolved conflict

---------

Co-authored-by: meike289 <63092915+meike289@users.noreply.github.com>
Co-authored-by: Nabin Hait <nabinhait@gmail.com>
2025-01-23 18:18:17 +05:30
marination
60feb7cbd4 fix: Wrong bank_ac_no filter + simplify convoluted logic 2025-01-23 13:14:25 +01:00
marination
153e961df7 fix: Use process.extract to get the corresponding party doc name of the result
- rapidfuzz accepts an iterable or a dict. dict input gives the dict key and value in the result
2025-01-23 13:13:12 +01:00
marination
86f4bf6e01 fix: Set right party name in bank transaction
- If party name and docname are different, set the docname in Bank Transaction
2025-01-23 13:12:59 +01:00
ruthra kumar
7fdf2a7d45 Merge pull request #45399 from frappe/mergify/bp/version-15-hotfix/pr-44790
refactor: configurable posting date for Exc Gain / Loss journal (backport #44790)
2025-01-23 17:30:38 +05:30
ruthra kumar
3906e5c33f chore: use correct decorator 2025-01-23 17:05:36 +05:30
ruthra kumar
72581dd0bf Merge pull request #45400 from ruthra-kumar/manual_addition_of_translation
refactor: more translation in bengali
2025-01-23 16:52:16 +05:30
ruthra kumar
10ee6f3e22 chore: resolve conflict 2025-01-23 16:36:55 +05:30
ruthra kumar
db4fe59bca Merge pull request #45398 from frappe/mergify/bp/version-15-hotfix/pr-44950
fix: postal_code_move_and_fixes (backport #44950)
2025-01-23 16:35:05 +05:30
samsul580
495273365b feat(translations): add Bengali translations for signature and client details 2025-01-23 16:31:59 +05:30
ruthra kumar
3c3f092382 refactor: support JE posting date in semi-auto reconciilation tool
(cherry picked from commit a71718883e)

# Conflicts:
#	erpnext/accounts/doctype/process_payment_reconciliation_log_allocations/process_payment_reconciliation_log_allocations.json
2025-01-23 10:59:54 +00:00
ruthra kumar
693687d8a3 test: exc gain/loss posting date based on configuration
(cherry picked from commit 2f3281579a)
2025-01-23 10:59:53 +00:00
ruthra kumar
c070a140f2 refactor: only apply configuration on normal payments
patch to update default value

(cherry picked from commit b2c3da135e)
2025-01-23 10:59:53 +00:00
ruthra kumar
f411bcc8b5 refactor: allow reconciliation date for exchange gain / loss
(cherry picked from commit 95af63e305)
2025-01-23 10:59:52 +00:00
ruthra kumar
763cc18aad refactor: configurable posting date for Exc Gain / Loss journal
(cherry picked from commit 5257413a93)
2025-01-23 10:59:52 +00:00
ruthra kumar
671f728c4a refactor: configurable posting date for Exc Gain / Loss journal
(cherry picked from commit 3fbd2ca0d9)
2025-01-23 10:59:52 +00:00
mahsem
0e088dde36 fix: postal_code_move_and_fixes
(cherry picked from commit 185bbb4c20)
2025-01-23 10:48:01 +00:00
Diptanil Saha
546da29761 chore: quickbooks migrator integration removal (#45393) 2025-01-23 14:17:14 +05:30
rohitwaghchaure
0eac720182 Merge pull request #45395 from frappe/mergify/bp/version-15-hotfix/pr-45394
fix: JobCardTimeLog' object has no attribute 'remaining_time_in_mins' (backport #45394)
2025-01-23 13:40:16 +05:30
Rohit Waghchaure
ef15429d98 fix: JobCardTimeLog' object has no attribute 'remaining_time_in_mins'
(cherry picked from commit 41dda35db7)
2025-01-23 07:53:24 +00:00
Diptanil Saha
b9b4f6316d feat: pos configuration for print receipt on complete order (#45392) 2025-01-23 13:07:27 +05:30
mergify[bot]
04f5a72e08 perf: optimize DB calls with frappe.get_all (backport #45289) (#45391)
perf: optimize DB calls with frappe.get_all (#45289)

* perf: reduce multiple db queries

* fix: use frappe._dict instread of extra iteration

---------

Co-authored-by: Sanket322 <shahsanket322003.com>
(cherry picked from commit 2a400dd3f8)

Co-authored-by: Sanket Shah <113279972+Sanket322@users.noreply.github.com>
2025-01-23 13:01:12 +05:30
mergify[bot]
412e22fb4e fix: added item_group filter in item_code field in stock balance report (backport #45340) (#45389)
fix: added item_group filter in item_code field in stock balance report (#45340)

* fix: added item_group filter in item_code field in stock balance report

* feat: added filter to not show non stock items

(cherry picked from commit fe43d20545)

Co-authored-by: Mihir Kandoi <kandoimihir@gmail.com>
2025-01-23 11:25:33 +05:30
mergify[bot]
767529f0ec fix: batch qty calculation (backport #45367) (#45388)
fix: batch qty calculation

(cherry picked from commit f07a71a882)

Co-authored-by: Rohit Waghchaure <rohitw1991@gmail.com>
2025-01-23 11:17:14 +05:30
mergify[bot]
2403cdc4d7 fix: System was allowing to save payment schedule amount less than grand total (backport #45322) (#45381)
fix: System was allowing to save payment schedule amount less than grand total (#45322)

* fix: System was allowing to save payment schedule amount less than grand_total

* style: After run pre-commit

(cherry picked from commit b26f0b6633)

Co-authored-by: Diógenes Souza <103958767+devdiogenes@users.noreply.github.com>
2025-01-23 11:16:09 +05:30
mergify[bot]
4e367dedec fix: validate non-stock item for exchange loss/gain (backport #45306) (#45380)
fix: validate non-stock item for exchange loss/gain (#45306)

* fix: validate non-stock item

* test: add unit test to validate non-stock item exchange difference

* fix: use usd supplier

(cherry picked from commit 05579959f2)

Co-authored-by: Rethik M <85231069+rs-rethik@users.noreply.github.com>
2025-01-23 11:15:51 +05:30
mergify[bot]
f8099a6847 fix: set preferred email in Employee via backend controller (backport #45320) (#45379)
fix: set preferred email in Employee via backend controller (#45320)

fix: set preferred email in Employee (backend)

Set "Preferred Email" for Employee via validate. Unset value when
prefered_contact_email is also unset.

(cherry picked from commit 4481ca83ff)

Co-authored-by: gavin <gavin18d@gmail.com>
2025-01-23 11:15:22 +05:30
rohitwaghchaure
e7f1cda3c1 Merge pull request #45385 from frappe/mergify/bp/version-15-hotfix/pr-45382
fix: precision issue causing incorrect status (backport #45382)
2025-01-22 20:48:30 +05:30
Rohit Waghchaure
46a2b7a07e fix: precision issue causing incorrect status
(cherry picked from commit 4a7586cc01)
2025-01-22 14:48:23 +00:00
mergify[bot]
bdc65daadd fix: added debounce to prevent multiple clicks (backport #45369) (#45376)
fix: added debounce to prevent multiple clicks (#45369)

* fix: added debounce to prevent multiple clicks

* fix: linters check

(cherry picked from commit 9ff3101b2d)

Co-authored-by: Khushi Rawat <142375893+khushi8112@users.noreply.github.com>
2025-01-22 17:53:04 +05:30
Deepesh Garg
7848f1146b Merge pull request #45372 from frappe/mergify/bp/version-15-hotfix/pr-45371
fix: Do no query GLs if no PCVs are posted (backport #45371)
2025-01-22 14:22:28 +05:30
Deepesh Garg
ad06652ed5 fix: Do no query GLs if no PCVs are posted
(cherry picked from commit f4d1a54588)
2025-01-22 08:33:40 +00:00
ruthra kumar
98797fa918 Merge pull request #45368 from frappe/mergify/bp/version-15-hotfix/pr-45202
fix: Correct Party Bank Account mapping in `Payment Entry` from Transactional Doctypes (backport #45202)
2025-01-22 13:00:13 +05:30
DaizyModi
4a390ae3de fix: Correct Party Bank Account mapping in Payment Entry
(cherry picked from commit 376bdc75f4)
2025-01-22 07:12:16 +00:00
327 changed files with 12417 additions and 3842 deletions

4
.github/release.yml vendored Normal file
View File

@@ -0,0 +1,4 @@
changelog:
exclude:
labels:
- skip-release-notes

View File

@@ -0,0 +1,30 @@
name: "Auto-label PRs based on title"
on:
pull_request_target:
types: [opened, reopened]
jobs:
add-label-if-prefix-matches:
permissions:
contents: read
pull-requests: write
runs-on: ubuntu-latest
steps:
- name: Check PR title and add label if it matches prefixes
uses: actions/github-script@v7
continue-on-error: true
with:
script: |
const title = context.payload.pull_request.title.toLowerCase();
const prefixes = ['chore', 'ci', 'style', 'test', 'refactor'];
// Check if the PR title starts with any of the prefixes
if (prefixes.some(prefix => title.startsWith(prefix))) {
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.payload.pull_request.number,
labels: ['skip-release-notes']
});
}

View File

@@ -57,7 +57,7 @@ jobs:
run: echo "127.0.0.1 test_site" | sudo tee -a /etc/hosts
- name: Cache pip
uses: actions/cache@v2
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/*requirements.txt', '**/pyproject.toml') }}
@@ -66,7 +66,7 @@ jobs:
${{ runner.os }}-
- name: Cache node modules
uses: actions/cache@v2
uses: actions/cache@v4
env:
cache-name: cache-node-modules
with:
@@ -81,7 +81,7 @@ jobs:
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- uses: actions/cache@v2
- uses: actions/cache@v4
id: yarn-cache
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}

View File

@@ -76,7 +76,7 @@ jobs:
run: echo "127.0.0.1 test_site" | sudo tee -a /etc/hosts
- name: Cache pip
uses: actions/cache@v2
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/*requirements.txt', '**/pyproject.toml') }}
@@ -85,7 +85,7 @@ jobs:
${{ runner.os }}-
- name: Cache node modules
uses: actions/cache@v2
uses: actions/cache@v4
env:
cache-name: cache-node-modules
with:
@@ -100,7 +100,7 @@ jobs:
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- uses: actions/cache@v2
- uses: actions/cache@v4
id: yarn-cache
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}

View File

@@ -66,7 +66,7 @@ jobs:
run: echo "127.0.0.1 test_site" | sudo tee -a /etc/hosts
- name: Cache pip
uses: actions/cache@v2
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/*requirements.txt', '**/pyproject.toml') }}
@@ -75,7 +75,7 @@ jobs:
${{ runner.os }}-
- name: Cache node modules
uses: actions/cache@v2
uses: actions/cache@v4
env:
cache-name: cache-node-modules
with:
@@ -90,7 +90,7 @@ jobs:
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- uses: actions/cache@v2
- uses: actions/cache@v4
id: yarn-cache
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}

View File

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

View File

@@ -4,7 +4,7 @@
import frappe
from frappe import _, throw
from frappe.utils import cint, cstr
from frappe.utils import add_to_date, cint, cstr, pretty_date
from frappe.utils.nestedset import NestedSet, get_ancestors_of, get_descendants_of
import erpnext
@@ -481,6 +481,7 @@ def get_account_autoname(account_number, account_name, company):
@frappe.whitelist()
def update_account_number(name, account_name, account_number=None, from_descendant=False):
_ensure_idle_system()
account = frappe.get_cached_doc("Account", name)
if not account:
return
@@ -501,7 +502,7 @@ def update_account_number(name, account_name, account_number=None, from_descenda
"name",
)
if old_name:
if old_name and not from_descendant:
# same account in parent company exists
allow_child_account_creation = _("Allow Account Creation Against Child Company")
@@ -542,6 +543,7 @@ def update_account_number(name, account_name, account_number=None, from_descenda
@frappe.whitelist()
def merge_account(old, new):
_ensure_idle_system()
# Validate properties before merging
new_account = frappe.get_cached_doc("Account", new)
old_account = frappe.get_cached_doc("Account", old)
@@ -595,3 +597,31 @@ def sync_update_account_number_in_child(
for d in frappe.db.get_values("Account", filters=filters, fieldname=["company", "name"], as_dict=True):
update_account_number(d["name"], account_name, account_number, from_descendant=True)
def _ensure_idle_system():
# Don't allow renaming if accounting entries are actively being updated, there are two main reasons:
# 1. Correctness: It's next to impossible to ensure that renamed account is not being used *right now*.
# 2. Performance: Renaming requires locking out many tables entirely and severely degrades performance.
if frappe.flags.in_test:
return
last_gl_update = None
try:
# We also lock inserts to GL entry table with for_update here.
last_gl_update = frappe.db.get_value("GL Entry", {}, "modified", for_update=True, wait=False)
except frappe.QueryTimeoutError:
# wait=False fails immediately if there's an active transaction.
last_gl_update = add_to_date(None, seconds=-1)
if not last_gl_update:
return
if last_gl_update > add_to_date(None, minutes=-5):
frappe.throw(
_(
"Last GL Entry update was done {}. This operation is not allowed while system is actively being used. Please wait for 5 minutes before retrying."
).format(pretty_date(last_gl_update)),
title=_("System In Use"),
)

View File

@@ -116,6 +116,7 @@ def identify_is_group(child):
return is_group
@frappe.whitelist()
def get_chart(chart_template, existing_company=None):
chart = {}
if existing_company:

View File

@@ -0,0 +1,532 @@
{
"country_code": "ch",
"name": "240812 Schulkontenrahmen VEB - DE",
"tree": {
"Aktiven": {
"account_number": "1",
"is_group": 1,
"root_type": "Asset",
"Umlaufvermögen": {
"account_number": "10",
"is_group": 1,
"Flüssige Mittel": {
"account_number": "100",
"is_group": 1,
"Kasse": {
"account_number": "1000",
"account_type": "Cash"
},
"Bankguthaben": {
"account_number": "1020",
"account_type": "Bank"
}
},
"Kurzfristig gehaltene Aktiven mit Börsenkurs": {
"account_number": "106",
"is_group": 1,
"Wertschriften": {
"account_number": "1060"
},
"Wertberichtigungen Wertschriften": {
"account_number": "1069"
}
},
"Forderungen aus Lieferungen und Leistungen": {
"account_number": "110",
"is_group": 1,
"Forderungen aus Lieferungen und Leistungen (Debitoren)": {
"account_number": "1100"
},
"Delkredere": {
"account_number": "1109"
}
},
"Übrige kurzfristige Forderungen": {
"account_number": "114",
"is_group": 1,
"Vorschüsse und Darlehen": {
"account_number": "1140"
},
"Wertberichtigungen Vorschüsse und Darlehen": {
"account_number": "1149"
},
"Vorsteuer MWST Material, Waren, Dienstleistungen, Energie": {
"account_number": "1170"
},
"Vorsteuer MWST Investitionen, übriger Betriebsaufwand": {
"account_number": "1171"
},
"Verrechnungssteuer": {
"account_number": "1176"
},
"Forderungen gegenüber Sozialversicherungen und Vorsorgeeinrichtungen": {
"account_number": "1180"
},
"Quellensteuer": {
"account_number": "1189"
},
"Sonstige kurzfristige Forderungen": {
"account_number": "1190"
},
"Wertberichtigungen sonstige kurzfristige Forderungen": {
"account_number": "1199"
}
},
"Vorräte und nicht fakturierte Dienstleistungen": {
"account_number": "120",
"is_group": 1,
"Handelswaren": {
"account_number": "1200"
},
"Rohstoffe": {
"account_number": "1210"
},
"Werkstoffe": {
"account_number": "1220"
},
"Hilfs- und Verbrauchsmaterial": {
"account_number": "1230"
},
"Handelswaren in Konsignation": {
"account_number": "1250"
},
"Fertige Erzeugnisse": {
"account_number": "1260"
},
"Unfertige Erzeugnisse": {
"account_number": "1270"
},
"Nicht fakturierte Dienstleistungen": {
"account_number": "1280"
}
},
"Aktive Rechnungsabgrenzungen": {
"account_number": "130",
"is_group": 1,
"Bezahlter Aufwand des Folgejahres": {
"account_number": "1300"
},
"Noch nicht erhaltener Ertrag": {
"account_number": "1301"
}
}
},
"Anlagevermögen": {
"account_number": "14",
"is_group": 1,
"Finanzanlagen": {
"account_number": "140",
"is_group": 1,
"Wertschriften": {
"account_number": "1400"
},
"Wertberichtigungen Wertschriften": {
"account_number": "1409"
},
"Darlehen": {
"account_number": "1440"
},
"Hypotheken": {
"account_number": "1441"
},
"Wertberichtigungen langfristige Forderungen": {
"account_number": "1449"
}
},
"Beteiligungen": {
"account_number": "148",
"is_group": 1,
"Beteiligungen": {
"account_number": "1480"
},
"Wertberichtigungen Beteiligungen": {
"account_number": "1489"
}
},
"Mobile Sachanlagen": {
"account_number": "150",
"is_group": 1,
"Maschinen und Apparate": {
"account_number": "1500"
},
"Wertberichtigungen Maschinen und Apparate": {
"account_number": "1509"
},
"Mobiliar und Einrichtungen": {
"account_number": "1510"
},
"Wertberichtigungen Mobiliar und Einrichtungen": {
"account_number": "1519"
},
"Büromaschinen, Informatik, Kommunikationstechnologie": {
"account_number": "1520"
},
"Wertberichtigungen Büromaschinen, Informatik, Kommunikationstechnologie": {
"account_number": "1529"
},
"Fahrzeuge": {
"account_number": "1530"
},
"Wertberichtigungen Fahrzeuge": {
"account_number": "1539"
},
"Werkzeuge und Geräte": {
"account_number": "1540"
},
"Wertberichtigungen Werkzeuge und Geräte": {
"account_number": "1549"
}
},
"Immobile Sachanlagen": {
"account_number": "160",
"is_group": 1,
"Geschäftsliegenschaften": {
"account_number": "1600"
},
"Wertberichtigungen Geschäftsliegenschaften": {
"account_number": "1609"
}
},
"Immaterielle Werte": {
"account_number": "170",
"is_group": 1,
"Patente, Know-how, Lizenzen, Rechte, Entwicklungen": {
"account_number": "1700"
},
"Wertberichtigungen Patente, Know-how, Lizenzen, Rechte, Entwicklungen": {
"account_number": "1709"
},
"Goodwill": {
"account_number": "1770"
},
"Wertberichtigungen Goodwill": {
"account_number": "1779"
}
},
"Nicht einbezahltes Grund-, Gesellschafter- oder Stiftungskapital": {
"account_number": "180",
"is_group": 1,
"Nicht einbezahltes Aktien-, Stamm-, Anteilschein- oder Stiftungskapital": {
"account_number": "1850"
}
}
}
},
"Passiven": {
"account_number": "2",
"is_group": 1,
"root_type": "Liability",
"Kurzfristiges Fremdkapital": {
"account_number": "20",
"is_group": 1,
"Verbindlichkeiten aus Lieferungen und Leistungen": {
"account_number": "200",
"is_group": 1,
"Verbindlichkeiten aus Lieferungen und Leistungen (Kreditoren)": {
"account_number": "2000"
},
"Erhaltene Anzahlungen": {
"account_number": "2030"
}
},
"Kurzfristige verzinsliche Verbindlichkeiten": {
"account_number": "210",
"is_group": 1,
"Bankverbindlichkeiten": {
"account_number": "2100"
},
"Verbindlichkeiten aus Finanzierungsleasing": {
"account_number": "2120"
},
"Übrige verzinsliche Verbindlichkeiten": {
"account_number": "2140"
}
},
"Übrige kurzfristige Verbindlichkeiten": {
"account_number": "220",
"is_group": 1,
"Geschuldete MWST (Umsatzsteuer)": {
"account_number": "2200"
},
"Abrechnungskonto MWST": {
"account_number": "2201"
},
"Verrechnungssteuer": {
"account_number": "2206"
},
"Direkte Steuern": {
"account_number": "2208"
},
"Sonstige kurzfristige Verbindlichkeiten": {
"account_number": "2210"
},
"Beschlossene Ausschüttungen": {
"account_number": "2261"
},
"Sozialversicherungen und Vorsorgeeinrichtungen": {
"account_number": "2270"
},
"Quellensteuer": {
"account_number": "2279"
}
},
"Passive Rechnungsabgrenzungen und kurzfristige Rückstellungen": {
"account_number": "230",
"is_group": 1,
"Noch nicht bezahlter Aufwand": {
"account_number": "2300"
},
"Erhaltener Ertrag des Folgejahres": {
"account_number": "2301"
},
"Kurzfristige Rückstellungen": {
"account_number": "2330"
}
}
},
"Langfristiges Fremdkapital": {
"account_number": "24",
"is_group": 1,
"Langfristige verzinsliche Verbindlichkeiten": {
"account_number": "240",
"is_group": 1,
"Bankverbindlichkeiten": {
"account_number": "2400"
},
"Verbindlichkeiten aus Finanzierungsleasing": {
"account_number": "2420"
},
"Obligationenanleihen": {
"account_number": "2430"
},
"Darlehen": {
"account_number": "2450"
},
"Hypotheken": {
"account_number": "2451"
}
},
"Übrige langfristige Verbindlichkeiten": {
"account_number": "250",
"is_group": 1,
"Übrige langfristige Verbindlichkeiten (unverzinslich)": {
"account_number": "2500"
}
},
"Rückstellungen sowie vom Gesetz vorgesehene ähnliche Positionen": {
"account_number": "260",
"is_group": 1,
"Rückstellungen": {
"account_number": "2600"
}
}
},
"Eigenkapital (juristische Personen)": {
"account_number": "28",
"is_group": 1,
"Grund-, Gesellschafter- oder Stiftungskapital": {
"account_number": "280",
"is_group": 1,
"Aktien-, Stamm-, Anteilschein- oder Stiftungskapital": {
"account_number": "2800"
}
},
"Reserven und Jahresgewinn oder Jahresverlust": {
"account_number": "290",
"is_group": 1,
"Gesetzliche Kapitalreserve": {
"account_number": "2900"
},
"Reserve für eigene Kapitalanteile": {
"account_number": "2930"
},
"Aufwertungsreserve": {
"account_number": "2940"
},
"Gesetzliche Gewinnreserve": {
"account_number": "2950"
},
"Freiwillige Gewinnreserven": {
"account_number": "2960"
},
"Gewinnvortrag oder Verlustvortrag": {
"account_number": "2970"
},
"Jahresgewinn oder Jahresverlust": {
"account_number": "2979"
},
"Eigene Aktien, Stammanteile oder Anteilscheine (Minusposten)": {
"account_number": "2980"
}
}
}
},
"Betrieblicher Ertrag aus Lieferungen und Leistungen": {
"account_number": "3",
"is_group": 1,
"root_type": "Income",
"Produktionserlöse": {
"account_number": "3000"
},
"Handelserlöse": {
"account_number": "3200"
},
"Dienstleistungserlöse": {
"account_number": "3400"
},
"Übrige Erlöse aus Lieferungen und Leistungen": {
"account_number": "3600"
},
"Eigenleistungen": {
"account_number": "3700"
},
"Eigenverbrauch": {
"account_number": "3710"
},
"Erlösminderungen": {
"account_number": "3800"
},
"Verluste Forderungen (Debitoren), Veränderung Delkredere": {
"account_number": "3805"
},
"Bestandesänderungen unfertige Erzeugnisse": {
"account_number": "3900"
},
"Bestandesänderungen fertige Erzeugnisse": {
"account_number": "3901"
},
"Bestandesänderungen nicht fakturierte Dienstleistungen": {
"account_number": "3940"
}
},
"Aufwand für Material, Handelswaren, Dienstleistungen und Energie": {
"account_number": "4",
"is_group": 1,
"root_type": "Expense",
"Materialaufwand Produktion": {
"account_number": "4000"
},
"Handelswarenaufwand": {
"account_number": "4200"
},
"Aufwand für bezogene Dienstleistungen": {
"account_number": "4400"
},
"Energieaufwand zur Leistungserstellung": {
"account_number": "4500"
},
"Aufwandminderungen": {
"account_number": "4900"
}
},
"Personalaufwand": {
"account_number": "5",
"is_group": 1,
"root_type": "Expense",
"Lohnaufwand": {
"account_number": "5000"
},
"Sozialversicherungsaufwand": {
"account_number": "5700"
},
"Übriger Personalaufwand": {
"account_number": "5800"
},
"Leistungen Dritter": {
"account_number": "5900"
}
},
"Übriger betrieblicher Aufwand, Abschreibungen und Wertberichtigungen sowie Finanzergebnis": {
"account_number": "6",
"is_group": 1,
"root_type": "Expense",
"Raumaufwand": {
"account_number": "6000"
},
"Unterhalt, Reparaturen, Ersatz mobile Sachanlagen": {
"account_number": "6100"
},
"Leasingaufwand mobile Sachanlagen": {
"account_number": "6105"
},
"Fahrzeug- und Transportaufwand": {
"account_number": "6200"
},
"Fahrzeugleasing und -mieten": {
"account_number": "6260"
},
"Sachversicherungen, Abgaben, Gebühren, Bewilligungen": {
"account_number": "6300"
},
"Energie- und Entsorgungsaufwand": {
"account_number": "6400"
},
"Verwaltungsaufwand": {
"account_number": "6500"
},
"Informatikaufwand inkl. Leasing": {
"account_number": "6570"
},
"Werbeaufwand": {
"account_number": "6600"
},
"Sonstiger betrieblicher Aufwand": {
"account_number": "6700"
},
"Abschreibungen und Wertberichtigungen auf Positionen des Anlagevermögens": {
"account_number": "6800"
},
"Finanzaufwand": {
"account_number": "6900"
},
"Finanzertrag": {
"account_number": "6950"
}
},
"Betrieblicher Nebenerfolg": {
"account_number": "7",
"is_group": 1,
"root_type": "Income",
"Ertrag Nebenbetrieb": {
"account_number": "7000"
},
"Aufwand Nebenbetrieb": {
"account_number": "7010"
},
"Ertrag betriebliche Liegenschaft": {
"account_number": "7500"
},
"Aufwand betriebliche Liegenschaft": {
"account_number": "7510"
}
},
"Betriebsfremder, ausserordentlicher, einmaliger oder periodenfremder Aufwand und Ertrag": {
"account_number": "8",
"is_group": 1,
"root_type": "Expense",
"Betriebsfremder Aufwand": {
"account_number": "8000"
},
"Betriebsfremder Ertrag": {
"account_number": "8100"
},
"Ausserordentlicher, einmaliger oder periodenfremder Aufwand": {
"account_number": "8500"
},
"Ausserordentlicher, einmaliger oder periodenfremder Ertrag": {
"account_number": "8510"
},
"Direkte Steuern": {
"account_number": "8900"
}
},
"Abschluss": {
"account_number": "9",
"is_group": 1,
"root_type": "Equity",
"Jahresgewinn oder Jahresverlust": {
"account_number": "9200"
}
}
}
}

View File

@@ -98,7 +98,7 @@
"Office Maintenance Expenses": {},
"Office Rent": {},
"Postal Expenses": {},
"Print and Stationary": {},
"Print and Stationery": {},
"Rounded Off": {
"account_type": "Round Off"
},

View File

@@ -31,7 +31,8 @@
"label": "Reference Document Type",
"options": "DocType",
"read_only_depends_on": "eval:!doc.__islocal",
"reqd": 1
"reqd": 1,
"search_index": 1
},
{
"default": "0",

View File

@@ -41,6 +41,11 @@ class AccountingDimension(Document):
self.set_fieldname_and_label()
def validate(self):
self.validate_doctype()
validate_column_name(self.fieldname)
self.validate_dimension_defaults()
def validate_doctype(self):
if self.document_type in (
*core_doctypes_list,
"Accounting Dimension",
@@ -49,6 +54,7 @@ class AccountingDimension(Document):
"Accounting Dimension Detail",
"Company",
"Account",
"Finance Book",
):
msg = _("Not allowed to create accounting dimension for {0}").format(self.document_type)
frappe.throw(msg)
@@ -61,9 +67,6 @@ class AccountingDimension(Document):
if not self.is_new():
self.validate_document_type_change()
validate_column_name(self.fieldname)
self.validate_dimension_defaults()
def validate_document_type_change(self):
doctype_before_save = frappe.db.get_value("Accounting Dimension", self.name, "document_type")
if doctype_before_save != self.document_type:
@@ -102,6 +105,7 @@ class AccountingDimension(Document):
def on_update(self):
frappe.flags.accounting_dimensions = None
frappe.flags.accounting_dimensions_details = None
def make_dimension_in_accounting_doctypes(doc, doclist=None):
@@ -262,7 +266,7 @@ def get_checks_for_pl_and_bs_accounts():
frappe.flags.accounting_dimensions_details = frappe.db.sql(
"""SELECT p.label, p.disabled, p.fieldname, c.default_dimension, c.company, c.mandatory_for_pl, c.mandatory_for_bs
FROM `tabAccounting Dimension`p ,`tabAccounting Dimension Detail` c
WHERE p.name = c.parent""",
WHERE p.name = c.parent AND p.disabled = 0""",
as_dict=1,
)

View File

@@ -47,6 +47,7 @@
"auto_reconciliation_job_trigger",
"reconciliation_queue_size",
"column_break_resa",
"exchange_gain_loss_posting_date",
"invoicing_settings_tab",
"accounts_transactions_settings_section",
"over_billing_allowance",
@@ -389,7 +390,7 @@
{
"fieldname": "section_break_jpd0",
"fieldtype": "Section Break",
"label": "Payment Reconciliations"
"label": "Payment Reconciliation Settings"
},
{
"default": "0",
@@ -523,6 +524,14 @@
"fieldname": "ignore_is_opening_check_for_reporting",
"fieldtype": "Check",
"label": "Ignore Is Opening check for reporting"
},
{
"default": "Payment",
"description": "Only applies for Normal Payments",
"fieldname": "exchange_gain_loss_posting_date",
"fieldtype": "Select",
"label": "Posting Date Inheritance for Exchange Gain / Loss",
"options": "Invoice\nPayment\nReconciliation Date"
}
],
"icon": "icon-cog",
@@ -530,7 +539,7 @@
"index_web_pages_for_search": 1,
"issingle": 1,
"links": [],
"modified": "2025-01-18 21:24:19.840745",
"modified": "2025-01-23 13:15:44.077853",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Accounts Settings",

View File

@@ -45,6 +45,7 @@ class AccountsSettings(Document):
enable_fuzzy_matching: DF.Check
enable_immutable_ledger: DF.Check
enable_party_matching: DF.Check
exchange_gain_loss_posting_date: DF.Literal["Invoice", "Payment", "Reconciliation Date"]
frozen_accounts_modifier: DF.Link | None
general_ledger_remarks_length: DF.Int
ignore_account_closing_balance: DF.Check

View File

@@ -159,9 +159,6 @@ def get_payment_entries_for_bank_clearance(
as_dict=1,
)
if bank_account:
condition += "and bank_account = %(bank_account)s"
payment_entries = frappe.db.sql(
f"""
select
@@ -183,7 +180,6 @@ def get_payment_entries_for_bank_clearance(
"account": account,
"from": from_date,
"to": to_date,
"bank_account": bank_account,
},
as_dict=1,
)

View File

@@ -19,10 +19,15 @@ frappe.ui.form.on("Bank Reconciliation Tool", {
},
onload: function (frm) {
if (!frm.doc.company) {
frm.set_value("company", frappe.defaults.get_default("company"));
}
// Set default filter dates
let today = frappe.datetime.get_today();
frm.doc.bank_statement_from_date = frappe.datetime.add_months(today, -1);
frm.doc.bank_statement_to_date = today;
frm.trigger("bank_account");
},
@@ -98,7 +103,7 @@ frappe.ui.form.on("Bank Reconciliation Tool", {
make_reconciliation_tool(frm) {
frm.get_field("reconciliation_tool_cards").$wrapper.empty();
if (frm.doc.bank_account && frm.doc.bank_statement_to_date) {
if (frm.doc.company && frm.doc.bank_account && frm.doc.bank_statement_to_date) {
frm.trigger("get_cleared_balance").then(() => {
if (
frm.doc.bank_account &&
@@ -114,7 +119,7 @@ frappe.ui.form.on("Bank Reconciliation Tool", {
},
get_account_opening_balance(frm) {
if (frm.doc.bank_account && frm.doc.bank_statement_from_date) {
if (frm.doc.company && frm.doc.bank_account && frm.doc.bank_statement_from_date) {
frappe.call({
method: "erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool.get_account_balance",
args: {
@@ -130,7 +135,7 @@ frappe.ui.form.on("Bank Reconciliation Tool", {
},
get_cleared_balance(frm) {
if (frm.doc.bank_account && frm.doc.bank_statement_to_date) {
if (frm.doc.company && frm.doc.bank_account && frm.doc.bank_statement_to_date) {
return frappe.call({
method: "erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool.get_account_balance",
args: {

View File

@@ -374,9 +374,36 @@ def auto_reconcile_vouchers(
to_reference_date=None,
):
frappe.flags.auto_reconcile_vouchers = True
reconciled, partially_reconciled = set(), set()
bank_transactions = get_bank_transactions(bank_account)
if len(bank_transactions) > 10:
frappe.enqueue(
method="erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool.start_auto_reconcile",
queue="long",
bank_transactions=bank_transactions,
from_date=from_date,
to_date=to_date,
filter_by_reference_date=filter_by_reference_date,
from_reference_date=from_reference_date,
to_reference_date=to_reference_date,
)
frappe.msgprint(_("Auto Reconciliation has started in the background"))
else:
start_auto_reconcile(
bank_transactions,
from_date,
to_date,
filter_by_reference_date,
from_reference_date,
to_reference_date,
)
def start_auto_reconcile(
bank_transactions, from_date, to_date, filter_by_reference_date, from_reference_date, to_reference_date
):
reconciled, partially_reconciled = set(), set()
for transaction in bank_transactions:
linked_payments = get_linked_payments(
transaction.name,
@@ -414,7 +441,6 @@ def auto_reconcile_vouchers(
frappe.msgprint(title=_("Auto Reconciliation"), msg=alert_message, indicator=indicator)
frappe.flags.auto_reconcile_vouchers = False
return reconciled, partially_reconciled
def get_auto_reconcile_message(partially_reconciled, reconciled):
@@ -802,7 +828,6 @@ def get_je_matching_query(
.where(je.clearance_date.isnull())
.where(jea.account == common_filters.bank_account)
.where(amount_equality if exact_match else getattr(jea, amount_field) > 0.0)
.where(je.docstatus == 1)
.where(filter_by_date)
.orderby(je.cheque_date if cint(filter_by_reference_date) else je.posting_date)
)

View File

@@ -45,45 +45,41 @@ class AutoMatchbyAccountIBAN:
if not (self.bank_party_account_number or self.bank_party_iban):
return None
result = self.match_account_in_party()
return result
return self.match_account_in_party()
def match_account_in_party(self) -> tuple | None:
"""Check if there is a IBAN/Account No. match in Customer/Supplier/Employee"""
result = None
parties = get_parties_in_order(self.deposit)
or_filters = self.get_or_filters()
"""
Returns (Party Type, Party) if a matching account is found in Bank Account or Employee:
1. Get party from a matching (iban/account no) Bank Account
2. If not found, get party from Employee with matching bank account details (iban/account no)
"""
if not (self.bank_party_account_number or self.bank_party_iban):
# Nothing to match
return None
for party in parties:
party_result = frappe.db.get_all(
"Bank Account", or_filters=or_filters, pluck="party", limit_page_length=1
)
# Search for a matching Bank Account that has party set
party_result = frappe.db.get_all(
"Bank Account",
or_filters=self.get_or_filters(),
filters={"party_type": ("is", "set"), "party": ("is", "set")},
fields=["party", "party_type"],
limit_page_length=1,
)
if result := party_result[0] if party_result else None:
return (result["party_type"], result["party"])
if party == "Employee" and not party_result:
# Search in Bank Accounts first for Employee, and then Employee record
if "bank_account_no" in or_filters:
or_filters["bank_ac_no"] = or_filters.pop("bank_account_no")
# If no party is found, search in Employee (since it has bank account details)
if employee_result := frappe.db.get_all(
"Employee", or_filters=self.get_or_filters("Employee"), pluck="name", limit_page_length=1
):
return ("Employee", employee_result[0])
party_result = frappe.db.get_all(
party, or_filters=or_filters, pluck="name", limit_page_length=1
)
if "bank_ac_no" in or_filters:
or_filters["bank_account_no"] = or_filters.pop("bank_ac_no")
if party_result:
result = (
party,
party_result[0],
)
break
return result
def get_or_filters(self) -> dict:
def get_or_filters(self, party: str | None = None) -> dict:
"""Return OR filters for Bank Account and IBAN"""
or_filters = {}
if self.bank_party_account_number:
or_filters["bank_account_no"] = self.bank_party_account_number
bank_ac_field = "bank_ac_no" if party == "Employee" else "bank_account_no"
or_filters[bank_ac_field] = self.bank_party_account_number
if self.bank_party_iban:
or_filters["iban"] = self.bank_party_iban
@@ -103,8 +99,7 @@ class AutoMatchbyPartyNameDescription:
if not (self.bank_party_name or self.description):
return None
result = self.match_party_name_desc_in_party()
return result
return self.match_party_name_desc_in_party()
def match_party_name_desc_in_party(self) -> tuple | None:
"""Fuzzy search party name and/or description against parties in the system"""
@@ -113,7 +108,8 @@ class AutoMatchbyPartyNameDescription:
for party in parties:
filters = {"status": "Active"} if party == "Employee" else {"disabled": 0}
names = frappe.get_all(party, filters=filters, pluck=party.lower() + "_name")
field = f"{party.lower()}_name"
names = frappe.get_all(party, filters=filters, fields=[f"{field} as party_name", "name"])
for field in ["bank_party_name", "description"]:
if not self.get(field):
@@ -132,16 +128,14 @@ class AutoMatchbyPartyNameDescription:
def fuzzy_search_and_return_result(self, party, names, field) -> tuple | None:
skip = False
result = process.extract(query=self.get(field), choices=names, scorer=fuzz.token_set_ratio)
result = process.extract(
query=self.get(field),
choices={row.get("name"): row.get("party_name") for row in names},
scorer=fuzz.token_set_ratio,
)
party_name, skip = self.process_fuzzy_result(result)
if not party_name:
return None, skip
return (
party,
party_name,
), skip
return ((party, party_name), skip) if party_name else (None, skip)
def process_fuzzy_result(self, result: list | None):
"""
@@ -150,30 +144,30 @@ class AutoMatchbyPartyNameDescription:
Returns: Result, Skip (whether or not to discontinue matching)
"""
PARTY, SCORE, CUTOFF = 0, 1, 80
SCORE, PARTY_ID, CUTOFF = 1, 2, 80
if not result or not len(result):
return None, False
first_result = result[0]
if len(result) == 1:
return (first_result[PARTY] if first_result[SCORE] > CUTOFF else None), True
return (first_result[PARTY_ID] if first_result[SCORE] > CUTOFF else None), True
second_result = result[1]
if first_result[SCORE] > CUTOFF:
second_result = result[1]
# If multiple matches with the same score, return None but discontinue matching
# Matches were found but were too close to distinguish between
if first_result[SCORE] == second_result[SCORE]:
return None, True
return first_result[PARTY], True
return first_result[PARTY_ID], True
else:
return None, False
def get_parties_in_order(deposit: float) -> list:
parties = ["Supplier", "Employee", "Customer"] # most -> least likely to receive
if flt(deposit) > 0:
parties = ["Customer", "Supplier", "Employee"] # most -> least likely to pay
return parties
return (
["Customer", "Supplier", "Employee"] # most -> least likely to pay us
if flt(deposit) > 0
else ["Supplier", "Employee", "Customer"] # most -> least likely to receive from us
)

View File

@@ -128,7 +128,7 @@ class TestCouponCode(unittest.TestCase):
item_code="_Test Tesla Car",
rate=5000,
qty=1,
do_not_submit=True,
do_not_save=True,
)
self.assertEqual(so.items[0].rate, 5000)

View File

@@ -279,7 +279,8 @@
{
"fieldname": "transaction_exchange_rate",
"fieldtype": "Float",
"label": "Transaction Exchange Rate"
"label": "Transaction Exchange Rate",
"precision": "9"
},
{
"fieldname": "debit_in_transaction_currency",
@@ -357,7 +358,7 @@
"idx": 1,
"in_create": 1,
"links": [],
"modified": "2024-08-22 13:03:39.997475",
"modified": "2025-02-21 14:36:49.431166",
"modified_by": "Administrator",
"module": "Accounts",
"name": "GL Entry",

View File

@@ -129,7 +129,7 @@ class GLEntry(Document):
if not self.get(k):
frappe.throw(_("{0} is required").format(_(self.meta.get_label(k))))
if not (self.party_type and self.party):
if not self.is_cancelled and not (self.party_type and self.party):
account_type = frappe.get_cached_value("Account", self.account, "account_type")
if account_type == "Receivable":
frappe.throw(

View File

@@ -124,3 +124,20 @@ class TestGLEntry(unittest.TestCase):
str(e),
"Party Type and Party can only be set for Receivable / Payable account_Test Account Cost for Goods Sold - _TC",
)
def test_validate_account_party_type_shareholder(self):
jv = make_journal_entry(
"Opening Balance Equity - _TC",
"Cash - _TC",
100,
"_Test Cost Center - _TC",
save=False,
submit=False,
)
for row in jv.accounts:
row.party_type = "Shareholder"
break
jv.save().submit()
self.assertEqual(1, jv.docstatus)

View File

@@ -430,12 +430,6 @@ frappe.ui.form.on("Journal Entry Account", {
});
}
},
cost_center: function (frm, dt, dn) {
// Don't reset for Gain/Loss type journals, as it will make Debit and Credit values '0'
if (frm.doc.voucher_type != "Exchange Gain Or Loss") {
erpnext.journal_entry.set_account_details(frm, dt, dn);
}
},
account: function (frm, dt, dn) {
erpnext.journal_entry.set_account_details(frm, dt, dn);

View File

@@ -141,6 +141,7 @@ class JournalEntry(AccountsController):
self.validate_empty_accounts_table()
self.validate_inter_company_accounts()
self.validate_depr_entry_voucher_type()
self.validate_company_in_accounting_dimension()
self.validate_advance_accounts()
if self.docstatus == 0:
@@ -575,8 +576,22 @@ class JournalEntry(AccountsController):
if customers:
from erpnext.selling.doctype.customer.customer import check_credit_limit
customer_details = frappe._dict(
frappe.db.get_all(
"Customer Credit Limit",
filters={
"parent": ["in", customers],
"parenttype": ["=", "Customer"],
"company": ["=", self.company],
},
fields=["parent", "bypass_credit_limit_check"],
as_list=True,
)
)
for customer in customers:
check_credit_limit(customer, self.company)
ignore_outstanding_sales_order = bool(customer_details.get(customer))
check_credit_limit(customer, self.company, ignore_outstanding_sales_order)
def validate_cheque_info(self):
if self.voucher_type in ["Bank Entry"]:
@@ -1059,14 +1074,15 @@ class JournalEntry(AccountsController):
gl_map = []
company_currency = erpnext.get_company_currency(self.company)
self.transaction_currency = company_currency
self.transaction_exchange_rate = 1
if self.multi_currency:
for row in self.get("accounts"):
if row.account_currency != company_currency:
self.currency = row.account_currency
self.conversion_rate = row.exchange_rate
# Journal assumes the first foreign currency as transaction currency
self.transaction_currency = row.account_currency
self.transaction_exchange_rate = row.exchange_rate
break
else:
self.currency = company_currency
for d in self.get("accounts"):
if d.debit or d.credit or (self.voucher_type == "Exchange Gain Or Loss"):
@@ -1091,6 +1107,18 @@ class JournalEntry(AccountsController):
"credit_in_account_currency": flt(
d.credit_in_account_currency, d.precision("credit_in_account_currency")
),
"transaction_currency": self.transaction_currency,
"transaction_exchange_rate": self.transaction_exchange_rate,
"debit_in_transaction_currency": flt(
d.debit_in_account_currency, d.precision("debit_in_account_currency")
)
if self.transaction_currency == d.account_currency
else flt(d.debit, d.precision("debit")) / self.transaction_exchange_rate,
"credit_in_transaction_currency": flt(
d.credit_in_account_currency, d.precision("credit_in_account_currency")
)
if self.transaction_currency == d.account_currency
else flt(d.credit, d.precision("credit")) / self.transaction_exchange_rate,
"against_voucher_type": d.reference_type,
"against_voucher": d.reference_name,
"remarks": remarks,

View File

@@ -146,10 +146,9 @@ class TestJournalEntry(unittest.TestCase):
"credit_in_account_currency": 0 if diff > 0 else abs(diff),
},
)
jv.insert()
if account_bal == stock_bal:
self.assertRaises(StockAccountInvalidTransaction, jv.submit)
self.assertRaises(StockAccountInvalidTransaction, jv.save)
frappe.db.rollback()
else:
jv.submit()
@@ -576,7 +575,7 @@ class TestJournalEntry(unittest.TestCase):
order_by="account",
)
expected = [
{"account": "_Test Bank - _TC", "transaction_exchange_rate": 1.0},
{"account": "_Test Bank - _TC", "transaction_exchange_rate": 85.0},
{"account": "_Test Receivable USD - _TC", "transaction_exchange_rate": 85.0},
]
self.assertEqual(expected, actual)
@@ -592,13 +591,14 @@ def make_journal_entry(
save=True,
submit=False,
project=None,
company=None,
):
if not cost_center:
cost_center = "_Test Cost Center - _TC"
jv = frappe.new_doc("Journal Entry")
jv.posting_date = posting_date or nowdate()
jv.company = "_Test Company"
jv.company = company or "_Test Company"
jv.user_remark = "test"
jv.multi_currency = 1
jv.set(

View File

@@ -258,6 +258,10 @@ frappe.ui.form.on("Payment Entry", {
frappe.flags.allocate_payment_amount = true;
},
validate: async function (frm) {
await frm.events.set_exchange_gain_loss_deduction(frm);
},
validate_company: (frm) => {
if (!frm.doc.company) {
frappe.throw({ message: __("Please select a Company first."), title: __("Mandatory") });
@@ -812,27 +816,41 @@ frappe.ui.form.on("Payment Entry", {
paid_amount: function (frm) {
frm.set_value("base_paid_amount", flt(frm.doc.paid_amount) * flt(frm.doc.source_exchange_rate));
let company_currency = frappe.get_doc(":Company", frm.doc.company).default_currency;
if (!frm.doc.received_amount) {
if (frm.doc.paid_from_account_currency == frm.doc.paid_to_account_currency) {
frm.set_value("received_amount", frm.doc.paid_amount);
} else if (company_currency == frm.doc.paid_to_account_currency) {
frm.set_value("received_amount", frm.doc.base_paid_amount);
frm.set_value("base_received_amount", frm.doc.base_paid_amount);
}
}
frm.trigger("reset_received_amount");
frm.events.hide_unhide_fields(frm);
},
received_amount: function (frm) {
let company_currency = frappe.get_doc(":Company", frm.doc.company).default_currency;
frm.set_paid_amount_based_on_received_amount = true;
if (!frm.doc.paid_amount && frm.doc.paid_from_account_currency == frm.doc.paid_to_account_currency) {
frm.set_value("paid_amount", frm.doc.received_amount);
if (frm.doc.target_exchange_rate) {
frm.set_value("source_exchange_rate", frm.doc.target_exchange_rate);
}
frm.set_value("base_paid_amount", frm.doc.base_received_amount);
}
frm.set_value(
"base_received_amount",
flt(frm.doc.received_amount) * flt(frm.doc.target_exchange_rate)
);
if (!frm.doc.paid_amount) {
if (frm.doc.paid_from_account_currency == frm.doc.paid_to_account_currency) {
frm.set_value("paid_amount", frm.doc.received_amount);
if (frm.doc.target_exchange_rate) {
frm.set_value("source_exchange_rate", frm.doc.target_exchange_rate);
}
frm.set_value("base_paid_amount", frm.doc.base_received_amount);
} else if (company_currency == frm.doc.paid_from_account_currency) {
frm.set_value("paid_amount", frm.doc.base_received_amount);
frm.set_value("base_paid_amount", frm.doc.base_received_amount);
}
}
if (frm.doc.payment_type == "Pay")
frm.events.allocate_party_amount_against_ref_docs(frm, frm.doc.received_amount, true);
else frm.events.set_unallocated_amount(frm);
@@ -1879,8 +1897,6 @@ function prompt_for_missing_account(frm, account) {
(values) => resolve(values?.[account]),
__("Please Specify Account")
);
dialog.on_hide = () => resolve("");
});
}

View File

@@ -224,6 +224,7 @@
"label": "Accounts"
},
{
"allow_on_submit": 1,
"depends_on": "party",
"fieldname": "party_balance",
"fieldtype": "Currency",
@@ -253,6 +254,7 @@
"reqd": 1
},
{
"allow_on_submit": 1,
"depends_on": "paid_from",
"fieldname": "paid_from_account_balance",
"fieldtype": "Currency",
@@ -286,6 +288,7 @@
"reqd": 1
},
{
"allow_on_submit": 1,
"depends_on": "paid_to",
"fieldname": "paid_to_account_balance",
"fieldtype": "Currency",
@@ -806,7 +809,7 @@
"table_fieldname": "payment_entries"
}
],
"modified": "2025-01-13 16:03:47.169699",
"modified": "2025-01-31 17:27:28.555246",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Entry",

View File

@@ -7,6 +7,7 @@ from functools import reduce
import frappe
from frappe import ValidationError, _, qb, scrub, throw
from frappe.model.meta import get_field_precision
from frappe.query_builder import Tuple
from frappe.query_builder.functions import Count
from frappe.utils import cint, comma_or, flt, getdate, nowdate
@@ -25,6 +26,10 @@ from erpnext.accounts.doctype.invoice_discounting.invoice_discounting import (
get_party_account_based_on_invoice_discounting,
)
from erpnext.accounts.doctype.journal_entry.journal_entry import get_default_bank_cash_account
from erpnext.accounts.doctype.repost_accounting_ledger.repost_accounting_ledger import (
validate_docs_for_deferred_accounting,
validate_docs_for_voucher_types,
)
from erpnext.accounts.doctype.tax_withholding_category.tax_withholding_category import (
get_party_tax_withholding_details,
)
@@ -33,7 +38,7 @@ from erpnext.accounts.general_ledger import (
make_reverse_gl_entries,
process_gl_map,
)
from erpnext.accounts.party import get_party_account
from erpnext.accounts.party import complete_contact_details, get_party_account, set_contact_details
from erpnext.accounts.utils import (
cancel_exchange_gain_loss_journal,
get_account_currency,
@@ -114,6 +119,23 @@ class PaymentEntry(AccountsController):
self.update_advance_paid() # advance_paid_status depends on the payment request amount
self.set_status()
def validate_for_repost(self):
validate_docs_for_voucher_types(["Payment Entry"])
validate_docs_for_deferred_accounting([self.name], [])
def on_update_after_submit(self):
# Flag will be set on Reconciliation
# Reconciliation tool will anyways repost ledger entries. So, no need to check and do implicit repost.
if self.flags.get("ignore_reposting_on_reconciliation"):
return
self.needs_repost = self.check_if_fields_updated(
fields_to_check=[], child_tables={"references": [], "taxes": [], "deductions": []}
)
if self.needs_repost:
self.validate_for_repost()
self.repost_accounting_entries()
def set_liability_account(self):
# Auto setting liability account should only be done during 'draft' status
if self.docstatus > 0 or self.payment_type == "Internal Transfer":
@@ -418,6 +440,12 @@ class PaymentEntry(AccountsController):
self.party_name = frappe.db.get_value(self.party_type, self.party, "name")
if self.party:
if not self.contact_person:
set_contact_details(
self, party=frappe._dict({"name": self.party}), party_type=self.party_type
)
else:
complete_contact_details(self)
if not self.party_balance:
self.party_balance = get_balance_on(
party_type=self.party_type, party=self.party, date=self.posting_date, company=self.company
@@ -543,7 +571,7 @@ class PaymentEntry(AccountsController):
if d.reference_doctype not in valid_reference_doctypes:
frappe.throw(
_("Reference Doctype must be one of {0}").format(
comma_or(_(d) for d in valid_reference_doctypes)
comma_or([_(d) for d in valid_reference_doctypes])
)
)
@@ -715,16 +743,39 @@ class PaymentEntry(AccountsController):
outstanding = flt(invoice_paid_amount_map.get(key, {}).get("outstanding"))
discounted_amt = flt(invoice_paid_amount_map.get(key, {}).get("discounted_amt"))
conversion_rate = frappe.db.get_value(key[2], {"name": key[1]}, "conversion_rate")
base_paid_amount_precision = get_field_precision(
frappe.get_meta("Payment Schedule").get_field("base_paid_amount")
)
base_outstanding_precision = get_field_precision(
frappe.get_meta("Payment Schedule").get_field("base_outstanding")
)
base_paid_amount = flt(
(allocated_amount - discounted_amt) * conversion_rate, base_paid_amount_precision
)
base_outstanding = flt(allocated_amount * conversion_rate, base_outstanding_precision)
if cancel:
frappe.db.sql(
"""
UPDATE `tabPayment Schedule`
SET
paid_amount = `paid_amount` - %s,
base_paid_amount = `base_paid_amount` - %s,
discounted_amount = `discounted_amount` - %s,
outstanding = `outstanding` + %s
outstanding = `outstanding` + %s,
base_outstanding = `base_outstanding` - %s
WHERE parent = %s and payment_term = %s""",
(allocated_amount - discounted_amt, discounted_amt, allocated_amount, key[1], key[0]),
(
allocated_amount - discounted_amt,
base_paid_amount,
discounted_amt,
allocated_amount,
base_outstanding,
key[1],
key[0],
),
)
else:
if allocated_amount > outstanding:
@@ -740,10 +791,20 @@ class PaymentEntry(AccountsController):
UPDATE `tabPayment Schedule`
SET
paid_amount = `paid_amount` + %s,
base_paid_amount = `base_paid_amount` + %s,
discounted_amount = `discounted_amount` + %s,
outstanding = `outstanding` - %s
outstanding = `outstanding` - %s,
base_outstanding = `base_outstanding` - %s
WHERE parent = %s and payment_term = %s""",
(allocated_amount - discounted_amt, discounted_amt, allocated_amount, key[1], key[0]),
(
allocated_amount - discounted_amt,
base_paid_amount,
discounted_amt,
allocated_amount,
base_outstanding,
key[1],
key[0],
),
)
def get_allocated_amount_in_transaction_currency(
@@ -1196,15 +1257,22 @@ class PaymentEntry(AccountsController):
self.set("remarks", "\n".join(remarks))
def set_transaction_currency_and_rate(self):
company_currency = erpnext.get_company_currency(self.company)
self.transaction_currency = company_currency
self.transaction_exchange_rate = 1
if self.paid_from_account_currency != company_currency:
self.transaction_currency = self.paid_from_account_currency
self.transaction_exchange_rate = self.source_exchange_rate
elif self.paid_to_account_currency != company_currency:
self.transaction_currency = self.paid_to_account_currency
self.transaction_exchange_rate = self.target_exchange_rate
def build_gl_map(self):
if self.payment_type in ("Receive", "Pay") and not self.get("party_account_field"):
self.setup_party_account_field()
company_currency = erpnext.get_company_currency(self.company)
if self.paid_from_account_currency != company_currency:
self.currency = self.paid_from_account_currency
elif self.paid_to_account_currency != company_currency:
self.currency = self.paid_to_account_currency
self.set_transaction_currency_and_rate()
gl_entries = []
self.add_party_gl_entries(gl_entries)
@@ -1283,6 +1351,9 @@ class PaymentEntry(AccountsController):
"cost_center": cost_center,
dr_or_cr + "_in_account_currency": d.allocated_amount,
dr_or_cr: allocated_amount_in_company_currency,
dr_or_cr + "_in_transaction_currency": d.allocated_amount
if self.transaction_currency == self.party_account_currency
else allocated_amount_in_company_currency / self.transaction_exchange_rate,
},
item=self,
)
@@ -1327,6 +1398,9 @@ class PaymentEntry(AccountsController):
"account_currency": self.party_account_currency,
"cost_center": self.cost_center,
dr_or_cr + "_in_account_currency": self.unallocated_amount,
dr_or_cr + "_in_transaction_currency": self.unallocated_amount
if self.party_account_currency == self.transaction_currency
else base_unallocated_amount / self.transaction_exchange_rate,
dr_or_cr: base_unallocated_amount,
},
item=self,
@@ -1344,6 +1418,7 @@ class PaymentEntry(AccountsController):
def make_advance_gl_entries(
self, entry: object | dict = None, cancel: bool = 0, update_outstanding: str = "Yes"
):
self.set_transaction_currency_and_rate()
gl_entries = []
self.add_advance_gl_entries(gl_entries, entry)
@@ -1423,9 +1498,16 @@ class PaymentEntry(AccountsController):
frappe.db.set_value("Payment Entry Reference", invoice.name, "reconcile_effect_on", posting_date)
dr_or_cr, account = self.get_dr_and_account_for_advances(invoice)
base_allocated_amount = self.calculate_base_allocated_amount_for_reference(invoice)
args_dict["account"] = account
args_dict[dr_or_cr] = self.calculate_base_allocated_amount_for_reference(invoice)
args_dict[dr_or_cr] = base_allocated_amount
args_dict[dr_or_cr + "_in_account_currency"] = invoice.allocated_amount
args_dict[dr_or_cr + "_in_transaction_currency"] = (
invoice.allocated_amount
if self.party_account_currency == self.transaction_currency
else base_allocated_amount / self.transaction_exchange_rate
)
args_dict.update(
{
"against_voucher_type": invoice.reference_doctype,
@@ -1443,8 +1525,13 @@ class PaymentEntry(AccountsController):
args_dict[dr_or_cr + "_in_account_currency"] = 0
dr_or_cr = "debit" if dr_or_cr == "credit" else "credit"
args_dict["account"] = self.party_account
args_dict[dr_or_cr] = self.calculate_base_allocated_amount_for_reference(invoice)
args_dict[dr_or_cr] = base_allocated_amount
args_dict[dr_or_cr + "_in_account_currency"] = invoice.allocated_amount
args_dict[dr_or_cr + "_in_transaction_currency"] = (
invoice.allocated_amount
if self.party_account_currency == self.transaction_currency
else base_allocated_amount / self.transaction_exchange_rate
)
args_dict.update(
{
"against_voucher_type": "Payment Entry",
@@ -1466,6 +1553,9 @@ class PaymentEntry(AccountsController):
"account_currency": self.paid_from_account_currency,
"against": self.party if self.payment_type == "Pay" else self.paid_to,
"credit_in_account_currency": self.paid_amount,
"credit_in_transaction_currency": self.paid_amount
if self.paid_from_account_currency == self.transaction_currency
else self.base_paid_amount / self.transaction_exchange_rate,
"credit": self.base_paid_amount,
"cost_center": self.cost_center,
"post_net_value": True,
@@ -1481,6 +1571,9 @@ class PaymentEntry(AccountsController):
"account_currency": self.paid_to_account_currency,
"against": self.party if self.payment_type == "Receive" else self.paid_from,
"debit_in_account_currency": self.received_amount,
"debit_in_transaction_currency": self.received_amount
if self.paid_to_account_currency == self.transaction_currency
else self.base_received_amount / self.transaction_exchange_rate,
"debit": self.base_received_amount,
"cost_center": self.cost_center,
},
@@ -1516,6 +1609,8 @@ class PaymentEntry(AccountsController):
dr_or_cr + "_in_account_currency": base_tax_amount
if account_currency == self.company_currency
else d.tax_amount,
dr_or_cr + "_in_transaction_currency": base_tax_amount
/ self.transaction_exchange_rate,
"cost_center": d.cost_center,
"post_net_value": True,
},
@@ -1541,6 +1636,8 @@ class PaymentEntry(AccountsController):
rev_dr_or_cr + "_in_account_currency": base_tax_amount
if account_currency == self.company_currency
else d.tax_amount,
rev_dr_or_cr + "_in_transaction_currency": base_tax_amount
/ self.transaction_exchange_rate,
"cost_center": self.cost_center,
"post_net_value": True,
},
@@ -1563,6 +1660,7 @@ class PaymentEntry(AccountsController):
"account_currency": account_currency,
"against": self.party or self.paid_from,
"debit_in_account_currency": d.amount,
"debit_in_transaction_currency": d.amount / self.transaction_exchange_rate,
"debit": d.amount,
"cost_center": d.cost_center,
},
@@ -1576,6 +1674,14 @@ class PaymentEntry(AccountsController):
elif self.payment_type in ("Pay", "Internal Transfer"):
return self.paid_from
def get_value_in_transaction_currency(self, account_currency, gl_dict, field):
company_currency = erpnext.get_company_currency(self.company)
conversion_rate = self.target_exchange_rate
if self.paid_from_account_currency != company_currency:
conversion_rate = self.source_exchange_rate
return flt(gl_dict.get(field, 0) / (conversion_rate or 1))
def update_advance_paid(self):
if self.payment_type in ("Receive", "Pay") and self.party:
for d in self.get("references"):
@@ -1790,7 +1896,7 @@ class PaymentEntry(AccountsController):
paid_amount -= sum(flt(d.amount, precision) for d in self.deductions)
for ref in self.references:
reference_outstanding_amount = ref.outstanding_amount
reference_outstanding_amount = flt(ref.outstanding_amount)
abs_outstanding_amount = abs(reference_outstanding_amount)
if reference_outstanding_amount > 0:
@@ -1814,7 +1920,7 @@ class PaymentEntry(AccountsController):
allocated_positive_outstanding = paid_amount + allocated_negative_outstanding
elif self.party_type in ("Supplier", "Employee"):
elif self.party_type in ("Supplier", "Customer"):
if paid_amount > total_negative_outstanding:
if total_negative_outstanding == 0:
frappe.msgprint(
@@ -2235,10 +2341,17 @@ def get_outstanding_reference_documents(args, validate=False):
outstanding_invoices = []
negative_outstanding_invoices = []
party_account = args.get("party_account")
# get party account if advance account is set.
if args.get("book_advance_payments_in_separate_party_account"):
party_account = get_party_account(args.get("party_type"), args.get("party"), args.get("company"))
else:
party_account = args.get("party_account")
accounts = get_party_account(
args.get("party_type"), args.get("party"), args.get("company"), include_advance=True
)
advance_account = accounts[1] if len(accounts) >= 1 else None
if party_account == advance_account:
party_account = accounts[0]
if args.get("get_outstanding_invoices"):
outstanding_invoices = get_outstanding_invoices(
@@ -2806,7 +2919,7 @@ def get_payment_entry(
pe.party_type = party_type
pe.party = doc.get(scrub(party_type))
pe.contact_person = doc.get("contact_person")
pe.contact_email = doc.get("contact_email")
complete_contact_details(pe)
pe.ensure_supplier_is_not_blocked()
pe.paid_from = party_account if payment_type == "Receive" else bank.account
@@ -2818,6 +2931,9 @@ def get_payment_entry(
pe.paid_amount = paid_amount
pe.received_amount = received_amount
pe.letter_head = doc.get("letter_head")
pe.bank_account = frappe.db.get_value(
"Bank Account", {"is_company_account": 1, "is_default": 1, "company": doc.company}, "name"
)
if dt in ["Purchase Order", "Sales Order", "Sales Invoice", "Purchase Invoice"]:
pe.project = doc.get("project") or reduce(
@@ -2826,7 +2942,7 @@ def get_payment_entry(
if pe.party_type in ["Customer", "Supplier"]:
bank_account = get_party_bank_account(pe.party_type, pe.party)
pe.set("bank_account", bank_account)
pe.set("party_bank_account", bank_account)
pe.set_bank_account_data()
# only Purchase Invoice can be blocked individually
@@ -3300,13 +3416,14 @@ def add_income_discount_loss(pe, doc, total_discount_percent) -> float:
"""Add loss on income discount in base currency."""
precision = doc.precision("total")
base_loss_on_income = doc.get("base_total") * (total_discount_percent / 100)
positive_negative = -1 if pe.payment_type == "Pay" else 1
pe.append(
"deductions",
{
"account": frappe.get_cached_value("Company", pe.company, "default_discount_account"),
"cost_center": pe.cost_center or frappe.get_cached_value("Company", pe.company, "cost_center"),
"amount": flt(base_loss_on_income, precision),
"amount": flt(base_loss_on_income, precision) * positive_negative,
},
)
@@ -3318,6 +3435,7 @@ def add_tax_discount_loss(pe, doc, total_discount_percentage) -> float:
tax_discount_loss = {}
base_total_tax_loss = 0
precision = doc.precision("tax_amount_after_discount_amount", "taxes")
positive_negative = -1 if pe.payment_type == "Pay" else 1
# The same account head could be used more than once
for tax in doc.get("taxes", []):
@@ -3340,7 +3458,7 @@ def add_tax_discount_loss(pe, doc, total_discount_percentage) -> float:
"account": account,
"cost_center": pe.cost_center
or frappe.get_cached_value("Company", pe.company, "cost_center"),
"amount": flt(loss, precision),
"amount": flt(loss, precision) * positive_negative,
},
)

View File

@@ -282,6 +282,48 @@ class TestPaymentEntry(FrappeTestCase):
self.assertEqual(si.payment_schedule[0].paid_amount, 200.0)
self.assertEqual(si.payment_schedule[1].paid_amount, 36.0)
def test_payment_entry_against_payment_terms_with_discount_on_pi(self):
pi = make_purchase_invoice(do_not_save=1)
create_payment_terms_template_with_discount()
pi.payment_terms_template = "Test Discount Template"
frappe.db.set_value("Company", pi.company, "default_discount_account", "Write Off - _TC")
pi.append(
"taxes",
{
"charge_type": "On Net Total",
"account_head": "_Test Account Service Tax - _TC",
"cost_center": "_Test Cost Center - _TC",
"description": "Service Tax",
"rate": 18,
},
)
pi.save()
pi.submit()
frappe.db.set_single_value("Accounts Settings", "book_tax_discount_loss", 1)
pe_with_tax_loss = get_payment_entry("Purchase Invoice", pi.name, bank_account="_Test Cash - _TC")
self.assertEqual(pe_with_tax_loss.references[0].payment_term, "30 Credit Days with 10% Discount")
self.assertEqual(pe_with_tax_loss.payment_type, "Pay")
self.assertEqual(pe_with_tax_loss.references[0].allocated_amount, 295.0)
self.assertEqual(pe_with_tax_loss.paid_amount, 265.5)
self.assertEqual(pe_with_tax_loss.difference_amount, 0)
self.assertEqual(pe_with_tax_loss.deductions[0].amount, -25.0) # Loss on Income
self.assertEqual(pe_with_tax_loss.deductions[1].amount, -4.5) # Loss on Tax
self.assertEqual(pe_with_tax_loss.deductions[1].account, "_Test Account Service Tax - _TC")
frappe.db.set_single_value("Accounts Settings", "book_tax_discount_loss", 0)
pe = get_payment_entry("Purchase Invoice", pi.name, bank_account="_Test Cash - _TC")
self.assertEqual(pe.references[0].payment_term, "30 Credit Days with 10% Discount")
self.assertEqual(pe.payment_type, "Pay")
self.assertEqual(pe.references[0].allocated_amount, 295.0)
self.assertEqual(pe.paid_amount, 265.5)
self.assertEqual(pe.deductions[0].amount, -29.5)
self.assertEqual(pe.difference_amount, 0)
def test_payment_entry_against_payment_terms_with_discount(self):
si = create_sales_invoice(do_not_save=1, qty=1, rate=200)
create_payment_terms_template_with_discount()

View File

@@ -335,6 +335,7 @@ class PaymentReconciliation(Document):
for payment in non_reconciled_payments:
row = self.append("payments", {})
row.update(payment)
row.is_advance = payment.book_advance_payments_in_separate_party_account
def get_invoice_entries(self):
# Fetch JVs, Sales and Purchase Invoices for 'invoices' to reconcile against
@@ -424,6 +425,9 @@ class PaymentReconciliation(Document):
def allocate_entries(self, args):
self.validate_entries()
exc_gain_loss_posting_date = frappe.db.get_single_value(
"Accounts Settings", "exchange_gain_loss_posting_date", cache=True
)
invoice_exchange_map = self.get_invoice_exchange_map(args.get("invoices"), args.get("payments"))
default_exchange_gain_loss_account = frappe.get_cached_value(
"Company", self.company, "exchange_gain_loss_account"
@@ -450,6 +454,11 @@ class PaymentReconciliation(Document):
res.difference_account = default_exchange_gain_loss_account
res.exchange_rate = inv.get("exchange_rate")
res.update({"gain_loss_posting_date": pay.get("posting_date")})
if not pay.get("is_advance"):
if exc_gain_loss_posting_date == "Invoice":
res.update({"gain_loss_posting_date": inv.get("invoice_date")})
elif exc_gain_loss_posting_date == "Reconciliation Date":
res.update({"gain_loss_posting_date": nowdate()})
if pay.get("amount") == 0:
entries.append(res)

View File

@@ -313,6 +313,7 @@ class PaymentRequest(Document):
"payer_name": data.customer_name,
"order_id": self.name,
"currency": self.currency,
"payment_gateway": self.payment_gateway,
}
)
@@ -767,26 +768,39 @@ def get_existing_payment_request_amount(ref_dt, ref_dn, statuses: list | None =
def get_existing_paid_amount(doctype, name):
PL = frappe.qb.DocType("Payment Ledger Entry")
PLE = frappe.qb.DocType("Payment Ledger Entry")
PER = frappe.qb.DocType("Payment Entry Reference")
query = (
frappe.qb.from_(PL)
frappe.qb.from_(PLE)
.left_join(PER)
.on(
(PER.reference_doctype == PL.against_voucher_type) & (PER.reference_name == PL.against_voucher_no)
(PLE.against_voucher_type == PER.reference_doctype)
& (PLE.against_voucher_no == PER.reference_name)
& (PLE.voucher_type == PER.parenttype)
& (PLE.voucher_no == PER.parent)
)
.select(
Abs(Sum(PLE.amount)).as_("total_amount"),
Abs(Sum(frappe.qb.terms.Case().when(PER.payment_request.isnotnull(), PLE.amount).else_(0))).as_(
"request_paid_amount"
),
)
.where(
(PLE.voucher_type.isin([doctype, "Journal Entry", "Payment Entry"]))
& (PLE.against_voucher_type == doctype)
& (PLE.against_voucher_no == name)
& (PLE.delinked == 0)
& (PLE.docstatus == 1)
& (PLE.amount < 0)
)
.select(Abs(Sum(PL.amount)).as_("total_paid_amount"))
.where(PL.against_voucher_type.eq(doctype))
.where(PL.against_voucher_no.eq(name))
.where(PL.amount < 0)
.where(PL.delinked == 0)
.where(PER.docstatus == 1)
.where(PER.payment_request.isnull())
)
response = query.run()
return response[0][0] if response[0] else 0
result = query.run()
ledger_amount = flt(result[0][0]) if result else 0
request_paid_amount = flt(result[0][1]) if result else 0
return ledger_amount - request_paid_amount
def get_gateway_details(args): # nosemgrep

View File

@@ -83,8 +83,7 @@ class TestPaymentRequest(FrappeTestCase):
def test_payment_entry_against_purchase_invoice(self):
si_usd = make_purchase_invoice(
customer="_Test Supplier USD",
debit_to="_Test Payable USD - _TC",
supplier="_Test Supplier USD",
currency="USD",
conversion_rate=50,
)
@@ -108,8 +107,7 @@ class TestPaymentRequest(FrappeTestCase):
def test_multiple_payment_entry_against_purchase_invoice(self):
purchase_invoice = make_purchase_invoice(
customer="_Test Supplier USD",
debit_to="_Test Payable USD - _TC",
supplier="_Test Supplier USD",
currency="USD",
conversion_rate=50,
)
@@ -544,6 +542,73 @@ class TestPaymentRequest(FrappeTestCase):
self.assertEqual(pr.grand_total, si.outstanding_amount)
def test_partial_paid_invoice_with_more_payment_entry(self):
pi = make_purchase_invoice(currency="INR", qty=1, rate=500)
pi.submit()
pi_1 = make_purchase_invoice(currency="INR", qty=1, rate=300)
pi_1.submit()
pr = make_payment_request(dt="Purchase Invoice", dn=pi.name, mute_email=1, submit_doc=0, return_doc=1)
pr.grand_total = 200
pr.submit()
pr.create_payment_entry()
pr_1 = make_payment_request(
dt="Purchase Invoice", dn=pi.name, mute_email=1, submit_doc=0, return_doc=1
)
pr_1.grand_total = 200
pr_1.submit()
pr_1.create_payment_entry()
pe = get_payment_entry(dt="Purchase Invoice", dn=pi.name)
pe.paid_amount = 200
pe.references[0].reference_doctype = pi.doctype
pe.references[0].reference_name = pi.name
pe.references[0].grand_total = pi.grand_total
pe.references[0].outstanding_amount = pi.outstanding_amount
pe.references[0].allocated_amount = 100
pe.append(
"references",
{
"reference_doctype": pi_1.doctype,
"reference_name": pi_1.name,
"grand_total": pi_1.grand_total,
"outstanding_amount": pi_1.outstanding_amount,
"allocated_amount": 100,
},
)
pr_2 = make_payment_request(dt="Purchase Invoice", dn=pi.name, mute_email=1)
pi.load_from_db()
self.assertEqual(pr_2.grand_total, pi.outstanding_amount)
def test_consider_journal_entry_and_return_invoice(self):
from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry
si = create_sales_invoice(currency="INR", qty=5, rate=500)
je = make_journal_entry("_Test Cash - _TC", "Debtors - _TC", 500, save=False)
je.accounts[1].party_type = "Customer"
je.accounts[1].party = si.customer
je.accounts[1].reference_type = "Sales Invoice"
je.accounts[1].reference_name = si.name
je.accounts[1].credit_in_account_currency = 500
je.submit()
pe = get_payment_entry("Sales Invoice", si.name)
pe.paid_amount = 500
pe.references[0].allocated_amount = 500
pe.save()
pe.submit()
cr_note = create_sales_invoice(qty=-1, rate=500, is_return=1, return_against=si.name, do_not_save=1)
cr_note.update_outstanding_for_self = 0
cr_note.save()
cr_note.submit()
si.load_from_db()
pr = make_payment_request(dt="Sales Invoice", dn=si.name, mute_email=1)
self.assertEqual(pr.grand_total, si.outstanding_amount)
def test_partial_paid_invoice_with_submitted_payment_entry(self):
pi = make_purchase_invoice(currency="INR", qty=1, rate=5000)

View File

@@ -24,7 +24,9 @@
"paid_amount",
"discounted_amount",
"column_break_3",
"base_payment_amount"
"base_payment_amount",
"base_outstanding",
"base_paid_amount"
],
"fields": [
{
@@ -155,19 +157,35 @@
"fieldtype": "Currency",
"label": "Payment Amount (Company Currency)",
"options": "Company:company:default_currency"
},
{
"fieldname": "base_outstanding",
"fieldtype": "Currency",
"label": "Outstanding (Company Currency)",
"options": "Company:company:default_currency",
"read_only": 1
},
{
"depends_on": "base_paid_amount",
"fieldname": "base_paid_amount",
"fieldtype": "Currency",
"label": "Paid Amount (Company Currency)",
"options": "Company:company:default_currency",
"read_only": 1
}
],
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2022-09-16 13:57:06.382859",
"modified": "2025-03-11 11:06:51.792982",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Schedule",
"owner": "Administrator",
"permissions": [],
"quick_entry": 1,
"sort_field": "modified",
"row_format": "Dynamic",
"sort_field": "creation",
"sort_order": "DESC",
"states": [],
"track_changes": 1

View File

@@ -14,6 +14,8 @@ class PaymentSchedule(Document):
if TYPE_CHECKING:
from frappe.types import DF
base_outstanding: DF.Currency
base_paid_amount: DF.Currency
base_payment_amount: DF.Currency
description: DF.SmallText | None
discount: DF.Float

View File

@@ -139,7 +139,7 @@ class PeriodClosingVoucher(AccountsController):
self.cancel_gl_entries()
def make_gl_entries(self):
if self.get_gle_count_in_selected_period() > 5000:
if frappe.db.estimate_count("GL Entry") > 100_000:
frappe.enqueue(
process_gl_and_closing_entries,
doc=self,
@@ -154,16 +154,6 @@ class PeriodClosingVoucher(AccountsController):
else:
process_gl_and_closing_entries(self)
def get_gle_count_in_selected_period(self):
return frappe.db.count(
"GL Entry",
{
"posting_date": ["between", [self.period_start_date, self.period_end_date]],
"company": self.company,
"is_cancelled": 0,
},
)
def get_pcv_gl_entries(self):
self.pl_accounts_reverse_gle = []
self.closing_account_gle = []

View File

@@ -27,6 +27,7 @@ class TestPeriodClosingVoucher(unittest.TestCase):
account1="Cash - TPC",
account2="Sales - TPC",
cost_center=cost_center,
company=company,
save=False,
)
jv1.company = company
@@ -39,6 +40,7 @@ class TestPeriodClosingVoucher(unittest.TestCase):
account1="Cost of Goods Sold - TPC",
account2="Cash - TPC",
cost_center=cost_center,
company=company,
save=False,
)
jv2.company = company
@@ -156,6 +158,7 @@ class TestPeriodClosingVoucher(unittest.TestCase):
amount=400,
cost_center=cost_center,
posting_date="2021-03-15",
company=company,
)
jv.company = company
jv.finance_book = create_finance_book().name
@@ -198,6 +201,7 @@ class TestPeriodClosingVoucher(unittest.TestCase):
account1="Cash - TPC",
account2="Sales - TPC",
cost_center=cost_center,
company=company,
save=False,
)
jv1.company = company
@@ -220,6 +224,7 @@ class TestPeriodClosingVoucher(unittest.TestCase):
account1="Cash - TPC",
account2="Sales - TPC",
cost_center=cost_center1,
company=company,
save=False,
)
jv1.company = company
@@ -232,6 +237,7 @@ class TestPeriodClosingVoucher(unittest.TestCase):
account1="Cash - TPC",
account2="Sales - TPC",
cost_center=cost_center2,
company=company,
save=False,
)
jv2.company = company
@@ -261,6 +267,7 @@ class TestPeriodClosingVoucher(unittest.TestCase):
account1="Cash - TPC",
account2="Sales - TPC",
cost_center=cost_center2,
company=company,
save=False,
)

View File

@@ -39,10 +39,12 @@ class TestPOSClosingEntry(unittest.TestCase):
pos_inv1 = create_pos_invoice(rate=3500, do_not_submit=1)
pos_inv1.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 3500})
pos_inv1.save()
pos_inv1.submit()
pos_inv2 = create_pos_invoice(rate=3200, do_not_submit=1)
pos_inv2.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 3200})
pos_inv2.save()
pos_inv2.submit()
pcv_doc = make_closing_entry_from_opening(opening_entry)
@@ -68,6 +70,7 @@ class TestPOSClosingEntry(unittest.TestCase):
pos_inv = create_pos_invoice(rate=3500, do_not_submit=1, item_name="Test Item", without_item_code=1)
pos_inv.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 3500})
pos_inv.save()
pos_inv.submit()
pcv_doc = make_closing_entry_from_opening(opening_entry)
@@ -86,10 +89,12 @@ class TestPOSClosingEntry(unittest.TestCase):
pos_inv1 = create_pos_invoice(rate=3500, do_not_submit=1)
pos_inv1.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 3500})
pos_inv1.save()
pos_inv1.submit()
pos_inv2 = create_pos_invoice(rate=3200, do_not_submit=1)
pos_inv2.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 3200})
pos_inv2.save()
pos_inv2.submit()
# make return entry of pos_inv2
@@ -111,10 +116,12 @@ class TestPOSClosingEntry(unittest.TestCase):
pos_inv1 = create_pos_invoice(rate=3500, do_not_submit=1)
pos_inv1.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 3500})
pos_inv1.save()
pos_inv1.submit()
pos_inv2 = create_pos_invoice(rate=3200, do_not_submit=1)
pos_inv2.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 3200})
pos_inv2.save()
pos_inv2.submit()
pcv_doc = make_closing_entry_from_opening(opening_entry)
@@ -165,6 +172,7 @@ class TestPOSClosingEntry(unittest.TestCase):
opening_entry = create_opening_entry(pos_profile, test_user.name)
pos_inv1 = create_pos_invoice(rate=350, do_not_submit=1, pos_profile=pos_profile.name)
pos_inv1.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 3500})
pos_inv1.save()
pos_inv1.submit()
# if in between a mandatory accounting dimension is added to the POS Profile then
@@ -218,14 +226,27 @@ class TestPOSClosingEntry(unittest.TestCase):
opening_entry = create_opening_entry(pos_profile, test_user.name)
pos_inv = create_pos_invoice(
item_code=item_code, qty=5, rate=300, use_serial_batch_fields=1, batch_no=batch_no
item_code=item_code,
qty=5,
rate=300,
use_serial_batch_fields=1,
batch_no=batch_no,
do_not_submit=True,
)
pos_inv.payments[0].amount = pos_inv.grand_total
pos_inv.save()
pos_inv.submit()
pos_inv2 = create_pos_invoice(
item_code=item_code, qty=5, rate=300, use_serial_batch_fields=1, batch_no=batch_no
item_code=item_code,
qty=5,
rate=300,
use_serial_batch_fields=1,
batch_no=batch_no,
do_not_submit=True,
)
batch_qty = frappe.db.get_value("Batch", batch_no, "batch_qty")
self.assertEqual(batch_qty, 10)
pos_inv2.payments[0].amount = pos_inv2.grand_total
pos_inv2.save()
pos_inv2.submit()
batch_qty_with_pos = get_batch_qty(batch_no, "_Test Warehouse - _TC", item_code)
self.assertEqual(batch_qty_with_pos, 0.0)
@@ -256,9 +277,6 @@ class TestPOSClosingEntry(unittest.TestCase):
pcv_doc.reload()
pcv_doc.cancel()
batch_qty = frappe.db.get_value("Batch", batch_no, "batch_qty")
self.assertEqual(batch_qty, 10)
batch_qty_with_pos = get_batch_qty(batch_no, "_Test Warehouse - _TC", item_code)
self.assertEqual(batch_qty_with_pos, 0.0)

View File

@@ -1623,6 +1623,5 @@
"states": [],
"timeline_field": "customer",
"title_field": "title",
"track_changes": 1,
"track_seen": 1
}
"track_changes": 1
}

View File

@@ -20,6 +20,10 @@ from erpnext.controllers.queries import item_query as _item_query
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
class PartialPaymentValidationError(frappe.ValidationError):
pass
class POSInvoice(SalesInvoice):
# begin: auto-generated types
# This code is auto-generated. Do not modify anything in this block.
@@ -210,6 +214,7 @@ class POSInvoice(SalesInvoice):
self.validate_payment_amount()
self.validate_loyalty_transaction()
self.validate_company_with_pos_company()
self.validate_full_payment()
if self.coupon_code:
from erpnext.accounts.doctype.pricing_rule.utils import validate_coupon_code
@@ -477,6 +482,20 @@ class POSInvoice(SalesInvoice):
if self.redeem_loyalty_points and self.loyalty_program and self.loyalty_points:
validate_loyalty_points(self, self.loyalty_points)
def validate_full_payment(self):
invoice_total = flt(self.rounded_total) or flt(self.grand_total)
if self.docstatus == 1:
if self.is_return and self.paid_amount != invoice_total:
frappe.throw(
msg=_("Partial Payment in POS Invoice is not allowed."), exc=PartialPaymentValidationError
)
if self.paid_amount < invoice_total:
frappe.throw(
msg=_("Partial Payment in POS Invoice is not allowed."), exc=PartialPaymentValidationError
)
def set_status(self, update=False, status=None, update_modified=True):
if self.is_new():
if self.get("amended_from"):

View File

@@ -7,7 +7,7 @@ import unittest
import frappe
from frappe import _
from erpnext.accounts.doctype.pos_invoice.pos_invoice import make_sales_return
from erpnext.accounts.doctype.pos_invoice.pos_invoice import PartialPaymentValidationError, make_sales_return
from erpnext.accounts.doctype.pos_profile.test_pos_profile import make_pos_profile
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
from erpnext.stock.doctype.item.test_item import make_item
@@ -313,7 +313,7 @@ class TestPOSInvoice(unittest.TestCase):
)
pos.append(
"payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 1000, "default": 1}
"payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 2000, "default": 1}
)
pos.insert()
@@ -324,6 +324,11 @@ class TestPOSInvoice(unittest.TestCase):
# partial return 1
pos_return1.get("items")[0].qty = -1
pos_return1.set("payments", [])
pos_return1.append(
"payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": -1000, "default": 1}
)
pos_return1.paid_amount = -1000
pos_return1.submit()
pos_return1.reload()
@@ -338,6 +343,11 @@ class TestPOSInvoice(unittest.TestCase):
# partial return 2
pos_return2 = make_sales_return(pos.name)
pos_return2.set("payments", [])
pos_return2.append(
"payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": -1000, "default": 1}
)
pos_return2.paid_amount = -1000
pos_return2.submit()
self.assertEqual(pos_return2.get("items")[0].qty, -1)
@@ -373,6 +383,15 @@ class TestPOSInvoice(unittest.TestCase):
inv.payments = []
self.assertRaises(frappe.ValidationError, inv.insert)
def test_partial_payment(self):
pos_inv = create_pos_invoice(rate=10000, do_not_save=1)
pos_inv.append(
"payments",
{"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 9000},
)
pos_inv.insert()
self.assertRaises(PartialPaymentValidationError, pos_inv.submit)
def test_serialized_item_transaction(self):
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_item
@@ -581,7 +600,13 @@ class TestPOSInvoice(unittest.TestCase):
"Test Loyalty Customer", company="_Test Company", loyalty_program="Test Single Loyalty"
)
inv = create_pos_invoice(customer="Test Loyalty Customer", rate=10000)
inv = create_pos_invoice(customer="Test Loyalty Customer", rate=10000, do_not_save=1)
inv.append(
"payments",
{"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 10000},
)
inv.insert()
inv.submit()
lpe = frappe.get_doc(
"Loyalty Point Entry",
@@ -607,7 +632,13 @@ class TestPOSInvoice(unittest.TestCase):
)
# add 10 loyalty points
create_pos_invoice(customer="Test Loyalty Customer", rate=10000)
pos_inv = create_pos_invoice(customer="Test Loyalty Customer", rate=10000, do_not_save=1)
pos_inv.append(
"payments",
{"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 10000},
)
pos_inv.paid_amount = 10000
pos_inv.submit()
before_lp_details = get_loyalty_program_details_with_points(
"Test Loyalty Customer", company="_Test Company", loyalty_program="Test Single Loyalty"
@@ -641,10 +672,12 @@ class TestPOSInvoice(unittest.TestCase):
test_user, pos_profile = init_user_and_profile()
pos_inv = create_pos_invoice(rate=300, additional_discount_percentage=10, do_not_submit=1)
pos_inv.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 270})
pos_inv.save()
pos_inv.submit()
pos_inv2 = create_pos_invoice(rate=3200, do_not_submit=1)
pos_inv2.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 3200})
pos_inv2.save()
pos_inv2.submit()
consolidate_pos_invoices()
@@ -676,6 +709,7 @@ class TestPOSInvoice(unittest.TestCase):
"included_in_print_rate": 1,
},
)
pos_inv.save()
pos_inv.submit()
pos_inv2 = create_pos_invoice(rate=300, qty=2, do_not_submit=1)
@@ -692,6 +726,7 @@ class TestPOSInvoice(unittest.TestCase):
"included_in_print_rate": 1,
},
)
pos_inv2.save()
pos_inv2.submit()
consolidate_pos_invoices()
@@ -744,6 +779,7 @@ class TestPOSInvoice(unittest.TestCase):
"included_in_print_rate": 1,
},
)
pos_inv2.save()
pos_inv2.submit()
consolidate_pos_invoices()
@@ -774,7 +810,10 @@ class TestPOSInvoice(unittest.TestCase):
# POS Invoice 1, for the batch without bundle
pos_inv1 = create_pos_invoice(item="_BATCH ITEM Test For Reserve", rate=300, qty=15, do_not_save=1)
pos_inv1.append(
"payments",
{"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 4500},
)
pos_inv1.items[0].batch_no = batch_no
pos_inv1.save()
pos_inv1.submit()
@@ -790,8 +829,14 @@ class TestPOSInvoice(unittest.TestCase):
# POS Invoice 2, for the batch with bundle
pos_inv2 = create_pos_invoice(
item="_BATCH ITEM Test For Reserve", rate=300, qty=10, batch_no=batch_no
item="_BATCH ITEM Test For Reserve", rate=300, qty=10, batch_no=batch_no, do_not_save=1
)
pos_inv2.append(
"payments",
{"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 3000},
)
pos_inv2.save()
pos_inv2.submit()
pos_inv2.reload()
self.assertTrue(pos_inv2.items[0].serial_and_batch_bundle)
@@ -826,6 +871,10 @@ class TestPOSInvoice(unittest.TestCase):
pos_inv1 = create_pos_invoice(
item=item.name, rate=300, qty=1, do_not_submit=1, batch_no="TestBatch 01"
)
pos_inv1.append(
"payments",
{"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 300},
)
pos_inv1.save()
pos_inv1.submit()

View File

@@ -8,11 +8,14 @@ import frappe
from frappe import _
from frappe.model.document import Document
from frappe.model.mapper import map_child_doc, map_doc
from frappe.query_builder import DocType
from frappe.utils import cint, flt, get_time, getdate, nowdate, nowtime
from frappe.utils.background_jobs import enqueue, is_job_enqueued
from frappe.utils.scheduler import is_scheduler_inactive
from erpnext.accounts.doctype.pos_profile.pos_profile import required_accounting_dimensions
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import (
get_checks_for_pl_and_bs_accounts,
)
class POSInvoiceMergeLog(Document):
@@ -116,17 +119,18 @@ class POSInvoiceMergeLog(Document):
returns = [d for d in pos_invoice_docs if d.get("is_return") == 1]
sales = [d for d in pos_invoice_docs if d.get("is_return") == 0]
sales_invoice, credit_note = "", ""
sales_invoice, credit_notes = "", {}
sales_invoice_doc = None
if sales:
sales_invoice_doc = self.process_merging_into_sales_invoice(sales)
sales_invoice = sales_invoice_doc.name
if returns:
credit_note = self.process_merging_into_credit_note(returns, sales_invoice_doc)
distinguished_returns = self.distinguish_return_pos_invoices(returns, sales_invoice_doc)
credit_notes = self.process_merging_into_credit_notes(distinguished_returns)
self.save() # save consolidated_sales_invoice & consolidated_credit_note ref in merge log
self.update_pos_invoices(pos_invoice_docs, sales_invoice, credit_note)
self.update_pos_invoices(pos_invoice_docs, sales_invoice, credit_notes)
def on_cancel(self):
pos_invoice_docs = [frappe.get_cached_doc("POS Invoice", d.pos_invoice) for d in self.pos_invoices]
@@ -156,34 +160,50 @@ class POSInvoiceMergeLog(Document):
return sales_invoice
def process_merging_into_credit_note(self, data, sales_invoice_doc=None):
credit_note = self.get_new_sales_invoice()
credit_note.is_return = 1
def process_merging_into_credit_notes(self, data):
credit_notes = {}
for key, value in data.items():
if not value:
continue
credit_note = self.merge_pos_invoice_into(credit_note, data)
referenes = {}
credit_note = self.get_new_sales_invoice()
credit_note.is_return = 1
if sales_invoice_doc:
credit_note.return_against = sales_invoice_doc.name
credit_note = self.merge_pos_invoice_into(credit_note, value)
credit_note.return_against = key
for d in sales_invoice_doc.items:
referenes[d.item_code] = d.name
credit_note.is_consolidated = 1
credit_note.set_posting_time = 1
credit_note.posting_date = getdate(self.posting_date)
credit_note.posting_time = get_time(self.posting_time)
# TODO: return could be against multiple sales invoice which could also have been consolidated?
# credit_note.return_against = self.consolidated_invoice
credit_note.save()
credit_note.submit()
for d in credit_note.items:
d.sales_invoice_item = referenes.get(d.item_code)
self.consolidated_credit_note = credit_note.name
credit_notes[credit_note.name] = [d.name for d in value]
credit_note.is_consolidated = 1
credit_note.set_posting_time = 1
credit_note.posting_date = getdate(self.posting_date)
credit_note.posting_time = get_time(self.posting_time)
# TODO: return could be against multiple sales invoice which could also have been consolidated?
# credit_note.return_against = self.consolidated_invoice
credit_note.save()
credit_note.submit()
return credit_notes
self.consolidated_credit_note = credit_note.name
def distinguish_return_pos_invoices(self, data, sales_invoice_doc=None):
return_invoices = {}
return credit_note.name
return_invoices[sales_invoice_doc.name if sales_invoice_doc else None] = []
for doc in data:
sales_invoices_of_return_against = frappe.db.get_value(
"POS Invoice", doc.return_against, "consolidated_invoice"
)
if sales_invoices_of_return_against:
if sales_invoices_of_return_against in return_invoices:
return_invoices[sales_invoices_of_return_against].append(doc)
else:
return_invoices[sales_invoices_of_return_against] = [doc]
else:
return_invoices[sales_invoice_doc.name if sales_invoice_doc else None].append(doc)
return return_invoices
def merge_pos_invoice_into(self, invoice, data):
items, payments, taxes = [], [], []
@@ -209,33 +229,20 @@ class POSInvoiceMergeLog(Document):
loyalty_amount_sum += doc.loyalty_amount
for item in doc.get("items"):
found = False
for i in items:
if (
i.item_code == item.item_code
and not i.serial_and_batch_bundle
and not i.serial_no
and not i.batch_no
and i.uom == item.uom
and i.net_rate == item.net_rate
and i.warehouse == item.warehouse
):
found = True
i.qty = i.qty + item.qty
i.amount = i.amount + item.net_amount
i.net_amount = i.amount
i.base_amount = i.base_amount + item.base_net_amount
i.base_net_amount = i.base_amount
if not found:
item.rate = item.net_rate
item.amount = item.net_amount
item.base_amount = item.base_net_amount
item.price_list_rate = 0
si_item = map_child_doc(item, invoice, {"doctype": "Sales Invoice Item"})
if item.serial_and_batch_bundle:
si_item.serial_and_batch_bundle = item.serial_and_batch_bundle
items.append(si_item)
item.rate = item.net_rate
item.amount = item.net_amount
item.base_amount = item.base_net_amount
item.price_list_rate = 0
si_item = map_child_doc(item, invoice, {"doctype": "Sales Invoice Item"})
si_item.pos_invoice = doc.name
si_item.pos_invoice_item = item.name
if doc.is_return:
si_item.sales_invoice_item = get_sales_invoice_item(
doc.return_against, item.pos_invoice_item
)
if item.serial_and_batch_bundle:
si_item.serial_and_batch_bundle = item.serial_and_batch_bundle
items.append(si_item)
for tax in doc.get("taxes"):
found = False
@@ -292,22 +299,23 @@ class POSInvoiceMergeLog(Document):
invoice.disable_rounded_total = cint(
frappe.db.get_value("POS Profile", invoice.pos_profile, "disable_rounded_total")
)
accounting_dimensions = required_accounting_dimensions()
accounting_dimensions = get_checks_for_pl_and_bs_accounts()
accounting_dimensions_fields = [d.fieldname for d in accounting_dimensions]
dimension_values = frappe.db.get_value(
"POS Profile", {"name": invoice.pos_profile}, accounting_dimensions, as_dict=1
"POS Profile", {"name": invoice.pos_profile}, accounting_dimensions_fields, as_dict=1
)
for dimension in accounting_dimensions:
dimension_value = dimension_values.get(dimension)
dimension_value = dimension_values.get(dimension.fieldname)
if not dimension_value:
if not dimension_value and (dimension.mandatory_for_pl or dimension.mandatory_for_bs):
frappe.throw(
_("Please set Accounting Dimension {} in {}").format(
frappe.bold(frappe.unscrub(dimension)),
frappe.bold(dimension.label),
frappe.get_desk_link("POS Profile", invoice.pos_profile),
)
)
invoice.set(dimension, dimension_value)
invoice.set(dimension.fieldname, dimension_value)
if self.merge_invoices_based_on == "Customer Group":
invoice.flags.ignore_pos_profile = True
@@ -324,16 +332,16 @@ class POSInvoiceMergeLog(Document):
return sales_invoice
def update_pos_invoices(self, invoice_docs, sales_invoice="", credit_note=""):
def update_pos_invoices(self, invoice_docs, sales_invoice="", credit_notes=None):
for doc in invoice_docs:
doc.load_from_db()
doc.update(
{
"consolidated_invoice": None
if self.docstatus == 2
else (credit_note if doc.is_return else sales_invoice)
}
)
inv = sales_invoice
if doc.is_return:
for key, value in credit_notes.items():
if doc.name in value:
inv = key
break
doc.update({"consolidated_invoice": None if self.docstatus == 2 else inv})
doc.set_status(update=True)
doc.save()
@@ -625,3 +633,26 @@ def get_error_message(message) -> str:
return message["message"]
except Exception:
return str(message)
def get_sales_invoice_item(return_against_pos_invoice, pos_invoice_item):
try:
SalesInvoice = DocType("Sales Invoice")
SalesInvoiceItem = DocType("Sales Invoice Item")
query = (
frappe.qb.from_(SalesInvoice)
.from_(SalesInvoiceItem)
.select(SalesInvoiceItem.name)
.where(
(SalesInvoice.name == SalesInvoiceItem.parent)
& (SalesInvoice.is_return == 0)
& (SalesInvoiceItem.pos_invoice == return_against_pos_invoice)
& (SalesInvoiceItem.pos_invoice_item == pos_invoice_item)
)
)
result = query.run(as_dict=True)
return result[0].name if result else None
except Exception:
return None

View File

@@ -28,14 +28,17 @@ class TestPOSInvoiceMergeLog(unittest.TestCase):
pos_inv = create_pos_invoice(rate=300, do_not_submit=1)
pos_inv.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 300})
pos_inv.save()
pos_inv.submit()
pos_inv2 = create_pos_invoice(rate=3200, do_not_submit=1)
pos_inv2.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 3200})
pos_inv2.save()
pos_inv2.submit()
pos_inv3 = create_pos_invoice(customer="_Test Customer 2", rate=2300, do_not_submit=1)
pos_inv3.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 2300})
pos_inv3.save()
pos_inv3.submit()
consolidate_pos_invoices()
@@ -61,14 +64,17 @@ class TestPOSInvoiceMergeLog(unittest.TestCase):
pos_inv = create_pos_invoice(rate=300, do_not_submit=1)
pos_inv.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 300})
pos_inv.save()
pos_inv.submit()
pos_inv2 = create_pos_invoice(rate=3200, do_not_submit=1)
pos_inv2.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 3200})
pos_inv2.save()
pos_inv2.submit()
pos_inv3 = create_pos_invoice(customer="_Test Customer 2", rate=2300, do_not_submit=1)
pos_inv3.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 2300})
pos_inv3.save()
pos_inv3.submit()
pos_inv_cn = make_sales_return(pos_inv.name)
@@ -122,6 +128,8 @@ class TestPOSInvoiceMergeLog(unittest.TestCase):
},
)
inv.insert()
inv.payments[0].amount = inv.grand_total
inv.save()
inv.submit()
inv2 = create_pos_invoice(qty=1, rate=100, do_not_save=True)
@@ -138,6 +146,8 @@ class TestPOSInvoiceMergeLog(unittest.TestCase):
},
)
inv2.insert()
inv2.payments[0].amount = inv.grand_total
inv2.save()
inv2.submit()
consolidate_pos_invoices()
@@ -272,7 +282,7 @@ class TestPOSInvoiceMergeLog(unittest.TestCase):
inv2.submit()
inv3 = create_pos_invoice(qty=3, rate=600, do_not_save=True)
inv3.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 1000})
inv3.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 1800})
inv3.insert()
inv3.submit()
@@ -280,8 +290,8 @@ class TestPOSInvoiceMergeLog(unittest.TestCase):
inv.load_from_db()
consolidated_invoice = frappe.get_doc("Sales Invoice", inv.consolidated_invoice)
self.assertEqual(consolidated_invoice.outstanding_amount, 800)
self.assertNotEqual(consolidated_invoice.status, "Paid")
self.assertNotEqual(consolidated_invoice.outstanding_amount, 800)
self.assertEqual(consolidated_invoice.status, "Paid")
finally:
frappe.set_user("Administrator")
@@ -416,6 +426,7 @@ class TestPOSInvoiceMergeLog(unittest.TestCase):
do_not_submit=1,
)
pos_inv.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 100})
pos_inv.save()
pos_inv.submit()
pos_inv_cn = make_sales_return(pos_inv.name)
@@ -430,6 +441,7 @@ class TestPOSInvoiceMergeLog(unittest.TestCase):
do_not_submit=1,
)
pos_inv2.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 100})
pos_inv2.save()
pos_inv2.submit()
consolidate_pos_invoices()

View File

@@ -23,11 +23,13 @@
"hide_unavailable_items",
"auto_add_item_to_cart",
"validate_stock_on_save",
"print_receipt_on_order_complete",
"column_break_16",
"update_stock",
"ignore_pricing_rule",
"allow_rate_change",
"allow_discount_change",
"disable_grand_total_to_default_mop",
"section_break_23",
"item_groups",
"column_break_25",
@@ -375,6 +377,18 @@
"fieldname": "disable_rounded_total",
"fieldtype": "Check",
"label": "Disable Rounded Total"
},
{
"default": "0",
"fieldname": "print_receipt_on_order_complete",
"fieldtype": "Check",
"label": "Print Receipt on Order Complete"
},
{
"default": "0",
"fieldname": "disable_grand_total_to_default_mop",
"fieldtype": "Check",
"label": "Disable auto setting Grand Total to default Payment Mode"
}
],
"icon": "icon-cog",
@@ -402,7 +416,7 @@
"link_fieldname": "pos_profile"
}
],
"modified": "2022-08-10 12:57:06.241439",
"modified": "2025-01-29 13:12:30.796630",
"modified_by": "Administrator",
"module": "Accounts",
"name": "POS Profile",

View File

@@ -4,9 +4,14 @@
import frappe
from frappe import _, msgprint, scrub, unscrub
from frappe.core.doctype.user_permission.user_permission import get_permitted_documents
from frappe.model.document import Document
from frappe.utils import get_link_to_form, now
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import (
get_checks_for_pl_and_bs_accounts,
)
class POSProfile(Document):
# begin: auto-generated types
@@ -36,6 +41,7 @@ class POSProfile(Document):
currency: DF.Link
customer: DF.Link | None
customer_groups: DF.Table[POSCustomerGroup]
disable_grand_total_to_default_mop: DF.Check
disable_rounded_total: DF.Check
disabled: DF.Check
expense_account: DF.Link | None
@@ -47,6 +53,7 @@ class POSProfile(Document):
letter_head: DF.Link | None
payments: DF.Table[POSPaymentMethod]
print_format: DF.Link | None
print_receipt_on_order_complete: DF.Check
select_print_heading: DF.Link | None
selling_price_list: DF.Link | None
tax_category: DF.Link | None
@@ -68,15 +75,19 @@ class POSProfile(Document):
self.validate_accounting_dimensions()
def validate_accounting_dimensions(self):
acc_dim_names = required_accounting_dimensions()
for acc_dim in acc_dim_names:
if not self.get(acc_dim):
acc_dims = get_checks_for_pl_and_bs_accounts()
for acc_dim in acc_dims:
if (
self.company == acc_dim.company
and not self.get(acc_dim.fieldname)
and (acc_dim.mandatory_for_pl or acc_dim.mandatory_for_bs)
):
frappe.throw(
_(
"{0} is a mandatory Accounting Dimension. <br>"
"Please set a value for {0} in Accounting Dimensions section."
).format(
unscrub(frappe.bold(acc_dim)),
frappe.bold(acc_dim.label),
),
title=_("Mandatory Accounting Dimension"),
)
@@ -194,17 +205,41 @@ class POSProfile(Document):
def get_item_groups(pos_profile):
item_groups = []
pos_profile = frappe.get_cached_doc("POS Profile", pos_profile)
permitted_item_groups = get_permitted_nodes("Item Group")
if pos_profile.get("item_groups"):
# Get items based on the item groups defined in the POS profile
for data in pos_profile.get("item_groups"):
item_groups.extend(
["%s" % frappe.db.escape(d.name) for d in get_child_nodes("Item Group", data.item_group)]
[
"%s" % frappe.db.escape(d.name)
for d in get_child_nodes("Item Group", data.item_group)
if not permitted_item_groups or d.name in permitted_item_groups
]
)
if not item_groups and permitted_item_groups:
item_groups = ["%s" % frappe.db.escape(d) for d in permitted_item_groups]
return list(set(item_groups))
def get_permitted_nodes(group_type):
nodes = []
permitted_nodes = get_permitted_documents(group_type)
if not permitted_nodes:
return nodes
for node in permitted_nodes:
if frappe.db.get_value(group_type, node, "is_group"):
nodes.extend([d.name for d in get_child_nodes(group_type, node)])
else:
nodes.append(node)
return nodes
def get_child_nodes(group_type, root):
lft, rgt = frappe.db.get_value(group_type, root, ["lft", "rgt"])
return frappe.db.sql(
@@ -214,23 +249,6 @@ def get_child_nodes(group_type, root):
)
def required_accounting_dimensions():
p = frappe.qb.DocType("Accounting Dimension")
c = frappe.qb.DocType("Accounting Dimension Detail")
acc_dim_doc = (
frappe.qb.from_(p)
.inner_join(c)
.on(p.name == c.parent)
.select(c.parent)
.where((c.mandatory_for_bs == 1) | (c.mandatory_for_pl == 1))
.where(p.disabled == 0)
).run(as_dict=1)
acc_dim_names = [scrub(d.parent) for d in acc_dim_doc]
return acc_dim_names
@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
def pos_profile_query(doctype, txt, searchfield, start, page_len, filters):

View File

@@ -53,6 +53,7 @@
"column_break_42",
"free_item_uom",
"round_free_qty",
"dont_enforce_free_item_qty",
"is_recursive",
"recurse_for",
"apply_recursion_over",
@@ -643,12 +644,19 @@
"fieldname": "has_priority",
"fieldtype": "Check",
"label": "Has Priority"
},
{
"default": "0",
"depends_on": "eval:doc.price_or_product_discount == 'Product'",
"fieldname": "dont_enforce_free_item_qty",
"fieldtype": "Check",
"label": "Don't Enforce Free Item Qty"
}
],
"icon": "fa fa-gift",
"idx": 1,
"links": [],
"modified": "2024-09-16 18:14:51.314765",
"modified": "2025-02-17 18:15:39.824639",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Pricing Rule",

View File

@@ -60,6 +60,7 @@ class PricingRule(Document):
disable: DF.Check
discount_amount: DF.Currency
discount_percentage: DF.Float
dont_enforce_free_item_qty: DF.Check
for_price_list: DF.Link | None
free_item: DF.Link | None
free_item_rate: DF.Currency
@@ -415,8 +416,6 @@ def get_pricing_rule_for_item(args, doc=None, for_validate=False):
"parent": args.parent,
"parenttype": args.parenttype,
"child_docname": args.get("child_docname"),
"discount_percentage": 0.0,
"discount_amount": 0,
}
)
@@ -455,8 +454,7 @@ def get_pricing_rule_for_item(args, doc=None, for_validate=False):
if pricing_rule.coupon_code_based == 1:
if not args.coupon_code:
return item_details
continue
coupon_code = frappe.db.get_value(
doctype="Coupon Code", filters={"pricing_rule": pricing_rule.name}, fieldname="name"
)
@@ -647,7 +645,7 @@ def remove_pricing_rule_for_item(pricing_rules, item_details, item_code=None, ra
if pricing_rule.margin_type in ["Percentage", "Amount"]:
item_details.margin_rate_or_amount = 0.0
item_details.margin_type = None
elif pricing_rule.get("free_item"):
elif pricing_rule.get("free_item") and not pricing_rule.get("dont_enforce_free_item_qty"):
item_details.remove_free_item = (
item_code if pricing_rule.get("same_item") else pricing_rule.get("free_item")
)

View File

@@ -428,6 +428,54 @@ class TestPricingRule(FrappeTestCase):
self.assertEqual(so.items[1].is_free_item, 1)
self.assertEqual(so.items[1].item_code, "_Test Item 2")
def test_dont_enforce_free_item_qty(self):
# this test is only for testing non-enforcement as all other tests in this file already test with enforcement
frappe.delete_doc_if_exists("Pricing Rule", "_Test Pricing Rule")
test_record = {
"doctype": "Pricing Rule",
"title": "_Test Pricing Rule",
"apply_on": "Item Code",
"currency": "USD",
"items": [
{
"item_code": "_Test Item",
}
],
"selling": 1,
"rate_or_discount": "Discount Percentage",
"rate": 0,
"min_qty": 0,
"max_qty": 7,
"discount_percentage": 17.5,
"price_or_product_discount": "Product",
"same_item": 0,
"free_item": "_Test Item 2",
"free_qty": 1,
"company": "_Test Company",
}
pricing_rule = frappe.get_doc(test_record.copy()).insert()
# With enforcement
so = make_sales_order(item_code="_Test Item", qty=1, do_not_submit=True)
self.assertEqual(so.items[1].is_free_item, 1)
self.assertEqual(so.items[1].item_code, "_Test Item 2")
# Test 1 : Saving a document with an item with pricing list without it's corresponding free item will cause it the free item to be refetched on save
so.items.pop(1)
so.save()
so.reload()
self.assertEqual(len(so.items), 2)
# Without enforcement
pricing_rule.dont_enforce_free_item_qty = 1
pricing_rule.save()
# Test 2 : Deleted free item will not be fetched again on save without enforcement
so.items.pop(1)
so.save()
so.reload()
self.assertEqual(len(so.items), 1)
def test_cumulative_pricing_rule(self):
frappe.delete_doc_if_exists("Pricing Rule", "_Test Cumulative Pricing Rule")
test_record = {
@@ -1451,6 +1499,7 @@ def make_pricing_rule(**args):
"discount_amount": args.discount_amount or 0.0,
"apply_multiple_pricing_rules": args.apply_multiple_pricing_rules or 0,
"has_priority": args.has_priority or 0,
"enforce_free_item_qty": args.dont_enforce_free_item_qty or 0,
}
)

View File

@@ -713,7 +713,10 @@ def apply_pricing_rule_for_free_items(doc, pricing_rule_args):
args.pop((item.item_code, item.pricing_rules))
for free_item in args.values():
doc.append("items", free_item)
if doc.is_new() or not frappe.get_value(
"Pricing Rule", free_item["pricing_rules"], "dont_enforce_free_item_qty"
):
doc.append("items", free_item)
def get_pricing_rule_items(pr_doc, other_items=False) -> list:

View File

@@ -20,6 +20,7 @@
"is_advance",
"section_break_5",
"difference_amount",
"gain_loss_posting_date",
"column_break_7",
"difference_account",
"exchange_rate",
@@ -153,11 +154,16 @@
"fieldtype": "Check",
"in_list_view": 1,
"label": "Reconciled"
},
{
"fieldname": "gain_loss_posting_date",
"fieldtype": "Date",
"label": "Difference Posting Date"
}
],
"istable": 1,
"links": [],
"modified": "2023-03-20 21:05:43.121945",
"modified": "2025-01-23 16:09:01.058574",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Process Payment Reconciliation Log Allocations",
@@ -167,4 +173,4 @@
"sort_order": "DESC",
"states": [],
"track_changes": 1
}
}

View File

@@ -20,6 +20,7 @@ class ProcessPaymentReconciliationLogAllocations(Document):
difference_account: DF.Link | None
difference_amount: DF.Currency
exchange_rate: DF.Float
gain_loss_posting_date: DF.Date | None
invoice_number: DF.DynamicLink
invoice_type: DF.Link
is_advance: DF.Data | None

View File

@@ -236,17 +236,21 @@ def get_ar_filters(doc, entry):
def get_html(doc, filters, entry, col, res, ageing):
base_template_path = "frappe/www/printview.html"
template_path = (
"erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.html"
if doc.report == "General Ledger"
else "erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts_accounts_receivable.html"
)
template_path = "erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts_accounts_receivable.html"
if doc.report == "General Ledger":
template_path = (
"erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.html"
)
process_soa_html = frappe.get_hooks("process_soa_html")
# fetching custom print format for Process Statement of Accounts
if process_soa_html and process_soa_html.get(doc.report):
template_path = process_soa_html[doc.report][-1]
if doc.letter_head:
from frappe.www.printview import get_letter_head
letter_head = get_letter_head(doc, 0)
html = frappe.render_template(
template_path,
{
@@ -262,7 +266,6 @@ def get_html(doc, filters, entry, col, res, ageing):
else None,
},
)
html = frappe.render_template(
base_template_path,
{"body": html, "css": get_print_style(), "title": "Statement For " + entry.customer},
@@ -321,9 +324,12 @@ def get_recipients_and_cc(customer, doc):
recipients = []
for clist in doc.customers:
if clist.customer == customer:
recipients.append(clist.billing_email)
if clist.billing_email:
for email in clist.billing_email.split(","):
recipients.append(email.strip())
if doc.primary_mandatory and clist.primary_email:
recipients.append(clist.primary_email)
for email in clist.primary_email.split(","):
recipients.append(email.strip())
cc = []
if doc.cc_to != "":
try:

View File

@@ -332,6 +332,8 @@ erpnext.accounts.PurchaseInvoice = class PurchaseInvoice extends erpnext.buying.
if (this.frm.doc.__onload && this.frm.doc.__onload.load_after_mapping) return;
let payment_terms_template = this.frm.doc.payment_terms_template;
erpnext.utils.get_party_details(
this.frm,
"erpnext.accounts.party.get_party_details",
@@ -352,6 +354,12 @@ erpnext.accounts.PurchaseInvoice = class PurchaseInvoice extends erpnext.buying.
me.frm.doc.tax_withholding_category = me.frm.supplier_tds;
me.frm.set_df_property("apply_tds", "read_only", me.frm.supplier_tds ? 0 : 1);
me.frm.set_df_property("tax_withholding_category", "hidden", me.frm.supplier_tds ? 0 : 1);
// while duplicating, don't change payment terms
if (me.frm.doc.__run_link_triggers === false) {
me.frm.set_value("payment_terms_template", payment_terms_template);
me.frm.refresh_field("payment_terms_template");
}
}
);
}
@@ -368,6 +376,18 @@ erpnext.accounts.PurchaseInvoice = class PurchaseInvoice extends erpnext.buying.
}
}
tax_withholding_category(frm) {
var me = this;
let filtered_taxes = (me.frm.doc.taxes || []).filter((row) => !row.is_tax_withholding_account);
me.frm.clear_table("taxes");
filtered_taxes.forEach((row) => {
me.frm.add_child("taxes", row);
});
me.frm.refresh_field("taxes");
}
credit_to() {
var me = this;
if (this.frm.doc.credit_to) {

View File

@@ -10,7 +10,6 @@ from frappe.utils import cint, cstr, flt, formatdate, get_link_to_form, getdate,
import erpnext
from erpnext.accounts.deferred_revenue import validate_service_stop_date
from erpnext.accounts.doctype.gl_entry.gl_entry import update_outstanding_amt
from erpnext.accounts.doctype.repost_accounting_ledger.repost_accounting_ledger import (
validate_docs_for_deferred_accounting,
validate_docs_for_voucher_types,
@@ -33,7 +32,7 @@ from erpnext.accounts.general_ledger import (
merge_similar_entries,
)
from erpnext.accounts.party import get_due_date, get_party_account
from erpnext.accounts.utils import get_account_currency, get_fiscal_year
from erpnext.accounts.utils import get_account_currency, get_fiscal_year, update_voucher_outstanding
from erpnext.assets.doctype.asset.asset import is_cwip_accounting_enabled
from erpnext.assets.doctype.asset_category.asset_category import get_asset_category_account
from erpnext.buying.utils import check_on_hold_or_closed_status
@@ -838,12 +837,12 @@ class PurchaseInvoice(BuyingController):
def update_supplier_outstanding(self, update_outstanding):
if update_outstanding == "No":
update_outstanding_amt(
self.credit_to,
"Supplier",
self.supplier,
self.doctype,
self.return_against if cint(self.is_return) and self.return_against else self.name,
update_voucher_outstanding(
voucher_type=self.doctype,
voucher_no=self.return_against if cint(self.is_return) and self.return_against else self.name,
account=self.credit_to,
party_type="Supplier",
party=self.supplier,
)
def get_gl_entries(self, warehouse_account=None):
@@ -872,6 +871,7 @@ class PurchaseInvoice(BuyingController):
self.make_payment_gl_entries(gl_entries)
self.make_write_off_gl_entry(gl_entries)
self.make_gle_for_rounding_adjustment(gl_entries)
self.set_transaction_currency_and_rate_in_gl_map(gl_entries)
return gl_entries
def check_asset_cwip_enabled(self):
@@ -917,6 +917,7 @@ class PurchaseInvoice(BuyingController):
"credit_in_account_currency": base_grand_total
if self.party_account_currency == self.company_currency
else grand_total,
"credit_in_transaction_currency": grand_total,
"against_voucher": against_voucher,
"against_voucher_type": self.doctype,
"project": self.project,
@@ -952,7 +953,7 @@ class PurchaseInvoice(BuyingController):
valuation_tax_accounts = [
d.account_head
for d in self.get("taxes")
if d.category in ("Valuation", "Total and Valuation")
if d.category in ("Valuation", "Valuation and Total")
and flt(d.base_tax_amount_after_discount_amount)
]
@@ -968,7 +969,6 @@ class PurchaseInvoice(BuyingController):
for item in self.get("items"):
if flt(item.base_net_amount):
account_currency = get_account_currency(item.expense_account)
if item.item_code:
frappe.get_cached_value("Item", item.item_code, "asset_category")
@@ -977,6 +977,7 @@ class PurchaseInvoice(BuyingController):
and self.auto_accounting_for_stock
and (item.item_code in stock_items or item.is_fixed_asset)
):
account_currency = get_account_currency(item.expense_account)
# warehouse account
warehouse_debit_amount = self.make_stock_adjustment_entry(
gl_entries, item, voucher_wise_stock_value, account_currency
@@ -992,6 +993,7 @@ class PurchaseInvoice(BuyingController):
"project": item.project or self.project,
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
"debit": warehouse_debit_amount,
"debit_in_transaction_currency": item.net_amount,
},
warehouse_account[item.warehouse]["account_currency"],
item=item,
@@ -1012,6 +1014,7 @@ class PurchaseInvoice(BuyingController):
"project": item.project or self.project,
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
"debit": -1 * flt(credit_amount, item.precision("base_net_amount")),
"debit_in_transaction_currency": item.net_amount,
},
warehouse_account[item.from_warehouse]["account_currency"],
item=item,
@@ -1026,6 +1029,7 @@ class PurchaseInvoice(BuyingController):
"account": item.expense_account,
"against": self.supplier,
"debit": flt(item.base_net_amount, item.precision("base_net_amount")),
"debit_in_transaction_currency": item.net_amount,
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
"cost_center": item.cost_center,
"project": item.project,
@@ -1043,6 +1047,10 @@ class PurchaseInvoice(BuyingController):
"account": item.expense_account,
"against": self.supplier,
"debit": warehouse_debit_amount,
"debit_in_transaction_currency": flt(
warehouse_debit_amount / self.conversion_rate,
item.precision("net_amount"),
),
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
"cost_center": item.cost_center,
"project": item.project or self.project,
@@ -1055,7 +1063,9 @@ class PurchaseInvoice(BuyingController):
# Amount added through landed-cost-voucher
if landed_cost_entries:
if (item.item_code, item.name) in landed_cost_entries:
for account, amount in landed_cost_entries[(item.item_code, item.name)].items():
for account, base_amount in landed_cost_entries[
(item.item_code, item.name)
].items():
gl_entries.append(
self.get_gl_dict(
{
@@ -1063,8 +1073,9 @@ class PurchaseInvoice(BuyingController):
"against": item.expense_account,
"cost_center": item.cost_center,
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
"credit": flt(amount["base_amount"]),
"credit_in_account_currency": flt(amount["amount"]),
"credit": flt(base_amount["base_amount"]),
"credit_in_account_currency": flt(base_amount["amount"]),
"credit_in_transaction_currency": item.net_amount,
"project": item.project or self.project,
},
item=item,
@@ -1087,6 +1098,7 @@ class PurchaseInvoice(BuyingController):
"project": item.project or self.project,
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
"credit": flt(item.rm_supp_cost),
"credit_in_transaction_currency": item.net_amount,
},
warehouse_account[self.supplier_warehouse]["account_currency"],
item=item,
@@ -1100,7 +1112,8 @@ class PurchaseInvoice(BuyingController):
else item.deferred_expense_account
)
dummy, amount = self.get_amount_and_base_amount(item, None)
account_currency = get_account_currency(expense_account)
amount, base_amount = self.get_amount_and_base_amount(item, None)
if provisional_accounting_for_non_stock_items:
self.make_provisional_gl_entry(gl_entries, item)
@@ -1111,7 +1124,8 @@ class PurchaseInvoice(BuyingController):
{
"account": expense_account,
"against": self.supplier,
"debit": amount,
"debit": base_amount,
"debit_in_transaction_currency": amount,
"cost_center": item.cost_center,
"project": item.project or self.project,
},
@@ -1126,6 +1140,7 @@ class PurchaseInvoice(BuyingController):
exchange_rate_map[item.purchase_receipt]
and self.conversion_rate != exchange_rate_map[item.purchase_receipt]
and item.net_rate == net_rate_map[item.pr_detail]
and item.item_code in stock_items
):
discrepancy_caused_by_exchange_rate_difference = (
item.qty * item.net_rate
@@ -1184,6 +1199,10 @@ class PurchaseInvoice(BuyingController):
"account": stock_rbnb,
"against": self.supplier,
"debit": flt(item.item_tax_amount, item.precision("item_tax_amount")),
"debit_in_transaction_currency": flt(
item.item_tax_amount / self.conversion_rate,
item.precision("item_tax_amount"),
),
"remarks": self.remarks or _("Accounting Entry for Stock"),
"cost_center": self.cost_center,
"project": item.project or self.project,
@@ -1299,6 +1318,7 @@ class PurchaseInvoice(BuyingController):
"account": cost_of_goods_sold_account,
"against": item.expense_account,
"debit": stock_adjustment_amt,
"debit_in_transaction_currency": stock_adjustment_amt / self.conversion_rate,
"remarks": self.get("remarks") or _("Stock Adjustment"),
"cost_center": item.cost_center,
"project": item.project or self.project,
@@ -1310,6 +1330,38 @@ class PurchaseInvoice(BuyingController):
warehouse_debit_amount = stock_amount
elif self.is_return and self.update_stock and self.is_internal_supplier and warehouse_debit_amount:
net_rate = item.base_net_amount
if item.sales_incoming_rate: # for internal transfer
net_rate = item.qty * item.sales_incoming_rate
stock_amount = (
net_rate
+ item.item_tax_amount
+ flt(item.landed_cost_voucher_amount)
+ flt(item.get("amount_difference_with_purchase_invoice"))
)
if flt(stock_amount, net_amt_precision) != flt(warehouse_debit_amount, net_amt_precision):
cost_of_goods_sold_account = self.get_company_default("default_expense_account")
stock_adjustment_amt = stock_amount - warehouse_debit_amount
gl_entries.append(
self.get_gl_dict(
{
"account": cost_of_goods_sold_account,
"against": item.expense_account,
"debit": stock_adjustment_amt,
"debit_in_transaction_currency": stock_adjustment_amt / self.conversion_rate,
"remarks": self.get("remarks") or _("Stock Adjustment"),
"cost_center": item.cost_center,
"project": item.project or self.project,
},
account_currency,
item=item,
)
)
return warehouse_debit_amount
def make_tax_gl_entries(self, gl_entries):
@@ -1332,6 +1384,7 @@ class PurchaseInvoice(BuyingController):
dr_or_cr + "_in_account_currency": base_amount
if account_currency == self.company_currency
else amount,
dr_or_cr + "_in_transaction_currency": amount,
"cost_center": tax.cost_center,
},
account_currency,
@@ -1378,6 +1431,10 @@ class PurchaseInvoice(BuyingController):
"cost_center": tax.cost_center,
"against": self.supplier,
"credit": applicable_amount,
"credit_in_transaction_currency": flt(
applicable_amount / self.conversion_rate,
frappe.get_precision("Purchase Invoice Item", "item_tax_amount"),
),
"remarks": self.remarks or _("Accounting Entry for Stock"),
},
item=tax,
@@ -1396,6 +1453,10 @@ class PurchaseInvoice(BuyingController):
"cost_center": tax.cost_center,
"against": self.supplier,
"credit": valuation_tax[tax.name],
"credit_in_transaction_currency": flt(
valuation_tax[tax.name] / self.conversion_rate,
frappe.get_precision("Purchase Invoice Item", "item_tax_amount"),
),
"remarks": self.remarks or _("Accounting Entry for Stock"),
},
item=tax,
@@ -1411,6 +1472,7 @@ class PurchaseInvoice(BuyingController):
"account": self.unrealized_profit_loss_account,
"against": self.supplier,
"credit": flt(self.total_taxes_and_charges),
"credit_in_transaction_currency": flt(self.total_taxes_and_charges),
"credit_in_account_currency": flt(self.base_total_taxes_and_charges),
"cost_center": self.cost_center,
},
@@ -1460,6 +1522,7 @@ class PurchaseInvoice(BuyingController):
"debit_in_account_currency": self.base_paid_amount
if self.party_account_currency == self.company_currency
else self.paid_amount,
"debit_in_transaction_currency": self.paid_amount,
"against_voucher": self.return_against
if cint(self.is_return) and self.return_against
else self.name,
@@ -1481,6 +1544,7 @@ class PurchaseInvoice(BuyingController):
"credit_in_account_currency": self.base_paid_amount
if bank_account_currency == self.company_currency
else self.paid_amount,
"credit_in_transaction_currency": self.paid_amount,
"cost_center": self.cost_center,
},
bank_account_currency,
@@ -1505,6 +1569,7 @@ class PurchaseInvoice(BuyingController):
"debit_in_account_currency": self.base_write_off_amount
if self.party_account_currency == self.company_currency
else self.write_off_amount,
"debit_in_transaction_currency": self.write_off_amount,
"against_voucher": self.return_against
if cint(self.is_return) and self.return_against
else self.name,
@@ -1525,6 +1590,7 @@ class PurchaseInvoice(BuyingController):
"credit_in_account_currency": self.base_write_off_amount
if write_off_account_currency == self.company_currency
else self.write_off_amount,
"credit_in_transaction_currency": self.write_off_amount,
"cost_center": self.cost_center or self.write_off_cost_center,
},
item=self,
@@ -1796,13 +1862,13 @@ class PurchaseInvoice(BuyingController):
self.remove(d)
## Add pending vouchers on which tax was withheld
for voucher_no, voucher_details in voucher_wise_amount.items():
for row in voucher_wise_amount:
self.append(
"tax_withheld_vouchers",
{
"voucher_name": voucher_no,
"voucher_type": voucher_details.get("voucher_type"),
"taxable_amount": voucher_details.get("amount"),
"voucher_name": row.voucher_name,
"voucher_type": row.voucher_type,
"taxable_amount": row.taxable_amount,
},
)

View File

@@ -45,12 +45,16 @@ frappe.listview_settings["Purchase Invoice"] = {
},
onload: function (listview) {
listview.page.add_action_item(__("Purchase Receipt"), () => {
erpnext.bulk_transaction_processing.create(listview, "Purchase Invoice", "Purchase Receipt");
});
if (frappe.model.can_create("Purchase Receipt")) {
listview.page.add_action_item(__("Purchase Receipt"), () => {
erpnext.bulk_transaction_processing.create(listview, "Purchase Invoice", "Purchase Receipt");
});
}
listview.page.add_action_item(__("Payment"), () => {
erpnext.bulk_transaction_processing.create(listview, "Purchase Invoice", "Payment Entry");
});
if (frappe.model.can_create("Payment Entry")) {
listview.page.add_action_item(__("Payment"), () => {
erpnext.bulk_transaction_processing.create(listview, "Purchase Invoice", "Payment Entry");
});
}
},
};

View File

@@ -372,6 +372,53 @@ class TestPurchaseInvoice(FrappeTestCase, StockTestMixin):
self.assertEqual(discrepancy_caused_by_exchange_rate_diff, amount)
def test_purchase_invoice_with_exchange_rate_difference_for_non_stock_item(self):
from erpnext.stock.doctype.purchase_receipt.purchase_receipt import (
make_purchase_invoice as create_purchase_invoice,
)
# Creating Purchase Invoice with USD currency
pr = frappe.new_doc("Purchase Receipt")
pr.currency = "USD"
pr.company = "_Test Company with perpetual inventory"
pr.conversion_rate = (70,)
pr.supplier = "_Test Supplier USD"
pr.append(
"items",
{
"item_code": "_Test Non Stock Item",
"qty": 1,
"rate": 100,
},
)
pr.append(
"items",
{"item_code": "_Test Item", "qty": 1, "rate": 5, "warehouse": "Stores - TCP1"},
)
pr.insert()
pr.submit()
# Createing purchase invoice against Purchase Receipt
pi = create_purchase_invoice(pr.name)
pi.conversion_rate = 80
pi.credit_to = "_Test Payable USD - TCP1"
pi.insert()
pi.submit()
# Get exchnage gain and loss account
exchange_gain_loss_account = frappe.db.get_value("Company", pi.company, "exchange_gain_loss_account")
# fetching the latest GL Entry with exchange gain and loss account account
amount = frappe.db.get_value(
"GL Entry", {"account": exchange_gain_loss_account, "voucher_no": pi.name}, "debit"
)
discrepancy_caused_by_exchange_rate_diff = abs(
pi.items[1].base_net_amount - pr.items[1].base_net_amount
)
self.assertEqual(discrepancy_caused_by_exchange_rate_diff, amount)
def test_purchase_invoice_change_naming_series(self):
pi = frappe.copy_doc(test_records[1])
pi.insert()
@@ -2435,6 +2482,76 @@ class TestPurchaseInvoice(FrappeTestCase, StockTestMixin):
item.reload()
self.assertEqual(item.last_purchase_rate, 0)
def test_adjust_incoming_rate_from_pi_with_multi_currency_and_partial_billing(self):
frappe.db.set_single_value("Buying Settings", "maintain_same_rate", 0)
frappe.db.set_single_value("Buying Settings", "set_landed_cost_based_on_purchase_invoice_rate", 1)
pr = make_purchase_receipt(
qty=10, rate=10, currency="USD", do_not_save=1, supplier="_Test Supplier USD"
)
pr.conversion_rate = 5300
pr.save()
pr.submit()
incoming_rate = frappe.db.get_value(
"Stock Ledger Entry",
{"voucher_type": "Purchase Receipt", "voucher_no": pr.name},
"incoming_rate",
)
self.assertEqual(incoming_rate, 53000) # Asserting to confirm if the default calculation is correct
pi = create_purchase_invoice_from_receipt(pr.name)
for row in pi.items:
row.qty = 1
pi.save()
pi.submit()
incoming_rate = frappe.db.get_value(
"Stock Ledger Entry",
{"voucher_type": "Purchase Receipt", "voucher_no": pr.name},
"incoming_rate",
)
# Test 1 : Incoming rate should not change as only the qty has changed and not the rate (this was not the case before)
self.assertEqual(incoming_rate, 53000)
pi = create_purchase_invoice_from_receipt(pr.name)
for row in pi.items:
row.qty = 1
row.rate = 9
pi.save()
pi.submit()
incoming_rate = frappe.db.get_value(
"Stock Ledger Entry",
{"voucher_type": "Purchase Receipt", "voucher_no": pr.name},
"incoming_rate",
)
# Test 2 : Rate in new PI is lower than PR, so incoming rate should also be lower
self.assertEqual(incoming_rate, 50350)
pi = create_purchase_invoice_from_receipt(pr.name)
for row in pi.items:
row.qty = 1
row.rate = 12
pi.save()
pi.submit()
incoming_rate = frappe.db.get_value(
"Stock Ledger Entry",
{"voucher_type": "Purchase Receipt", "voucher_no": pr.name},
"incoming_rate",
)
# Test 3 : Rate in new PI is higher than PR, so incoming rate should also be higher
self.assertEqual(incoming_rate, 54766.667)
frappe.db.set_single_value("Buying Settings", "set_landed_cost_based_on_purchase_invoice_rate", 0)
frappe.db.set_single_value("Buying Settings", "maintain_same_rate", 1)
def test_opening_invoice_rounding_adjustment_validation(self):
pi = make_purchase_invoice(do_not_save=1)
pi.items[0].rate = 99.98
@@ -2522,6 +2639,50 @@ class TestPurchaseInvoice(FrappeTestCase, StockTestMixin):
"Buying Settings", "bill_for_rejected_quantity_in_purchase_invoice", original_value
)
def test_trx_currency_debit_credit_for_high_precision(self):
exc_rate = 0.737517516
pi = make_purchase_invoice(
currency="USD", conversion_rate=exc_rate, qty=1, rate=2000, do_not_save=True
)
pi.supplier = "_Test Supplier USD"
pi.save().submit()
expected = (
("_Test Account Cost for Goods Sold - _TC", 1475.04, 0.0, 2000.0, 0.0, "USD", exc_rate),
("_Test Payable USD - _TC", 0.0, 1475.04, 0.0, 2000.0, "USD", exc_rate),
)
actual = frappe.db.get_all(
"GL Entry",
filters={"voucher_no": pi.name},
fields=[
"account",
"debit",
"credit",
"debit_in_transaction_currency",
"credit_in_transaction_currency",
"transaction_currency",
"transaction_exchange_rate",
],
order_by="account",
as_list=1,
)
self.assertEqual(actual, expected)
def test_prevents_fully_returned_invoice_with_zero_quantity(self):
from erpnext.controllers.sales_and_purchase_return import StockOverReturnError, make_return_doc
invoice = make_purchase_invoice(qty=10)
return_doc = make_return_doc(invoice.doctype, invoice.name)
return_doc.items[0].qty = -10
return_doc.save().submit()
return_doc = make_return_doc(invoice.doctype, invoice.name)
return_doc.items[0].qty = 0
self.assertRaises(StockOverReturnError, return_doc.save)
def set_advance_flag(company, flag, default_account):
frappe.db.set_value(

View File

@@ -461,7 +461,8 @@
"depends_on": "eval:!doc.is_fixed_asset && doc.use_serial_batch_fields === 1 && parent.update_stock === 1",
"fieldname": "serial_no",
"fieldtype": "Text",
"label": "Serial No"
"label": "Serial No",
"no_copy": 1
},
{
"depends_on": "eval:!doc.is_fixed_asset && doc.use_serial_batch_fields === 1 && parent.update_stock === 1",
@@ -975,7 +976,7 @@
"idx": 1,
"istable": 1,
"links": [],
"modified": "2024-10-28 15:06:19.246141",
"modified": "2025-03-12 16:33:12.453290",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice Item",
@@ -985,4 +986,4 @@
"sort_field": "modified",
"sort_order": "DESC",
"states": []
}
}

View File

@@ -8,6 +8,8 @@ from frappe import _, qb
from frappe.model.document import Document
from frappe.utils.data import comma_and
from erpnext.stock import get_warehouse_account_map
class RepostAccountingLedger(Document):
# begin: auto-generated types
@@ -97,6 +99,9 @@ class RepostAccountingLedger(Document):
doc = frappe.get_doc(x.voucher_type, x.voucher_no)
if doc.doctype in ["Payment Entry", "Journal Entry"]:
gle_map = doc.build_gl_map()
elif doc.doctype == "Purchase Receipt":
warehouse_account_map = get_warehouse_account_map(doc.company)
gle_map = doc.get_gl_entries(warehouse_account_map)
else:
gle_map = doc.get_gl_entries()
@@ -177,6 +182,14 @@ def start_repost(account_repost_doc=str) -> None:
doc.force_set_against_expense_account()
doc.make_gl_entries()
elif doc.doctype == "Purchase Receipt":
if not repost_doc.delete_cancelled_entries:
doc.docstatus = 2
doc.make_gl_entries_on_cancel()
doc.docstatus = 1
doc.make_gl_entries(from_repost=True)
elif doc.doctype in ["Payment Entry", "Journal Entry", "Expense Claim"]:
if not repost_doc.delete_cancelled_entries:
doc.make_gl_entries(1)

View File

@@ -12,6 +12,8 @@ from erpnext.accounts.doctype.payment_request.payment_request import make_paymen
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
from erpnext.accounts.test.accounts_mixin import AccountsTestMixin
from erpnext.accounts.utils import get_fiscal_year
from erpnext.stock.doctype.item.test_item import make_item
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import get_gl_entries, make_purchase_receipt
class TestRepostAccountingLedger(AccountsTestMixin, FrappeTestCase):
@@ -204,9 +206,81 @@ class TestRepostAccountingLedger(AccountsTestMixin, FrappeTestCase):
self.assertIsNotNone(frappe.db.exists("GL Entry", {"voucher_no": si.name, "is_cancelled": 1}))
self.assertIsNotNone(frappe.db.exists("GL Entry", {"voucher_no": pe.name, "is_cancelled": 1}))
def test_06_repost_purchase_receipt(self):
from erpnext.accounts.doctype.account.test_account import create_account
provisional_account = create_account(
account_name="Provision Account",
parent_account="Current Liabilities - _TC",
company=self.company,
)
another_provisional_account = create_account(
account_name="Another Provision Account",
parent_account="Current Liabilities - _TC",
company=self.company,
)
company = frappe.get_doc("Company", self.company)
company.enable_provisional_accounting_for_non_stock_items = 1
company.default_provisional_account = provisional_account
company.save()
test_cc = company.cost_center
default_expense_account = company.default_expense_account
item = make_item(properties={"is_stock_item": 0})
pr = make_purchase_receipt(company=self.company, item_code=item.name, rate=1000.0, qty=1.0)
pr_gl_entries = get_gl_entries(pr.doctype, pr.name, skip_cancelled=True)
expected_pr_gles = [
{"account": provisional_account, "debit": 0.0, "credit": 1000.0, "cost_center": test_cc},
{"account": default_expense_account, "debit": 1000.0, "credit": 0.0, "cost_center": test_cc},
]
self.assertEqual(expected_pr_gles, pr_gl_entries)
# change the provisional account
frappe.db.set_value(
"Purchase Receipt Item",
pr.items[0].name,
"provisional_expense_account",
another_provisional_account,
)
repost_doc = frappe.new_doc("Repost Accounting Ledger")
repost_doc.company = self.company
repost_doc.delete_cancelled_entries = True
repost_doc.append("vouchers", {"voucher_type": pr.doctype, "voucher_no": pr.name})
repost_doc.save().submit()
pr_gles_after_repost = get_gl_entries(pr.doctype, pr.name, skip_cancelled=True)
expected_pr_gles_after_repost = [
{"account": default_expense_account, "debit": 1000.0, "credit": 0.0, "cost_center": test_cc},
{"account": another_provisional_account, "debit": 0.0, "credit": 1000.0, "cost_center": test_cc},
]
self.assertEqual(len(pr_gles_after_repost), len(expected_pr_gles_after_repost))
self.assertEqual(expected_pr_gles_after_repost, pr_gles_after_repost)
# teardown
repost_doc.cancel()
repost_doc.delete()
pr.reload()
pr.cancel()
company.enable_provisional_accounting_for_non_stock_items = 0
company.default_provisional_account = None
company.save()
def update_repost_settings():
allowed_types = ["Sales Invoice", "Purchase Invoice", "Payment Entry", "Journal Entry"]
allowed_types = [
"Sales Invoice",
"Purchase Invoice",
"Payment Entry",
"Journal Entry",
"Purchase Receipt",
]
repost_settings = frappe.get_doc("Repost Accounting Ledger Settings")
for x in allowed_types:
repost_settings.append("allowed_types", {"document_type": x, "allowed": True})

View File

@@ -16,6 +16,10 @@ erpnext.accounts.SalesInvoiceController = class SalesInvoiceController extends (
setup(doc) {
this.setup_posting_date_time_check();
super.setup(doc);
this.frm.make_methods = {
Dunning: this.make_dunning.bind(this),
"Invoice Discounting": this.make_invoice_discounting.bind(this),
};
}
company() {
super.company();
@@ -61,9 +65,10 @@ erpnext.accounts.SalesInvoiceController = class SalesInvoiceController extends (
refresh(doc, dt, dn) {
const me = this;
super.refresh();
if (cur_frm.msgbox && cur_frm.msgbox.$wrapper.is(":visible")) {
if (this.frm?.msgbox && this.frm.msgbox.$wrapper.is(":visible")) {
// hide new msgbox
cur_frm.msgbox.hide();
this.frm.msgbox.hide();
}
this.frm.toggle_reqd("due_date", !this.frm.doc.is_return);
@@ -121,12 +126,9 @@ erpnext.accounts.SalesInvoiceController = class SalesInvoiceController extends (
},
__("Create")
);
cur_frm.add_custom_button(
this.frm.add_custom_button(
__("Invoice Discounting"),
function () {
cur_frm.events.create_invoice_discounting(cur_frm);
},
this.make_invoice_discounting.bind(this),
__("Create")
);
@@ -135,22 +137,14 @@ erpnext.accounts.SalesInvoiceController = class SalesInvoiceController extends (
.reduce((prev, current) => prev || current, false);
if (payment_is_overdue) {
this.frm.add_custom_button(
__("Dunning"),
() => {
this.frm.events.create_dunning(this.frm);
},
__("Create")
);
this.frm.add_custom_button(__("Dunning"), this.make_dunning.bind(this), __("Create"));
}
}
if (doc.docstatus === 1) {
cur_frm.add_custom_button(
__("Maintenance Schedule"),
function () {
cur_frm.cscript.make_maintenance_schedule();
},
this.make_maintenance_schedule.bind(this),
__("Create")
);
}
@@ -185,6 +179,20 @@ erpnext.accounts.SalesInvoiceController = class SalesInvoiceController extends (
erpnext.accounts.unreconcile_payment.add_unreconcile_btn(me.frm);
}
make_invoice_discounting() {
frappe.model.open_mapped_doc({
method: "erpnext.accounts.doctype.sales_invoice.sales_invoice.create_invoice_discounting",
frm: this.frm,
});
}
make_dunning() {
frappe.model.open_mapped_doc({
method: "erpnext.accounts.doctype.sales_invoice.sales_invoice.create_dunning",
frm: this.frm,
});
}
make_maintenance_schedule() {
frappe.model.open_mapped_doc({
method: "erpnext.accounts.doctype.sales_invoice.sales_invoice.make_maintenance_schedule",
@@ -889,8 +897,16 @@ frappe.ui.form.on("Sales Invoice", {
project: function (frm) {
if (frm.doc.project) {
frm.events.add_timesheet_data(frm, {
project: frm.doc.project,
frappe.call({
method: "is_auto_fetch_timesheet_enabled",
doc: frm.doc,
callback: function (r) {
if (cint(r.message)) {
frm.events.add_timesheet_data(frm, {
project: frm.doc.project,
});
}
},
});
}
},
@@ -906,9 +922,25 @@ frappe.ui.form.on("Sales Invoice", {
}
const timesheets = await frm.events.get_timesheet_data(frm, kwargs);
if (kwargs.item_code) {
frm.events.add_timesheet_item(frm, kwargs.item_code, timesheets);
}
return frm.events.set_timesheet_data(frm, timesheets);
},
add_timesheet_item: function (frm, item_code, timesheets) {
const row = frm.add_child("items");
frappe.model.set_value(row.doctype, row.name, "item_code", item_code);
frappe.model.set_value(
row.doctype,
row.name,
"qty",
timesheets.reduce((a, b) => a + (b["billing_hours"] || 0.0), 0.0)
);
},
async get_timesheet_data(frm, kwargs) {
return frappe
.call({
@@ -1006,6 +1038,22 @@ frappe.ui.form.on("Sales Invoice", {
fieldtype: "Date",
reqd: 1,
},
{
label: __("Item Code"),
fieldname: "item_code",
fieldtype: "Link",
options: "Item",
get_query: () => {
return {
query: "erpnext.controllers.queries.item_query",
filters: {
is_sales_item: 1,
customer: frm.doc.customer,
has_variants: 0,
},
};
},
},
{
fieldtype: "Column Break",
fieldname: "col_break_1",
@@ -1030,6 +1078,7 @@ frappe.ui.form.on("Sales Invoice", {
from_time: data.from_time,
to_time: data.to_time,
project: data.project,
item_code: data.item_code,
});
d.hide();
},
@@ -1045,20 +1094,6 @@ frappe.ui.form.on("Sales Invoice", {
frm.set_df_property("return_against", "label", __("Adjustment Against"));
}
},
create_invoice_discounting: function (frm) {
frappe.model.open_mapped_doc({
method: "erpnext.accounts.doctype.sales_invoice.sales_invoice.create_invoice_discounting",
frm: frm,
});
},
create_dunning: function (frm) {
frappe.model.open_mapped_doc({
method: "erpnext.accounts.doctype.sales_invoice.sales_invoice.create_dunning",
frm: frm,
});
},
});
frappe.ui.form.on("Sales Invoice Timesheet", {

View File

@@ -299,7 +299,8 @@
"oldfieldname": "project_name",
"oldfieldtype": "Link",
"options": "Project",
"print_hide": 1
"print_hide": 1,
"search_index": 1
},
{
"default": "0",
@@ -2176,6 +2177,7 @@
"print_hide": 1
}
],
"grid_page_length": 50,
"icon": "fa fa-file-text",
"idx": 181,
"is_submittable": 1,
@@ -2186,7 +2188,7 @@
"link_fieldname": "consolidated_invoice"
}
],
"modified": "2025-01-14 11:38:30.446370",
"modified": "2025-03-17 19:32:31.809658",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice",
@@ -2232,6 +2234,7 @@
}
],
"quick_entry": 1,
"row_format": "Dynamic",
"search_fields": "posting_date, due_date, customer, base_grand_total, outstanding_amount",
"show_name_in_global_search": 1,
"sort_field": "modified",
@@ -2241,4 +2244,4 @@
"title_field": "title",
"track_changes": 1,
"track_seen": 1
}
}

View File

@@ -24,7 +24,11 @@ from erpnext.accounts.doctype.tax_withholding_category.tax_withholding_category
)
from erpnext.accounts.general_ledger import get_round_off_account_and_cost_center
from erpnext.accounts.party import get_due_date, get_party_account, get_party_details
from erpnext.accounts.utils import cancel_exchange_gain_loss_journal, get_account_currency
from erpnext.accounts.utils import (
cancel_exchange_gain_loss_journal,
get_account_currency,
update_voucher_outstanding,
)
from erpnext.assets.doctype.asset.depreciation import (
depreciate_asset,
get_disposal_account_and_cost_center,
@@ -456,6 +460,8 @@ class SalesInvoice(SellingController):
self.make_bundle_for_sales_purchase_return(table_name)
self.make_bundle_using_old_serial_batch_fields(table_name)
self.update_stock_reservation_entries()
self.update_stock_ledger()
# this sequence because outstanding may get -ve
@@ -557,6 +563,7 @@ class SalesInvoice(SellingController):
self.make_gl_entries_on_cancel()
if self.update_stock == 1:
self.update_stock_reservation_entries()
self.repost_future_sle_and_gle()
self.db_set("status", "Cancelled")
@@ -671,7 +678,13 @@ class SalesInvoice(SellingController):
"Account", self.debit_to, "account_currency", cache=True
)
if not self.due_date and self.customer:
self.due_date = get_due_date(self.posting_date, "Customer", self.customer, self.company)
self.due_date = get_due_date(
self.posting_date,
"Customer",
self.customer,
self.company,
template_name=self.payment_terms_template,
)
super().set_missing_values(for_validate)
@@ -1083,11 +1096,15 @@ class SalesInvoice(SellingController):
timesheet.billing_amount = ts_doc.total_billable_amount
def update_timesheet_billing_for_project(self):
if not self.timesheets and self.project:
if not self.timesheets and self.project and self.is_auto_fetch_timesheet_enabled():
self.add_timesheet_data()
else:
self.calculate_billing_amount_for_timesheet()
@frappe.whitelist()
def is_auto_fetch_timesheet_enabled(self):
return frappe.db.get_single_value("Projects Settings", "fetch_timesheet_in_sales_invoice")
@frappe.whitelist()
def add_timesheet_data(self):
self.set("timesheets", [])
@@ -1192,14 +1209,14 @@ class SalesInvoice(SellingController):
make_reverse_gl_entries(voucher_type=self.doctype, voucher_no=self.name)
if update_outstanding == "No":
from erpnext.accounts.doctype.gl_entry.gl_entry import update_outstanding_amt
update_outstanding_amt(
self.debit_to,
"Customer",
self.customer,
self.doctype,
self.return_against if cint(self.is_return) and self.return_against else self.name,
update_voucher_outstanding(
voucher_type=self.doctype,
voucher_no=self.return_against
if cint(self.is_return) and self.return_against
else self.name,
account=self.debit_to,
party_type="Customer",
party=self.customer,
)
elif self.docstatus == 2 and cint(self.update_stock) and cint(auto_accounting_for_stock):
@@ -1230,6 +1247,7 @@ class SalesInvoice(SellingController):
self.make_write_off_gl_entry(gl_entries)
self.make_gle_for_rounding_adjustment(gl_entries)
self.set_transaction_currency_and_rate_in_gl_map(gl_entries)
return gl_entries
def make_customer_gl_entry(self, gl_entries):
@@ -1263,6 +1281,7 @@ class SalesInvoice(SellingController):
"debit_in_account_currency": base_grand_total
if self.party_account_currency == self.company_currency
else grand_total,
"debit_in_transaction_currency": grand_total,
"against_voucher": against_voucher,
"against_voucher_type": self.doctype,
"cost_center": self.cost_center,
@@ -1294,6 +1313,9 @@ class SalesInvoice(SellingController):
if account_currency == self.company_currency
else flt(amount, tax.precision("tax_amount_after_discount_amount"))
),
"credit_in_transaction_currency": flt(
amount, tax.precision("tax_amount_after_discount_amount")
),
"cost_center": tax.cost_center,
},
account_currency,
@@ -1311,6 +1333,7 @@ class SalesInvoice(SellingController):
"against": self.customer,
"debit": flt(self.total_taxes_and_charges),
"debit_in_account_currency": flt(self.base_total_taxes_and_charges),
"debit_in_transaction_currency": flt(self.total_taxes_and_charges),
"cost_center": self.cost_center,
},
account_currency,
@@ -1409,6 +1432,7 @@ class SalesInvoice(SellingController):
if account_currency == self.company_currency
else flt(amount, item.precision("net_amount"))
),
"credit_in_transaction_currency": flt(amount, item.precision("net_amount")),
"cost_center": item.cost_center,
"project": item.project or self.project,
},
@@ -1460,6 +1484,7 @@ class SalesInvoice(SellingController):
+ cstr(self.loyalty_redemption_account)
+ " for the Loyalty Program",
"credit": self.loyalty_amount,
"credit_in_transaction_currency": self.loyalty_amount,
"against_voucher": self.return_against if cint(self.is_return) else self.name,
"against_voucher_type": self.doctype,
"cost_center": self.cost_center,
@@ -1474,6 +1499,7 @@ class SalesInvoice(SellingController):
"cost_center": self.cost_center or self.loyalty_redemption_cost_center,
"against": self.customer,
"debit": self.loyalty_amount,
"debit_in_transaction_currency": self.loyalty_amount,
"remark": "Loyalty Points redeemed by the customer",
},
item=self,
@@ -1507,6 +1533,7 @@ class SalesInvoice(SellingController):
"credit_in_account_currency": payment_mode.base_amount
if self.party_account_currency == self.company_currency
else payment_mode.amount,
"credit_in_transaction_currency": payment_mode.amount,
"against_voucher": against_voucher,
"against_voucher_type": self.doctype,
"cost_center": self.cost_center,
@@ -1526,6 +1553,7 @@ class SalesInvoice(SellingController):
"debit_in_account_currency": payment_mode.base_amount
if payment_mode_account_currency == self.company_currency
else payment_mode.amount,
"debit_in_transaction_currency": payment_mode.amount,
"cost_center": self.cost_center,
},
payment_mode_account_currency,
@@ -1550,6 +1578,7 @@ class SalesInvoice(SellingController):
"debit_in_account_currency": flt(self.base_change_amount)
if self.party_account_currency == self.company_currency
else flt(self.change_amount),
"debit_in_transaction_currency": flt(self.change_amount),
"against_voucher": self.return_against
if cint(self.is_return) and self.return_against
else self.name,
@@ -1568,6 +1597,7 @@ class SalesInvoice(SellingController):
"account": self.account_for_change_amount,
"against": self.customer,
"credit": self.base_change_amount,
"credit_in_transaction_currency": self.change_amount,
"cost_center": self.cost_center,
},
item=self,
@@ -1599,6 +1629,9 @@ class SalesInvoice(SellingController):
if self.party_account_currency == self.company_currency
else flt(self.write_off_amount, self.precision("write_off_amount"))
),
"credit_in_transaction_currency": flt(
self.write_off_amount, self.precision("write_off_amount")
),
"against_voucher": self.return_against if cint(self.is_return) else self.name,
"against_voucher_type": self.doctype,
"cost_center": self.cost_center,
@@ -1619,6 +1652,9 @@ class SalesInvoice(SellingController):
if write_off_account_currency == self.company_currency
else flt(self.write_off_amount, self.precision("write_off_amount"))
),
"debit_in_transaction_currency": flt(
self.write_off_amount, self.precision("write_off_amount")
),
"cost_center": self.cost_center or self.write_off_cost_center or default_cost_center,
},
write_off_account_currency,
@@ -1663,6 +1699,9 @@ class SalesInvoice(SellingController):
"credit_in_account_currency": flt(
self.rounding_adjustment, self.precision("rounding_adjustment")
),
"credit_in_transaction_currency": flt(
self.rounding_adjustment, self.precision("rounding_adjustment")
),
"credit": flt(
self.base_rounding_adjustment, self.precision("base_rounding_adjustment")
),
@@ -1926,13 +1965,16 @@ def is_overdue(doc, total):
"base_payment_amount" if doc.party_account_currency != doc.currency else "payment_amount"
)
payable_amount = sum(
payment.get(payment_amount_field)
for payment in doc.payment_schedule
if getdate(payment.due_date) < today
payable_amount = flt(
sum(
payment.get(payment_amount_field)
for payment in doc.payment_schedule
if getdate(payment.due_date) < today
),
doc.precision("outstanding_amount"),
)
return (total - outstanding_amount) < payable_amount
return flt(total - outstanding_amount, doc.precision("outstanding_amount")) < payable_amount
def get_discounting_status(sales_invoice):

View File

@@ -32,12 +32,16 @@ frappe.listview_settings["Sales Invoice"] = {
right_column: "grand_total",
onload: function (listview) {
listview.page.add_action_item(__("Delivery Note"), () => {
erpnext.bulk_transaction_processing.create(listview, "Sales Invoice", "Delivery Note");
});
if (frappe.model.can_create("Delivery Note")) {
listview.page.add_action_item(__("Delivery Note"), () => {
erpnext.bulk_transaction_processing.create(listview, "Sales Invoice", "Delivery Note");
});
}
listview.page.add_action_item(__("Payment"), () => {
erpnext.bulk_transaction_processing.create(listview, "Sales Invoice", "Payment Entry");
});
if (frappe.model.can_create("Payment Entry")) {
listview.page.add_action_item(__("Payment"), () => {
erpnext.bulk_transaction_processing.create(listview, "Sales Invoice", "Payment Entry");
});
}
},
};

View File

@@ -1819,17 +1819,6 @@ class TestSalesInvoice(FrappeTestCase):
for field in expected_gle:
self.assertEqual(expected_gle[field], gle[field])
def test_invoice_exchange_rate(self):
si = create_sales_invoice(
customer="_Test Customer USD",
debit_to="_Test Receivable USD - _TC",
currency="USD",
conversion_rate=1,
do_not_save=1,
)
self.assertRaises(frappe.ValidationError, si.save)
def test_invalid_currency(self):
# Customer currency = USD
@@ -4235,6 +4224,7 @@ class TestSalesInvoice(FrappeTestCase):
si = create_sales_invoice(do_not_submit=True)
project = frappe.new_doc("Project")
project.company = "_Test Company"
project.project_name = "Test Total Billed Amount"
project.save()
@@ -4245,6 +4235,69 @@ class TestSalesInvoice(FrappeTestCase):
doc = frappe.get_doc("Project", project.name)
self.assertEqual(doc.total_billed_amount, si.grand_total)
def test_total_billed_amount_with_different_projects(self):
# This test case is for checking the scenario where project is set at document level and for **some** child items only, not all
from copy import copy
si = create_sales_invoice(do_not_submit=True)
project = frappe.new_doc("Project")
project.company = "_Test Company"
project.project_name = "Test Total Billed Amount"
project.save()
si.project = project.name
si.items.append(copy(si.items[0]))
si.items.append(copy(si.items[0]))
si.items[0].project = project.name
si.items[1].project = project.name
# Not setting project on last item
si.items[1].insert()
si.items[2].insert()
si.submit()
project.reload()
self.assertIsNone(si.items[2].project)
self.assertEqual(project.total_billed_amount, 300)
def test_pos_returns_with_party_account_currency(self):
from erpnext.accounts.doctype.sales_invoice.sales_invoice import make_sales_return
pos_profile = make_pos_profile()
pos_profile.payments = []
pos_profile.append("payments", {"default": 1, "mode_of_payment": "Cash"})
pos_profile.save()
pos = create_sales_invoice(
customer="_Test Customer USD",
currency="USD",
conversion_rate=86.595000000,
qty=2,
do_not_save=True,
)
pos.is_pos = 1
pos.pos_profile = pos_profile.name
pos.debit_to = "_Test Receivable USD - _TC"
pos.append("payments", {"mode_of_payment": "Cash", "account": "_Test Bank - _TC", "amount": 20.35})
pos.save().submit()
pos_return = make_sales_return(pos.name)
self.assertEqual(abs(pos_return.payments[0].amount), pos.payments[0].amount)
def test_prevents_fully_returned_invoice_with_zero_quantity(self):
from erpnext.controllers.sales_and_purchase_return import StockOverReturnError, make_return_doc
invoice = create_sales_invoice(qty=10)
return_doc = make_return_doc(invoice.doctype, invoice.name)
return_doc.items[0].qty = -10
return_doc.save().submit()
return_doc = make_return_doc(invoice.doctype, invoice.name)
return_doc.items[0].qty = 0
self.assertRaises(StockOverReturnError, return_doc.save)
def set_advance_flag(company, flag, default_account):
frappe.db.set_value(

View File

@@ -105,6 +105,9 @@
"delivery_note",
"dn_detail",
"delivered_qty",
"column_break_vwhb",
"pos_invoice",
"pos_invoice_item",
"internal_transfer_section",
"purchase_order",
"column_break_92",
@@ -630,6 +633,7 @@
"fieldname": "serial_no",
"fieldtype": "Text",
"label": "Serial No",
"no_copy": 1,
"oldfieldname": "serial_no",
"oldfieldtype": "Small Text"
},
@@ -945,19 +949,41 @@
"no_copy": 1,
"print_hide": 1,
"read_only": 1
},
{
"fieldname": "pos_invoice_item",
"fieldtype": "Data",
"ignore_user_permissions": 1,
"label": "POS Invoice Item",
"no_copy": 1,
"print_hide": 1,
"read_only": 1
},
{
"fieldname": "column_break_vwhb",
"fieldtype": "Column Break"
},
{
"fieldname": "pos_invoice",
"fieldtype": "Link",
"label": "POS Invoice",
"no_copy": 1,
"options": "POS Invoice",
"print_hide": 1,
"search_index": 1
}
],
"idx": 1,
"istable": 1,
"links": [],
"modified": "2024-11-25 16:27:33.287341",
"modified": "2025-03-12 16:33:52.503777",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice Item",
"naming_rule": "Random",
"owner": "Administrator",
"permissions": [],
"sort_field": "modified",
"sort_field": "creation",
"sort_order": "DESC",
"states": []
}
}

View File

@@ -64,6 +64,8 @@ class SalesInvoiceItem(Document):
parent: DF.Data
parentfield: DF.Data
parenttype: DF.Data
pos_invoice: DF.Link | None
pos_invoice_item: DF.Data | None
price_list_rate: DF.Currency
pricing_rules: DF.SmallText | None
project: DF.Link | None

View File

@@ -634,9 +634,7 @@ class Subscription(Document):
"""
invoice = frappe.get_all(
self.invoice_document_type,
{
"subscription": self.name,
},
{"subscription": self.name, "docstatus": ("<", 2)},
limit=1,
order_by="to_date desc",
pluck="name",
@@ -675,6 +673,7 @@ class Subscription(Document):
self.invoice_document_type,
{
"subscription": self.name,
"docstatus": 1,
"status": ["!=", "Paid"],
},
)

View File

@@ -13,17 +13,15 @@
"fields": [
{
"fieldname": "voucher_type",
"fieldtype": "Link",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Voucher Type",
"options": "DocType"
"label": "Voucher Type"
},
{
"fieldname": "voucher_name",
"fieldtype": "Dynamic Link",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Voucher Name",
"options": "voucher_type"
"label": "Voucher Name"
},
{
"fieldname": "taxable_amount",
@@ -36,7 +34,7 @@
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2023-01-13 13:40:41.479208",
"modified": "2025-02-05 16:39:14.863698",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Tax Withheld Vouchers",

View File

@@ -18,8 +18,8 @@ class TaxWithheldVouchers(Document):
parentfield: DF.Data
parenttype: DF.Data
taxable_amount: DF.Currency
voucher_name: DF.DynamicLink | None
voucher_type: DF.Link | None
voucher_name: DF.Data | None
voucher_type: DF.Data | None
# end: auto-generated types
pass

View File

@@ -10,6 +10,7 @@ frappe.ui.form.on("Tax Withholding Category", {
filters: {
company: child.company,
root_type: ["in", ["Asset", "Liability"]],
is_group: 0,
},
};
}

View File

@@ -36,27 +36,38 @@ class TaxWithholdingCategory(Document):
def validate(self):
self.validate_dates()
self.validate_accounts()
self.validate_companies_and_accounts()
self.validate_thresholds()
def validate_dates(self):
last_date = None
for d in self.get("rates"):
last_to_date = None
rates = sorted(self.get("rates"), key=lambda d: getdate(d.from_date))
for d in rates:
if getdate(d.from_date) >= getdate(d.to_date):
frappe.throw(_("Row #{0}: From Date cannot be before To Date").format(d.idx))
# validate overlapping of dates
if last_date and getdate(d.to_date) < getdate(last_date):
if last_to_date and getdate(d.from_date) < getdate(last_to_date):
frappe.throw(_("Row #{0}: Dates overlapping with other row").format(d.idx))
def validate_accounts(self):
existing_accounts = []
last_to_date = d.to_date
def validate_companies_and_accounts(self):
existing_accounts = set()
companies = set()
for d in self.get("accounts"):
# validate duplicate company
if d.get("company") in companies:
frappe.throw(_("Company {0} added multiple times").format(frappe.bold(d.get("company"))))
companies.add(d.get("company"))
# validate duplicate account
if d.get("account") in existing_accounts:
frappe.throw(_("Account {0} added multiple times").format(frappe.bold(d.get("account"))))
validate_account_head(d.idx, d.get("account"), d.get("company"))
existing_accounts.append(d.get("account"))
existing_accounts.add(d.get("account"))
def validate_thresholds(self):
for d in self.get("rates"):
@@ -87,6 +98,7 @@ def get_party_details(inv):
def get_party_tax_withholding_details(inv, tax_withholding_category=None):
if inv.doctype == "Payment Entry":
inv.tax_withholding_net_total = inv.net_total
inv.base_tax_withholding_net_total = inv.net_total
pan_no = ""
parties = []
@@ -269,7 +281,10 @@ def get_lower_deduction_certificate(company, posting_date, tax_details, pan_no):
def get_tax_amount(party_type, parties, inv, tax_details, posting_date, pan_no=None):
vouchers, voucher_wise_amount = get_invoice_vouchers(
parties, tax_details, inv.company, party_type=party_type
parties,
tax_details,
inv.company,
party_type=party_type,
)
payment_entry_vouchers = get_payment_entry_vouchers(
@@ -326,7 +341,7 @@ def get_tax_amount(party_type, parties, inv, tax_details, posting_date, pan_no=N
# once tds is deducted, not need to add vouchers in the invoice
voucher_wise_amount = {}
else:
tax_amount = get_tds_amount(ldc, parties, inv, tax_details, vouchers)
tax_amount = get_tds_amount(ldc, parties, inv, tax_details, voucher_wise_amount)
elif party_type == "Customer":
if tax_deducted:
@@ -356,13 +371,28 @@ def is_tax_deducted_on_the_basis_of_inv(vouchers):
def get_invoice_vouchers(parties, tax_details, company, party_type="Supplier"):
doctype = "Purchase Invoice" if party_type == "Supplier" else "Sales Invoice"
field = (
"base_tax_withholding_net_total as base_net_total" if party_type == "Supplier" else "base_net_total"
)
voucher_wise_amount = {}
voucher_wise_amount = []
vouchers = []
ldcs = frappe.db.get_all(
"Lower Deduction Certificate",
filters={
"valid_from": [">=", tax_details.from_date],
"valid_upto": ["<=", tax_details.to_date],
"company": company,
"supplier": ["in", parties],
},
fields=["supplier", "valid_from", "valid_upto", "rate"],
)
doctype = "Purchase Invoice" if party_type == "Supplier" else "Sales Invoice"
field = [
"base_tax_withholding_net_total as base_net_total" if party_type == "Supplier" else "base_net_total",
"name",
"grand_total",
"posting_date",
]
filters = {
"company": company,
frappe.scrub(party_type): ["in", parties],
@@ -376,15 +406,29 @@ def get_invoice_vouchers(parties, tax_details, company, party_type="Supplier"):
{"apply_tds": 1, "tax_withholding_category": tax_details.get("tax_withholding_category")}
)
invoices_details = frappe.get_all(doctype, filters=filters, fields=["name", field])
invoices_details = frappe.get_all(doctype, filters=filters, fields=field)
for d in invoices_details:
vouchers.append(d.name)
voucher_wise_amount.update({d.name: {"amount": d.base_net_total, "voucher_type": doctype}})
d = frappe._dict(
{
"voucher_name": d.name,
"voucher_type": doctype,
"taxable_amount": d.base_net_total,
"grand_total": d.grand_total,
"posting_date": d.posting_date,
}
)
if ldc := [x for x in ldcs if d.posting_date >= x.valid_from and d.posting_date <= x.valid_upto]:
if ldc[0].supplier in parties and ldc[0].rate == 0:
d.update({"taxable_amount": 0})
vouchers.append(d.voucher_name)
voucher_wise_amount.append(d)
journal_entries_details = frappe.db.sql(
"""
SELECT j.name, ja.credit - ja.debit AS amount
SELECT j.name, ja.credit - ja.debit AS amount, ja.reference_type
FROM `tabJournal Entry` j, `tabJournal Entry Account` ja
WHERE
j.name = ja.parent
@@ -406,10 +450,18 @@ def get_invoice_vouchers(parties, tax_details, company, party_type="Supplier"):
as_dict=1,
)
if journal_entries_details:
for d in journal_entries_details:
vouchers.append(d.name)
voucher_wise_amount.update({d.name: {"amount": d.amount, "voucher_type": "Journal Entry"}})
for d in journal_entries_details:
vouchers.append(d.name)
voucher_wise_amount.append(
frappe._dict(
{
"voucher_name": d.name,
"voucher_type": "Journal Entry",
"taxable_amount": d.amount,
"reference_type": d.reference_type,
}
)
)
return vouchers, voucher_wise_amount
@@ -508,12 +560,24 @@ def get_advance_tax_across_fiscal_year(tax_deducted_on_advances, tax_details):
return advance_tax_from_across_fiscal_year
def get_tds_amount(ldc, parties, inv, tax_details, vouchers):
def get_tds_amount(ldc, parties, inv, tax_details, voucher_wise_amount):
tds_amount = 0
invoice_filters = {"name": ("in", vouchers), "docstatus": 1, "apply_tds": 1}
pi_grand_total = 0
pi_base_net_total = 0
jv_credit_amt = 0
pe_credit_amt = 0
for row in voucher_wise_amount:
if row.voucher_type == "Purchase Invoice":
pi_grand_total += row.get("grand_total", 0)
pi_base_net_total += row.get("taxable_amount", 0)
if row.voucher_type == "Journal Entry" and row.reference_type != "Purchase Invoice":
jv_credit_amt += row.get("taxable_amount", 0)
## for TDS to be deducted on advances
payment_entry_filters = {
pe_filters = {
"party_type": "Supplier",
"party": ("in", parties),
"docstatus": 1,
@@ -524,70 +588,49 @@ def get_tds_amount(ldc, parties, inv, tax_details, vouchers):
"company": inv.company,
}
field = "sum(tax_withholding_net_total)"
consider_party_ledger_amt = cint(tax_details.consider_party_ledger_amount)
if cint(tax_details.consider_party_ledger_amount):
invoice_filters.pop("apply_tds", None)
field = "sum(grand_total)"
payment_entry_filters.pop("apply_tax_withholding_amount", None)
payment_entry_filters.pop("tax_withholding_category", None)
supp_inv_credit_amt = frappe.db.get_value("Purchase Invoice", invoice_filters, field) or 0.0
supp_jv_credit_amt = (
frappe.db.get_value(
"Journal Entry Account",
{
"parent": ("in", vouchers),
"docstatus": 1,
"party": ("in", parties),
"reference_type": ("!=", "Purchase Invoice"),
},
"sum(credit_in_account_currency - debit_in_account_currency)",
)
or 0.0
)
if consider_party_ledger_amt:
pe_filters.pop("apply_tax_withholding_amount", None)
pe_filters.pop("tax_withholding_category", None)
# Get Amount via payment entry
payment_entry_amounts = frappe.db.get_all(
payment_entries = frappe.db.get_all(
"Payment Entry",
filters=payment_entry_filters,
fields=["sum(unallocated_amount) as amount", "payment_type"],
group_by="payment_type",
filters=pe_filters,
fields=["name", "unallocated_amount as taxable_amount", "payment_type"],
)
supp_credit_amt = supp_jv_credit_amt
supp_credit_amt += inv.get("tax_withholding_net_total", 0)
for type in payment_entry_amounts:
if type.payment_type == "Pay":
supp_credit_amt += type.amount
else:
supp_credit_amt -= type.amount
for row in payment_entries:
value = row.taxable_amount if row.payment_type == "Pay" else -1 * row.taxable_amount
pe_credit_amt += value
voucher_wise_amount.append(
frappe._dict(
{
"voucher_name": row.name,
"voucher_type": "Payment Entry",
"taxable_amount": value,
}
)
)
threshold = tax_details.get("threshold", 0)
cumulative_threshold = tax_details.get("cumulative_threshold", 0)
supp_credit_amt = jv_credit_amt + pe_credit_amt + inv.get("tax_withholding_net_total", 0)
tax_withholding_net_total = inv.get("base_tax_withholding_net_total", 0)
if inv.doctype != "Payment Entry":
tax_withholding_net_total = inv.get("base_tax_withholding_net_total", 0)
else:
tax_withholding_net_total = inv.get("tax_withholding_net_total", 0)
# if consider_party_ledger_amount is checked, then threshold will be based on grand total
amt_for_threshold = pi_grand_total if consider_party_ledger_amt else pi_base_net_total
has_cumulative_threshold_breached = (
cumulative_threshold and (supp_credit_amt + supp_inv_credit_amt) >= cumulative_threshold
cumulative_threshold_breached = (
cumulative_threshold and (supp_credit_amt + amt_for_threshold) >= cumulative_threshold
)
if (threshold and tax_withholding_net_total >= threshold) or (has_cumulative_threshold_breached):
# Get net total again as TDS is calculated on net total
# Grand is used to just check for threshold breach
net_total = (
frappe.db.get_value("Purchase Invoice", invoice_filters, "sum(tax_withholding_net_total)") or 0.0
)
supp_credit_amt += net_total
if (threshold and tax_withholding_net_total >= threshold) or (cumulative_threshold_breached):
supp_credit_amt += pi_base_net_total
if has_cumulative_threshold_breached and cint(tax_details.tax_on_excess_amount):
supp_credit_amt = net_total + tax_withholding_net_total - cumulative_threshold
if cumulative_threshold_breached and cint(tax_details.tax_on_excess_amount):
supp_credit_amt = pi_base_net_total + tax_withholding_net_total - cumulative_threshold
if ldc and is_valid_certificate(ldc, inv.get("posting_date") or inv.get("transaction_date"), 0):
tds_amount = get_lower_deduction_amount(

View File

@@ -7,7 +7,7 @@ import unittest
import frappe
from frappe.custom.doctype.custom_field.custom_field import create_custom_fields
from frappe.tests.utils import FrappeTestCase, change_settings
from frappe.utils import add_days, today
from frappe.utils import add_days, add_months, today
from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry
from erpnext.accounts.utils import get_fiscal_year
@@ -519,7 +519,7 @@ class TestTaxWithholdingCategory(FrappeTestCase):
payment = get_payment_entry(order.doctype, order.name)
payment.apply_tax_withholding_amount = 1
payment.tax_withholding_category = "Cumulative Threshold TDS"
payment.submit()
payment.save().submit()
self.assertEqual(payment.taxes[0].tax_amount, 4000)
def test_multi_category_single_supplier(self):
@@ -569,6 +569,15 @@ class TestTaxWithholdingCategory(FrappeTestCase):
pi1.submit()
invoices.append(pi1)
pe = create_payment_entry(
payment_type="Pay", party_type="Supplier", party="Test TDS Supplier6", paid_amount=1000
)
pe.apply_tax_withholding_amount = 1
pe.tax_withholding_category = "Test Multi Invoice Category"
pe.save()
pe.submit()
invoices.append(pe)
pi2 = create_purchase_invoice(supplier="Test TDS Supplier6", rate=9000, do_not_save=True)
pi2.apply_tds = 1
pi2.tax_withholding_category = "Test Multi Invoice Category"
@@ -584,6 +593,8 @@ class TestTaxWithholdingCategory(FrappeTestCase):
self.assertTrue(pi2.tax_withheld_vouchers[0].taxable_amount == pi1.net_total)
self.assertTrue(pi2.tax_withheld_vouchers[1].voucher_name == pi.name)
self.assertTrue(pi2.tax_withheld_vouchers[1].taxable_amount == pi.net_total)
self.assertTrue(pi2.tax_withheld_vouchers[2].voucher_name == pe.name)
self.assertTrue(pi2.tax_withheld_vouchers[2].taxable_amount == pe.paid_amount)
# cancel invoices to avoid clashing
for d in reversed(invoices):
@@ -655,6 +666,49 @@ class TestTaxWithholdingCategory(FrappeTestCase):
pi2.cancel()
pi3.cancel()
def test_ldc_at_0_rate(self):
frappe.db.set_value(
"Supplier",
"Test LDC Supplier",
{
"tax_withholding_category": "Test Service Category",
"pan": "ABCTY1234D",
},
)
fiscal_year = get_fiscal_year(today(), company="_Test Company")
valid_from = fiscal_year[1]
valid_upto = add_months(valid_from, 1)
create_lower_deduction_certificate(
supplier="Test LDC Supplier",
certificate_no="1AE0423AAJ",
tax_withholding_category="Test Service Category",
tax_rate=0,
limit=50000,
valid_from=valid_from,
valid_upto=valid_upto,
)
pi1 = create_purchase_invoice(
supplier="Test LDC Supplier", rate=35000, posting_date=valid_from, set_posting_time=True
)
pi1.submit()
self.assertEqual(pi1.taxes, [])
pi2 = create_purchase_invoice(
supplier="Test LDC Supplier",
rate=35000,
posting_date=add_days(valid_upto, 1),
set_posting_time=True,
)
pi2.submit()
self.assertEqual(len(pi2.taxes), 1)
# pi1 net total shouldn't be included as it lies within LDC at rate of '0'
self.assertEqual(pi2.taxes[0].tax_amount, 3500)
pi1.cancel()
pi2.cancel()
def set_previous_fy_and_tax_category(self):
test_company = "_Test Company"
category = "Cumulative Threshold TDS"
@@ -812,7 +866,8 @@ def create_purchase_invoice(**args):
pi = frappe.get_doc(
{
"doctype": "Purchase Invoice",
"posting_date": today(),
"set_posting_time": args.set_posting_time or False,
"posting_date": args.posting_date or today(),
"apply_tds": 0 if args.do_not_apply_tds else 1,
"supplier": args.supplier,
"company": "_Test Company",
@@ -1150,7 +1205,9 @@ def create_tax_withholding_category(
).insert()
def create_lower_deduction_certificate(supplier, tax_withholding_category, tax_rate, certificate_no, limit):
def create_lower_deduction_certificate(
supplier, tax_withholding_category, tax_rate, certificate_no, limit, valid_from=None, valid_upto=None
):
fiscal_year = get_fiscal_year(today(), company="_Test Company")
if not frappe.db.exists("Lower Deduction Certificate", certificate_no):
frappe.get_doc(
@@ -1161,8 +1218,8 @@ def create_lower_deduction_certificate(supplier, tax_withholding_category, tax_r
"certificate_no": certificate_no,
"tax_withholding_category": tax_withholding_category,
"fiscal_year": fiscal_year[0],
"valid_from": fiscal_year[1],
"valid_upto": fiscal_year[2],
"valid_from": valid_from or fiscal_year[1],
"valid_upto": valid_upto or fiscal_year[2],
"rate": tax_rate,
"certificate_limit": limit,
}

View File

@@ -35,7 +35,7 @@ def make_gl_entries(
make_acc_dimensions_offsetting_entry(gl_map)
validate_accounting_period(gl_map)
validate_disabled_accounts(gl_map)
gl_map = process_gl_map(gl_map, merge_entries)
gl_map = process_gl_map(gl_map, merge_entries, from_repost=from_repost)
if gl_map and len(gl_map) > 1:
if gl_map[0].voucher_type != "Period Closing Voucher":
create_payment_ledger_entry(
@@ -81,6 +81,10 @@ def make_acc_dimensions_offsetting_entry(gl_map):
"credit_in_account_currency": credit,
"remarks": _("Offsetting for Accounting Dimension") + f" - {dimension.name}",
"against_voucher": None,
"account_currency": dimension.account_currency,
# Party Type and Party are restricted to Receivable and Payable accounts
"party_type": None,
"party": None,
}
)
offsetting_entry["against_voucher_type"] = None
@@ -108,6 +112,9 @@ def get_accounting_dimensions_for_offsetting_entry(gl_map, company):
accounting_dimensions_to_offset = []
for acc_dimension in acc_dimensions:
values = set([entry.get(acc_dimension.fieldname) for entry in gl_map])
acc_dimension.account_currency = frappe.get_cached_value(
"Account", acc_dimension.offsetting_account, "account_currency"
)
if len(values) > 1:
accounting_dimensions_to_offset.append(acc_dimension)
@@ -163,12 +170,12 @@ def validate_accounting_period(gl_map):
)
def process_gl_map(gl_map, merge_entries=True, precision=None):
def process_gl_map(gl_map, merge_entries=True, precision=None, from_repost=False):
if not gl_map:
return []
if gl_map[0].voucher_type != "Period Closing Voucher":
gl_map = distribute_gl_based_on_cost_center_allocation(gl_map, precision)
gl_map = distribute_gl_based_on_cost_center_allocation(gl_map, precision, from_repost)
if merge_entries:
gl_map = merge_similar_entries(gl_map, precision)
@@ -178,13 +185,17 @@ def process_gl_map(gl_map, merge_entries=True, precision=None):
return gl_map
def distribute_gl_based_on_cost_center_allocation(gl_map, precision=None):
def distribute_gl_based_on_cost_center_allocation(gl_map, precision=None, from_repost=False):
new_gl_map = []
for d in gl_map:
cost_center = d.get("cost_center")
# Validate budget against main cost center
validate_expense_against_budget(d, expense_amount=flt(d.debit, precision) - flt(d.credit, precision))
if not from_repost:
validate_expense_against_budget(
d, expense_amount=flt(d.debit, precision) - flt(d.credit, precision)
)
cost_center_allocation = get_cost_center_allocation_data(
gl_map[0]["company"], gl_map[0]["posting_date"], cost_center
)
@@ -426,7 +437,7 @@ def process_debit_credit_difference(gl_map):
voucher_no = gl_map[0].voucher_no
allowance = get_debit_credit_allowance(voucher_type, precision)
debit_credit_diff = get_debit_credit_difference(gl_map, precision)
debit_credit_diff, trx_cur_debit_credit_diff = get_debit_credit_difference(gl_map, precision)
if abs(debit_credit_diff) > allowance:
if not (
@@ -437,9 +448,9 @@ def process_debit_credit_difference(gl_map):
raise_debit_credit_not_equal_error(debit_credit_diff, voucher_type, voucher_no)
elif abs(debit_credit_diff) >= (1.0 / (10**precision)):
make_round_off_gle(gl_map, debit_credit_diff, precision)
make_round_off_gle(gl_map, debit_credit_diff, trx_cur_debit_credit_diff, precision)
debit_credit_diff = get_debit_credit_difference(gl_map, precision)
debit_credit_diff, trx_cur_debit_credit_diff = get_debit_credit_difference(gl_map, precision)
if abs(debit_credit_diff) > allowance:
if not (
voucher_type == "Journal Entry"
@@ -451,14 +462,23 @@ def process_debit_credit_difference(gl_map):
def get_debit_credit_difference(gl_map, precision):
debit_credit_diff = 0.0
trx_cur_debit_credit_diff = 0
for entry in gl_map:
entry.debit = flt(entry.debit, precision)
entry.credit = flt(entry.credit, precision)
debit_credit_diff += entry.debit - entry.credit
debit_credit_diff = flt(debit_credit_diff, precision)
entry.debit_in_transaction_currency = flt(entry.debit_in_transaction_currency, precision)
entry.credit_in_transaction_currency = flt(entry.credit_in_transaction_currency, precision)
trx_cur_debit_credit_diff += (
entry.debit_in_transaction_currency - entry.credit_in_transaction_currency
)
return debit_credit_diff
debit_credit_diff = flt(debit_credit_diff, precision)
trx_cur_debit_credit_diff = flt(trx_cur_debit_credit_diff, precision)
return debit_credit_diff, trx_cur_debit_credit_diff
def get_debit_credit_allowance(voucher_type, precision):
@@ -485,7 +505,7 @@ def has_opening_entries(gl_map: list) -> bool:
return False
def make_round_off_gle(gl_map, debit_credit_diff, precision):
def make_round_off_gle(gl_map, debit_credit_diff, trx_cur_debit_credit_diff, precision):
round_off_account, round_off_cost_center, round_off_for_opening = get_round_off_account_and_cost_center(
gl_map[0].company, gl_map[0].voucher_type, gl_map[0].voucher_no
)
@@ -530,6 +550,12 @@ def make_round_off_gle(gl_map, debit_credit_diff, precision):
"credit_in_account_currency": debit_credit_diff if debit_credit_diff > 0 else 0,
"debit": abs(debit_credit_diff) if debit_credit_diff < 0 else 0,
"credit": debit_credit_diff if debit_credit_diff > 0 else 0,
"debit_in_transaction_currency": abs(trx_cur_debit_credit_diff)
if trx_cur_debit_credit_diff < 0
else 0,
"credit_in_transaction_currency": trx_cur_debit_credit_diff
if trx_cur_debit_credit_diff > 0
else 0,
"cost_center": round_off_cost_center,
"party_type": None,
"party": None,
@@ -676,11 +702,15 @@ def make_reverse_gl_entries(
debit_in_account_currency = new_gle.get("debit_in_account_currency", 0)
credit_in_account_currency = new_gle.get("credit_in_account_currency", 0)
debit_in_transaction_currency = new_gle.get("debit_in_transaction_currency", 0)
credit_in_transaction_currency = new_gle.get("credit_in_transaction_currency", 0)
new_gle["debit"] = credit
new_gle["credit"] = debit
new_gle["debit_in_account_currency"] = credit_in_account_currency
new_gle["credit_in_account_currency"] = debit_in_account_currency
new_gle["debit_in_transaction_currency"] = credit_in_transaction_currency
new_gle["credit_in_transaction_currency"] = debit_in_transaction_currency
new_gle["remarks"] = "On cancellation of " + new_gle["voucher_no"]
new_gle["is_cancelled"] = 1

View File

@@ -279,9 +279,7 @@ def get_regional_address_details(party_details, doctype, company):
pass
def set_contact_details(party_details, party, party_type):
party_details.contact_person = get_default_contact(party_type, party.name)
def complete_contact_details(party_details):
if not party_details.contact_person:
party_details.update(
{
@@ -310,6 +308,11 @@ def set_contact_details(party_details, party, party_type):
party_details.update(contact_details)
def set_contact_details(party_details, party, party_type):
party_details.contact_person = get_default_contact(party_type, party.name)
complete_contact_details(party_details)
def set_other_values(party_details, party, party_type):
# copy
if party_type == "Customer":
@@ -572,12 +575,13 @@ def validate_party_accounts(doc):
@frappe.whitelist()
def get_due_date(posting_date, party_type, party, company=None, bill_date=None):
def get_due_date(posting_date, party_type, party, company=None, bill_date=None, template_name=None):
"""Get due date from `Payment Terms Template`"""
due_date = None
if (bill_date or posting_date) and party:
due_date = bill_date or posting_date
template_name = get_payment_terms_template(party, party_type, company)
if not template_name:
template_name = get_payment_terms_template(party, party_type, company)
if template_name:
due_date = get_due_date_from_template(template_name, posting_date, bill_date).strftime("%Y-%m-%d")
@@ -765,7 +769,7 @@ def validate_account_party_type(self):
if self.party_type and self.party:
account_type = frappe.get_cached_value("Account", self.account, "account_type")
if account_type and (account_type not in ["Receivable", "Payable"]):
if account_type and (account_type not in ["Receivable", "Payable", "Equity"]):
frappe.throw(
_(
"Party Type and Party can only be set for Receivable / Payable account<br><br>" "{0}"

View File

@@ -44,7 +44,7 @@
{% endfor %}
<tr>
<td class="right" colspan="3" ><strong>Total (debit) </strong></td>
<td class="left" >{{ gl | sum(attribute='debit') }}</td>
<td class="left" >{{ gl | sum(attribute='debit') | round(2) }}</td>
</tr>
<tr>
<td class="top-bottom" colspan="5"><strong>Credit</strong></td>
@@ -61,7 +61,7 @@
{% endfor %}
<tr>
<td class="right" colspan="3"><strong>Total (credit) </strong></td>
<td class="left" >{{ gl | sum(attribute='credit') }}</td>
<td class="left" >{{ gl | sum(attribute='credit') | round(2) }}</td>
</tr>
<tr>
<td class="top-bottom" colspan="5"><b>Narration: </b>{{ gl[0].remarks }}</td>

View File

@@ -0,0 +1,161 @@
{%- macro add_header(page_num, max_pages, doc, letter_head, no_letterhead, footer, print_settings=None, print_heading_template=None) -%}
{% if letter_head and not no_letterhead %}
<div class="letter-head">{{ letter_head }}</div>
{% endif %}
{% if print_heading_template %}
{{ frappe.render_template(print_heading_template, {"doc":doc}) }}
{% else %}
{% endif %}
{%- if doc.meta.is_submittable and doc.docstatus==2-%}
<div class="text-center" document-status="cancelled">
<h4 style="margin: 0px;">{{ _("CANCELLED") }}</h4>
</div>
{%- endif -%}
{%- endmacro -%}
{% for page in layout %}
<div class="page-break">
<div {% if print_settings.repeat_header_footer %} id="header-html" class="hidden-pdf" {% endif %}>
{{ add_header(loop.index, layout|len, doc, letter_head, no_letterhead, footer, print_settings) }}
</div>
<style>
.taxes-section .order-taxes.mt-5{
margin-top: 0px !important;
}
.taxes-section .order-taxes .border-btm.pb-5{
padding-bottom: 0px !important;
}
.print-format label{
color: #74808b;
font-size: 12px;
margin-bottom: 4px;
}
</style>
{% if print_settings.repeat_header_footer %}
<div id="footer-html" class="visible-pdf">
{% if not no_letterhead and footer %}
<div class="letter-head-footer">
{{ footer }}
</div>
{% endif %}
<p class="text-center small page-number visible-pdf">
{{ _("Page {0} of {1}").format('<span class="page"></span>', '<span class="topage"></span>') }}
</p>
</div>
{% endif %}
<div class="row section-break" style="margin-bottom: 10px;">
<div class="col-xs-6 p-0">
<div class="col-xs-12 value text-uppercase"><b>{{ doc.customer }}</b></div>
<div class="col-xs-12">
{{ doc.address_display }}
</div>
<div class="col-xs-12">
{{ _("Contact: ")+doc.contact_display if doc.contact_display else '' }}
</div>
<div class="col-xs-12">
{{ _("Mobile: ")+doc.contact_mobile if doc.contact_mobile else '' }}
</div>
</div>
<div class="col-xs-3"></div>
<div class="col-xs-3" style="padding-left: 5px;">
<div>
<div><label>{{ _("Invoice ID") }}</label></div>
<div>{{ doc.name }}</div>
</div>
<div style="margin-top: 20px;">
<div><label>{{ _("Invoice Date") }}</label></div>
<div>{{ frappe.utils.format_date(doc.posting_date) }}</div>
</div>
<div style="margin-top: 20px;">
<div><label>{{ _("Due Date") }}</label></div>
<div>{{ frappe.utils.format_date(doc.due_date) }}</div>
</div>
</div>
</div>
<div class="section-break">
<table class="table table-bordered table-condensed mb-0" style="width: 100%; border-collapse: collapse; font-size: 12px;">
<colgroup>
<col style="width: 5%">
<col style="width: 45%">
<col style="width: 10%">
<col style="width: 20%">
<col style="width: 20%">
</colgroup>
<thead>
<tr>
<th class="text-uppercase" style="text-align:center">{{ _("Sr") }}</th>
<th class="text-uppercase" style="text-align:center">{{ _("Details") }}</th>
<th class="text-uppercase" style="text-align:center">{{ _("Qty") }}</th>
<th class="text-uppercase" style="text-align:right">{{ _("Rate") }}</th>
<th class="text-uppercase" style="text-align:right">{{ _("Amount") }}</th>
</tr>
</thead>
{% for item in doc.items %}
<tr>
<td style="text-align:center">{{ loop.index }}</td>
<td>
<b>{{ item.item_code }}: {{ item.item_name }}</b>
{% if (item.description != item.item_name) %}
<br>{{ item.description }}
{% endif %}
</td>
<td style="text-align: center;">
{{ item.get_formatted("qty", 0) }}
{{ item.get_formatted("uom", 0) }}
</td>
<td style="text-align: right;">{{ item.get_formatted("net_rate", doc) }}</td>
<td style="text-align: right;">{{ item.get_formatted("net_amount", doc) }}</td>
</tr>
{% endfor %}
</table>
<!-- total -->
<div class="row">
<div class="col-xs-6">
<div>
<label>{{ _("Amount in Words") }}</label>
{{ doc.in_words }}
</div>
<div style="margin-top: 20px;">
<label>{{ _("Payment Status") }}</label>
{{ doc.status }}
</div>
</div>
<div class="col-xs-6">
<div class="row section-break">
<div class="col-xs-7"><div>{{ _("Sub Total") }}</div></div>
<div class="col-xs-5" style="text-align: right;">{{ doc.get_formatted("net_total", doc) }}</div>
</div>
<div>
{% for d in doc.taxes %}
{% if d.tax_amount %}
<div class="row">
<div class="col-xs-8"><div>{{ _(d.description) }}</div></div>
<div class="col-xs-4" style="text-align: right;">{{ d.get_formatted("tax_amount") }}</div>
</div>
{% endif %}
{% endfor %}
</div>
<div class="row">
<div class="col-xs-7"><div>{{ _("Total") }}</div></div>
<div class="col-xs-5" style="text-align: right;">{{ doc.get_formatted("grand_total", doc) }}</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-12">
<div class="row important data-field">
<div class="col-xs-12"><label>{{ _("Terms and Conditions") }}: </label></div>
<div class="col-xs-12">{{ doc.terms if doc.terms else '' }}</div>
</div>
</div>
</div>
</div>
{% endfor %}

View File

@@ -0,0 +1,32 @@
{
"absolute_value": 0,
"align_labels_right": 0,
"creation": "2025-01-22 16:23:51.012200",
"css": "",
"custom_format": 0,
"default_print_language": "en",
"disabled": 0,
"doc_type": "Sales Invoice",
"docstatus": 0,
"doctype": "Print Format",
"font": "",
"font_size": 14,
"idx": 0,
"line_breaks": 0,
"margin_bottom": 0.0,
"margin_left": 0.0,
"margin_right": 0.0,
"margin_top": 0.0,
"modified": "2025-01-22 16:23:51.012200",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice Print",
"owner": "Administrator",
"page_number": "Hide",
"print_format_builder": 0,
"print_format_builder_beta": 0,
"print_format_type": "Jinja",
"raw_printing": 0,
"show_section_headings": 0,
"standard": "Yes"
}

View File

@@ -89,6 +89,7 @@ frappe.query_reports["Accounts Payable"] = {
fieldname: "party",
label: __("Party"),
fieldtype: "MultiSelectList",
options: "party_type",
get_data: function (txt) {
if (!frappe.query_report.filters) return;

View File

@@ -66,6 +66,7 @@ frappe.query_reports["Accounts Payable Summary"] = {
fieldname: "party",
label: __("Party"),
fieldtype: "MultiSelectList",
options: "party_type",
get_data: function (txt) {
if (!frappe.query_report.filters) return;

View File

@@ -56,6 +56,7 @@ frappe.query_reports["Accounts Receivable"] = {
fieldname: "party",
label: __("Party"),
fieldtype: "MultiSelectList",
options: "party_type",
get_data: function (txt) {
if (!frappe.query_report.filters) return;

View File

@@ -517,10 +517,10 @@ class ReceivablePayableReport:
select
si.name, si.party_account_currency, si.currency, si.conversion_rate,
si.total_advance, ps.due_date, ps.payment_term, ps.payment_amount, ps.base_payment_amount,
ps.description, ps.paid_amount, ps.discounted_amount
ps.description, ps.paid_amount, ps.base_paid_amount, ps.discounted_amount
from `tab{row.voucher_type}` si, `tabPayment Schedule` ps
where
si.name = ps.parent and
si.name = ps.parent and ps.parenttype = '{row.voucher_type}' and
si.name = %s and
si.is_return = 0
order by ps.paid_amount desc, due_date
@@ -540,20 +540,24 @@ class ReceivablePayableReport:
# Deduct that from paid amount pre allocation
row.paid -= flt(payment_terms_details[0].total_advance)
company_currency = frappe.get_value("Company", self.filters.get("company"), "default_currency")
# If single payment terms, no need to split the row
if len(payment_terms_details) == 1 and payment_terms_details[0].payment_term:
self.append_payment_term(row, payment_terms_details[0], original_row)
self.append_payment_term(row, payment_terms_details[0], original_row, company_currency)
return
for d in payment_terms_details:
term = frappe._dict(original_row)
self.append_payment_term(row, d, term)
self.append_payment_term(row, d, term, company_currency)
def append_payment_term(self, row, d, term):
if d.currency == d.party_account_currency:
def append_payment_term(self, row, d, term, company_currency):
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"):
invoiced = d.payment_amount
else:
invoiced = d.base_payment_amount
paid_amount = d.paid_amount
row.payment_terms.append(
term.update(
@@ -562,15 +566,15 @@ class ReceivablePayableReport:
"invoiced": invoiced,
"invoice_grand_total": row.invoiced,
"payment_term": d.description or d.payment_term,
"paid": d.paid_amount + d.discounted_amount,
"paid": paid_amount + d.discounted_amount,
"credit_note": 0.0,
"outstanding": invoiced - d.paid_amount - d.discounted_amount,
"outstanding": invoiced - paid_amount - d.discounted_amount,
}
)
)
if d.paid_amount:
row["paid"] -= d.paid_amount + d.discounted_amount
if paid_amount:
row["paid"] -= paid_amount + d.discounted_amount
def allocate_closing_to_term(self, row, term, key):
if row[key]:
@@ -729,11 +733,13 @@ class ReceivablePayableReport:
"company": self.filters.company,
"update_outstanding_for_self": 0,
}
or_filters = {}
for party_type in self.party_type:
if party_type := self.filters.party_type:
party_field = scrub(party_type)
if self.filters.get(party_field):
or_filters.update({party_field: self.filters.get(party_field)})
if parties := self.filters.get("party"):
or_filters.update({party_field: ["in", parties]})
self.return_entries = frappe._dict(
frappe.get_all(
doctype, filters=filters, or_filters=or_filters, fields=["name", "return_against"], as_list=1

View File

@@ -66,6 +66,7 @@ frappe.query_reports["Accounts Receivable Summary"] = {
fieldname: "party",
label: __("Party"),
fieldtype: "MultiSelectList",
options: "party_type",
get_data: function (txt) {
if (!frappe.query_report.filters) return;

View File

@@ -50,6 +50,7 @@ def get_group_by_asset_category_data(filters):
flt(row.accumulated_depreciation_as_on_from_date)
+ flt(row.depreciation_amount_during_the_period)
- flt(row.depreciation_eliminated_during_the_period)
- flt(row.depreciation_eliminated_via_reversal)
)
row.net_asset_value_as_on_from_date = flt(row.value_as_on_from_date) - flt(
@@ -144,6 +145,130 @@ def get_asset_categories_for_grouped_by_category(filters):
)
def get_assets_for_grouped_by_category(filters):
condition = ""
if filters.get("asset_category"):
condition = f" and a.asset_category = '{filters.get('asset_category')}'"
finance_book_filter = ""
if filters.get("finance_book"):
finance_book_filter += " and ifnull(gle.finance_book, '')=%(finance_book)s"
condition += " and exists (select 1 from `tabAsset Depreciation Schedule` ads where ads.asset = a.name and ads.finance_book = %(finance_book)s)"
# nosemgrep
return frappe.db.sql(
f"""
SELECT results.asset_category,
sum(results.accumulated_depreciation_as_on_from_date) as accumulated_depreciation_as_on_from_date,
sum(results.depreciation_eliminated_via_reversal) as depreciation_eliminated_via_reversal,
sum(results.depreciation_eliminated_during_the_period) as depreciation_eliminated_during_the_period,
sum(results.depreciation_amount_during_the_period) as depreciation_amount_during_the_period
from (SELECT a.asset_category,
ifnull(sum(case when gle.posting_date < %(from_date)s and (ifnull(a.disposal_date, 0) = 0 or a.disposal_date >= %(from_date)s) then
gle.debit
else
0
end), 0) as accumulated_depreciation_as_on_from_date,
ifnull(sum(case when gle.posting_date <= %(to_date)s and ifnull(a.disposal_date, 0) = 0 then
gle.credit
else
0
end), 0) as depreciation_eliminated_via_reversal,
ifnull(sum(case when ifnull(a.disposal_date, 0) != 0 and a.disposal_date >= %(from_date)s
and a.disposal_date <= %(to_date)s and gle.posting_date <= a.disposal_date then
gle.debit
else
0
end), 0) as depreciation_eliminated_during_the_period,
ifnull(sum(case when gle.posting_date >= %(from_date)s and gle.posting_date <= %(to_date)s
and (ifnull(a.disposal_date, 0) = 0 or gle.posting_date <= a.disposal_date) then
gle.debit
else
0
end), 0) as depreciation_amount_during_the_period
from `tabGL Entry` gle
join `tabAsset` a on
gle.against_voucher = a.name
join `tabAsset Category Account` aca on
aca.parent = a.asset_category and aca.company_name = %(company)s
join `tabCompany` company on
company.name = %(company)s
where
a.docstatus=1
and a.company=%(company)s
and a.purchase_date <= %(to_date)s
and gle.is_cancelled = 0
and gle.account = ifnull(aca.depreciation_expense_account, company.depreciation_expense_account)
{condition} {finance_book_filter}
group by a.asset_category
union
SELECT a.asset_category,
ifnull(sum(case when ifnull(a.disposal_date, 0) != 0 and a.disposal_date < %(from_date)s then
0
else
a.opening_accumulated_depreciation
end), 0) as accumulated_depreciation_as_on_from_date,
0 as depreciation_eliminated_via_reversal,
ifnull(sum(case when a.disposal_date >= %(from_date)s and a.disposal_date <= %(to_date)s then
a.opening_accumulated_depreciation
else
0
end), 0) as depreciation_eliminated_during_the_period,
0 as depreciation_amount_during_the_period
from `tabAsset` a
where a.docstatus=1 and a.company=%(company)s and a.purchase_date <= %(to_date)s {condition}
group by a.asset_category) as results
group by results.asset_category
""",
{
"to_date": filters.to_date,
"from_date": filters.from_date,
"company": filters.company,
"finance_book": filters.get("finance_book", ""),
},
as_dict=1,
)
def get_group_by_asset_data(filters):
data = []
asset_details = get_asset_details_for_grouped_by_category(filters)
assets = get_assets_for_grouped_by_asset(filters)
for asset_detail in asset_details:
row = frappe._dict()
row.update(asset_detail)
row.value_as_on_to_date = (
flt(row.value_as_on_from_date)
+ flt(row.value_of_new_purchase)
- flt(row.value_of_sold_asset)
- flt(row.value_of_scrapped_asset)
- flt(row.value_of_capitalized_asset)
)
row.update(next(asset for asset in assets if asset["asset"] == asset_detail.get("name", "")))
row.accumulated_depreciation_as_on_to_date = (
flt(row.accumulated_depreciation_as_on_from_date)
+ flt(row.depreciation_amount_during_the_period)
- flt(row.depreciation_eliminated_during_the_period)
- flt(row.depreciation_eliminated_via_reversal)
)
row.net_asset_value_as_on_from_date = flt(row.value_as_on_from_date) - flt(
row.accumulated_depreciation_as_on_from_date
)
row.net_asset_value_as_on_to_date = flt(row.value_as_on_to_date) - flt(
row.accumulated_depreciation_as_on_to_date
)
data.append(row)
return data
def get_asset_details_for_grouped_by_category(filters):
condition = ""
if filters.get("asset"):
@@ -223,123 +348,6 @@ def get_asset_details_for_grouped_by_category(filters):
)
def get_group_by_asset_data(filters):
data = []
asset_details = get_asset_details_for_grouped_by_category(filters)
assets = get_assets_for_grouped_by_asset(filters)
for asset_detail in asset_details:
row = frappe._dict()
row.update(asset_detail)
row.value_as_on_to_date = (
flt(row.value_as_on_from_date)
+ flt(row.value_of_new_purchase)
- flt(row.value_of_sold_asset)
- flt(row.value_of_scrapped_asset)
- flt(row.value_of_capitalized_asset)
)
row.update(next(asset for asset in assets if asset["asset"] == asset_detail.get("name", "")))
row.accumulated_depreciation_as_on_to_date = (
flt(row.accumulated_depreciation_as_on_from_date)
+ flt(row.depreciation_amount_during_the_period)
- flt(row.depreciation_eliminated_during_the_period)
)
row.net_asset_value_as_on_from_date = flt(row.value_as_on_from_date) - flt(
row.accumulated_depreciation_as_on_from_date
)
row.net_asset_value_as_on_to_date = flt(row.value_as_on_to_date) - flt(
row.accumulated_depreciation_as_on_to_date
)
data.append(row)
return data
def get_assets_for_grouped_by_category(filters):
condition = ""
if filters.get("asset_category"):
condition = f" and a.asset_category = '{filters.get('asset_category')}'"
finance_book_filter = ""
if filters.get("finance_book"):
finance_book_filter += " and ifnull(gle.finance_book, '')=%(finance_book)s"
condition += " and exists (select 1 from `tabAsset Depreciation Schedule` ads where ads.asset = a.name and ads.finance_book = %(finance_book)s)"
# nosemgrep
return frappe.db.sql(
f"""
SELECT results.asset_category,
sum(results.accumulated_depreciation_as_on_from_date) as accumulated_depreciation_as_on_from_date,
sum(results.depreciation_eliminated_during_the_period) as depreciation_eliminated_during_the_period,
sum(results.depreciation_amount_during_the_period) as depreciation_amount_during_the_period
from (SELECT a.asset_category,
ifnull(sum(case when gle.posting_date < %(from_date)s and (ifnull(a.disposal_date, 0) = 0 or a.disposal_date >= %(from_date)s) then
gle.debit
else
0
end), 0) as accumulated_depreciation_as_on_from_date,
ifnull(sum(case when ifnull(a.disposal_date, 0) != 0 and a.disposal_date >= %(from_date)s
and a.disposal_date <= %(to_date)s and gle.posting_date <= a.disposal_date then
gle.debit
else
0
end), 0) as depreciation_eliminated_during_the_period,
ifnull(sum(case when gle.posting_date >= %(from_date)s and gle.posting_date <= %(to_date)s
and (ifnull(a.disposal_date, 0) = 0 or gle.posting_date <= a.disposal_date) then
gle.debit
else
0
end), 0) as depreciation_amount_during_the_period
from `tabGL Entry` gle
join `tabAsset` a on
gle.against_voucher = a.name
join `tabAsset Category Account` aca on
aca.parent = a.asset_category and aca.company_name = %(company)s
join `tabCompany` company on
company.name = %(company)s
where
a.docstatus=1
and a.company=%(company)s
and a.purchase_date <= %(to_date)s
and gle.debit != 0
and gle.is_cancelled = 0
and gle.account = ifnull(aca.depreciation_expense_account, company.depreciation_expense_account)
{condition} {finance_book_filter}
group by a.asset_category
union
SELECT a.asset_category,
ifnull(sum(case when ifnull(a.disposal_date, 0) != 0 and (a.disposal_date < %(from_date)s or a.disposal_date > %(to_date)s) then
0
else
a.opening_accumulated_depreciation
end), 0) as accumulated_depreciation_as_on_from_date,
ifnull(sum(case when a.disposal_date >= %(from_date)s and a.disposal_date <= %(to_date)s then
a.opening_accumulated_depreciation
else
0
end), 0) as depreciation_eliminated_during_the_period,
0 as depreciation_amount_during_the_period
from `tabAsset` a
where a.docstatus=1 and a.company=%(company)s and a.purchase_date <= %(to_date)s {condition}
group by a.asset_category) as results
group by results.asset_category
""",
{
"to_date": filters.to_date,
"from_date": filters.from_date,
"company": filters.company,
"finance_book": filters.get("finance_book", ""),
},
as_dict=1,
)
def get_assets_for_grouped_by_asset(filters):
condition = ""
if filters.get("asset"):
@@ -354,6 +362,7 @@ def get_assets_for_grouped_by_asset(filters):
f"""
SELECT results.name as asset,
sum(results.accumulated_depreciation_as_on_from_date) as accumulated_depreciation_as_on_from_date,
sum(results.depreciation_eliminated_via_reversal) as depreciation_eliminated_via_reversal,
sum(results.depreciation_eliminated_during_the_period) as depreciation_eliminated_during_the_period,
sum(results.depreciation_amount_during_the_period) as depreciation_amount_during_the_period
from (SELECT a.name as name,
@@ -362,6 +371,11 @@ def get_assets_for_grouped_by_asset(filters):
else
0
end), 0) as accumulated_depreciation_as_on_from_date,
ifnull(sum(case when gle.posting_date <= %(to_date)s and ifnull(a.disposal_date, 0) = 0 then
gle.credit
else
0
end), 0) as depreciation_eliminated_via_reversal,
ifnull(sum(case when ifnull(a.disposal_date, 0) != 0 and a.disposal_date >= %(from_date)s
and a.disposal_date <= %(to_date)s and gle.posting_date <= a.disposal_date then
gle.debit
@@ -385,18 +399,18 @@ def get_assets_for_grouped_by_asset(filters):
a.docstatus=1
and a.company=%(company)s
and a.purchase_date <= %(to_date)s
and gle.debit != 0
and gle.is_cancelled = 0
and gle.account = ifnull(aca.depreciation_expense_account, company.depreciation_expense_account)
{finance_book_filter} {condition}
group by a.name
union
SELECT a.name as name,
ifnull(sum(case when ifnull(a.disposal_date, 0) != 0 and (a.disposal_date < %(from_date)s or a.disposal_date > %(to_date)s) then
ifnull(sum(case when ifnull(a.disposal_date, 0) != 0 and a.disposal_date < %(from_date)s then
0
else
a.opening_accumulated_depreciation
end), 0) as accumulated_depreciation_as_on_from_date,
0 as depreciation_as_on_from_date_credit,
ifnull(sum(case when a.disposal_date >= %(from_date)s and a.disposal_date <= %(to_date)s then
a.opening_accumulated_depreciation
else
@@ -503,6 +517,12 @@ def get_columns(filters):
"fieldtype": "Currency",
"width": 270,
},
{
"label": _("Depreciation eliminated via reversal"),
"fieldname": "depreciation_eliminated_via_reversal",
"fieldtype": "Currency",
"width": 270,
},
{
"label": _("Net Asset value as on") + " " + formatdate(filters.day_before_from_date),
"fieldname": "net_asset_value_as_on_from_date",

View File

@@ -27,6 +27,7 @@ def get_report_filters(report_filters):
["Purchase Invoice", "docstatus", "=", 1],
["Purchase Invoice", "per_received", "<", 100],
["Purchase Invoice", "update_stock", "=", 0],
["Purchase Invoice", "is_opening", "!=", "Yes"],
]
if report_filters.get("purchase_invoice"):

View File

@@ -91,6 +91,7 @@ function get_filters() {
fieldname: "budget_against_filter",
label: __("Dimension Filter"),
fieldtype: "MultiSelectList",
options: "budget_against",
get_data: function (txt) {
if (!frappe.query_report.filters) return;

View File

@@ -263,6 +263,7 @@ def get_actual_details(name, filters):
and ba.account=gl.account
and b.{budget_against} = gl.{budget_against}
and gl.fiscal_year between %s and %s
and gl.is_cancelled = 0
and b.{budget_against} = %s
and exists(
select

View File

@@ -307,6 +307,7 @@ class Deferred_Revenue_and_Expense_Report:
.where(
(inv.docstatus == 1)
& (deferred_flag_field == 1)
& (inv.company == self.filters.company)
& (
(
(self.period_list[0].from_date >= inv_item.service_start_date)

View File

@@ -2,5 +2,27 @@
// For license information, please see license.txt
frappe.query_reports["Delivered Items To Be Billed"] = {
filters: [],
filters: [
{
label: __("Company"),
fieldname: "company",
fieldtype: "Link",
options: "Company",
reqd: 1,
default: frappe.defaults.get_default("Company"),
},
{
label: __("As on Date"),
fieldname: "posting_date",
fieldtype: "Date",
reqd: 1,
default: frappe.datetime.get_today(),
},
{
label: __("Delivery Note"),
fieldname: "delivery_note",
fieldtype: "Link",
options: "Delivery Note",
},
],
};

View File

@@ -3,6 +3,7 @@
from frappe import _
from pypika import Order
from erpnext.accounts.report.non_billed_report import get_ordered_to_be_billed_data
@@ -10,7 +11,7 @@ from erpnext.accounts.report.non_billed_report import get_ordered_to_be_billed_d
def execute(filters=None):
columns = get_column()
args = get_args()
data = get_ordered_to_be_billed_data(args)
data = get_ordered_to_be_billed_data(args, filters)
return columns, data
@@ -76,13 +77,6 @@ def get_column():
"options": "Project",
"width": 120,
},
{
"label": _("Company"),
"fieldname": "company",
"fieldtype": "Link",
"options": "Company",
"width": 120,
},
]
@@ -92,5 +86,6 @@ def get_args():
"party": "customer",
"date": "posting_date",
"order": "name",
"order_by": "desc",
"order_by": Order.desc,
"reference_field": "delivery_note",
}

View File

@@ -630,7 +630,7 @@ def get_cost_centers_with_children(cost_centers):
def get_columns(periodicity, period_list, accumulated_values=1, company=None, cash_flow=False):
columns = [
{
"fieldname": "account",
"fieldname": "account" if not cash_flow else "section",
"label": _("Account") if not cash_flow else _("Section"),
"fieldtype": "Link",
"options": "Account",

View File

@@ -73,6 +73,7 @@ frappe.query_reports["General Ledger"] = {
fieldname: "party",
label: __("Party"),
fieldtype: "MultiSelectList",
options: "party_type",
get_data: function (txt) {
if (!frappe.query_report.filters) return;
@@ -151,6 +152,7 @@ frappe.query_reports["General Ledger"] = {
fieldname: "cost_center",
label: __("Cost Center"),
fieldtype: "MultiSelectList",
options: "Cost Center",
get_data: function (txt) {
return frappe.db.get_link_options("Cost Center", txt, {
company: frappe.query_report.get_filter_value("company"),
@@ -161,6 +163,7 @@ frappe.query_reports["General Ledger"] = {
fieldname: "project",
label: __("Project"),
fieldtype: "MultiSelectList",
options: "Project",
get_data: function (txt) {
return frappe.db.get_link_options("Project", txt, {
company: frappe.query_report.get_filter_value("company"),

View File

@@ -534,6 +534,7 @@ def get_accountwise_gle(filters, accounting_dimensions, gl_entries, gle_map, tot
for dim in accounting_dimensions:
keylist.append(gle.get(dim))
keylist.append(gle.get("cost_center"))
keylist.append(gle.get("project"))
key = tuple(keylist)
if key not in consolidated_gle:
@@ -679,10 +680,11 @@ def get_columns(filters):
{"label": _("Against Account"), "fieldname": "against", "width": 120},
{"label": _("Party Type"), "fieldname": "party_type", "width": 100},
{"label": _("Party"), "fieldname": "party", "width": 100},
{"label": _("Project"), "options": "Project", "fieldname": "project", "width": 100},
]
if filters.get("include_dimensions"):
columns.append({"label": _("Project"), "options": "Project", "fieldname": "project", "width": 100})
for dim in get_accounting_dimensions(as_list=False):
columns.append(
{"label": _(dim.label), "options": dim.label, "fieldname": dim.fieldname, "width": 100}

View File

@@ -67,6 +67,7 @@ frappe.query_reports["Gross Profit"] = {
fieldname: "cost_center",
label: __("Cost Center"),
fieldtype: "MultiSelectList",
options: "Cost Center",
get_data: function (txt) {
return frappe.db.get_link_options("Cost Center", txt, {
company: frappe.query_report.get_filter_value("company"),
@@ -77,6 +78,7 @@ frappe.query_reports["Gross Profit"] = {
fieldname: "project",
label: __("Project"),
fieldtype: "MultiSelectList",
options: "Project",
get_data: function (txt) {
return frappe.db.get_link_options("Project", txt, {
company: frappe.query_report.get_filter_value("company"),

View File

@@ -1,5 +1,5 @@
{
"add_total_row": 1,
"add_total_row": 0,
"columns": [],
"creation": "2013-02-25 17:03:34",
"disable_prepared_report": 0,
@@ -9,7 +9,7 @@
"filters": [],
"idx": 3,
"is_standard": "Yes",
"modified": "2022-02-11 10:18:36.956558",
"modified": "2025-01-27 18:40:24.493829",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Gross Profit",

View File

@@ -178,7 +178,14 @@ def get_data_when_grouped_by_invoice(columns, gross_profit_data, filters, group_
# removing Item Code and Item Name columns
del columns[4:6]
total_base_amount = 0
total_buying_amount = 0
for src in gross_profit_data.si_list:
if src.indent == 1:
total_base_amount += src.base_amount or 0.0
total_buying_amount += src.buying_amount or 0.0
row = frappe._dict()
row.indent = src.indent
row.parent_invoice = src.parent_invoice
@@ -189,17 +196,57 @@ def get_data_when_grouped_by_invoice(columns, gross_profit_data, filters, group_
data.append(row)
total_gross_profit = total_base_amount - total_buying_amount
data.append(
frappe._dict(
{
"sales_invoice": "Total",
"qty": None,
"avg._selling_rate": None,
"valuation_rate": None,
"selling_amount": total_base_amount,
"buying_amount": total_buying_amount,
"gross_profit": total_gross_profit,
"gross_profit_%": flt(
(total_gross_profit / total_base_amount) * 100.0,
cint(frappe.db.get_default("currency_precision")) or 3,
)
if total_base_amount
else 0,
}
)
)
def get_data_when_not_grouped_by_invoice(gross_profit_data, filters, group_wise_columns, data):
for src in gross_profit_data.grouped_data:
row = []
for col in group_wise_columns.get(scrub(filters.group_by)):
row.append(src.get(col))
total_base_amount = 0
total_buying_amount = 0
row.append(filters.currency)
group_columns = group_wise_columns.get(scrub(filters.group_by))
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
row = [src.get(col) for col in group_columns] + [filters.currency]
data.append(row)
total_gross_profit = total_base_amount - total_buying_amount
currency_precision = cint(frappe.db.get_default("currency_precision")) or 3
gross_profit_percent = (total_gross_profit / total_base_amount * 100.0) if total_base_amount else 0
total_row = {
group_columns[0]: "Total",
"base_amount": total_base_amount,
"buying_amount": total_buying_amount,
"gross_profit": total_gross_profit,
"gross_profit_percent": flt(gross_profit_percent, currency_precision),
}
total_row = [total_row.get(col, None) for col in [*group_columns, "currency"]]
data.append(total_row)
def get_columns(group_wise_columns, filters):
columns = []

View File

@@ -605,3 +605,33 @@ class TestGrossProfit(FrappeTestCase):
item_from_sinv2 = [x for x in data if x.parent_invoice == sinv2.name]
self.assertEqual(len(item_from_sinv2), 1)
self.assertEqual(1800, item_from_sinv2[0].valuation_rate)
def test_gross_profit_groupby_invoices(self):
create_sales_invoice(
qty=1,
rate=100,
company=self.company,
customer=self.customer,
item_code=self.item,
item_name=self.item,
cost_center=self.cost_center,
warehouse=self.warehouse,
debit_to=self.debit_to,
parent_cost_center=self.cost_center,
update_stock=0,
currency="INR",
income_account=self.income_account,
expense_account=self.expense_account,
)
filters = frappe._dict(
company=self.company, from_date=nowdate(), to_date=nowdate(), 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)

View File

@@ -4,11 +4,12 @@
import frappe
from frappe.model.meta import get_field_precision
from frappe.query_builder.functions import IfNull, Round
from erpnext import get_default_currency
def get_ordered_to_be_billed_data(args):
def get_ordered_to_be_billed_data(args, filters=None):
doctype, party = args.get("doctype"), args.get("party")
child_tab = doctype + " Item"
precision = (
@@ -18,47 +19,57 @@ def get_ordered_to_be_billed_data(args):
or 2
)
project_field = get_project_field(doctype, party)
doctype = frappe.qb.DocType(doctype)
child_doctype = frappe.qb.DocType(child_tab)
return frappe.db.sql(
"""
Select
`{parent_tab}`.name, `{parent_tab}`.{date_field},
`{parent_tab}`.{party}, `{parent_tab}`.{party}_name,
`{child_tab}`.item_code,
`{child_tab}`.base_amount,
(`{child_tab}`.billed_amt * ifnull(`{parent_tab}`.conversion_rate, 1)),
(`{child_tab}`.base_rate * ifnull(`{child_tab}`.returned_qty, 0)),
(`{child_tab}`.base_amount -
(`{child_tab}`.billed_amt * ifnull(`{parent_tab}`.conversion_rate, 1)) -
(`{child_tab}`.base_rate * ifnull(`{child_tab}`.returned_qty, 0))),
`{child_tab}`.item_name, `{child_tab}`.description,
{project_field}, `{parent_tab}`.company
from
`{parent_tab}`, `{child_tab}`
where
`{parent_tab}`.name = `{child_tab}`.parent and `{parent_tab}`.docstatus = 1
and `{parent_tab}`.status not in ('Closed', 'Completed')
and `{child_tab}`.amount > 0
and (`{child_tab}`.base_amount -
round(`{child_tab}`.billed_amt * ifnull(`{parent_tab}`.conversion_rate, 1), {precision}) -
(`{child_tab}`.base_rate * ifnull(`{child_tab}`.returned_qty, 0))) > 0
order by
`{parent_tab}`.{order} {order_by}
""".format(
parent_tab="tab" + doctype,
child_tab="tab" + child_tab,
precision=precision,
party=party,
date_field=args.get("date"),
project_field=project_field,
order=args.get("order"),
order_by=args.get("order_by"),
docname = filters.get(args.get("reference_field"), None)
project_field = get_project_field(doctype, child_doctype, party)
query = (
frappe.qb.from_(doctype)
.inner_join(child_doctype)
.on(doctype.name == child_doctype.parent)
.select(
doctype.name,
doctype[args.get("date")].as_("date"),
doctype[party],
doctype[party + "_name"],
child_doctype.item_code,
child_doctype.base_amount.as_("amount"),
(child_doctype.billed_amt * IfNull(doctype.conversion_rate, 1)).as_("billed_amount"),
(child_doctype.base_rate * IfNull(child_doctype.returned_qty, 0)).as_("returned_amount"),
(
child_doctype.base_amount
- (child_doctype.billed_amt * IfNull(doctype.conversion_rate, 1))
- (child_doctype.base_rate * IfNull(child_doctype.returned_qty, 0))
).as_("pending_amount"),
child_doctype.item_name,
child_doctype.description,
project_field,
)
.where(
(doctype.docstatus == 1)
& (doctype.status.notin(["Closed", "Completed"]))
& (doctype.company == filters.get("company"))
& (doctype.posting_date <= filters.get("posting_date"))
& (child_doctype.amount > 0)
& (
child_doctype.base_amount
- Round(child_doctype.billed_amt * IfNull(doctype.conversion_rate, 1), precision)
- (child_doctype.base_rate * IfNull(child_doctype.returned_qty, 0))
)
> 0
)
.orderby(doctype[args.get("order")], order=args.get("order_by"))
)
if docname:
query = query.where(doctype.name == docname)
def get_project_field(doctype, party):
return query.run(as_dict=True)
def get_project_field(doctype, child_doctype, party):
if party == "supplier":
doctype = doctype + " Item"
return "`tab%s`.project" % (doctype)
return child_doctype.project
return doctype.project

View File

@@ -50,6 +50,7 @@ function get_filters() {
fieldname: "party",
label: __("Party"),
fieldtype: "MultiSelectList",
options: "party_type",
get_data: function (txt) {
if (!frappe.query_report.filters) return;

View File

@@ -2,5 +2,27 @@
// For license information, please see license.txt
frappe.query_reports["Received Items To Be Billed"] = {
filters: [],
filters: [
{
label: __("Company"),
fieldname: "company",
fieldtype: "Link",
options: "Company",
reqd: 1,
default: frappe.defaults.get_default("Company"),
},
{
label: __("As on Date"),
fieldname: "posting_date",
fieldtype: "Date",
reqd: 1,
default: frappe.datetime.get_today(),
},
{
label: __("Purchase Receipt"),
fieldname: "purchase_receipt",
fieldtype: "Link",
options: "Purchase Receipt",
},
],
};

View File

@@ -3,6 +3,7 @@
from frappe import _
from pypika import Order
from erpnext.accounts.report.non_billed_report import get_ordered_to_be_billed_data
@@ -10,7 +11,7 @@ from erpnext.accounts.report.non_billed_report import get_ordered_to_be_billed_d
def execute(filters=None):
columns = get_column()
args = get_args()
data = get_ordered_to_be_billed_data(args)
data = get_ordered_to_be_billed_data(args, filters)
return columns, data
@@ -76,13 +77,6 @@ def get_column():
"options": "Project",
"width": 120,
},
{
"label": _("Company"),
"fieldname": "company",
"fieldtype": "Link",
"options": "Company",
"width": 120,
},
]
@@ -92,5 +86,6 @@ def get_args():
"party": "supplier",
"date": "posting_date",
"order": "name",
"order_by": "desc",
"order_by": Order.desc,
"reference_field": "purchase_receipt",
}

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