Compare commits

...

649 Commits

Author SHA1 Message Date
Frappe PR Bot
c910b8ab03 chore(release): Bumped to Version 14.70.2
## [14.70.2](https://github.com/frappe/erpnext/compare/v14.70.1...v14.70.2) (2024-05-23)

### Bug Fixes

* Fetch outstanding and total amount for reference journal entry ([94c3ee6](94c3ee645d))
2024-05-23 11:01:54 +00:00
ruthra kumar
b9ebb50a02 Merge pull request #41600 from frappe/mergify/bp/version-14/pr-40957
fix: Fetch correct outstanding and total amount for reference journal entry (backport #40920) (backport #40957)
2024-05-23 16:30:31 +05:30
ruthra kumar
38cc28a4c3 chore: resolve conflicts
(cherry picked from commit 5230d411bf)
2024-05-23 10:39:16 +00:00
ruthra kumar
bbb9b9e3b6 chore: remove unused imports
(cherry picked from commit a6bf7c1ebd)
2024-05-23 10:39:15 +00:00
Nabin Hait
94c3ee645d fix: Fetch outstanding and total amount for reference journal entry
(cherry picked from commit f331f9b15c)

# Conflicts:
#	erpnext/accounts/doctype/payment_entry/payment_entry.js
#	erpnext/accounts/doctype/payment_entry/payment_entry.py
(cherry picked from commit 50f6afd588)
2024-05-23 10:39:15 +00:00
Frappe PR Bot
b7d6a54bed chore(release): Bumped to Version 14.70.1
## [14.70.1](https://github.com/frappe/erpnext/compare/v14.70.0...v14.70.1) (2024-05-22)

### Bug Fixes

* minor Dr and Cr between Purchase Receipt and Purchase Invoice ([82d206b](82d206b709))
* possible sql error on General Ledger ([dfb4c47](dfb4c47089))
* print format bold for field "total" ([89d507e](89d507e07e))
* priority not working for multiple pricing rules (backport [#41516](https://github.com/frappe/erpnext/issues/41516)) ([#41524](https://github.com/frappe/erpnext/issues/41524)) ([97fdda8](97fdda8a7c))
* typerror on hide_fields ([331a743](331a743d69))
* validate reorder group warehouse (backport [#41478](https://github.com/frappe/erpnext/issues/41478)) ([#41479](https://github.com/frappe/erpnext/issues/41479)) ([2659535](26595351cc))
2024-05-22 08:46:30 +00:00
ruthra kumar
05e4dae1b8 Merge pull request #41575 from frappe/version-14-hotfix
chore: release v14
2024-05-22 14:15:11 +05:30
mergify[bot]
97fdda8a7c fix: priority not working for multiple pricing rules (backport #41516) (#41524)
* fix: priority not working for multiple pricing rules (#41516)

(cherry picked from commit 5cf5b18aea)

# Conflicts:
#	erpnext/accounts/doctype/pricing_rule/pricing_rule.json
#	erpnext/accounts/doctype/pricing_rule/pricing_rule.py
#	erpnext/patches.txt

* chore: fix conflicts

* chore: fix conflicts

* chore: fix conflicts

---------

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-05-20 13:39:39 +05:30
ruthra kumar
9802333397 Merge pull request #41527 from frappe/mergify/bp/version-14-hotfix/pr-41523
fix: minor Dr and Cr between Purchase Receipt and Purchase Invoice (backport #41523)
2024-05-20 08:32:24 +05:30
ruthra kumar
82d206b709 fix: minor Dr and Cr between Purchase Receipt and Purchase Invoice
This applies for Provisional Accounting for Non-stock items

(cherry picked from commit 1c0a24424a)
2024-05-17 12:21:28 +00:00
ruthra kumar
80810c2ebb Merge pull request #41518 from frappe/mergify/bp/version-14-hotfix/pr-41517
fix: typerror on hide_fields (backport #41517)
2024-05-17 14:54:06 +05:30
ruthra kumar
331a743d69 fix: typerror on hide_fields
(cherry picked from commit deb9766f2a)
2024-05-17 14:51:57 +05:30
ruthra kumar
32a1fea8f0 Merge pull request #41512 from frappe/mergify/bp/version-14-hotfix/pr-41511
fix: possible sql error on General Ledger (backport #41511)
2024-05-17 11:17:24 +05:30
ruthra kumar
dfb4c47089 fix: possible sql error on General Ledger
(cherry picked from commit 76131f8e10)
2024-05-17 05:26:54 +00:00
mergify[bot]
0cbf049608 chore(BOM Explorer): display items in the same order as in the BOM (backport #41496) (#41510)
chore(BOM Explorer): display items in the same order as in the BOM (#41496)

(cherry picked from commit bd381cc0c6)

Co-authored-by: Samuel Danieli <23150094+scdanieli@users.noreply.github.com>
2024-05-17 09:37:03 +05:30
ruthra kumar
3f0cb47464 Merge pull request #41500 from frappe/mergify/bp/version-14-hotfix/pr-40072
fix: print format bold for field "total" (backport #40072)
2024-05-16 15:35:48 +05:30
Nihantra C. Patel
89d507e07e fix: print format bold for field "total"
(cherry picked from commit 3c9640df27)
2024-05-16 10:04:03 +00:00
mergify[bot]
26595351cc fix: validate reorder group warehouse (backport #41478) (#41479)
fix: validate reorder group warehouse (#41478)

(cherry picked from commit 0363afcfd0)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-05-15 15:15:41 +05:30
Frappe PR Bot
dfaca93292 chore(release): Bumped to Version 14.70.0
# [14.70.0](https://github.com/frappe/erpnext/compare/v14.69.1...v14.70.0) (2024-05-15)

### Bug Fixes

* "Based on" field always has the value "Not applicable" ([1078a98](1078a98cce))
* address filter and quotation to for prospect ([c9e7f45](c9e7f450c5))
* address filter and quotation to for prospect ([6902780](690278042d))
* address filter and quotation to for prospect ([754e193](754e193c76))
* consistent use of "Address & Contact" (backport [#41386](https://github.com/frappe/erpnext/issues/41386)) ([#41387](https://github.com/frappe/erpnext/issues/41387)) ([256d6a4](256d6a47ac))
* data getting override in delivery trip (backport [#41431](https://github.com/frappe/erpnext/issues/41431)) ([#41432](https://github.com/frappe/erpnext/issues/41432)) ([5366356](5366356400))
* Default dates in report ([c3244f0](c3244f009b))
* default fiscal year ([7a380f5](7a380f584d))
* Duplicate party name column in AR/AP report ([a8be5f0](a8be5f0789))
* PSOA ageing ([e69e540](e69e5404d3))

### Features

* allow to pick manually qty / batches / serial nos (backport [#40723](https://github.com/frappe/erpnext/issues/40723)) ([#41435](https://github.com/frappe/erpnext/issues/41435)) ([7b28d7d](7b28d7d2b8))
2024-05-15 05:12:14 +00:00
Deepesh Garg
40de3f3481 Merge pull request #41458 from frappe/version-14-hotfix
chore: release v14
2024-05-15 10:40:58 +05:30
Deepesh Garg
fc2614612b Merge pull request #41466 from frappe/mergify/bp/version-14-hotfix/pr-41258
fix: PSOA ageing (#41258)
2024-05-14 21:19:17 +05:30
Deepesh Garg
e69e5404d3 fix: PSOA ageing
(cherry picked from commit fed2d11905)
2024-05-14 14:40:36 +00:00
Nabin Hait
14ec6351ae Merge pull request #41448 from frappe/mergify/bp/version-14-hotfix/pr-41412
fix: Duplicate party name column in AR/AP report (backport #41412)
2024-05-14 20:02:56 +05:30
Deepesh Garg
a8be5f0789 fix: Duplicate party name column in AR/AP report
(cherry picked from commit 7501fe8ebd)
2024-05-14 02:53:49 +00:00
Deepesh Garg
42312c5bba Merge pull request #41170 from deepeshgarg007/default_dates_in_reports
fix: Default dates in report
2024-05-14 08:21:51 +05:30
mergify[bot]
7b28d7d2b8 feat: allow to pick manually qty / batches / serial nos (backport #40723) (#41435)
* feat: allow to pick manually qty / batches / serial nos

(cherry picked from commit 50dd9fa8a3)

# Conflicts:
#	erpnext/stock/doctype/pick_list/pick_list.json
#	erpnext/stock/doctype/pick_list/pick_list.py

* chore: fix conflicts

* chore: fix conflicts

---------

Co-authored-by: Rohit Waghchaure <rohitw1991@gmail.com>
2024-05-13 21:37:13 +05:30
mergify[bot]
5366356400 fix: data getting override in delivery trip (backport #41431) (#41432)
fix: data getting override in delivery trip (#41431)

fix: data getting override
(cherry picked from commit 663fcb374d)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-05-13 16:31:34 +05:30
Deepesh Garg
7a380f584d fix: default fiscal year 2024-05-11 17:51:53 +05:30
mergify[bot]
256d6a47ac fix: consistent use of "Address & Contact" (backport #41386) (#41387)
Co-authored-by: Raffael Meyer <14891507+barredterra@users.noreply.github.com>
fix: consistent use of "Address & Contact" (#41386)
2024-05-10 17:42:27 +02:00
Akhil Narang
67e06615a3 Merge pull request #41406 from frappe/mergify/bp/version-14-hotfix/pr-37031
fix: "Based on" field always has the value "Not applicable" (backport #37031)
2024-05-10 16:44:33 +05:30
HarryPaulo
1078a98cce fix: "Based on" field always has the value "Not applicable"
(cherry picked from commit fae640c56f)
2024-05-10 11:13:03 +00:00
ruthra kumar
d87ffae03f Merge pull request #41394 from frappe/mergify/bp/version-14-hotfix/pr-41040
fix: address filter and quotation to for prospect (backport #41040)
2024-05-09 12:48:48 +05:30
ruthra kumar
0404941fb2 chore: resolve conflict 2024-05-09 12:21:29 +05:30
ruthra kumar
c4dfcbec96 refactor: make use of doc.quotation_to
(cherry picked from commit 754c7f6d1c)

# Conflicts:
#	erpnext/selling/doctype/quotation/quotation.js
2024-05-09 06:45:53 +00:00
Nihantra Patel
c9e7f450c5 fix: address filter and quotation to for prospect
(cherry picked from commit 2896e3666c)
2024-05-09 06:45:53 +00:00
Nihantra Patel
690278042d fix: address filter and quotation to for prospect
(cherry picked from commit 24a68a79df)
2024-05-09 06:45:52 +00:00
Nihantra Patel
754e193c76 fix: address filter and quotation to for prospect
(cherry picked from commit fe5b88522e)

# Conflicts:
#	erpnext/selling/doctype/quotation/quotation.js
2024-05-09 06:45:52 +00:00
Frappe PR Bot
9d5e4b3b3a chore(release): Bumped to Version 14.69.1
## [14.69.1](https://github.com/frappe/erpnext/compare/v14.69.0...v14.69.1) (2024-05-09)

### Bug Fixes

* added brand column in Warehouse wise Item Balance Age and Value … (backport [#41280](https://github.com/frappe/erpnext/issues/41280)) ([#41281](https://github.com/frappe/erpnext/issues/41281)) ([d727c52](d727c52421))
* Cost center not getting saved in PSOA ([e82ea12](e82ea12cbc))
* filter validation for batch-wise balance history report (backport [#41356](https://github.com/frappe/erpnext/issues/41356)) ([#41360](https://github.com/frappe/erpnext/issues/41360)) ([339256b](339256bc71))
* incorrect query for Purchase Invoice rate in GP ([93b30d9](93b30d9f11))
* missing Item Name on Save for Quotation created from Item (backport [#41233](https://github.com/frappe/erpnext/issues/41233)) ([#41303](https://github.com/frappe/erpnext/issues/41303)) ([a26ae64](a26ae64385))
* pricing rule rounding ([d2ce927](d2ce927891))
* reset rate for serial batch supplied items ([#41293](https://github.com/frappe/erpnext/issues/41293)) ([cd33199](cd33199da2))

### Performance Improvements

* index on item code for the Pick List Item doctype (backport [#41357](https://github.com/frappe/erpnext/issues/41357)) ([#41362](https://github.com/frappe/erpnext/issues/41362)) ([4647ec8](4647ec8892))
2024-05-09 05:30:06 +00:00
ruthra kumar
d7709cf4e4 Merge pull request #41354 from frappe/version-14-hotfix
chore: release v14
2024-05-09 10:58:39 +05:30
mergify[bot]
4647ec8892 perf: index on item code for the Pick List Item doctype (backport #41357) (#41362)
* perf: index on item code for the Pick List Item doctype (#41357)

(cherry picked from commit 0887161f2a)

# Conflicts:
#	erpnext/stock/doctype/pick_list_item/pick_list_item.json

* chore: fix conflicts

---------

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-05-08 11:38:02 +05:30
mergify[bot]
339256bc71 fix: filter validation for batch-wise balance history report (backport #41356) (#41360)
fix: filter validation for batch-wise balance history report (#41356)

fix: filter validation for batchwise balance history report
(cherry picked from commit 544fc60093)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-05-08 00:15:33 +05:30
ruthra kumar
c3d567b291 Merge pull request #41348 from frappe/mergify/bp/version-14-hotfix/pr-41288
fix: pricing rule rounding (backport #41288)
2024-05-07 10:32:20 +05:30
ruthra kumar
e068bec212 refactor(test): test floor based rounding
(cherry picked from commit c41a037174)
2024-05-07 04:32:04 +00:00
ruthra kumar
d2ce927891 fix: pricing rule rounding
Consider a pricing rule of 20:1 with recursion enabled, free items
should follow the below progression

|   Qty | Free item qty |
|-------+---------------|
|  0-19 |             0 |
| 20-39 |             1 |
| 40-59 |             2 |

(cherry picked from commit 9bf37426c1)
2024-05-07 04:32:03 +00:00
mergify[bot]
a26ae64385 fix: missing Item Name on Save for Quotation created from Item (backport #41233) (#41303)
fix: missing Item Name on Save for Quotation created from Item (#41233)

* fix: missing Item Name on Save for Quotation created from Item

* fix: missing Item Name on Save for Quotation created from Item

(cherry picked from commit c8e92cb1b2)

Co-authored-by: HENRY Florian <florian.henry@open-concept.pro>
2024-05-06 21:46:18 +05:30
s-aga-r
cd33199da2 fix: reset rate for serial batch supplied items (#41293) 2024-05-06 21:37:27 +05:30
ruthra kumar
27100401aa Merge pull request #41336 from frappe/mergify/bp/version-14-hotfix/pr-41334
fix: incorrect query for Purchase Invoice rate in GP (backport #41334)
2024-05-06 13:17:58 +05:30
ruthra kumar
93b30d9f11 fix: incorrect query for Purchase Invoice rate in GP
(cherry picked from commit bd8382c592)
2024-05-06 07:24:49 +00:00
Deepesh Garg
904f369e99 Merge pull request #41324 from frappe/mergify/bp/version-14-hotfix/pr-41318
fix: Cost center not getting saved in PSOA (#41318)
2024-05-06 12:25:14 +05:30
Deepesh Garg
7b9c22775c chore: resolve conflicts 2024-05-06 11:52:26 +05:30
Deepesh Garg
6aa8d5fb4b chore: resolve conflicts 2024-05-06 11:29:53 +05:30
Deepesh Garg
e82ea12cbc fix: Cost center not getting saved in PSOA
(cherry picked from commit 58f7039630)

# Conflicts:
#	erpnext/accounts/doctype/psoa_cost_center/psoa_cost_center.json
#	erpnext/accounts/doctype/psoa_cost_center/psoa_cost_center.py
2024-05-04 08:26:55 +00:00
mergify[bot]
d727c52421 fix: added brand column in Warehouse wise Item Balance Age and Value … (backport #41280) (#41281)
fix: added brand column in Warehouse wise Item Balance Age and Value … (#41280)

fix: added brand coulmn in Warehouse wise Item Balance Age and Value report
(cherry picked from commit 1cbc200770)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-05-03 17:53:52 +05:30
Frappe PR Bot
5ae29655f9 chore(release): Bumped to Version 14.69.0
# [14.69.0](https://github.com/frappe/erpnext/compare/v14.68.2...v14.69.0) (2024-05-02)

### Bug Fixes

* 'NoneType' object has no attribute '_read_rowdata_packet_unbuffered' ([949aa93](949aa9346c))
* args when get the delivery note in delivery trip ([abe64aa](abe64aa1ab))
* args when get the delivery note in delivery trip ([1a7b3c4](1a7b3c437d))
* display term name for single term invoices ([58b68b7](58b68b7597))
* duplicate column in the stock ledger report ([3fcdcef](3fcdcef178))
* handle stock balance unbuffered_cursor error (backport [#41186](https://github.com/frappe/erpnext/issues/41186)) ([#41187](https://github.com/frappe/erpnext/issues/41187)) ([59010c9](59010c9a61))
* incorrectly applying TDS when Advance is in previous FY ([eb22fb9](eb22fb9326))
* mode of payment has precedance ([33d38ba](33d38ba3a7))
* multiple pricing rules with discount amount and discount percentage not working ([#41211](https://github.com/frappe/erpnext/issues/41211)) ([54313b5](54313b5db9))
* negative stock qty error for stock reconciliation ([#41283](https://github.com/frappe/erpnext/issues/41283)) ([9aa054c](9aa054c400))
* permission issue when user permission restricts on company ([45c4167](45c4167c86))
* validation to prevent overallocation ([8318286](8318286865))

### Features

* allow to do reposting for all stock transactions (audit) (backport [#41165](https://github.com/frappe/erpnext/issues/41165)) ([#41205](https://github.com/frappe/erpnext/issues/41205)) ([1e13193](1e1319351d))

### Performance Improvements

* timeout issue while submitting purchase receipt (v14) ([113351e](113351e850))
2024-05-02 04:31:43 +00:00
ruthra kumar
81a99309d8 Merge pull request #41264 from frappe/version-14-hotfix
chore: release v14
2024-05-02 09:59:30 +05:30
rohitwaghchaure
9aa054c400 fix: negative stock qty error for stock reconciliation (#41283)
fix: negative stock qty error for stock reco
2024-05-02 09:38:33 +05:30
ruthra kumar
82b2675aa8 Merge pull request #41269 from frappe/mergify/bp/version-14-hotfix/pr-41268
fix: validation to prevent overallocation (backport #41268)
2024-04-30 18:40:47 +05:30
ruthra kumar
8318286865 fix: validation to prevent overallocation
(cherry picked from commit bf755fab55)
2024-04-30 17:48:55 +05:30
ruthra kumar
f87411f40d Merge pull request #41254 from frappe/mergify/bp/version-14-hotfix/pr-41252
fix: permission issue when user permission restricts on company (backport #41252)
2024-04-30 14:19:39 +05:30
ruthra kumar
45c4167c86 fix: permission issue when user permission restricts on company 2024-04-30 12:24:32 +05:30
ruthra kumar
e0d1f2f6eb Merge pull request #41248 from frappe/mergify/bp/version-14-hotfix/pr-41240
fix: display term name for single term invoices in AR/AP (backport #41240)
2024-04-30 07:42:33 +05:30
ruthra kumar
ba45ea42f8 Merge pull request #41246 from frappe/mergify/bp/version-14-hotfix/pr-41194
fix: TDS incorrectly applied when Advance is in previous FY (backport #41194)
2024-04-30 07:42:23 +05:30
ruthra kumar
58b68b7597 fix: display term name for single term invoices
(cherry picked from commit 5fa4cfee04)
2024-04-30 01:40:17 +00:00
ruthra kumar
4d56c46446 test: TDS deduction across fiscal year
(cherry picked from commit 2f9a144023)
2024-04-30 07:04:21 +05:30
ruthra kumar
eb22fb9326 fix: incorrectly applying TDS when Advance is in previous FY
(cherry picked from commit b195f519e2)
2024-04-30 01:27:56 +00:00
rohitwaghchaure
54313b5db9 fix: multiple pricing rules with discount amount and discount percentage not working (#41211) 2024-04-29 20:53:10 +05:30
mergify[bot]
866b0c6ac7 chore: delete invalid translations (backport #41227) (#41228)
chore: delete invalid translations (#41227)

(cherry picked from commit 067419b7cd)

Co-authored-by: Ankush Menat <ankush@frappe.io>
2024-04-29 10:41:54 +05:30
mergify[bot]
1e1319351d feat: allow to do reposting for all stock transactions (audit) (backport #41165) (#41205)
* feat: allow to do reposting for all transactions (audit)

(cherry picked from commit aefbe21b46)

# Conflicts:
#	erpnext/stock/doctype/stock_reposting_settings/stock_reposting_settings.json
#	erpnext/stock/doctype/stock_reposting_settings/stock_reposting_settings.py

* chore: fix conflicts

* chore: fix conflicts

---------

Co-authored-by: Rohit Waghchaure <rohitw1991@gmail.com>
2024-04-26 14:25:51 +05:30
rohitwaghchaure
6b2874694e Merge pull request #41204 from rohitwaghchaure/fixed-unbuffered_cursor
fix: 'NoneType' object has no attribute '_read_rowdata_packet_unbuffe…
2024-04-26 13:50:07 +05:30
rohitwaghchaure
ff37706bef Merge pull request #41200 from frappe/mergify/bp/version-14-hotfix/pr-41185
fix: args when get the delivery note in delivery trip (backport #41185)
2024-04-26 13:36:14 +05:30
Rohit Waghchaure
949aa9346c fix: 'NoneType' object has no attribute '_read_rowdata_packet_unbuffered' 2024-04-26 13:25:46 +05:30
rohitwaghchaure
2f6fee9877 chore: fix conflicts 2024-04-26 13:15:32 +05:30
Nihantra Patel
abe64aa1ab fix: args when get the delivery note in delivery trip
(cherry picked from commit ca577f7aaa)
2024-04-26 07:40:32 +00:00
Nihantra Patel
1a7b3c437d fix: args when get the delivery note in delivery trip
(cherry picked from commit 2f359e201d)

# Conflicts:
#	erpnext/stock/doctype/delivery_note/delivery_note.py
2024-04-26 07:40:31 +00:00
rohitwaghchaure
da69b1e71b Merge pull request #41196 from frappe/mergify/bp/version-14-hotfix/pr-41192
fix: duplicate column in the stock ledger report (backport #41192)
2024-04-26 12:49:35 +05:30
Frappe PR Bot
d160f5b61a chore(release): Bumped to Version 14.68.2
## [14.68.2](https://github.com/frappe/erpnext/compare/v14.68.1...v14.68.2) (2024-04-26)

### Performance Improvements

* timeout issue while submitting purchase receipt (v14) ([c93840e](c93840eb56))
2024-04-26 06:53:19 +00:00
Rohit Waghchaure
3fcdcef178 fix: duplicate column in the stock ledger report
(cherry picked from commit be7fd6bfb4)
2024-04-26 06:53:08 +00:00
rohitwaghchaure
40ece3f5da Merge pull request #41193 from frappe/mergify/bp/version-14/pr-41174
perf: timeout issue while submitting purchase receipt (v14) (backport #41174)
2024-04-26 12:21:59 +05:30
Rohit Waghchaure
c93840eb56 perf: timeout issue while submitting purchase receipt (v14)
(cherry picked from commit 113351e850)
2024-04-26 05:27:47 +00:00
rohitwaghchaure
7656fe4bfc Merge pull request #41174 from rohitwaghchaure/fixed-performance-issue-for-serial-no-creation
perf: timeout issue while submitting purchase receipt (v14)
2024-04-26 10:56:28 +05:30
mergify[bot]
59010c9a61 fix: handle stock balance unbuffered_cursor error (backport #41186) (#41187)
fix: handle stock balance unbuffered_cursor error (#41186)

(cherry picked from commit 341fb6d8f3)

Co-authored-by: Ankush Menat <ankush@frappe.io>
2024-04-25 17:26:29 +05:30
Rohit Waghchaure
113351e850 perf: timeout issue while submitting purchase receipt (v14) 2024-04-25 12:10:29 +05:30
Frappe PR Bot
2026c986ba chore(release): Bumped to Version 14.68.1
## [14.68.1](https://github.com/frappe/erpnext/compare/v14.68.0...v14.68.1) (2024-04-25)

### Bug Fixes

* mode of payment has precedance ([7e52f72](7e52f72bed))
2024-04-25 03:43:28 +00:00
ruthra kumar
91c202f172 Merge pull request #41179 from frappe/mergify/bp/version-14/pr-41142
fix: mode of payment has precedance in Payment Entry (backport #41142)
2024-04-25 09:12:14 +05:30
ruthra kumar
7e52f72bed fix: mode of payment has precedance
Mode of Payment is given precedence over company/party bank account

(cherry picked from commit 4aef969879)
2024-04-25 09:06:04 +05:30
ruthra kumar
b9d28fc1ad Merge pull request #41178 from frappe/mergify/bp/version-14-hotfix/pr-41142
fix: mode of payment has precedance in Payment Entry (backport #41142)
2024-04-25 09:02:37 +05:30
ruthra kumar
33d38ba3a7 fix: mode of payment has precedance
Mode of Payment is given precedence over company/party bank account

(cherry picked from commit 4aef969879)
2024-04-25 08:58:01 +05:30
Deepesh Garg
ff8dba1cb7 Merge branch 'version-14-hotfix' of https://github.com/frappe/erpnext into default_dates_in_reports 2024-04-24 17:20:55 +05:30
Deepesh Garg
c3244f009b fix: Default dates in report 2024-04-24 16:59:51 +05:30
Frappe PR Bot
30b2cac423 chore(release): Bumped to Version 14.68.0
# [14.68.0](https://github.com/frappe/erpnext/compare/v14.67.2...v14.68.0) (2024-04-24)

### Bug Fixes

* account and stock manager read perm ([03ce9ee](03ce9ee321))
* allow Employee role to select cost center & project (accounting dimensions) (backport [#41160](https://github.com/frappe/erpnext/issues/41160)) ([#41161](https://github.com/frappe/erpnext/issues/41161)) ([bb48440](bb48440591))
* do not add actual expense twice for validating budget ([ec4f07f](ec4f07fd60))
* don't attempt to set gender from salutation (backport [#40997](https://github.com/frappe/erpnext/issues/40997)) ([#41072](https://github.com/frappe/erpnext/issues/41072)) ([5d05bf8](5d05bf8d4e))
* Missing args while fetching items from delivery note ([0df80ad](0df80ad923))
* Multiple partial payment requests against Purchase Invoice ([f1b75e8](f1b75e8c54))
* Party type in Payment Order ([a2e1d13](a2e1d132df))
* Permission for lower dedcution certificate ([a22be6f](a22be6f9b9))
* Test case ([5aef9d2](5aef9d2ef2))
* validate uom is integer for PR item (backport [#41074](https://github.com/frappe/erpnext/issues/41074)) ([#41076](https://github.com/frappe/erpnext/issues/41076)) ([9d0c1dc](9d0c1dc46f))

### Features

* Available batches report as on specific date ([8868cb1](8868cb147d))
* show expense breakup ([f087ec8](f087ec8df5))

### Performance Improvements

* stock ageing and batch-wise balance history report ([6017e7a](6017e7ac3e))
2024-04-24 07:32:43 +00:00
Deepesh Garg
67be2ba9dc Merge pull request #41151 from frappe/version-14-hotfix
chore: release v14
2024-04-24 13:01:19 +05:30
Deepesh Garg
3e81f0f578 Merge pull request #41100 from frappe/mergify/bp/version-14-hotfix/pr-41085
fix: Permission for lower deduction certificate (#41085)
2024-04-24 12:00:13 +05:30
mergify[bot]
bb48440591 fix: allow Employee role to select cost center & project (accounting dimensions) (backport #41160) (#41161)
* fix: allow Employee role to select cost center & project (accounting dimensions)

(cherry picked from commit d0d496a515)

# Conflicts:
#	erpnext/accounts/doctype/cost_center/cost_center.json
#	erpnext/projects/doctype/project/project.json

* chore: fix conflicts

---------

Co-authored-by: Rucha Mahabal <ruchamahabal2@gmail.com>
2024-04-24 11:43:33 +05:30
Deepesh Garg
35230a9692 chore: Resolve conflicts 2024-04-24 11:33:34 +05:30
Nabin Hait
df3ff1097c Merge pull request #41140 from frappe/mergify/bp/version-14-hotfix/pr-41136
fix: Missing args while fetching items from delivery note in Installation Note (backport #41136)
2024-04-24 10:59:16 +05:30
rohitwaghchaure
521bf31fe3 Merge pull request #41154 from rohitwaghchaure/feat-new-batch-report-v14
feat: Available batches report as on specific date
2024-04-23 17:17:26 +05:30
Rohit Waghchaure
8868cb147d feat: Available batches report as on specific date 2024-04-23 17:10:05 +05:30
Deepesh Garg
0dfae12f14 Merge pull request #41130 from frappe/mergify/bp/version-14-hotfix/pr-40797
fix: Party type in Payment Order (#40797)
2024-04-23 12:05:25 +05:30
Nabin Hait
0df80ad923 fix: Missing args while fetching items from delivery note
(cherry picked from commit bbe323fbb4)
2024-04-23 04:55:02 +00:00
rohitwaghchaure
c71d1118a9 Merge pull request #41138 from rohitwaghchaure/fixed-performance-for-stock-reports
perf: stock ageing and batch-wise balance history report
2024-04-23 10:12:19 +05:30
Rohit Waghchaure
6017e7ac3e perf: stock ageing and batch-wise balance history report 2024-04-23 06:56:41 +05:30
Deepesh Garg
d5784cc629 Merge pull request #41126 from frappe/mergify/bp/version-14-hotfix/pr-40812
fix: Multiple partial payment requests against Purchase Invoice (#40812)
2024-04-22 11:36:30 +05:30
Deepesh Garg
a2e1d132df fix: Party type in Payment Order
(cherry picked from commit 91fa41c9ec)
2024-04-22 06:05:12 +00:00
Gursheen Kaur Anand
3e912993e1 Merge pull request #41123 from frappe/mergify/bp/version-14-hotfix/pr-40769
fix: budget validation for purchase orders (backport #40769)
2024-04-21 18:57:52 +05:30
Deepesh Garg
5aef9d2ef2 fix: Test case
(cherry picked from commit 071e5ed648)
2024-04-21 11:50:38 +00:00
Deepesh Garg
f1b75e8c54 fix: Multiple partial payment requests against Purchase Invoice
(cherry picked from commit 45d5f6e00a)
2024-04-21 11:50:38 +00:00
Gursheen Anand
5b1c5e3fea refactor: show list for expense breakup
(cherry picked from commit 9a12376e29)
2024-04-21 11:26:19 +00:00
Gursheen Anand
f087ec8df5 feat: show expense breakup
(cherry picked from commit 59292a09c4)
2024-04-21 11:26:19 +00:00
Gursheen Anand
ec4f07fd60 fix: do not add actual expense twice for validating budget
(cherry picked from commit af26ac96e9)
2024-04-21 11:26:19 +00:00
Deepesh Garg
a22be6f9b9 fix: Permission for lower dedcution certificate
(cherry picked from commit f6f118855b)

# Conflicts:
#	erpnext/regional/doctype/lower_deduction_certificate/lower_deduction_certificate.json
2024-04-19 10:11:41 +00:00
Gursheen Kaur Anand
e8accd0256 Merge pull request #41094 from frappe/mergify/bp/version-14-hotfix/pr-41093
fix: accounts manager perm for FY (backport #41093)
2024-04-19 14:08:19 +05:30
Gursheen Kaur Anand
de3a423618 chore: resolve conflicts 2024-04-19 13:32:39 +05:30
Gursheen Anand
03ce9ee321 fix: account and stock manager read perm
(cherry picked from commit 572e844a91)

# Conflicts:
#	erpnext/accounts/doctype/fiscal_year/fiscal_year.json
2024-04-19 08:00:48 +00:00
mergify[bot]
9d0c1dc46f fix: validate uom is integer for PR item (backport #41074) (#41076)
* fix: validate uom is integer for PR item

(cherry picked from commit 9a290fdfc9)

# Conflicts:
#	erpnext/controllers/subcontracting_controller.py

* chore: `conflicts`

---------

Co-authored-by: s-aga-r <sagarsharma.s312@gmail.com>
2024-04-18 07:53:33 +05:30
mergify[bot]
5d05bf8d4e fix: don't attempt to set gender from salutation (backport #40997) (#41072)
Co-authored-by: Raffael Meyer <14891507+barredterra@users.noreply.github.com>
fix: don't attempt to set gender from salutation (#40997)
2024-04-17 17:54:03 +02:00
Frappe PR Bot
84789b7407 chore(release): Bumped to Version 14.67.2
## [14.67.2](https://github.com/frappe/erpnext/compare/v14.67.1...v14.67.2) (2024-04-17)

### Bug Fixes

* barcode not fetched on selection of item (backport [#40814](https://github.com/frappe/erpnext/issues/40814)) ([#41027](https://github.com/frappe/erpnext/issues/41027)) ([0bee921](0bee921d40))
* Delayed Order Report not working (backport [#41037](https://github.com/frappe/erpnext/issues/41037)) ([#41038](https://github.com/frappe/erpnext/issues/41038)) ([e956dbb](e956dbbf68))
* Don't call get_fiscal_year if setup is not done yet ([59cea9f](59cea9f4dd))
* Don't set delivery date as today while making SO from Quotation ([b47e224](b47e224a1c))
* exclude some query builder lines from ruff rules ([2425119](2425119b5e))
* expense account set as COGS for stock entry Material Issue (backport [#41026](https://github.com/frappe/erpnext/issues/41026)) ([#41028](https://github.com/frappe/erpnext/issues/41028)) ([153e0ba](153e0ba81b))
* get address if multiple companies ([c2b6b64](c2b6b64e2e))
* get address if multiple companies ([0493872](04938726d9))
* **gp:** SLEs not fetched for correct warehouse ([97e7b3f](97e7b3f3d3))
* incorrect exc gain/loss for PE against JE for payable accounts ([50a74ee](50a74ee7fe))
* Resolve merge conflicts ([cc925ae](cc925ae938))
* Subcontracting Receipt GL Entries (backport [#40773](https://github.com/frappe/erpnext/issues/40773)) ([#40978](https://github.com/frappe/erpnext/issues/40978)) ([c2c4548](c2c4548cc0))
* test cases ([79e23da](79e23dad2c))
* **treewide:** manual ruff fixes ([b087fb3](b087fb3d54))
* use 'eq' and isnull() on qb conditions ([b4ed2d2](b4ed2d2c16))
2024-04-17 06:12:30 +00:00
rohitwaghchaure
cd70c6c1b2 Merge pull request #41032 from frappe/version-14-hotfix
chore: release v14
2024-04-17 11:41:15 +05:30
ruthra kumar
4cc0a5851b Merge pull request #40854 from frappe/mergify/bp/version-14-hotfix/pr-40786
fix(gp): SLEs not fetched for correct warehouse (backport #40786)
2024-04-17 10:36:52 +05:30
ruthra kumar
6e9da0a729 Merge branch 'version-14-hotfix' into mergify/bp/version-14-hotfix/pr-40786 2024-04-17 10:16:55 +05:30
Dany Robert
97e7b3f3d3 fix(gp): SLEs not fetched for correct warehouse
(cherry picked from commit f958e8be06)
2024-04-17 10:15:29 +05:30
mergify[bot]
e956dbbf68 fix: Delayed Order Report not working (backport #41037) (#41038)
fix: Delayed Order Report not working (#41037)

(cherry picked from commit d69a18b826)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-04-16 18:24:45 +05:30
rohitwaghchaure
ebf5f13447 Merge branch 'version-14' into version-14-hotfix 2024-04-16 17:59:35 +05:30
ruthra kumar
9404dea97e Merge pull request #41034 from frappe/mergify/bp/version-14-hotfix/pr-40373
fix: get address if multiple companies (backport #40373)
2024-04-16 16:41:26 +05:30
ruthra kumar
ee06448f0d chore: resolve conflict 2024-04-16 16:38:32 +05:30
Nihantra C. Patel
c2b6b64e2e fix: get address if multiple companies
(cherry picked from commit 655a1797be)
2024-04-16 11:01:59 +00:00
Nihantra Patel
04938726d9 fix: get address if multiple companies
(cherry picked from commit c6cf1bec76)

# Conflicts:
#	erpnext/selling/doctype/sales_order/sales_order.js
2024-04-16 11:01:58 +00:00
mergify[bot]
153e0ba81b fix: expense account set as COGS for stock entry Material Issue (backport #41026) (#41028)
fix: expense account set as COGS for stock entry Material Issue (#41026)

(cherry picked from commit 03231e99ef)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-04-16 14:22:53 +05:30
mergify[bot]
0bee921d40 fix: barcode not fetched on selection of item (backport #40814) (#41027)
* fix: barcode not fetched on selection of item

(cherry picked from commit b0730293e2)

# Conflicts:
#	erpnext/stock/get_item_details.py

* chore: fix conflicts

* chore: fix test case

---------

Co-authored-by: Rohit Waghchaure <rohitw1991@gmail.com>
2024-04-16 14:22:32 +05:30
ruthra kumar
9d3c861766 Merge pull request #41022 from frappe/mergify/bp/version-14-hotfix/pr-41020
fix: incorrect exc gain/loss for PE against JE for payable accounts (backport #41020)
2024-04-16 11:31:40 +05:30
ruthra kumar
e8d05517c5 chore: resolve conflict 2024-04-16 11:07:39 +05:30
ruthra kumar
2ebdd93a83 test: exc gain/loss journals booking in Payable accounts
(cherry picked from commit 8821c98625)
2024-04-16 05:29:49 +00:00
ruthra kumar
50a74ee7fe fix: incorrect exc gain/loss for PE against JE for payable accounts
(cherry picked from commit 81b574053f)

# Conflicts:
#	erpnext/controllers/accounts_controller.py
2024-04-16 05:29:49 +00:00
Nabin Hait
da1c317c6c Merge pull request #41006 from frappe/mergify/bp/version-14-hotfix/pr-40858
fix: Don't set delivery date as today while making SO from Quotation (backport #40858)
2024-04-15 13:05:21 +05:30
Nabin Hait
79e23dad2c fix: test cases
(cherry picked from commit 65c74fa3c7)
2024-04-15 07:03:42 +00:00
Nabin Hait
b47e224a1c fix: Don't set delivery date as today while making SO from Quotation
(cherry picked from commit fec20decc1)
2024-04-15 07:03:42 +00:00
Deepesh Garg
3310358d36 Merge pull request #40947 from frappe/mergify/bp/version-14-hotfix/pr-40931
fix: Don't call get_fiscal_year if setup is not done yet (backport #40931)
2024-04-15 11:18:06 +05:30
Frappe PR Bot
7a6c0e5283 chore(release): Bumped to Version 14.67.1
## [14.67.1](https://github.com/frappe/erpnext/compare/v14.67.0...v14.67.1) (2024-04-12)

### Bug Fixes

* Subcontracting Receipt GL Entries (backport [#40773](https://github.com/frappe/erpnext/issues/40773)) (backport [#40978](https://github.com/frappe/erpnext/issues/40978)) ([#40982](https://github.com/frappe/erpnext/issues/40982)) ([4672f59](4672f59599))
2024-04-12 10:01:51 +00:00
mergify[bot]
4672f59599 fix: Subcontracting Receipt GL Entries (backport #40773) (backport #40978) (#40982)
* fix: Subcontracting Receipt GL Entries (backport #40773) (#40978)

* fix: Subcontracting Receipt GL Entries

(cherry picked from commit 9808ae92a4)

* chore: linter

---------

Co-authored-by: s-aga-r <sagarsharma.s312@gmail.com>
(cherry picked from commit c2c4548cc0)

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

* chore: `conflicts`

---------

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Co-authored-by: s-aga-r <sagarsharma.s312@gmail.com>
2024-04-12 15:30:27 +05:30
mergify[bot]
c2c4548cc0 fix: Subcontracting Receipt GL Entries (backport #40773) (#40978)
* fix: Subcontracting Receipt GL Entries

(cherry picked from commit 9808ae92a4)

* chore: linter

---------

Co-authored-by: s-aga-r <sagarsharma.s312@gmail.com>
2024-04-12 14:50:12 +05:30
Deepesh Garg
cc925ae938 fix: Resolve merge conflicts 2024-04-12 12:10:55 +05:30
Akhil Narang
f0ecc627fb Merge pull request #40943 from akhilnarang/v14-ruff
chore: backport ruff linting/formatting
2024-04-12 11:01:43 +05:30
Akhil Narang
cf3c26d80c chore: gitignore ruff format
Signed-off-by: Akhil Narang <me@akhilnarang.dev>
2024-04-12 11:01:32 +05:30
Corentin Flr
59cea9f4dd fix: Don't call get_fiscal_year if setup is not done yet
(cherry picked from commit c203fafb1b)

# Conflicts:
#	erpnext/public/js/utils.js
2024-04-10 15:17:44 +00:00
Frappe PR Bot
cc6bacb190 chore(release): Bumped to Version 14.67.0
# [14.67.0](https://github.com/frappe/erpnext/compare/v14.66.4...v14.67.0) (2024-04-10)

### Bug Fixes

* Get pro-rata depr amount based on correct days ([10d7600](10d760089e))
* group warehouse added in the stock reconciliation ([9dea6d3](9dea6d3393))
* ignore dimension validation for cancelled entries ([9745724](9745724d41))
* incorrect currency symbol in General Ledger print ([5896e75](5896e755bf))
* incorrect operator causing incorrect validation ([7e1ab75](7e1ab75b38))
* query_report.trigger_refresh is not a function ([a6145fa](a6145fa13c))
* translatable web footer ([#40834](https://github.com/frappe/erpnext/issues/40834)) ([b55d859](b55d8597e8))
* use reference type name to update exc rate ([09cda60](09cda60bdf))

### Features

* ledger health doctype ([b667a02](b667a02470))
* new hook `fields_for_group_similar_items` to group additional fields for print formats ([#40831](https://github.com/frappe/erpnext/issues/40831)) ([0172880](0172880fd3))

### Performance Improvements

* memory consumption for the Batch-Wise Balance History report ([3165682](3165682d7a))
2024-04-10 14:22:01 +00:00
Deepesh Garg
cebde2662d Merge pull request #40919 from frappe/version-14-hotfix
chore: release v14
2024-04-10 19:50:19 +05:30
ruthra kumar
b4ed2d2c16 fix: use 'eq' and isnull() on qb conditions
(cherry picked from commit eee86d2e4b)
(cherry picked from commit 22689958da)
Signed-off-by: Akhil Narang <me@akhilnarang.dev>
2024-04-10 17:13:31 +05:30
Akhil Narang
2425119b5e fix: exclude some query builder lines from ruff rules
`== None` and `== True` are intentional here

(cherry picked from commit ac69513f60)
(cherry picked from commit 41d7c03cbb)
Signed-off-by: Akhil Narang <me@akhilnarang.dev>
2024-04-10 17:13:31 +05:30
Akhil Narang
b087fb3d54 fix(treewide): manual ruff fixes
(cherry picked from commit f63396ef47)
(cherry picked from commit 7828eee014)
Signed-off-by: Akhil Narang <me@akhilnarang.dev>
2024-04-10 17:13:31 +05:30
Akhil Narang
4d34b1ead7 refactor(treewide): formatting and ruff fixes, + manually enabled F401
Signed-off-by: Akhil Narang <me@akhilnarang.dev>
2024-04-10 17:13:31 +05:30
barredterra
c28d19cf7f chore: switch to ruff for python formatting/linting
(cherry picked from commit 8afb7790de)
(cherry picked from commit 9eeedd8515)
Signed-off-by: Akhil Narang <me@akhilnarang.dev>
2024-04-10 17:07:51 +05:30
ruthra kumar
73d2595aa6 Merge pull request #40937 from frappe/mergify/bp/version-14-hotfix/pr-40936
fix: ignore dimension validation for cancelled entries (backport #40936)
2024-04-10 15:28:00 +05:30
ruthra kumar
9745724d41 fix: ignore dimension validation for cancelled entries
(cherry picked from commit 971c867f29)
2024-04-10 08:28:35 +00:00
ruthra kumar
a31b2e17f5 Merge pull request #40929 from frappe/mergify/bp/version-14-hotfix/pr-40695
feat: Periodically monitor ledger health (backport #40695)
2024-04-10 07:17:29 +05:30
ruthra kumar
46c76b166d chore: resolve conflicts 2024-04-09 19:59:09 +05:30
ruthra kumar
6079c5636e Merge pull request #40927 from frappe/mergify/bp/version-14-hotfix/pr-40926
fix: incorrect currency symbol in General Ledger print (backport #40926)
2024-04-09 19:54:29 +05:30
ruthra kumar
5808feaccf chore: use super() instead of super(__class__, self)
(cherry picked from commit 24d37d22a3)
2024-04-09 12:25:55 +00:00
ruthra kumar
98ad034b21 chore: make ledger health doctype read_only
(cherry picked from commit dc79213bb3)
2024-04-09 12:25:55 +00:00
ruthra kumar
277717a2e0 test: ledger monitoring function
(cherry picked from commit 4776d660b5)
2024-04-09 12:25:55 +00:00
ruthra kumar
0591f72e01 chore: schedule job to run daily
(cherry picked from commit f96cf111ed)
2024-04-09 12:25:54 +00:00
ruthra kumar
1af6b4256f chore: permission and UI changes
(cherry picked from commit 1a43ed763b)
2024-04-09 12:25:53 +00:00
ruthra kumar
6273a31b8c refactor: only run checks on specified companies
(cherry picked from commit 00eeacd06a)

# Conflicts:
#	erpnext/accounts/utils.py
2024-04-09 12:25:53 +00:00
ruthra kumar
f86c035f88 refactor: make health check configurable for companies
(cherry picked from commit 704925549b)
2024-04-09 12:25:52 +00:00
ruthra kumar
9981a900b2 refactor: control monitoring through settings page
(cherry picked from commit a42482ce35)

# Conflicts:
#	erpnext/accounts/utils.py
2024-04-09 12:25:52 +00:00
ruthra kumar
7a6ffccecc chore: settings page for health monitor
(cherry picked from commit b2fb7843d1)
2024-04-09 12:25:47 +00:00
ruthra kumar
58698c9aa4 refactor: barebones method to run checks
(cherry picked from commit 8c8d9be810)

# Conflicts:
#	erpnext/accounts/utils.py
2024-04-09 12:25:47 +00:00
ruthra kumar
bbe4ca7d74 refactor: flag for general and payment ledger mismatch
(cherry picked from commit d620b9eae8)
2024-04-09 12:25:46 +00:00
ruthra kumar
153fc91478 refactor: date on which vouchers was reported
(cherry picked from commit 402ffc6d27)
2024-04-09 12:25:45 +00:00
ruthra kumar
b667a02470 feat: ledger health doctype
(cherry picked from commit 9ed74dd8cc)
2024-04-09 12:25:45 +00:00
ruthra kumar
5896e755bf fix: incorrect currency symbol in General Ledger print
(cherry picked from commit 429e036e8c)
2024-04-09 12:16:41 +00:00
rohitwaghchaure
dd6c53df96 Merge pull request #40910 from rohitwaghchaure/fixed-perf-issue-for-batchwise-balance-history
perf: memory consumption for the Batch-Wise Balance History report
2024-04-09 17:36:43 +05:30
Rohit Waghchaure
3165682d7a perf: memory consumption for the Batch-Wise Balance History report 2024-04-08 19:03:48 +05:30
ruthra kumar
aff71970e5 Merge pull request #40904 from frappe/mergify/bp/version-14-hotfix/pr-40878
refactor: merge taxes from delivery note to Sales Invoice (backport #40878)
2024-04-08 16:18:48 +05:30
Sagar Vora
2b5ae1dbae Merge pull request #40906 from frappe/mergify/bp/version-14-hotfix/pr-40831 2024-04-08 10:22:43 +00:00
Sagar Vora
24709ab400 chore: fix conflict 2024-04-08 15:50:58 +05:30
Smit Vora
0172880fd3 feat: new hook fields_for_group_similar_items to group additional fields for print formats (#40831)
(cherry picked from commit f7c9e1538b)

# Conflicts:
#	erpnext/hooks.py
2024-04-08 10:18:15 +00:00
ruthra kumar
b76c00de68 chore: resolve conflict 2024-04-08 15:44:13 +05:30
ruthra kumar
ae1858f465 test: tax merging from 2 Delivery Note to Sales Invoice
(cherry picked from commit 39a48a2e2a)

# Conflicts:
#	erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
2024-04-08 09:09:36 +00:00
ruthra kumar
22b16a6b0e refactor: merge taxes from delivery note to Sales Invoice
(cherry picked from commit 550cbbd91c)
2024-04-08 09:09:34 +00:00
Frappe PR Bot
8d8feadeae chore(release): Bumped to Version 14.66.4
## [14.66.4](https://github.com/frappe/erpnext/compare/v14.66.3...v14.66.4) (2024-04-07)

### Bug Fixes

* incorrect operator causing incorrect validation ([60ba62e](60ba62e882))
2024-04-07 12:34:56 +00:00
rohitwaghchaure
5629ad21d2 Merge pull request #40898 from frappe/mergify/bp/version-14/pr-40893
fix: incorrect operator causing incorrect validation (backport #40883) (backport #40893)
2024-04-07 18:03:33 +05:30
Nabin Hait
1eb720a7b0 Merge pull request #40897 from nabinhait/pro-rata-depr-fix
fix: Get pro-rata depr amount based on correct days
2024-04-07 15:23:42 +05:30
rohitwaghchaure
c4e950f6b5 Merge pull request #40835 from frappe/mergify/bp/version-14-hotfix/pr-40834
fix: translatable web footer (backport #40834)
2024-04-07 14:35:45 +05:30
rohitwaghchaure
d4313f7109 Merge pull request #40859 from frappe/mergify/bp/version-14-hotfix/pr-40848
fix: group warehouse added in the stock reconciliation (backport #40848)
2024-04-07 14:34:33 +05:30
Rohit Waghchaure
60ba62e882 fix: incorrect operator causing incorrect validation
(cherry picked from commit 6b317b0c0d)
(cherry picked from commit 7e1ab75b38)
2024-04-07 09:04:00 +00:00
rohitwaghchaure
26d7354973 Merge pull request #40893 from frappe/mergify/bp/version-14-hotfix/pr-40883
fix: incorrect operator causing incorrect validation (backport #40883)
2024-04-07 14:33:10 +05:30
Nabin Hait
10d760089e fix: Get pro-rata depr amount based on correct days 2024-04-07 14:08:45 +05:30
Rohit Waghchaure
7e1ab75b38 fix: incorrect operator causing incorrect validation
(cherry picked from commit 6b317b0c0d)
2024-04-07 06:34:07 +00:00
rohitwaghchaure
0f9af4b82c Merge pull request #40888 from frappe/mergify/bp/version-14-hotfix/pr-40887
fix: query_report.trigger_refresh is not a function (backport #40887)
2024-04-07 12:02:16 +05:30
Rohit Waghchaure
a6145fa13c fix: query_report.trigger_refresh is not a function
(cherry picked from commit 30bbb58ca1)
2024-04-07 06:27:49 +00:00
ruthra kumar
cc2f861bca Merge pull request #40868 from frappe/mergify/bp/version-14-hotfix/pr-40856
fix: unwanted Exc Gain/Loss journals on Payment against Journal entry (backport #40856)
2024-04-05 11:01:48 +05:30
ruthra kumar
8f2fd5dec9 test: payment against JE reconciliation with different rates
(cherry picked from commit fe84558b77)
2024-04-05 05:03:56 +00:00
ruthra kumar
09cda60bdf fix: use reference type name to update exc rate
(cherry picked from commit c15690e475)
2024-04-05 05:03:56 +00:00
Rohit Waghchaure
9dea6d3393 fix: group warehouse added in the stock reconciliation
(cherry picked from commit 8f53bc0096)
2024-04-04 10:09:55 +00:00
Frappe PR Bot
fb076d34b1 chore(release): Bumped to Version 14.66.3
## [14.66.3](https://github.com/frappe/erpnext/compare/v14.66.2...v14.66.3) (2024-04-03)

### Bug Fixes

* cost center shouldn't update debit/credit in Exc gain/loss JV ([f66b53b](f66b53b2c1))
* do not fetch received items in purchase receipt ([e778d7e](e778d7e690))
* linter issues ([515f933](515f933362))
* markdown to text editor set for supplier quotation ([b5629d2](b5629d2d4e))
* payment_order_status should be no_copy ([8dff18e](8dff18eab4))
* Priority not copied from project template ([4f4470b](4f4470b9d2))
* show currency symbol in base currency in fixed asset register report ([cfe5f00](cfe5f009f6))
* show future payments allocated sales returns is considered as payment ([803ed90](803ed904a9))
* Warehouse linked company name in multicompany setup (backport [#40779](https://github.com/frappe/erpnext/issues/40779)) ([#40780](https://github.com/frappe/erpnext/issues/40780)) ([ceac42d](ceac42dfaa))
2024-04-03 10:32:43 +00:00
Deepesh Garg
fba888fe94 Merge pull request #40821 from frappe/version-14-hotfix
chore: release v14
2024-04-03 16:01:29 +05:30
Raffael Meyer
b55d8597e8 fix: translatable web footer (#40834)
(cherry picked from commit f3bcdbe5bd)
2024-04-02 15:16:18 +00:00
Nabin Hait
81081663c4 Merge pull request #40826 from frappe/mergify/bp/version-14-hotfix/pr-40584
fix: show currency symbol in base currency in fixed asset register report (backport #40584)
2024-04-02 18:29:58 +05:30
rohitwaghchaure
2f66542d71 Merge pull request #40824 from rohitwaghchaure/fixed-remove-enqueue-submit-cancel
chore: remove enqueue submit and cancel from the stock entry
2024-04-02 16:34:57 +05:30
Rohit Waghchaure
abc0294cbf chore: remove enqueue submit and cancel from stock entry 2024-04-02 16:10:28 +05:30
Nabin Hait
515f933362 fix: linter issues
(cherry picked from commit 21a40a2236)
2024-04-02 10:27:57 +00:00
Nabin Hait
cfe5f009f6 fix: show currency symbol in base currency in fixed asset register report
(cherry picked from commit 8b6220efd8)
2024-04-02 10:27:56 +00:00
ruthra kumar
cf74f8312e Merge pull request #40803 from frappe/mergify/bp/version-14-hotfix/pr-40181
fix: show future payments consider allocated sales returns (backport #40181)
2024-04-01 14:13:59 +05:30
Devin Slauenwhite
803ed904a9 fix: show future payments allocated sales returns is considered as payment
(cherry picked from commit 3381d0d945)
2024-04-01 07:34:41 +00:00
Devin Slauenwhite
72db656054 test: show future payments allocated sales returns is considered as payment
(cherry picked from commit daaa00bd4a)
2024-04-01 07:34:40 +00:00
rohitwaghchaure
44b72e7fc8 Merge pull request #40737 from frappe/mergify/bp/version-14-hotfix/pr-40731
fix: markdown to text editor set for supplier quotation (backport #40731)
2024-03-31 21:14:38 +05:30
rohitwaghchaure
31017774f6 chore: fix conflicts 2024-03-31 11:42:05 +05:30
rohitwaghchaure
9b8bb4d6a2 chore: fix conflicts 2024-03-31 11:41:44 +05:30
mergify[bot]
ceac42dfaa fix: Warehouse linked company name in multicompany setup (backport #40779) (#40780)
fix: Warehouse linked company name in multicompany setup (#40779)

(cherry picked from commit 679aea607b)

Co-authored-by: jeshani <56191568+jeshani@users.noreply.github.com>
2024-03-30 10:18:16 +05:30
ruthra kumar
998cc0a966 Merge pull request #40668 from frappe/mergify/bp/version-14-hotfix/pr-40634
refactor: better pop up message for Internal Customer validation (backport #40634)
2024-03-29 13:50:35 +05:30
ruthra kumar
e722c9a34a Merge pull request #40766 from frappe/mergify/bp/version-14-hotfix/pr-40758
fix: payment_order_status should be no_copy (backport #40758)
2024-03-29 13:49:08 +05:30
Ashish Shah
8dff18eab4 fix: payment_order_status should be no_copy
payment_order_status should be no_copy

(cherry picked from commit adee2ba541)
2024-03-29 07:57:03 +00:00
ruthra kumar
7363884ab3 Merge pull request #40762 from frappe/mergify/bp/version-14-hotfix/pr-40760
fix: cost center shouldn't update debit/credit in Exc gain/loss JV (backport #40760)
2024-03-29 11:47:05 +05:30
ruthra kumar
f66b53b2c1 fix: cost center shouldn't update debit/credit in Exc gain/loss JV
(cherry picked from commit 398d3022ef)
2024-03-29 06:13:47 +00:00
Frappe PR Bot
c1a95c05bc chore(release): Bumped to Version 14.66.2
## [14.66.2](https://github.com/frappe/erpnext/compare/v14.66.1...v14.66.2) (2024-03-29)

### Bug Fixes

* use sql to clear comments ([0322c1a](0322c1a36e))
2024-03-29 05:41:39 +00:00
ruthra kumar
db56d259cc Merge pull request #40747 from frappe/mergify/bp/version-14/pr-40739
refactor: use sql to clear comments (backport #40739)
2024-03-29 11:10:22 +05:30
ruthra kumar
0322c1a36e fix: use sql to clear comments
(cherry picked from commit 1f46c1530e)
2024-03-29 10:50:05 +05:30
ruthra kumar
bb35c334c0 Merge pull request #40744 from frappe/mergify/bp/version-14-hotfix/pr-40739
refactor: use sql to clear comments (backport #40739)
2024-03-28 19:42:02 +05:30
ruthra kumar
4d6fad26f3 refactor: use sql to clear comments
(cherry picked from commit 1f46c1530e)
2024-03-28 12:12:12 +00:00
Nihantra Patel
b5629d2d4e fix: markdown to text editor set for supplier quotation
(cherry picked from commit 9828d34b19)

# Conflicts:
#	erpnext/buying/doctype/supplier_quotation/supplier_quotation.json
#	erpnext/buying/doctype/supplier_quotation/supplier_quotation.py
2024-03-28 07:16:11 +00:00
rohitwaghchaure
b1105fb0ab Merge pull request #40721 from frappe/mergify/bp/version-14-hotfix/pr-40718
fix: do not fetch received items in purchase receipt (backport #40718)
2024-03-27 23:01:12 +05:30
Rohit Waghchaure
e778d7e690 fix: do not fetch received items in purchase receipt
(cherry picked from commit 5bff434902)
2024-03-27 17:11:25 +00:00
Frappe PR Bot
5827bdcbc2 chore(release): Bumped to Version 14.66.1
## [14.66.1](https://github.com/frappe/erpnext/compare/v14.66.0...v14.66.1) (2024-03-27)

### Bug Fixes

* Priority not copied from project template ([af6dd3b](af6dd3bcfb))
2024-03-27 11:21:16 +00:00
rohitwaghchaure
94f15797f5 Merge pull request #40712 from frappe/mergify/bp/version-14/pr-40710
fix: Priority not copied from project template (backport #40708) (backport #40710)
2024-03-27 16:50:07 +05:30
Rohit Waghchaure
af6dd3bcfb fix: Priority not copied from project template
(cherry picked from commit 33fd7b8a1f)
(cherry picked from commit 4f4470b9d2)
2024-03-27 10:49:11 +00:00
rohitwaghchaure
e947d65cb2 Merge pull request #40710 from frappe/mergify/bp/version-14-hotfix/pr-40708
fix: Priority not copied from project template (backport #40708)
2024-03-27 16:17:57 +05:30
Rohit Waghchaure
4f4470b9d2 fix: Priority not copied from project template
(cherry picked from commit 33fd7b8a1f)
2024-03-27 10:18:21 +00:00
Frappe PR Bot
4ea3876f30 chore(release): Bumped to Version 14.66.0
# [14.66.0](https://github.com/frappe/erpnext/compare/v14.65.8...v14.66.0) (2024-03-27)

### Bug Fixes

* achieved targets for sales partners ([f9ab763](f9ab763cc8))
* Add default finance book check in P&L statement ([4485121](4485121255))
* incorrect total qty in job card ([fb252ec](fb252ec29a))
* pass empty string email content of pos invoice ([ee7bd98](ee7bd98878))
* permissions during bulk transaction logs ([99faafb](99faafb5be))
* rate not fetching from the item price ([9b3c4ac](9b3c4ac575))
* rate reset to zero ([2f839fb](2f839fbf6d))
* remove microsecond from posting datetime ([#40017](https://github.com/frappe/erpnext/issues/40017)) ([c3f9338](c3f9338430))
* show correct variance for durations with no vouchers ([fe3bee4](fe3bee44e2))
* style for tax breakup ([e922ac7](e922ac7c31))
* use Text Editor for rendering tax breakup table ([bba1ac5](bba1ac5735))
* validate gl for previous fiscal year ([82b6133](82b613353b))
* wrong buying amount if delivered and billed qty varies ([2b31113](2b311131ba))

### Features

* bisect doctype ([5ad3918](5ad3918232))
* nodes doctype ([6afb6ff](6afb6ff4df))

### Performance Improvements

* add in some indexes (backport [#40590](https://github.com/frappe/erpnext/issues/40590)) ([#40604](https://github.com/frappe/erpnext/issues/40604)) ([390d3a6](390d3a6a9f))
* new column posting datetime in SLE to optimize stock ledger related queries ([5e68ebd](5e68ebd030))
2024-03-27 03:27:23 +00:00
Deepesh Garg
bd3b1bbbb8 Merge pull request #40677 from frappe/version-14-hotfix
chore: release v14
2024-03-27 08:56:10 +05:30
rohitwaghchaure
4a1cd943bd Merge pull request #40687 from frappe/mergify/bp/version-14-hotfix/pr-40684
fix: incorrect total qty in job card (backport #40684)
2024-03-26 19:54:15 +05:30
Rohit Waghchaure
fb252ec29a fix: incorrect total qty in job card
(cherry picked from commit c3546cf8e2)
2024-03-26 14:03:40 +00:00
Wolfram Schmidt
2834d25ce3 refactor: better pop message for Internal Customer validation
-added more meaningful description to message when using "internal Customer" scenario

(cherry picked from commit b132892b25)
2024-03-26 09:55:04 +05:30
Deepesh Garg
208a46fbe4 Merge pull request #40505 from frappe/mergify/bp/version-14-hotfix/pr-40503
fix: achieved targets for territory / partners bpv15 (#40503)
2024-03-26 09:03:14 +05:30
Deepesh Garg
2723e1f614 Merge pull request #40652 from frappe/mergify/bp/version-14-hotfix/pr-40640
fix: Add default finance book check-in P&L statement (#40640)
2024-03-25 17:08:57 +05:30
Deepesh Garg
4485121255 fix: Add default finance book check in P&L statement
(cherry picked from commit 5be3417fdf)
2024-03-25 09:14:41 +00:00
Frappe PR Bot
cf770e784d chore(release): Bumped to Version 14.65.8
## [14.65.8](https://github.com/frappe/erpnext/compare/v14.65.7...v14.65.8) (2024-03-25)

### Bug Fixes

* reset update outstanding flag for old records ([73c534c](73c534cf1a))
2024-03-25 02:57:34 +00:00
ruthra kumar
fda9c03d4d Merge pull request #40644 from frappe/mergify/bp/version-14/pr-40622
fix: reset update_outstanding_for_self flag for old records (backport #40622)
2024-03-25 08:26:21 +05:30
ruthra kumar
adec93de18 refactor: hide on print formats
(cherry picked from commit fdcdc8a56e)
2024-03-25 07:47:20 +05:30
ruthra kumar
73c534cf1a fix: reset update outstanding flag for old records
(cherry picked from commit a88bf8419e)
2024-03-25 07:47:16 +05:30
ruthra kumar
0ec1a88748 Merge pull request #40625 from frappe/mergify/bp/version-14-hotfix/pr-40622
refactor: reset update_outstanding_for_self flag for old records (backport #40622)
2024-03-24 16:24:37 +05:30
rohitwaghchaure
91400e1371 Merge pull request #40628 from frappe/mergify/bp/version-14-hotfix/pr-40017
fix: remove microsecond from posting datetime (backport #40017)
2024-03-23 18:39:04 +05:30
mergify[bot]
39711df27c Merge branch 'version-14-hotfix' into mergify/bp/version-14-hotfix/pr-40503 2024-03-23 09:10:52 +00:00
Deepesh Garg
03eb4d77ce Merge pull request #40514 from mmdanny89/email-point-of-sale
fix: pass empty string email content of pos invoice
2024-03-23 14:39:58 +05:30
rohitwaghchaure
c3f9338430 fix: remove microsecond from posting datetime (#40017)
(cherry picked from commit 0b04d04da3)
2024-03-23 03:07:37 +00:00
ruthra kumar
dbb4391f1e refactor: hide on print formats
(cherry picked from commit fdcdc8a56e)
2024-03-22 14:54:03 +00:00
ruthra kumar
22cec21c6f refactor: reset flag for old records
(cherry picked from commit a88bf8419e)
2024-03-22 14:54:03 +00:00
ruthra kumar
ab7f80625b Merge pull request #40615 from frappe/mergify/bp/version-14-hotfix/pr-38496
feat: utility to debug financial reports - Bisect Accounting Statements (backport #38496)
2024-03-22 16:23:22 +05:30
rohitwaghchaure
a4ddc4ee1b Merge pull request #40036 from frappe/mergify/bp/version-14-hotfix/pr-39800
perf: new column Posting Datetime in SLE to optimize stock ledger related queries (backport #39800)
2024-03-22 16:06:53 +05:30
Frappe PR Bot
1c6f5b6525 chore(release): Bumped to Version 14.65.7
## [14.65.7](https://github.com/frappe/erpnext/compare/v14.65.6...v14.65.7) (2024-03-22)

### Bug Fixes

* rate reset to zero ([e09b3ad](e09b3ad720))
2024-03-22 10:32:42 +00:00
rohitwaghchaure
a6b887312b Merge pull request #40620 from frappe/mergify/bp/version-14/pr-40618
fix: rate reset to zero (backport #40616) (backport #40618)
2024-03-22 16:01:27 +05:30
Rohit Waghchaure
e09b3ad720 fix: rate reset to zero
(cherry picked from commit 6821baa850)
(cherry picked from commit 2f839fbf6d)
2024-03-22 10:12:07 +00:00
rohitwaghchaure
07929d20aa Merge pull request #40618 from frappe/mergify/bp/version-14-hotfix/pr-40616
fix: rate reset to zero (backport #40616)
2024-03-22 15:41:07 +05:30
Rohit Waghchaure
2f839fbf6d fix: rate reset to zero
(cherry picked from commit 6821baa850)
2024-03-22 09:50:51 +00:00
ruthra kumar
9f3b6d21c3 chore: resolve JS linter issue 2024-03-22 14:42:57 +05:30
ruthra kumar
4eb1fbfe42 chore: resolve linter issues
(cherry picked from commit 0890b414b1)
2024-03-22 08:51:33 +00:00
ruthra kumar
3a38aacc30 refactor: cache results
(cherry picked from commit 14c8c8c33d)
2024-03-22 08:51:33 +00:00
ruthra kumar
48bfb9d315 refactor: flag to differentiate generated and default values
(cherry picked from commit 0925706d5e)
2024-03-22 08:51:33 +00:00
ruthra kumar
5d90b0fd1d refactor: save results in node
(cherry picked from commit ca14ae8f1b)
2024-03-22 08:51:32 +00:00
ruthra kumar
3cab242e9f chore: restrict only to administrator and type info
(cherry picked from commit 90c6d4dc85)
2024-03-22 08:51:32 +00:00
ruthra kumar
54e7f303e9 chore: change data type for summary fields
(cherry picked from commit 228aa1a244)
2024-03-22 08:51:32 +00:00
ruthra kumar
cd0a7fed41 refactor: adding labels to important section
(cherry picked from commit 993e2bfbf9)
2024-03-22 08:51:32 +00:00
ruthra kumar
84609abd65 chore: UI cleanup
(cherry picked from commit ea3071db66)
2024-03-22 08:51:31 +00:00
ruthra kumar
a76d19fe8f chore: add screen freeze on wait
(cherry picked from commit 395299803f)
2024-03-22 08:51:31 +00:00
ruthra kumar
ebea0fd203 chore: code cleanup
(cherry picked from commit 5e2d21c033)
2024-03-22 08:51:31 +00:00
ruthra kumar
f9c30968bf chore: hide internal variables section
(cherry picked from commit c4c3090f46)
2024-03-22 08:51:31 +00:00
ruthra kumar
a9a510547e chore: rename btree and remove debugging statements
(cherry picked from commit 6492019383)
2024-03-22 08:51:31 +00:00
ruthra kumar
c2f6f9d37f chore: hide internal fields and better painting logic for heatmap
(cherry picked from commit f6831fba13)
2024-03-22 08:51:30 +00:00
ruthra kumar
9d5c010071 refactor: working heatmap
(cherry picked from commit 16db6c2f47)
2024-03-22 08:51:30 +00:00
ruthra kumar
3cfc778bdb chore: hide some internal fields
(cherry picked from commit bd3dc6482e)
2024-03-22 08:51:30 +00:00
ruthra kumar
f06014afc3 refactor: calculate summary on tree navigation
(cherry picked from commit f7b7b2b438)
2024-03-22 08:51:30 +00:00
ruthra kumar
bee5744309 refactor: use DB to store tree and state
(cherry picked from commit 99fbd8ad18)
2024-03-22 08:51:30 +00:00
ruthra kumar
bc1f25b897 chore: use doctype as btree
(cherry picked from commit 9d20256366)
2024-03-22 08:51:30 +00:00
ruthra kumar
6afb6ff4df feat: nodes doctype
(cherry picked from commit 85f2a6dd54)
2024-03-22 08:51:29 +00:00
ruthra kumar
609ecbe804 chore: remove unwanted code
(cherry picked from commit de2eba0d98)
2024-03-22 08:51:29 +00:00
ruthra kumar
674d822985 refactor: add basic navigation
1. remove unnecessary columns
2. added basic tree navigation

(cherry picked from commit 705ef4f5a3)
2024-03-22 08:51:29 +00:00
ruthra kumar
66fae6466f refactor: ability to build and load tree from DB
(cherry picked from commit b2dde55f2c)
2024-03-22 08:51:29 +00:00
ruthra kumar
81f456bdc7 refactor: introduce node class
(cherry picked from commit d53b34c0ce)
2024-03-22 08:51:29 +00:00
ruthra kumar
a177137d6d refactor: more buttons
(cherry picked from commit a427029151)
2024-03-22 08:51:28 +00:00
ruthra kumar
d81be8d855 refactor: date validation
(cherry picked from commit 2de3e6ce6d)
2024-03-22 08:51:28 +00:00
ruthra kumar
0399acdc8e refactor: support for BFS and DFS
(cherry picked from commit 03a38ed025)
2024-03-22 08:51:28 +00:00
ruthra kumar
50963d9ad5 refactor: simplify DFS
(cherry picked from commit 26503a205f)
2024-03-22 08:51:28 +00:00
ruthra kumar
1639974948 refactor: Depth First Search(DFS)
(cherry picked from commit 5a25c80f2e)
2024-03-22 08:51:28 +00:00
ruthra kumar
57ec0d6b41 refactor: some logic
(cherry picked from commit 4c8a8c3bcd)
2024-03-22 08:51:27 +00:00
ruthra kumar
5ad3918232 feat: bisect doctype
(cherry picked from commit decdbd2782)
2024-03-22 08:51:27 +00:00
ruthra kumar
9e15ecfe34 refactor: primitive summary for p&l and balance sheet
(cherry picked from commit eb4c476490)
2024-03-22 08:51:27 +00:00
ruthra kumar
da17496e3d Merge pull request #40607 from frappe/mergify/bp/version-14-hotfix/pr-40520
fix: permissions during bulk transaction logs (backport #40520)
2024-03-22 10:33:49 +05:30
David
99faafb5be fix: permissions during bulk transaction logs
(cherry picked from commit 49dd4c1ef3)
2024-03-22 04:38:17 +00:00
ruthra kumar
6d39a7890e Merge pull request #40596 from frappe/mergify/bp/version-14-hotfix/pr-40386
fix: wrong buying amount if delivered and billed qty varies (backport #40386)
2024-03-22 09:04:26 +05:30
mergify[bot]
390d3a6a9f perf: add in some indexes (backport #40590) (#40604)
* perf: add in some indexes (#40590)

`Sales Invoice Item.purchase_order`
`Delivery Note Item.purchase_order`

Signed-off-by: Akhil Narang <me@akhilnarang.dev>
(cherry picked from commit 1cd38c860a)

# Conflicts:
#	erpnext/selling/doctype/sales_order_item/sales_order_item.json
#	erpnext/stock/doctype/delivery_note_item/delivery_note_item.json

* chore: `conflicts`

* chore: `conflicts`

---------

Co-authored-by: Akhil Narang <me@akhilnarang.dev>
Co-authored-by: s-aga-r <sagarsharma.s312@gmail.com>
2024-03-22 08:51:33 +05:30
Frappe PR Bot
14f7aef4d0 chore(release): Bumped to Version 14.65.6
## [14.65.6](https://github.com/frappe/erpnext/compare/v14.65.5...v14.65.6) (2024-03-21)

### Bug Fixes

* rate not fetching from the item price ([18279a6](18279a6dbd))
2024-03-21 17:33:34 +00:00
rohitwaghchaure
5f84e0d7e8 Merge pull request #40601 from frappe/mergify/bp/version-14/pr-40599
fix: rate not fetching from the item price (backport #40595) (backport #40599)
2024-03-21 23:02:23 +05:30
Rohit Waghchaure
18279a6dbd fix: rate not fetching from the item price
(cherry picked from commit d893a465d7)
(cherry picked from commit 9b3c4ac575)
2024-03-21 17:12:01 +00:00
rohitwaghchaure
5117ba5abf Merge pull request #40599 from frappe/mergify/bp/version-14-hotfix/pr-40595
fix: rate not fetching from the item price (backport #40595)
2024-03-21 22:40:58 +05:30
Rohit Waghchaure
9b3c4ac575 fix: rate not fetching from the item price
(cherry picked from commit d893a465d7)
2024-03-21 16:49:46 +00:00
ruthra kumar
d3a6153077 test: buying amt calculation if DN and SI differ in qty
(cherry picked from commit ccb51ded95)
2024-03-21 15:46:03 +00:00
Dany Robert
2b311131ba fix: wrong buying amount if delivered and billed qty varies
(cherry picked from commit b8da0d9334)
2024-03-21 15:46:02 +00:00
Gursheen Kaur Anand
c072cd941d Merge pull request #40583 from frappe/mergify/bp/version-14-hotfix/pr-40572
fix: PCV validation for previous fiscal year (backport #40572)
2024-03-21 12:44:09 +05:30
ruthra kumar
757cf8a76f Merge pull request #40581 from frappe/mergify/bp/version-14-hotfix/pr-40580
refactor: config changes in Transaction Deletion Record (backport #40580)
2024-03-21 11:07:17 +05:30
Gursheen Anand
82b613353b fix: validate gl for previous fiscal year
(cherry picked from commit a1d108c062)
2024-03-21 05:30:35 +00:00
ruthra kumar
5791c50fdf refactor: config changes in Transaction Deletion Record
(cherry picked from commit 4ba67fb3ec)
2024-03-21 05:17:16 +00:00
ruthra kumar
67481ad062 Merge pull request #40574 from frappe/mergify/bp/version-14-hotfix/pr-39717
refactor: Transaction Deletion record for large volumes (backport #39717)
2024-03-21 10:18:07 +05:30
ruthra kumar
1515bb7f0b refactor: replace get_job with create_job_id utility method 2024-03-21 09:53:55 +05:30
Frappe PR Bot
74ec853b97 chore(release): Bumped to Version 14.65.5
## [14.65.5](https://github.com/frappe/erpnext/compare/v14.65.4...v14.65.5) (2024-03-20)

### Bug Fixes

* style for tax breakup ([a0156e1](a0156e1e47))
* use Text Editor for rendering tax breakup table ([7df09d1](7df09d18e1))
2024-03-20 15:22:12 +00:00
Deepesh Garg
7ed625d5e1 Merge pull request #40569 from frappe/mergify/bp/version-14/pr-40563
fix: use `Text Editor` for rendering tax breakup table (backport #40563)
2024-03-20 20:50:31 +05:30
Gursheen Kaur Anand
33e0371c4d Merge pull request #40571 from frappe/mergify/bp/version-14-hotfix/pr-40563
fix: use `Text Editor` for rendering tax breakup table (backport #40563)
2024-03-20 20:39:19 +05:30
Gursheen Anand
381899bf5f chore: resolve conflicts 2024-03-20 20:25:31 +05:30
Rohit Waghchaure
1df54114a8 chore: fixed test case 2024-03-20 20:20:44 +05:30
Gursheen Anand
cf3b0ee41e chore: resolve conflicts 2024-03-20 20:15:20 +05:30
Gursheen Anand
957f55f6b1 chore: resolve conflicts 2024-03-20 20:12:36 +05:30
Rohit Waghchaure
77349a0af6 chore: fix test case 2024-03-20 20:09:22 +05:30
Rohit Waghchaure
c36a5d1ba3 chore: fix backport issues 2024-03-20 20:09:22 +05:30
rohitwaghchaure
44d4096ba1 chore: fix conflicts 2024-03-20 20:09:22 +05:30
rohitwaghchaure
a694a92df9 chore: fix conflicts 2024-03-20 20:09:22 +05:30
rohitwaghchaure
1c7128e77b chore: fix conflicts 2024-03-20 20:09:22 +05:30
rohitwaghchaure
c147ec168f chore: fix conflicts 2024-03-20 20:09:22 +05:30
rohitwaghchaure
717442c01f chore: fix conflicts 2024-03-20 20:09:22 +05:30
Rohit Waghchaure
ce7a53f810 chore: remove microsecond from posting_datetime
(cherry picked from commit a73ba2c0d2)

# Conflicts:
#	erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py
2024-03-20 20:08:37 +05:30
Rohit Waghchaure
1767dada8d test: test cases to test clash timestamp entries
(cherry picked from commit f04676aaed)
2024-03-20 20:08:36 +05:30
Rohit Waghchaure
5e68ebd030 perf: new column posting datetime in SLE to optimize stock ledger related queries
(cherry picked from commit d80ca523a4)
2024-03-20 20:07:36 +05:30
ruthra kumar
87fdb4e720 chore: resolve conflicts 2024-03-20 19:58:18 +05:30
ruthra kumar
e5722a772a chore: fix linting issue in JS
(cherry picked from commit 02c522b7cd)
2024-03-20 14:13:21 +00:00
ruthra kumar
35fcd032ad refactor(test): test cases modified to handle new approach
(cherry picked from commit 81309576b0)

# Conflicts:
#	erpnext/setup/demo.py
#	erpnext/setup/doctype/transaction_deletion_record/test_transaction_deletion_record.py
2024-03-20 14:13:21 +00:00
ruthra kumar
1fe14334f3 refactor: ability to process in single transaction
(cherry picked from commit a158b825d7)
2024-03-20 14:13:20 +00:00
ruthra kumar
b429f75d65 refactor: link running doc validation to company master
(cherry picked from commit 5a3afea8c7)

# Conflicts:
#	erpnext/setup/doctype/company/company.js
#	erpnext/setup/doctype/company/company.py
2024-03-20 14:13:20 +00:00
ruthra kumar
fab5c1170d chore: rename entry point
(cherry picked from commit 5fe0b20be1)
2024-03-20 14:13:19 +00:00
ruthra kumar
d496a1e58e chore: move status and error log to their own section
(cherry picked from commit 3cec62d4f8)
2024-03-20 14:13:19 +00:00
ruthra kumar
6ae9eb250f refactor: minor UI tweaks
(cherry picked from commit 0455d0c46c)
2024-03-20 14:13:19 +00:00
ruthra kumar
5e590389f3 refactor: exception propogation
(cherry picked from commit 4a55240e63)
2024-03-20 14:13:18 +00:00
ruthra kumar
1110dd93ff chore: code cleanup
(cherry picked from commit eea260b9f9)
2024-03-20 14:13:17 +00:00
ruthra kumar
0ea9ce7a5a refactor: better method naming
(cherry picked from commit 30463657bf)
2024-03-20 14:13:17 +00:00
ruthra kumar
cf6cb80d18 refactor: barebones hook on all doctypes with 'company' field
(cherry picked from commit ec194ef076)
2024-03-20 14:13:16 +00:00
ruthra kumar
e908003358 refactor: make sure only one task is running for doc
(cherry picked from commit 78c9cc63b1)
2024-03-20 14:13:16 +00:00
ruthra kumar
e142daca7f chore: hide docfield in list view
(cherry picked from commit 98afb4d468)
2024-03-20 14:13:15 +00:00
ruthra kumar
962105bc87 refactor: validations to prevent duplicate jobs
(cherry picked from commit 31a2da552b)
2024-03-20 14:13:15 +00:00
ruthra kumar
e600109872 refactor: no copy on summary table and more validations
(cherry picked from commit 55e93b3fe1)
2024-03-20 14:13:15 +00:00
ruthra kumar
97ed905627 refactor: reset all flags and remove unwanted code
(cherry picked from commit 2dbe68a09d)
2024-03-20 14:13:14 +00:00
ruthra kumar
c38cfd14f3 chore: show correct status in list view
(cherry picked from commit 1014940953)
2024-03-20 14:13:14 +00:00
ruthra kumar
341e467056 refactor: validate status before running events
(cherry picked from commit 86b5e2e277)
2024-03-20 14:13:14 +00:00
ruthra kumar
833df2c76b refactor: make Excluded doctype table read only
(cherry picked from commit 7c4cff2649)
2024-03-20 14:13:13 +00:00
ruthra kumar
a303788c71 chore: remove unwanted UI code
(cherry picked from commit b98a5e4edc)
2024-03-20 14:13:13 +00:00
ruthra kumar
0d791f594f refactor: use separate child table for summary
(cherry picked from commit 49d3bcbc8d)
2024-03-20 14:13:13 +00:00
ruthra kumar
b1367e839c refactor: chained callback
(cherry picked from commit b12ca65fcc)
2024-03-20 14:13:12 +00:00
ruthra kumar
e56138ddb0 refactor: reorder flags in Tasks section
(cherry picked from commit cccb2d5141)
2024-03-20 14:13:12 +00:00
ruthra kumar
c9d77044b0 refactor: use flags to decide on current stage
(cherry picked from commit 6a77d86a53)

# Conflicts:
#	erpnext/setup/doctype/transaction_deletion_record_item/transaction_deletion_record_item.py
2024-03-20 14:13:12 +00:00
ruthra kumar
5542985e25 refactor: UI trigger
(cherry picked from commit 8944ab8b6a)
2024-03-20 14:13:11 +00:00
ruthra kumar
52d22d8b55 refactor: tasks section and UI niceties
(cherry picked from commit d0dc2c6e77)
2024-03-20 14:13:11 +00:00
ruthra kumar
7280a76f73 refactor: set status and trigger job on submit
(cherry picked from commit 6fbb67b1d2)
2024-03-20 14:13:10 +00:00
ruthra kumar
07c98146c5 refactor: more options for 'status' and move it to top
(cherry picked from commit 0d65d878de)

# Conflicts:
#	erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py
2024-03-20 14:13:10 +00:00
Ankush Menat
e922ac7c31 fix: style for tax breakup
(cherry picked from commit 967540da18)

# Conflicts:
#	erpnext/public/scss/erpnext.scss
2024-03-20 13:12:16 +00:00
Gursheen Anand
bba1ac5735 fix: use Text Editor for rendering tax breakup table
(cherry picked from commit 1c63983873)

# Conflicts:
#	erpnext/accounts/doctype/pos_invoice/pos_invoice.py
#	erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
#	erpnext/accounts/doctype/sales_invoice/sales_invoice.py
#	erpnext/buying/doctype/purchase_order/purchase_order.json
#	erpnext/buying/doctype/purchase_order/purchase_order.py
#	erpnext/buying/doctype/supplier_quotation/supplier_quotation.json
#	erpnext/buying/doctype/supplier_quotation/supplier_quotation.py
#	erpnext/selling/doctype/quotation/quotation.json
#	erpnext/selling/doctype/quotation/quotation.py
#	erpnext/selling/doctype/sales_order/sales_order.py
#	erpnext/stock/doctype/delivery_note/delivery_note.json
#	erpnext/stock/doctype/delivery_note/delivery_note.py
#	erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
2024-03-20 13:12:15 +00:00
Ankush Menat
a0156e1e47 fix: style for tax breakup
(cherry picked from commit 967540da18)

# Conflicts:
#	erpnext/public/scss/erpnext.scss
2024-03-20 13:06:47 +00:00
Gursheen Anand
7df09d18e1 fix: use Text Editor for rendering tax breakup table
(cherry picked from commit 1c63983873)

# Conflicts:
#	erpnext/accounts/doctype/pos_invoice/pos_invoice.py
#	erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
#	erpnext/accounts/doctype/sales_invoice/sales_invoice.py
#	erpnext/buying/doctype/purchase_order/purchase_order.json
#	erpnext/buying/doctype/purchase_order/purchase_order.py
#	erpnext/buying/doctype/supplier_quotation/supplier_quotation.json
#	erpnext/buying/doctype/supplier_quotation/supplier_quotation.py
#	erpnext/selling/doctype/quotation/quotation.json
#	erpnext/selling/doctype/quotation/quotation.py
#	erpnext/selling/doctype/sales_order/sales_order.py
#	erpnext/stock/doctype/delivery_note/delivery_note.json
#	erpnext/stock/doctype/delivery_note/delivery_note.py
#	erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
2024-03-20 13:06:46 +00:00
Frappe PR Bot
b6575176f7 chore(release): Bumped to Version 14.65.4
## [14.65.4](https://github.com/frappe/erpnext/compare/v14.65.3...v14.65.4) (2024-03-20)

### Bug Fixes

* added index for voucher_detail_no in gl entry ([a1c8b93](a1c8b93e99))
* currency symbol for Landed Cost Voucher Amount (backport [#40550](https://github.com/frappe/erpnext/issues/40550)) ([#40553](https://github.com/frappe/erpnext/issues/40553)) ([7851311](785131121d))
* Data too long for column 'stock_queue' ([#40450](https://github.com/frappe/erpnext/issues/40450)) ([3340463](3340463b8e))
* flaky ecommerce test case ([#40534](https://github.com/frappe/erpnext/issues/40534)) ([b197c19](b197c1926f))
* get unique provisional accounts ([39d958c](39d958c507))
* index error on Exchange Rate Revaluation creation ([8813b6b](8813b6b2fd))
* invalid exchange loss booking on invoice againts base accounts ([a27f386](a27f386665))
* missing range for ageing summary ([9f0ad7a](9f0ad7a4ea))
* provisional entry for non-stock item ([0aef7f9](0aef7f9671))
* **Supplier Quotation Comparison:** group by options ([cfed706](cfed706c15))
* Update Existing Price List Rate not working (backport [#40333](https://github.com/frappe/erpnext/issues/40333)) ([#40526](https://github.com/frappe/erpnext/issues/40526)) ([64f1844](64f1844bc8))
* warehouse issue in pick list ([#40453](https://github.com/frappe/erpnext/issues/40453)) ([5a2eaf9](5a2eaf9092))
2024-03-20 05:23:36 +00:00
rohitwaghchaure
edce5770f0 Merge pull request #40537 from frappe/version-14-hotfix
chore: release v14
2024-03-20 10:52:20 +05:30
mergify[bot]
785131121d fix: currency symbol for Landed Cost Voucher Amount (backport #40550) (#40553)
* fix: currency symbol for Landed Cost Voucher Amount (#40550)

(cherry picked from commit 0725707cb1)

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

* chore: fix conflicts

---------

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-03-19 23:37:32 +05:30
Nabin Hait
419f2a5192 Merge pull request #40519 from nabinhait/provisional-entry-fix
fix: provisional entry for non-stock item
2024-03-19 21:58:56 +05:30
Nabin Hait
39d958c507 fix: get unique provisional accounts 2024-03-19 21:06:16 +05:30
Nabin Hait
a1c8b93e99 fix: added index for voucher_detail_no in gl entry 2024-03-19 18:35:11 +05:30
Nabin Hait
0aef7f9671 fix: provisional entry for non-stock item 2024-03-19 18:29:37 +05:30
mergify[bot]
64f1844bc8 fix: Update Existing Price List Rate not working (backport #40333) (#40526)
* fix: Update Existing Price List Rate not working (#40333)

(cherry picked from commit 09ea7edb86)

# Conflicts:
#	erpnext/selling/doctype/sales_order/test_sales_order.py
#	erpnext/setup/demo_data/item.json

* chore: fix conflicts

---------

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-03-19 18:11:50 +05:30
ruthra kumar
b197c1926f fix: flaky ecommerce test case (#40534)
* refactor(test): make use of fixtures

* refactor(test): rating are now restricted with [0..1]

* refactor(test): remove superfluous setup override
2024-03-19 17:54:35 +05:30
Raffael Meyer
76f27d99bb Merge pull request #40547 from frappe/mergify/bp/version-14-hotfix/pr-40546
fix(Supplier Quotation Comparison): group by options (backport #40546)
2024-03-19 13:07:40 +01:00
barredterra
cfed706c15 fix(Supplier Quotation Comparison): group by options
(cherry picked from commit 87e36d290e)
2024-03-19 11:51:37 +00:00
Gursheen Kaur Anand
93fe136386 Merge pull request #40530 from frappe/mergify/bp/version-14-hotfix/pr-40528
fix(minor): missing range for ageing summary in PSOA (backport #40528)
2024-03-19 12:44:16 +05:30
Gursheen Anand
9f0ad7a4ea fix: missing range for ageing summary
(cherry picked from commit 643cc022fd)
2024-03-19 07:11:18 +00:00
ruthra kumar
59a9a41e9d Merge pull request #40522 from frappe/mergify/bp/version-14-hotfix/pr-40502
refactor: toggle between 'http' and 'https' on exchange rate API (backport #40502)
2024-03-19 10:37:32 +05:30
ruthra kumar
33efa6960d chore: resolve conflicts 2024-03-19 10:14:24 +05:30
ruthra kumar
379616ab4b refactor: toggle between 'http' and 'https' on exchange rate API
(cherry picked from commit 8b81274769)

# Conflicts:
#	erpnext/accounts/doctype/currency_exchange_settings/currency_exchange_settings.py
2024-03-19 04:29:44 +00:00
ruthra kumar
8cb1293ffc Merge pull request #40515 from frappe/mergify/bp/version-14-hotfix/pr-40511
fix: invalid exchange loss booking on invoice against base accounts (backport #40511)
2024-03-18 21:05:51 +05:30
ruthra kumar
fe78214ea4 refactor(test): ensure Exchange gain/loss journals aren't created
(cherry picked from commit e1c2d006ca)
2024-03-18 15:14:44 +00:00
ruthra kumar
a27f386665 fix: invalid exchange loss booking on invoice againts base accounts
(cherry picked from commit 3d5dba6976)
2024-03-18 15:14:44 +00:00
Danny
ee7bd98878 fix: pass empty string email content of pos invoice 2024-03-18 10:47:42 -04:00
Gursheen Anand
fe3bee44e2 fix: show correct variance for durations with no vouchers
(cherry picked from commit bc78bc33f1)
2024-03-18 05:53:57 +00:00
Gursheen Anand
c3b8c00070 test: sales partner targets with invoices
(cherry picked from commit 1a3ea0c108)
2024-03-18 05:53:57 +00:00
Gursheen Anand
f9ab763cc8 fix: achieved targets for sales partners
(cherry picked from commit 1ac888715c)
2024-03-18 05:53:57 +00:00
ruthra kumar
c4c0510a1b Merge pull request #40496 from frappe/mergify/bp/version-14-hotfix/pr-40495
fix: index error on Exchange Rate Revaluation creation (backport #40495)
2024-03-17 08:10:46 +05:30
ruthra kumar
8813b6b2fd fix: index error on Exchange Rate Revaluation creation
(cherry picked from commit bb279e368c)
2024-03-17 02:21:33 +00:00
ruthra kumar
a0e839e31a Merge pull request #40489 from frappe/mergify/bp/version-14-hotfix/pr-40485
refactor: validate SO and SI references in Delivery Notes (backport #40485)
2024-03-16 15:28:12 +05:30
ruthra kumar
9d827e84be chore: resolve conflicts 2024-03-16 15:02:23 +05:30
ruthra kumar
f87f284616 test: SO reference validation
(cherry picked from commit 4f396d3049)

# Conflicts:
#	erpnext/selling/doctype/sales_order/test_sales_order.py
2024-03-16 09:29:07 +00:00
ruthra kumar
5f4a648dd4 refactor: validate SO and SI references
(cherry picked from commit 4d090bd3b8)

# Conflicts:
#	erpnext/stock/doctype/delivery_note/delivery_note.py
2024-03-16 09:29:07 +00:00
ruthra kumar
5f0920ab27 Merge pull request #40475 from frappe/mergify/bp/version-14-hotfix/pr-40473
refactor: enable no-copy for update_outstanding_for_self (backport #40473)
2024-03-16 10:09:37 +05:30
ruthra kumar
03cb07f591 Merge pull request #40465 from frappe/mergify/bp/version-14-hotfix/pr-40461
refactor: disallow '0' qty return invoices with stock effect (backport #40461)
2024-03-16 10:07:31 +05:30
ruthra kumar
90a5155fc1 refactor: enable no-copy for update_outstanding_for_self
(cherry picked from commit a1e8caa5c1)
2024-03-15 11:33:09 +00:00
ruthra kumar
0437274c58 chore: resolve conflict 2024-03-15 11:39:54 +05:30
ruthra kumar
a914eb5d40 test: validation to prevent '0' qty return with stock effect
(cherry picked from commit 647bba0f00)
2024-03-15 05:37:23 +00:00
ruthra kumar
b011a68a2a refactor: disallow '0' qty return invoices with stock effect
(cherry picked from commit 898affbee9)

# Conflicts:
#	erpnext/controllers/accounts_controller.py
2024-03-15 05:37:22 +00:00
Frappe PR Bot
009cdb732f chore(release): Bumped to Version 14.65.3
## [14.65.3](https://github.com/frappe/erpnext/compare/v14.65.2...v14.65.3) (2024-03-14)

### Bug Fixes

* Data too long for column 'stock_queue' (backport [#40450](https://github.com/frappe/erpnext/issues/40450)) ([#40452](https://github.com/frappe/erpnext/issues/40452)) ([0999d09](0999d09700))
* warehouse issue in pick list (backport [#40453](https://github.com/frappe/erpnext/issues/40453)) ([#40455](https://github.com/frappe/erpnext/issues/40455)) ([314e9f5](314e9f5787))
2024-03-14 07:36:22 +00:00
mergify[bot]
314e9f5787 fix: warehouse issue in pick list (backport #40453) (#40455)
fix: warehouse issue in pick list (#40453)

(cherry picked from commit 5a2eaf9092)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-03-14 13:04:41 +05:30
mergify[bot]
0999d09700 fix: Data too long for column 'stock_queue' (backport #40450) (#40452)
fix: Data too long for column 'stock_queue' (#40450)

(cherry picked from commit 3340463b8e)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-03-14 13:04:16 +05:30
rohitwaghchaure
5a2eaf9092 fix: warehouse issue in pick list (#40453) 2024-03-14 12:17:23 +05:30
rohitwaghchaure
3340463b8e fix: Data too long for column 'stock_queue' (#40450) 2024-03-14 11:39:29 +05:30
Frappe PR Bot
561f6a7af7 chore(release): Bumped to Version 14.65.2
## [14.65.2](https://github.com/frappe/erpnext/compare/v14.65.1...v14.65.2) (2024-03-14)

### Bug Fixes

* added index for price_list column in Item Price ([d279e23](d279e23623))
* Book depreciation until the asset disposal date and removed unwanted commits ([5fcf8c5](5fcf8c588a))
* convert str to date ([34c3e75](34c3e75d5c))
* flaky Accounts Receivable test case ([41bda58](41bda583e8))
* incorrect gross profit on the quotation (backport [#40438](https://github.com/frappe/erpnext/issues/40438)) ([#40441](https://github.com/frappe/erpnext/issues/40441)) ([fe54590](fe54590af7))
* linter issues ([ac0dd50](ac0dd5083f))
* linter issues ([668a931](668a93128b))
* linter issues ([acc0b2f](acc0b2faf8))
* minor fixes ([5cd9bf3](5cd9bf3bda))
* Patch to remove cancelled asset capitalization from asset ([23e256a](23e256aedf))
* Reload document on cancel to avoid document modified error ([c7ed854](c7ed854850))
* **test:** manually filter rows and assert ([5fe200b](5fe200bc4d))

### Performance Improvements

* Cache accounting dimension filter map ([e4bd173](e4bd173875))
* Cached accounting dimensions details ([8cd8b8f](8cd8b8f885))
* Caching in checking allowance for qty and amount ([8d682fa](8d682fa884))
* Caching in gl entry ([b07769d](b07769d8d7))
* Get bin details only for stock items ([6ff9e6e](6ff9e6ee84))
* Optimization for providional gl entries ([d7b738f](d7b738ff61))
* Optimzed code for merging similar gl entries ([aa75a60](aa75a60142))
* Performance optimization for validating budget ([f204d81](f204d810bb))
* refactored handling provisional gl entries for non-stock items ([49c7436](49c74369a5))
* skip unnecessary validation while transaction  cancellation ([05385e4](05385e4acb))
* validate expense against budget only if budget exists ([c15b2d5](c15b2d5490))
2024-03-14 06:01:38 +00:00
Nabin Hait
aa7c00135f Merge pull request #40443 from frappe/version-14-hotfix
chore: release v14
2024-03-14 11:30:17 +05:30
ruthra kumar
8500f9dad1 Merge pull request #40446 from frappe/mergify/copy/version-14-hotfix/pr-40445
fix: flaky Accounts Receivable test case (copy #40445)
2024-03-14 09:16:33 +05:30
ruthra kumar
5fe200bc4d fix(test): manually filter rows and assert 2024-03-14 08:54:41 +05:30
ruthra kumar
41bda583e8 fix: flaky Accounts Receivable test case
(cherry picked from commit 40bce240bde508801d07b9c38ededea5b4f297c8)
2024-03-13 16:33:46 +00:00
mergify[bot]
fe54590af7 fix: incorrect gross profit on the quotation (backport #40438) (#40441)
fix: incorrect gross profit on the quotation (#40438)

(cherry picked from commit f4a945aee4)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-03-13 21:55:26 +05:30
Nabin Hait
fa55cc68f8 Merge pull request #40263 from nabinhait/pi-optimization
perf: Performance optmization for Purchase Invoice submission
2024-03-13 18:17:41 +05:30
ruthra kumar
fa0a60c5d9 Merge pull request #40426 from frappe/mergify/bp/version-14-hotfix/pr-40372
refactor: checkbox to toggle standalone Credit/Debit note behaviour (backport #40372)
2024-03-13 16:28:38 +05:30
Nabin Hait
c1428a5655 Merge pull request #40246 from nabinhait/depreciation-asset-sale
fix: Book depreciation until the asset disposal date and removed unwanted commits
2024-03-13 13:17:18 +05:30
Nabin Hait
43a6a00912 Merge pull request #40125 from nabinhait/document-modified-error
fix: Reload document on cancel to avoid document modified error
2024-03-13 13:17:05 +05:30
ruthra kumar
5d178d2e24 refactor: pass 'name' to get_link_to_form 2024-03-13 13:16:56 +05:30
Nabin Hait
b5f0576a1b Merge pull request #40122 from nabinhait/remove-capitalized-in
fix: Patch to remove cancelled asset capitalization from asset
2024-03-13 13:16:29 +05:30
Nabin Hait
b07769d8d7 perf: Caching in gl entry 2024-03-13 13:02:51 +05:30
Nabin Hait
8d682fa884 perf: Caching in checking allowance for qty and amount 2024-03-13 13:00:10 +05:30
Nabin Hait
d279e23623 fix: added index for price_list column in Item Price 2024-03-13 12:58:13 +05:30
Nabin Hait
6ff9e6ee84 perf: Get bin details only for stock items 2024-03-13 12:57:33 +05:30
Nabin Hait
c15b2d5490 perf: validate expense against budget only if budget exists 2024-03-13 12:56:28 +05:30
Nabin Hait
49c74369a5 perf: refactored handling provisional gl entries for non-stock items 2024-03-13 12:54:13 +05:30
ruthra kumar
92ccef0ebc chore: resolve conflicts 2024-03-13 12:14:33 +05:30
ruthra kumar
ae6d1c14cb chore: better popup message
(cherry picked from commit 445d2acf50)

# Conflicts:
#	erpnext/controllers/accounts_controller.py
2024-03-13 06:12:45 +00:00
ruthra kumar
b746493830 test: cr note flag to update self
(cherry picked from commit ce3b1f09f5)
2024-03-13 06:12:44 +00:00
ruthra kumar
34053ec590 refactor: make AR/AP report aware of always standalone cr/dr notes
(cherry picked from commit 4d0c2d8e82)
2024-03-13 06:12:44 +00:00
ruthra kumar
adbc20736e chore: patch for updating flag in Cr/Dr notes
(cherry picked from commit 849f478894)
2024-03-13 06:12:44 +00:00
ruthra kumar
d1e3b2ab6e refactor: post ledger entries based on toggle
(cherry picked from commit 77aac6f571)
2024-03-13 06:12:44 +00:00
ruthra kumar
6d5e595440 refactor: checkbox in purchase invoice
(cherry picked from commit 767f2157e6)

# Conflicts:
#	erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
#	erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
2024-03-13 06:12:43 +00:00
ruthra kumar
1ddb162ef1 chore: update popup message
(cherry picked from commit adf13a19c4)

# Conflicts:
#	erpnext/controllers/accounts_controller.py
2024-03-13 06:12:43 +00:00
ruthra kumar
4d6b56e55b refactor: checkbox to toggle always standalone credit note
(cherry picked from commit 2cefe2a20e)

# Conflicts:
#	erpnext/accounts/doctype/sales_invoice/sales_invoice.json
#	erpnext/accounts/doctype/sales_invoice/sales_invoice.py
2024-03-13 06:12:43 +00:00
Frappe PR Bot
fa5a19b548 chore(release): Bumped to Version 14.65.1
## [14.65.1](https://github.com/frappe/erpnext/compare/v14.65.0...v14.65.1) (2024-03-12)

### Bug Fixes

* barcode field on line item not working (backport [#40381](https://github.com/frappe/erpnext/issues/40381)) ([#40383](https://github.com/frappe/erpnext/issues/40383)) ([80df609](80df6094e3))
* conditionally apply `is_group` filter in accounting dimension query (backport [#40414](https://github.com/frappe/erpnext/issues/40414)) ([#40415](https://github.com/frappe/erpnext/issues/40415)) ([cd40038](cd40038b18))
* error message wording ([#40403](https://github.com/frappe/erpnext/issues/40403)) ([7402303](74023035af))
* Filter for projects in Sales Cycle ([8d63d19](8d63d19d45))
* get_user_default_as_list args order ([e0d1b4b](e0d1b4b15f))
* incorrect work order status (backport [#40407](https://github.com/frappe/erpnext/issues/40407)) ([#40410](https://github.com/frappe/erpnext/issues/40410)) ([c413b04](c413b04539))
* load ignored doctype and include Mode of Payment Account ([#40334](https://github.com/frappe/erpnext/issues/40334)) ([411157c](411157c258))
* message for subscription when no current inv ([e9c2f6d](e9c2f6d6f1))
* MR Default Supplier search query (backport [#40273](https://github.com/frappe/erpnext/issues/40273)) ([#40350](https://github.com/frappe/erpnext/issues/40350)) ([c6fe409](c6fe409b56))
* qc created for raw materials during manufacture entry (backport [#40408](https://github.com/frappe/erpnext/issues/40408)) ([#40412](https://github.com/frappe/erpnext/issues/40412)) ([21b57d9](21b57d9aef))
* recursion issue while submitting work order (backport [#40400](https://github.com/frappe/erpnext/issues/40400)) ([#40401](https://github.com/frappe/erpnext/issues/40401)) ([06e3874](06e38749bc))
* Sender email in process statements of accounts ([ea605e7](ea605e76a3))
* **Shipment Parcel:** make length, width and height non-mandatory ([911a582](911a582941))
* subcontracting receipt -> alllow to change Batch / Serial Nos (v14) ([#40371](https://github.com/frappe/erpnext/issues/40371)) ([ffd04b3](ffd04b3960))
* UAE tax computation fix ([02cd8c4](02cd8c4b98))
2024-03-12 16:42:45 +00:00
Deepesh Garg
c24af0eb40 Merge pull request #40396 from frappe/version-14-hotfix
chore: release v14
2024-03-12 22:11:31 +05:30
mergify[bot]
cd40038b18 fix: conditionally apply is_group filter in accounting dimension query (backport #40414) (#40415)
fix: conditionally apply `is_group` filter in accounting dimension query (#40414)

(cherry picked from commit daf4ae2a6b)

Co-authored-by: Rucha Mahabal <ruchamahabal2@gmail.com>
2024-03-12 20:45:43 +05:30
Raffael Meyer
3dd4514478 Merge pull request #40405 from frappe/mergify/bp/version-14-hotfix/pr-40403
fix: error message wording (backport #40403)
2024-03-12 14:33:59 +01:00
mergify[bot]
c413b04539 fix: incorrect work order status (backport #40407) (#40410)
fix: incorrect work order status (#40407)

(cherry picked from commit 948297692e)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-03-12 18:34:35 +05:30
mergify[bot]
21b57d9aef fix: qc created for raw materials during manufacture entry (backport #40408) (#40412)
fix: qc created for raw materials during manufacture entry (#40408)

(cherry picked from commit f8a1a7f515)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-03-12 18:29:21 +05:30
Raffael Meyer
05e4517094 chore: resolve conflicts 2024-03-12 12:35:17 +01:00
Raffael Meyer
74023035af fix: error message wording (#40403)
(cherry picked from commit 79a0473705)

# Conflicts:
#	erpnext/accounts/doctype/subscription/subscription.py
2024-03-12 11:26:23 +00:00
mergify[bot]
06e38749bc fix: recursion issue while submitting work order (backport #40400) (#40401)
* fix: recursion issue while submitting work order (#40400)

(cherry picked from commit 72614bb8ff)

# Conflicts:
#	erpnext/manufacturing/doctype/job_card/job_card.py

* chore: fix conflicts

---------

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-03-12 16:53:48 +05:30
mergify[bot]
80df6094e3 fix: barcode field on line item not working (backport #40381) (#40383)
fix: barcode field on line item not working (#40381)

(cherry picked from commit 0da19a40a7)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-03-12 13:49:08 +05:30
Nabin Hait
34c3e75d5c fix: convert str to date 2024-03-12 12:16:41 +05:30
Nabin Hait
ac0dd5083f fix: linter issues 2024-03-12 12:10:55 +05:30
Nabin Hait
668a93128b fix: linter issues 2024-03-12 12:02:23 +05:30
Nabin Hait
5fcf8c588a fix: Book depreciation until the asset disposal date and removed unwanted commits 2024-03-12 11:56:47 +05:30
rohitwaghchaure
ffd04b3960 fix: subcontracting receipt -> alllow to change Batch / Serial Nos (v14) (#40371)
fix: subcontracting receipt -> alllow to change Batch / Serial Nos
2024-03-11 16:42:13 +05:30
mergify[bot]
c6fe409b56 fix: MR Default Supplier search query (backport #40273) (#40350)
fix: MR Default Supplier search query

(cherry picked from commit c0a1f298a1)

Co-authored-by: s-aga-r <sagarsharma.s312@gmail.com>
2024-03-11 11:07:48 +05:30
Ankush Menat
6b88cca9ad Merge pull request #40367 from ankush/mergify/bp/version-14-hotfix/pr-40206
style: format js code
2024-03-11 11:07:06 +05:30
Ankush Menat
4c629d31c6 style: format js files 2024-03-11 11:03:58 +05:30
barredterra
c46be27e9e ci: add prettier to pre-commit
(cherry picked from commit 2c16036ef3)
2024-03-11 11:03:56 +05:30
Deepesh Garg
2e45a3f491 Merge pull request #40363 from frappe/mergify/bp/version-14-hotfix/pr-40344
fix: get_user_default_as_list args order (#40344)
2024-03-10 22:32:29 +05:30
Deepesh Garg
3bea2d4d1d Merge pull request #40357 from frappe/mergify/bp/version-14-hotfix/pr-40323
fix: Filter for projects in Sales Cycle (#40323)
2024-03-10 22:32:11 +05:30
Devin Slauenwhite
e0d1b4b15f fix: get_user_default_as_list args order
(cherry picked from commit ac1961b687)
2024-03-10 15:45:31 +00:00
Deepesh Garg
306e76874d Merge pull request #40359 from frappe/mergify/bp/version-14-hotfix/pr-40325
fix: Sender email in process statements of accounts (#40325)
2024-03-10 19:57:28 +05:30
Deepesh Garg
407f0b929e Merge pull request #40009 from govindsmenokee/patch-12
fix: UAE tax computation fix
2024-03-10 19:55:39 +05:30
Deepesh Garg
d57af37ec7 Merge pull request #39724 from GursheenK/subscription-failed-msg
fix: message for failed subscription process
2024-03-10 19:33:41 +05:30
Deepesh Garg
ec3913fdd3 Merge pull request #40089 from frappe/mergify/bp/version-14-hotfix/pr-31463
feat: german translations (#31463)
2024-03-10 19:29:07 +05:30
Deepesh Garg
ea605e76a3 fix: Sender email in process statements of accounts
(cherry picked from commit 65a2f3d12c)
2024-03-10 13:57:34 +00:00
Deepesh Garg
8d63d19d45 fix: Filter for projects in Sales Cycle
(cherry picked from commit d0e0b66b2f)
2024-03-10 13:56:50 +00:00
Deepesh Garg
12d260c444 Merge pull request #40336 from frappe/mergify/bp/version-14-hotfix/pr-40334
fix: load ignored doctype and include Mode of Payment Account (#40334)
2024-03-10 19:25:24 +05:30
Nihantra C. Patel
411157c258 fix: load ignored doctype and include Mode of Payment Account (#40334)
(cherry picked from commit 68baa3612a)
2024-03-07 12:14:10 +00:00
Raffael Meyer
b29e70a126 Merge pull request #40320 from frappe/mergify/bp/version-14-hotfix/pr-40317
fix(Shipment Parcel): make length, width and height non-mandatory (backport #40317)
2024-03-06 19:49:47 +01:00
barredterra
911a582941 fix(Shipment Parcel): make length, width and height non-mandatory
It's tedious to enter all these values and some shipping providers only need to know the weigth and quantity. Companies can alwas cutomize the values to be mandatory, but the reverse is not possible. I'll make sure that the erpnext-shipping app does not break because of this (or fix any problems).

(cherry picked from commit 898c6e30eb)
2024-03-06 18:26:20 +00:00
Nabin Hait
05385e4acb perf: skip unnecessary validation while transaction cancellation 2024-03-06 22:33:36 +05:30
Nabin Hait
5cd9bf3bda fix: minor fixes 2024-03-06 21:04:07 +05:30
Nabin Hait
e4bd173875 perf: Cache accounting dimension filter map 2024-03-06 20:32:47 +05:30
Nabin Hait
acc0b2faf8 fix: linter issues 2024-03-06 17:43:27 +05:30
Frappe PR Bot
b424a184b9 chore(release): Bumped to Version 14.65.0
# [14.65.0](https://github.com/frappe/erpnext/compare/v14.64.0...v14.65.0) (2024-03-06)

### Bug Fixes

* account validation error on bank account after editing existing bank account ([8b3c809](8b3c809cb6))
* allow gain/loss for Journals against Journals ([52e1c2f](52e1c2f48b))
* do not allow to cancel incomplete reposting (backport [#40224](https://github.com/frappe/erpnext/issues/40224)) ([#40229](https://github.com/frappe/erpnext/issues/40229)) ([091d6f3](091d6f330a))
* don't override reference exchange rate ([e25ec41](e25ec4156e))
* handle partial invoice against provisional entry ([5f23614](5f23614960))
* incorrect exchange rate if JE has multi parties ([1b5a237](1b5a23709a))
* incorrect TCS on customer and suppliers with same name ([af56846](af568464db))
* make use of 'flt' to prevent really low precision exc gain/loss ([c1a0ac6](c1a0ac655e))
* make warning for previously existing SO an alert ([c8b817c](c8b817c87a))
* over billing qty along with rate ([14d9d29](14d9d29913))
* **Project:** filter department by company ([646b55e](646b55eeea))
* provisional reverse entry amount ([e62c49d](e62c49d9a6))
* rate change on changing of the qty (backport [#40241](https://github.com/frappe/erpnext/issues/40241)) ([#40242](https://github.com/frappe/erpnext/issues/40242)) ([b937c4b](b937c4be4f))
* **setup:** avoid duplicate entry for Analytics role (backport [#40183](https://github.com/frappe/erpnext/issues/40183)) ([#40184](https://github.com/frappe/erpnext/issues/40184)) ([035c90c](035c90c3b8))

### Features

* add company filter to child table field ([38baf8d](38baf8d406))
2024-03-06 03:31:16 +00:00
Deepesh Garg
0b364f6e8e Merge pull request #40281 from frappe/version-14-hotfix
chore: release v14
2024-03-06 08:59:57 +05:30
ruthra kumar
83734c6be4 Merge pull request #40283 from frappe/mergify/bp/version-14-hotfix/pr-40278
fix: incorrect TCS on customer and suppliers with same name (backport #40278)
2024-03-05 15:48:27 +05:30
ruthra kumar
af568464db fix: incorrect TCS on customer and suppliers with same name
(cherry picked from commit 9904a9868c)
2024-03-05 09:54:47 +00:00
Nabin Hait
aa75a60142 perf: Optimzed code for merging similar gl entries 2024-03-04 16:04:39 +05:30
Nabin Hait
8cd8b8f885 perf: Cached accounting dimensions details 2024-03-04 16:04:39 +05:30
Nabin Hait
f204d810bb perf: Performance optimization for validating budget 2024-03-04 16:04:39 +05:30
Nabin Hait
d7b738ff61 perf: Optimization for providional gl entries 2024-03-04 16:04:35 +05:30
mergify[bot]
091d6f330a fix: do not allow to cancel incomplete reposting (backport #40224) (#40229)
* fix: do not allow to cancel incomplete reposting (#40224)

(cherry picked from commit 72ac56b6c4)

# Conflicts:
#	erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py

* chore: fix conflicts

---------

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-03-04 13:14:32 +05:30
Gursheen Kaur Anand
cc923f50ef Merge pull request #40257 from GursheenK/remove-balance-fetching-in-JV
perf: remove unnecessary fetching of balances in JV
2024-03-04 11:16:01 +05:30
Gursheen Anand
2f8fe17b60 refactor: remove controller logic for setting balances 2024-03-04 00:37:29 +05:30
Gursheen Anand
e3d6f70eee refactor: exclude balances while setting currency 2024-03-04 00:37:26 +05:30
Gursheen Anand
a1c22811a2 refactor: exclude balance while setting acc details 2024-03-04 00:35:54 +05:30
Gursheen Anand
d715c29edc refactor: remove balance formatter 2024-03-04 00:35:54 +05:30
Gursheen Anand
85a7ce6d30 refactor: remove balance fields from jv account 2024-03-04 00:35:51 +05:30
Gursheen Kaur Anand
c42d7505bd Merge pull request #40204 from frappe/mergify/bp/version-14-hotfix/pr-39584
fix: use receipt amount for reverse provisional entry (backport #39584)
2024-03-03 18:24:57 +05:30
Gursheen Kaur Anand
29f4e68827 Merge pull request #40251 from frappe/mergify/bp/version-14-hotfix/pr-40250
fix(minor): company filter in cost center allocation (backport #40250)
2024-03-03 18:24:42 +05:30
Gursheen Anand
38baf8d406 feat: add company filter to child table field
(cherry picked from commit 51909077bd)
2024-03-03 12:45:33 +00:00
Gursheen Anand
89e7ad790f chore: linting issue 2024-03-03 18:00:10 +05:30
mergify[bot]
b937c4be4f fix: rate change on changing of the qty (backport #40241) (#40242)
fix: rate change on changing of the qty (#40241)

(cherry picked from commit e7d707797a)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-03-02 16:49:40 +05:30
ruthra kumar
793fdf9562 Merge pull request #40238 from frappe/mergify/bp/version-14-hotfix/pr-40220
refactor: Gain/Loss Journal creation for Journals against Journals (backport #40220)
2024-03-02 16:25:32 +05:30
ruthra kumar
753223da78 chore: resolve merge conflict 2024-03-02 16:00:29 +05:30
ruthra kumar
46063518d7 test: gain/loss on Journals against Journals
(cherry picked from commit 8a5078b826)

# Conflicts:
#	erpnext/controllers/tests/test_accounts_controller.py
2024-03-02 10:07:33 +00:00
ruthra kumar
52e1c2f48b fix: allow gain/loss for Journals against Journals
(cherry picked from commit 5b67631d40)

# Conflicts:
#	erpnext/accounts/doctype/journal_entry/journal_entry.py
2024-03-02 10:07:32 +00:00
ruthra kumar
c1a0ac655e fix: make use of 'flt' to prevent really low precision exc gain/loss
(cherry picked from commit 0aa72f841d)
2024-03-02 10:07:31 +00:00
ruthra kumar
21a10eee0d Merge pull request #40232 from frappe/mergify/bp/version-14-hotfix/pr-40149
fix: incorrect exchange rate if JE has multi parties (backport #40149)
2024-03-02 15:36:15 +05:30
ruthra kumar
64bf52899f chore: resolve linter 2024-03-02 14:57:48 +05:30
ruthra kumar
572def058f test: exchange rate fetch on JE with multiple forex parties
(cherry picked from commit ed95d41a51)
2024-03-02 14:39:37 +05:30
ruthra kumar
e25ec4156e fix: don't override reference exchange rate
(cherry picked from commit eaac02655b)
2024-03-02 08:22:41 +00:00
ruthra kumar
1b5a23709a fix: incorrect exchange rate if JE has multi parties
(cherry picked from commit 694c17487d)
2024-03-02 08:22:38 +00:00
Raffael Meyer
d7abb21f7b Merge pull request #40209 from frappe/mergify/bp/version-14-hotfix/pr-40203
fix(Project): filter department by company (backport #40203)
2024-02-29 23:34:17 +01:00
barredterra
646b55eeea fix(Project): filter department by company
(cherry picked from commit 5e736f0d06)
2024-02-29 17:30:05 +00:00
Gursheen Anand
c8b31833f5 test: partial billing for provisional accounting
(cherry picked from commit c5770f2ecc)
2024-02-29 15:48:37 +00:00
Gursheen Anand
aa52cd67bd test: overbilling for provisional accounting
(cherry picked from commit ff3ca50a4b)
2024-02-29 15:48:36 +00:00
Gursheen Anand
14d9d29913 fix: over billing qty along with rate
(cherry picked from commit cc96d2b50c)
2024-02-29 15:48:36 +00:00
Gursheen Anand
5f23614960 fix: handle partial invoice against provisional entry
(cherry picked from commit 2a46799188)
2024-02-29 15:48:36 +00:00
Gursheen Anand
e62c49d9a6 fix: provisional reverse entry amount
(cherry picked from commit 3e59c66806)
2024-02-29 15:48:36 +00:00
ruthra kumar
fca70e3d03 Merge pull request #40039 from SherinKR/bank_account_validation
fix: account validation error on bank account after editing existing bank account
2024-02-29 17:38:34 +05:30
Gursheen Kaur Anand
aeb555a426 Merge pull request #40188 from frappe/mergify/bp/version-14-hotfix/pr-40176
fix(minor): make warning for previously existing SO an alert (backport #40176)
2024-02-29 11:59:44 +05:30
mergify[bot]
035c90c3b8 fix(setup): avoid duplicate entry for Analytics role (backport #40183) (#40184)
fix(setup): avoid duplicate entry for Analytics role (#40183)

(cherry picked from commit 29f91a7919)

Co-authored-by: Rucha Mahabal <ruchamahabal2@gmail.com>
2024-02-29 11:34:23 +05:30
Gursheen Anand
c8b817c87a fix: make warning for previously existing SO an alert
(cherry picked from commit 24dcd64c16)
2024-02-29 06:03:26 +00:00
Frappe PR Bot
de6957262d chore(release): Bumped to Version 14.64.0
# [14.64.0](https://github.com/frappe/erpnext/compare/v14.63.3...v14.64.0) (2024-02-28)

### Bug Fixes

* add flags for repost to ensure correct accounting from India Compliance App ([8c772cf](8c772cfb9f))
* amount label according to party type ([bb3a7cd](bb3a7cdb3d))
* Cannot read properties of undefined (backport [#40081](https://github.com/frappe/erpnext/issues/40081)) ([#40082](https://github.com/frappe/erpnext/issues/40082)) ([579b27d](579b27d010))
* capacity planning issue in the job card (backport [#40092](https://github.com/frappe/erpnext/issues/40092)) ([#40100](https://github.com/frappe/erpnext/issues/40100)) ([8a573a1](8a573a1aff))
* check_credit_limit on_update_after_submit of Sales Order ([3112fca](3112fca087))
* communication_date in party dashboards (backport [#40005](https://github.com/frappe/erpnext/issues/40005)) ([#40020](https://github.com/frappe/erpnext/issues/40020)) ([b364fe7](b364fe7047))
* Completed Work Orders report not working ([c8e1409](c8e1409b80))
* Cr/Dr notes with POS Payments ([e5098c5](e5098c521b))
* default taxable value for item not found in item list ([30315ab](30315aba37))
* Delete linked asset movement record on cancellation of purchase receipt/invoice ([11bddc1](11bddc14bb))
* Delete orphaned asset movement item records ([46cd929](46cd929d00))
* delete PLE containing invoice in against ([08459ce](08459cef4a))
* do not make MR against raw materials of available sub assemblies (backport [#40085](https://github.com/frappe/erpnext/issues/40085)) ([#40086](https://github.com/frappe/erpnext/issues/40086)) ([e461185](e461185317))
* incorrect item name in MR (backport [#40018](https://github.com/frappe/erpnext/issues/40018)) ([#40023](https://github.com/frappe/erpnext/issues/40023)) ([079ba76](079ba7670c))
* linter issue ([ea1a0b3](ea1a0b3a28))
* linting issue ([65a2adf](65a2adfc55))
* linting issue ([e289aef](e289aef1b4))
* negative stock error while making stock reconciliation (backport [#40016](https://github.com/frappe/erpnext/issues/40016)) ([#40025](https://github.com/frappe/erpnext/issues/40025)) ([865cba4](865cba406f))
* on unreconciliation, update advance paid ([fe88a11](fe88a110b1))
* only check for delinked PLEs ([3d243a7](3d243a7fa5))
* only consider contributed qty towards achieved targets ([0484857](0484857402))
* parent warehouse checks in the production plan for sub-assemblies (backport [#40150](https://github.com/frappe/erpnext/issues/40150)) ([#40156](https://github.com/frappe/erpnext/issues/40156)) ([9a85ab4](9a85ab45e7))
* remove cancelled payment entry from Payment Period Based On Invoice Date ([2fc490a](2fc490a5d7))
* remove cancelled payment entry from PPBOID report ([a1c0c23](a1c0c2359f))
* remove config for default bank account in test ([ad60677](ad6067795f))
* sales funnel text color in light/dark theme ([#40132](https://github.com/frappe/erpnext/issues/40132)) ([193cd0d](193cd0db96))
* skip max discount validation for rate adjustment ([8c7d0d4](8c7d0d4b85))
* skip SO & DN validation for debit note ([882cf98](882cf98288))
* test for plaid bank account validation ([22db6f6](22db6f6b72))
* timesheet per billed state edge case (backport [#40010](https://github.com/frappe/erpnext/issues/40010)) ([#40028](https://github.com/frappe/erpnext/issues/40028)) ([2a2f314](2a2f314821))
* translatable columns in Sales Pipeline Analytics report ([3c170b9](3c170b9805))
* unique gl account for plaid bank accounts ([8638d14](8638d14bab))
* use correct variable name for hotfix branches ([812eebf](812eebf1ab))
* Webpages not working without login ([d6fad08](d6fad08d20))

### Features

* show contributed qty in transaction summary ([89d1942](89d19422d1))
* update billed amount in PO and PR ([019d8f9](019d8f92fe))
2024-02-28 05:13:29 +00:00
Deepesh Garg
e80bfd28ea Merge pull request #40147 from frappe/version-14-hotfix
chore: release v14
2024-02-28 10:42:13 +05:30
Deepesh Garg
19a7b6d122 Merge pull request #40169 from frappe/mergify/bp/version-14-hotfix/pr-40137
fix: default taxable value for item not found in item list (backport #40137)
2024-02-28 08:23:57 +05:30
ljain112
30315aba37 fix: default taxable value for item not found in item list
(cherry picked from commit 5885978fc2)
2024-02-27 16:39:03 +00:00
Deepesh Garg
1cc3351e6f Merge pull request #40164 from vorasmit/ic-deps-v14
fix: add flags for repost to ensure correct accounting from India Compliance App (#40162)
2024-02-27 22:08:29 +05:30
Smit Vora
8c772cfb9f fix: add flags for repost to ensure correct accounting from India Compliance App 2024-02-27 20:33:02 +05:30
Gursheen Kaur Anand
0b1689a3aa Merge pull request #40151 from frappe/mergify/bp/version-14-hotfix/pr-40095
fix: unique GL account for plaid bank accounts (backport #40095)
2024-02-27 17:47:32 +05:30
Gursheen Anand
88af431eea chore: semantic commits bump node version to 20 2024-02-27 17:20:01 +05:30
mergify[bot]
9a85ab45e7 fix: parent warehouse checks in the production plan for sub-assemblies (backport #40150) (#40156)
fix: parent warehouse checks in the production plan for sub-assemblies

(cherry picked from commit 6f5815e44f)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-02-27 17:18:24 +05:30
rohitwaghchaure
9ac09d1b8b Merge branch 'version-14' into version-14-hotfix 2024-02-27 17:16:56 +05:30
Gursheen Anand
22db6f6b72 fix: test for plaid bank account validation 2024-02-27 16:51:48 +05:30
Gursheen Kaur Anand
42382d2a0f Merge pull request #40153 from frappe/mergify/bp/version-14-hotfix/pr-40102
feat: toggle updation of billed amount in previous purchase docs (backport #40102)
2024-02-27 16:40:28 +05:30
Gursheen Kaur Anand
614119b3e1 chore: resolve conflicts 2024-02-27 16:04:34 +05:30
Gursheen Kaur Anand
8f983e6109 chore: resolve conflicts 2024-02-27 16:01:33 +05:30
Gursheen Kaur Anand
42b7be60ef chore: resolve conflicts 2024-02-27 15:57:43 +05:30
Gursheen Anand
a84fc0fe40 test: pr billed amount against debit note
(cherry picked from commit 6d40844894)
2024-02-27 10:23:59 +00:00
Gursheen Anand
4f87e73f55 test: po billed amount against debit note
(cherry picked from commit 81dbfe189e)

# Conflicts:
#	erpnext/buying/doctype/purchase_order/test_purchase_order.py
2024-02-27 10:23:58 +00:00
Gursheen Anand
019d8f92fe feat: update billed amount in PO and PR
(cherry picked from commit 9f6535472d)

# Conflicts:
#	erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
#	erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
2024-02-27 10:23:57 +00:00
Gursheen Anand
ad6067795f fix: remove config for default bank account in test
(cherry picked from commit c42444ab3b)
2024-02-27 10:10:18 +00:00
Gursheen Anand
8638d14bab fix: unique gl account for plaid bank accounts
(cherry picked from commit bf6e32a960)
2024-02-27 10:10:18 +00:00
Gursheen Kaur Anand
317738dc36 Merge pull request #40063 from frappe/mergify/bp/version-14-hotfix/pr-40035
fix: delete PLE containing invoice in against (backport #40035)
2024-02-27 12:41:42 +05:30
Gursheen Anand
65a2adfc55 fix: linting issue 2024-02-27 12:16:08 +05:30
Gursheen Kaur Anand
674f577647 Merge pull request #40065 from frappe/mergify/bp/version-14-hotfix/pr-40040
fix: skip max discount validation for rate adjustment (backport #40040)
2024-02-27 10:51:02 +05:30
Gursheen Anand
e289aef1b4 fix: linting issue 2024-02-27 09:59:08 +05:30
Nihantra C. Patel
193cd0db96 fix: sales funnel text color in light/dark theme (#40132)
* fix: sales funnel text color in light/dark theme

* fix: sales funnel text color in light/dark theme
2024-02-26 23:01:41 +05:30
ruthra kumar
ac3c23922a Merge pull request #40134 from frappe/mergify/bp/version-14-hotfix/pr-40133
fix: reset advance amount on unreconciliation of Sales/Purchase Orders (backport #40133)
2024-02-26 21:32:23 +05:30
ruthra kumar
812eebf1ab fix: use correct variable name for hotfix branches 2024-02-26 20:32:48 +05:30
mergify[bot]
8a573a1aff fix: capacity planning issue in the job card (backport #40092) (#40100)
* fix: capacity planning issue in the job card (#40092)

* fix: capacity planning issue in the job card

* test: test case to test capacity planning for workstation

(cherry picked from commit 75f8464724)

# Conflicts:
#	erpnext/manufacturing/doctype/job_card/job_card.py
#	erpnext/manufacturing/doctype/work_order/test_work_order.py

* chore: fix conflicts

* chore: fix conflicts

* chore: fix test cases

---------

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-02-26 18:52:05 +05:30
ruthra kumar
58c869c562 test: advance paid update on sales/purchase order unreconciliation
(cherry picked from commit 1f01ff3487)
2024-02-26 12:22:33 +00:00
ruthra kumar
fe88a110b1 fix: on unreconciliation, update advance paid
(cherry picked from commit c9e2f03a3a)
2024-02-26 12:22:33 +00:00
Nabin Hait
c7ed854850 fix: Reload document on cancel to avoid document modified error 2024-02-26 14:49:32 +05:30
ruthra kumar
5772cb1953 Merge pull request #40117 from frappe/mergify/bp/version-14-hotfix/pr-40113
refactor: patch to setup dimensions in Reconciliation tool (backport #40113)
2024-02-26 14:21:49 +05:30
ruthra kumar
6828a2d46d refactor: patch to setup dimensions in Reconciliation tool
(cherry picked from commit 461fb183fc)
2024-02-26 13:10:44 +05:30
Nabin Hait
23e256aedf fix: Patch to remove cancelled asset capitalization from asset 2024-02-26 12:53:06 +05:30
Gursheen Kaur Anand
8e1ec5ff31 Merge pull request #40108 from frappe/mergify/bp/version-14-hotfix/pr-40105
fix(minor): tax amount label according to party type (backport #40105)
2024-02-26 11:09:53 +05:30
Gursheen Kaur Anand
48dd8acfa1 Merge pull request #40110 from frappe/mergify/bp/version-14-hotfix/pr-40062
fix: sales person / partner achieved targets in report (backport #40062)
2024-02-26 11:08:43 +05:30
Gursheen Anand
57f4eb121c test: sales person target variance
(cherry picked from commit 7566c1ee78)
2024-02-26 05:09:41 +00:00
Gursheen Anand
89d19422d1 feat: show contributed qty in transaction summary
(cherry picked from commit a823f16dff)
2024-02-26 05:09:40 +00:00
Gursheen Anand
0484857402 fix: only consider contributed qty towards achieved targets
(cherry picked from commit 339698d172)
2024-02-26 05:09:40 +00:00
Gursheen Anand
bb3a7cdb3d fix: amount label according to party type
(cherry picked from commit 9c8d103d8a)
2024-02-26 05:05:27 +00:00
ruthra kumar
b3735d29bf Merge pull request #40090 from frappe/mergify/bp/version-14-hotfix/pr-40073
refactor: update payments section on item removal (backport #40073)
2024-02-25 09:29:51 +05:30
ruthra kumar
4bc6c55198 refactor: update payments section on item removal
(cherry picked from commit 406793a6ff)
2024-02-25 03:57:39 +00:00
barredterra
fe986989a9 chore: remove duplicate german translations 2024-02-24 18:29:46 +01:00
barredterra
2899d2bac1 chore: resolve conflicts 2024-02-24 18:28:51 +01:00
Samuel Danieli
2450a73c6f chore: german translations (#31463)
(cherry picked from commit 915102a400)

# Conflicts:
#	erpnext/translations/de.csv
2024-02-24 16:57:52 +00:00
mergify[bot]
e461185317 fix: do not make MR against raw materials of available sub assemblies (backport #40085) (#40086)
fix: do not make MR against raw materials of available sub assemblies (#40085)

(cherry picked from commit 4c9048fb39)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-02-24 21:02:45 +05:30
mergify[bot]
579b27d010 fix: Cannot read properties of undefined (backport #40081) (#40082)
* fix: Cannot read properties of undefined

(cherry picked from commit 44ed52c5cf)

* chore: fix linter issue

---------

Co-authored-by: Rohit Waghchaure <rohitw1991@gmail.com>
2024-02-24 17:22:37 +05:30
ruthra kumar
2b01b102b4 Merge pull request #40067 from frappe/mergify/bp/version-14-hotfix/pr-39830
fix: check_credit_limit on_update_after_submit of Sales Order (backport #39830)
2024-02-23 14:50:25 +05:30
ruthra kumar
db7c360fa1 test: credit limit on update after submit
(cherry picked from commit 467c0898e9)
2024-02-23 08:51:38 +00:00
Nihantra C. Patel
3112fca087 fix: check_credit_limit on_update_after_submit of Sales Order
(cherry picked from commit 17452b7693)
2024-02-23 08:51:38 +00:00
Gursheen Anand
882cf98288 fix: skip SO & DN validation for debit note
(cherry picked from commit e2d16955dd)
2024-02-23 07:28:17 +00:00
Gursheen Anand
8c7d0d4b85 fix: skip max discount validation for rate adjustment
(cherry picked from commit 5a3b133d65)
2024-02-23 07:28:17 +00:00
Ankush Menat
96703fb34d build: specify frappe dependency (#40060) 2024-02-23 12:42:10 +05:30
Gursheen Anand
3d243a7fa5 fix: only check for delinked PLEs
(cherry picked from commit 146c5b3e16)
2024-02-23 07:10:03 +00:00
Gursheen Anand
08459cef4a fix: delete PLE containing invoice in against
(cherry picked from commit c1e1fd8829)
2024-02-23 07:10:02 +00:00
ruthra kumar
05a9f766bc Merge pull request #40057 from frappe/mergify/bp/version-14-hotfix/pr-40011
fix: Ledger entries for Cr/Dr notes with POS Payments (backport #40011)
2024-02-23 06:20:46 +05:30
ruthra kumar
6eb7a18591 Merge pull request #40055 from frappe/mergify/bp/version-14-hotfix/pr-39831
fix: remove cancelled payment entry from Payment Period Based On Invoice Date (backport #39831)
2024-02-23 06:20:06 +05:30
ruthra kumar
9e9486d5ab refactor: skip popup for POS invoices
(cherry picked from commit 3634c4c284)
2024-02-23 00:33:09 +00:00
ruthra kumar
a9791c85c7 test: ledger entries of Cr Note of POS Invoice
(cherry picked from commit 4288713abe)
2024-02-23 00:33:09 +00:00
ruthra kumar
e5098c521b fix: Cr/Dr notes with POS Payments
(cherry picked from commit 68a23730f3)
2024-02-23 00:33:08 +00:00
Nihantra C. Patel
a1c0c2359f fix: remove cancelled payment entry from PPBOID report
(cherry picked from commit 186cc3d748)
2024-02-23 00:30:49 +00:00
Nihantra C. Patel
2fc490a5d7 fix: remove cancelled payment entry from Payment Period Based On Invoice Date
(cherry picked from commit a2a8a8f2e0)
2024-02-23 00:30:48 +00:00
ruthra kumar
9630dc7b88 Merge pull request #40048 from frappe/mergify/bp/version-14-hotfix/pr-39828
fix: translate Sales Pipeline Analytics report (backport #39828)
2024-02-22 20:47:16 +05:30
Nihantra C. Patel
3c170b9805 fix: translatable columns in Sales Pipeline Analytics report
(cherry picked from commit c5050c935b)
2024-02-22 14:54:51 +00:00
Frappe PR Bot
95197c0532 chore(release): Bumped to Version 14.63.3
## [14.63.3](https://github.com/frappe/erpnext/compare/v14.63.2...v14.63.3) (2024-02-22)

### Bug Fixes

* communication_date in party dashboards (backport [#40005](https://github.com/frappe/erpnext/issues/40005)) (backport [#40020](https://github.com/frappe/erpnext/issues/40020)) ([#40044](https://github.com/frappe/erpnext/issues/40044)) ([23e32b9](23e32b9b33))
2024-02-22 13:01:09 +00:00
mergify[bot]
23e32b9b33 fix: communication_date in party dashboards (backport #40005) (backport #40020) (#40044)
fix: communication_date in party dashboards (backport #40005) (#40020)

fix: accommodate for changed orderby statement

(cherry picked from commit 87df7ff717)

Co-authored-by: Gursheen Anand <gursheen@frappe.io>
(cherry picked from commit b364fe7047)

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2024-02-22 18:29:56 +05:30
Frappe PR Bot
0653f6854b chore(release): Bumped to Version 14.63.2
## [14.63.2](https://github.com/frappe/erpnext/compare/v14.63.1...v14.63.2) (2024-02-22)

### Bug Fixes

* Webpages not working without login ([a40e410](a40e410519))
2024-02-22 11:58:43 +00:00
rohitwaghchaure
ee125d5dd8 Merge pull request #40045 from frappe/mergify/bp/version-14/pr-40041
fix: Webpages not working without login (backport #40041)
2024-02-22 17:27:27 +05:30
Rohit Waghchaure
a40e410519 fix: Webpages not working without login
(cherry picked from commit d6fad08d20)
2024-02-22 11:22:20 +00:00
rohitwaghchaure
9d723df9b2 Merge pull request #40041 from rohitwaghchaure/fixed-not-able-to-view-pages
fix: Webpages not working without login
2024-02-22 16:51:25 +05:30
Rohit Waghchaure
d6fad08d20 fix: Webpages not working without login 2024-02-22 16:24:30 +05:30
mergify[bot]
b364fe7047 fix: communication_date in party dashboards (backport #40005) (#40020)
fix: accommodate for changed orderby statement

(cherry picked from commit 87df7ff717)

Co-authored-by: Gursheen Anand <gursheen@frappe.io>
2024-02-22 16:20:15 +05:30
SherinKR
8b3c809cb6 fix: account validation error on bank account after editing existing bank account 2024-02-22 15:56:58 +05:30
Frappe PR Bot
315d4dec90 chore(release): Bumped to Version 14.63.1
## [14.63.1](https://github.com/frappe/erpnext/compare/v14.63.0...v14.63.1) (2024-02-22)

### Bug Fixes

* negative stock error while making stock reconciliation (backport [#40016](https://github.com/frappe/erpnext/issues/40016)) ([#40025](https://github.com/frappe/erpnext/issues/40025)) ([7355fce](7355fce75e))
2024-02-22 08:18:35 +00:00
rohitwaghchaure
c826b5ce6c Merge pull request #40034 from frappe/mergify/bp/version-14/pr-40025
fix: negative stock error while making stock reconciliation (backport #40016) (backport #40025)
2024-02-22 13:46:44 +05:30
mergify[bot]
7355fce75e fix: negative stock error while making stock reconciliation (backport #40016) (#40025)
* fix: negative stock error while making stock reconciliation (#40016)

fix: negative stock error while making stock reco
(cherry picked from commit da184d709b)

# Conflicts:
#	erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py

* chore: fix conflicts

* chore: fix linter issue

---------

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
(cherry picked from commit 865cba406f)
2024-02-22 07:49:51 +00:00
mergify[bot]
2a2f314821 fix: timesheet per billed state edge case (backport #40010) (#40028)
fix: timesheet per billed state edge case (#40010)

If value is 100.0000x then it won't set status correctly but will set it the next time it's loaded from db.

(cherry picked from commit 38e88db2c9)

Co-authored-by: Ankush Menat <ankush@frappe.io>
2024-02-22 12:29:56 +05:30
mergify[bot]
865cba406f fix: negative stock error while making stock reconciliation (backport #40016) (#40025)
* fix: negative stock error while making stock reconciliation (#40016)

fix: negative stock error while making stock reco
(cherry picked from commit da184d709b)

# Conflicts:
#	erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py

* chore: fix conflicts

* chore: fix linter issue

---------

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-02-22 11:39:48 +05:30
mergify[bot]
079ba7670c fix: incorrect item name in MR (backport #40018) (#40023)
fix: incorrect item name in MR (#40018)

(cherry picked from commit 864d7ae04c)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-02-22 09:50:33 +05:30
Govind S Menokee
02cd8c4b98 fix: UAE tax computation fix 2024-02-21 19:46:44 +05:30
rohitwaghchaure
97b665b043 Merge pull request #40000 from frappe/mergify/bp/version-14-hotfix/pr-39998
fix: Completed Work Orders report not working (backport #39998)
2024-02-21 17:44:32 +05:30
Rohit Waghchaure
c8e1409b80 fix: Completed Work Orders report not working
(cherry picked from commit 11f4cb914a)
2024-02-21 11:20:43 +00:00
Nabin Hait
13a663c6cb Merge pull request #39971 from nabinhait/asset-movement-deletion-issue
fix: Delete linked asset movement record on cancellation of purchase receipt/invoice
2024-02-21 11:14:31 +05:30
Frappe PR Bot
8ab75560d5 chore(release): Bumped to Version 14.63.0
# [14.63.0](https://github.com/frappe/erpnext/compare/v14.62.4...v14.63.0) (2024-02-21)

### Bug Fixes

* 'NoneType' object is not iterable (backport [#39977](https://github.com/frappe/erpnext/issues/39977)) ([#39980](https://github.com/frappe/erpnext/issues/39980)) ([8e71665](8e71665e4f))
* Adjust amount in last row due to rounding ([963ddac](963ddac528))
* **Bank Transaction:** precision for `(un)allocated_amount` ([cea0e1f](cea0e1fb91)), closes [#39926](https://github.com/frappe/erpnext/issues/39926)
* fetch company terms ([83bf286](83bf28616e))
* group node in warehouse filter in Item-wise Sales Register ([4921b03](4921b038bd))
* **Issue:** create communication ([8deaba8](8deaba8def))
* linter issue ([a4fbea3](a4fbea3722))
* linter issue ([abceb1b](abceb1b611))
* linter issues ([e99485b](e99485bfa7))
* no need call for company method in sales invoice js ([45a0494](45a0494318))
* On cancelation of capitalization, reverse depreciation entry only if journal entry exists ([5b9905f](5b9905f27a))
* party item code in Blanket Order ([ee9a51f](ee9a51f93f))
* reconciliation issue due to notation difference ([dcf19c3](dcf19c3ed9))
* show active bom in the dropdown while making stock entry and MR (backport [#39974](https://github.com/frappe/erpnext/issues/39974)) ([#39975](https://github.com/frappe/erpnext/issues/39975)) ([385b08d](385b08dc50))
* typeerror 'Item Group' filter on Purchase Register ([b1a4249](b1a4249041))
* update_dimension is required and not need party account method ([5eaa11b](5eaa11b9e8))
* webpages are not showing ([#39988](https://github.com/frappe/erpnext/issues/39988)) ([64099b0](64099b0bf7))

### Features

* New financial views - Growth and margin views for P&L and balance sheet ([d913ec5](d913ec52db))
2024-02-21 05:30:04 +00:00
rohitwaghchaure
7561de1f4e Merge pull request #39978 from frappe/version-14-hotfix
chore: release v14
2024-02-21 10:58:47 +05:30
rohitwaghchaure
64099b0bf7 fix: webpages are not showing (#39988) 2024-02-21 09:26:58 +05:30
Nabin Hait
ea1a0b3a28 fix: linter issue 2024-02-21 08:43:10 +05:30
Nabin Hait
46cd929d00 fix: Delete orphaned asset movement item records 2024-02-20 18:36:23 +05:30
Nabin Hait
46762ead05 Merge pull request #39982 from nabinhait/asset-capitalization-cancel
fix: On cancelation of capitalization, reverse depreciation entry only if journal entry exists
2024-02-20 18:30:14 +05:30
Nabin Hait
5b9905f27a fix: On cancelation of capitalization, reverse depreciation entry only if journal entry exists 2024-02-20 17:54:58 +05:30
mergify[bot]
8e71665e4f fix: 'NoneType' object is not iterable (backport #39977) (#39980)
fix: 'NoneType' object is not iterable (#39977)

(cherry picked from commit 8e7d47b3a7)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-02-20 15:53:20 +05:30
mergify[bot]
385b08dc50 fix: show active bom in the dropdown while making stock entry and MR (backport #39974) (#39975)
fix: show active bom in the dropdown while making stock entry and MR (#39974)

(cherry picked from commit 133f8bd92a)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-02-20 13:13:35 +05:30
Nabin Hait
c53ced1224 Merge pull request #39874 from nabinhait/depreciation-last-row-adjustment
fix: Adjust amount in last row due to rounding
2024-02-20 13:13:02 +05:30
Nabin Hait
a4fbea3722 fix: linter issue 2024-02-20 12:31:34 +05:30
Nabin Hait
e99485bfa7 fix: linter issues 2024-02-20 12:24:36 +05:30
Nabin Hait
963ddac528 fix: Adjust amount in last row due to rounding 2024-02-20 12:24:36 +05:30
Nabin Hait
11bddc14bb fix: Delete linked asset movement record on cancellation of purchase receipt/invoice 2024-02-20 12:23:16 +05:30
Nabin Hait
947f138ea4 Merge pull request #39973 from nabinhait/linter-issue-1
Linter issue
2024-02-20 12:22:47 +05:30
Nabin Hait
abceb1b611 fix: linter issue 2024-02-20 12:21:12 +05:30
Nitali Mittal
d913ec52db feat: New financial views - Growth and margin views for P&L and balance sheet
feat: New financial views - Growth and margin views for P&L and balance sheet
2024-02-19 16:36:23 +05:30
ruthra kumar
e337a55a0b Merge pull request #39954 from frappe/mergify/bp/version-14-hotfix/pr-39914
refactor: add total row if only one party is being filtered (backport #39914)
2024-02-19 09:16:27 +05:30
ruthra kumar
310f338d9b Merge pull request #39952 from frappe/mergify/bp/version-14-hotfix/pr-39942
fix: group node in warehouse filter in Item-wise Sales Register (backport #39942)
2024-02-19 09:15:49 +05:30
ruthra kumar
b0c2d41ecb Merge pull request #39832 from ruthra-kumar/convert_latest_check_sql_to_qb
fix: reconciliation issue due to notation difference
2024-02-19 08:37:59 +05:30
ruthra kumar
241507a87f refactor: add total row if only one party is being filtered
(cherry picked from commit b1dfa2537b)
2024-02-19 02:56:40 +00:00
ruthra kumar
4921b038bd fix: group node in warehouse filter in Item-wise Sales Register
(cherry picked from commit 44538bd02a)
2024-02-19 02:56:18 +00:00
ruthra kumar
229e4f65b4 Merge pull request #39951 from ruthra-kumar/typerror_on_item_group_filter_in_purchase_register
fix: typerror on 'Item Group' filter on Item-Wise Purchase Register
2024-02-19 08:22:07 +05:30
ruthra kumar
a4f94ed631 Merge pull request #39949 from frappe/mergify/bp/version-14-hotfix/pr-39943
refactor: use popup to inform on additional reconciliation step for Cr/Dr Notes (backport #39943)
2024-02-19 08:21:39 +05:30
ruthra kumar
b1a4249041 fix: typeerror 'Item Group' filter on Purchase Register 2024-02-19 07:44:02 +05:30
ruthra kumar
5894bb3bbe refactor: use popup to inform on additional reconciliation step
(cherry picked from commit 0d260faa00)
2024-02-19 07:32:19 +05:30
Raffael Meyer
a83ce43845 Merge pull request #39906 from frappe/mergify/bp/version-14-hotfix/pr-39857
fix: fetch company terms (backport #39857)
2024-02-17 01:26:33 +01:00
Raffael Meyer
744de8595d Merge pull request #39927 from barredterra/bt-precision-v14 2024-02-17 00:32:15 +01:00
Raffael Meyer
e827507698 Merge pull request #39939 from frappe/mergify/bp/version-14-hotfix/pr-39938
fix(Issue): create communication (backport #39938)
2024-02-16 20:47:25 +01:00
barredterra
8deaba8def fix(Issue): create communication
Ignore permisions and mandatory. Required, for example, when Issue is created by Customer via portal.

(cherry picked from commit 3f1d008741)
2024-02-16 19:15:29 +00:00
barredterra
cea0e1fb91 fix(Bank Transaction): precision for (un)allocated_amount
Manual Backport of #39926
2024-02-15 19:58:16 +01:00
rohitwaghchaure
51dc3f57e1 Merge pull request #39917 from frappe/mergify/bp/version-14-hotfix/pr-39905
fix: party item code in Blanket Order (backport #39905)
2024-02-15 17:56:34 +05:30
rohitwaghchaure
ca8fb17ee8 chore: fix conflicts 2024-02-15 17:32:34 +05:30
rohitwaghchaure
1cca51afc6 chore: fix linter issue
(cherry picked from commit 230a7d8d53)
2024-02-15 09:33:41 +00:00
Rohit Waghchaure
ee9a51f93f fix: party item code in Blanket Order
(cherry picked from commit 1a8f7f9403)

# Conflicts:
#	erpnext/manufacturing/doctype/blanket_order_item/blanket_order_item.py
2024-02-15 09:33:40 +00:00
kunhi
5eaa11b9e8 fix: update_dimension is required and not need party account method
(cherry picked from commit e6949d71f6)
2024-02-14 14:54:44 +00:00
kunhi
45a0494318 fix: no need call for company method in sales invoice js
(cherry picked from commit e3bd8d10b0)
2024-02-14 14:54:44 +00:00
kunhi
83bf28616e fix: fetch company terms
(cherry picked from commit d97b6d38ef)
2024-02-14 14:54:43 +00:00
Frappe PR Bot
22ace5cb5a chore(release): Bumped to Version 14.62.4
## [14.62.4](https://github.com/frappe/erpnext/compare/v14.62.3...v14.62.4) (2024-02-14)

### Bug Fixes

*  production plan issue with sales order (backport [#39901](https://github.com/frappe/erpnext/issues/39901)) ([#39903](https://github.com/frappe/erpnext/issues/39903)) ([ab7e323](ab7e323648))
* accommodate for default rounding method in v14 ([d6a758d](d6a758d1f4))
* broken route option in Profitability report ([f79e0d1](f79e0d1e37))
* calculate `stock_value_diff` ([8f58b61](8f58b613e4))
* cancel asset capitalization ([2438600](24386006d6))
* do not throw validation for canceled SLE (backport [#39769](https://github.com/frappe/erpnext/issues/39769)) ([#39810](https://github.com/frappe/erpnext/issues/39810)) ([2885b8f](2885b8fa44))
* Handling circular linking while cancelling asset capitalization ([f2d094d](f2d094d1ab))
* incorrect planned qty in PP (backport [#39785](https://github.com/frappe/erpnext/issues/39785)) ([#39792](https://github.com/frappe/erpnext/issues/39792)) ([df9d52d](df9d52d3ce))
* landed cost voucher not submitting because of incorrect reference (backport [#39898](https://github.com/frappe/erpnext/issues/39898)) ([#39899](https://github.com/frappe/erpnext/issues/39899)) ([d0b9c56](d0b9c568d3))
* remove duplicates from tax category map ([c56f3a5](c56f3a58ab))
* set rate for PO created against BO (backport [#39765](https://github.com/frappe/erpnext/issues/39765)) ([#39766](https://github.com/frappe/erpnext/issues/39766)) ([de47e67](de47e67dfa))
* set route options to cost center ([#37235](https://github.com/frappe/erpnext/issues/37235)) ([79a16ba](79a16bad15))
* **ux:** set rate as price list rate on uom change in MR (backport [#39816](https://github.com/frappe/erpnext/issues/39816)) ([#39817](https://github.com/frappe/erpnext/issues/39817)) ([de6e8c7](de6e8c74c5))

### Performance Improvements

* cached get_last_purchase_details to fix performance issue (backport [#39854](https://github.com/frappe/erpnext/issues/39854)) ([#39855](https://github.com/frappe/erpnext/issues/39855)) ([08e0271](08e02710cd))
* production plan submission (backport [#39846](https://github.com/frappe/erpnext/issues/39846)) ([#39859](https://github.com/frappe/erpnext/issues/39859)) ([a61cffd](a61cffd7c2))
2024-02-14 12:06:19 +00:00
rohitwaghchaure
4fd7b01beb Merge pull request #39881 from frappe/version-14-hotfix
chore: release v14
2024-02-14 17:34:41 +05:30
mergify[bot]
ab7e323648 fix: production plan issue with sales order (backport #39901) (#39903)
fix:  production plan issue with sales order (#39901)

(cherry picked from commit d0df5df4a6)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-02-14 17:28:50 +05:30
mergify[bot]
d0b9c568d3 fix: landed cost voucher not submitting because of incorrect reference (backport #39898) (#39899)
fix: landed cost voucher not submitting because of incorrect reference (#39898)

(cherry picked from commit 6239fd704b)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-02-14 15:57:48 +05:30
Raffael Meyer
6b53288975 Merge pull request #39893 from frappe/mergify/bp/version-14-hotfix/pr-39868
fix(Purchase Receipt): calculate `stock_value_diff` (backport #39868)
2024-02-14 01:22:09 +01:00
barredterra
8f58b613e4 fix: calculate stock_value_diff
`d.item_tax_amount` is already in base currency.

(cherry picked from commit 5df5851798)
2024-02-13 23:52:34 +00:00
Nabin Hait
6460e649a5 Merge pull request #39814 from nabinhait/asset-capitalization-cancellation
fix: Handling circular linking while cancelling asset capitalization
2024-02-13 09:46:31 +05:30
mergify[bot]
a61cffd7c2 perf: production plan submission (backport #39846) (#39859)
perf: production plan submission

(cherry picked from commit aa1c69dd7a)

Co-authored-by: s-aga-r <sagarsharma.s312@gmail.com>
2024-02-12 18:17:49 +05:30
mergify[bot]
08e02710cd perf: cached get_last_purchase_details to fix performance issue (backport #39854) (#39855)
perf: cached get_last_purchase_details to fix performance issue (#39854)

(cherry picked from commit b966c06a4f)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-02-12 15:54:03 +05:30
Nabin Hait
24386006d6 fix: cancel asset capitalization 2024-02-12 11:44:41 +05:30
mergify[bot]
de6e8c74c5 fix(ux): set rate as price list rate on uom change in MR (backport #39816) (#39817)
* fix: add price list rate field in MR Item

(cherry picked from commit 61a29eb5fb)

# Conflicts:
#	erpnext/stock/doctype/material_request_item/material_request_item.py

* fix: set rate as price list rate on uom change

(cherry picked from commit 5cf0759b0c)

* chore: linter

(cherry picked from commit 1745371cd6)

* chore: `conflicts`

---------

Co-authored-by: s-aga-r <sagarsharma.s312@gmail.com>
2024-02-11 17:38:37 +05:30
mergify[bot]
79a16bad15 fix: set route options to cost center (#37235)
fix: set route to cost center

cost center mapping is not correct

(cherry picked from commit 5e4b73918d)

Co-authored-by: NIYAZ RAZAK <76736615+niyazrazak@users.noreply.github.com>
2024-02-11 17:19:59 +05:30
ruthra kumar
dcf19c3ed9 fix: reconciliation issue due to notation difference 2024-02-09 16:50:14 +05:30
ruthra kumar
157d17d0f3 Merge pull request #39808 from ruthra-kumar/dimension_filter_issue_in_profitability_report
fix: incorrect route options on Profitability to Profit and Loss report
2024-02-08 15:53:26 +05:30
Nabin Hait
f2d094d1ab fix: Handling circular linking while cancelling asset capitalization 2024-02-08 15:51:29 +05:30
Frappe PR Bot
8caf655529 chore(release): Bumped to Version 14.62.3
## [14.62.3](https://github.com/frappe/erpnext/compare/v14.62.2...v14.62.3) (2024-02-08)

### Bug Fixes

* do not throw validation for canceled SLE (backport [#39769](https://github.com/frappe/erpnext/issues/39769)) ([#39810](https://github.com/frappe/erpnext/issues/39810)) ([d6054db](d6054dbdbd))
2024-02-08 09:12:55 +00:00
rohitwaghchaure
408d026465 Merge pull request #39812 from frappe/mergify/bp/version-14/pr-39810
fix: do not throw validation for canceled SLE (backport #39769) (backport #39810)
2024-02-08 14:41:43 +05:30
mergify[bot]
d6054dbdbd fix: do not throw validation for canceled SLE (backport #39769) (#39810)
fix: do not throw validation for cancelled sle

(cherry picked from commit 32ccf3524a)

Co-authored-by: Rohit Waghchaure <rohitw1991@gmail.com>
(cherry picked from commit 2885b8fa44)
2024-02-08 08:50:17 +00:00
mergify[bot]
2885b8fa44 fix: do not throw validation for canceled SLE (backport #39769) (#39810)
fix: do not throw validation for cancelled sle

(cherry picked from commit 32ccf3524a)

Co-authored-by: Rohit Waghchaure <rohitw1991@gmail.com>
2024-02-08 14:18:50 +05:30
ruthra kumar
f79e0d1e37 fix: broken route option in Profitability report 2024-02-08 13:22:55 +05:30
rohitwaghchaure
a9c95567cb Merge pull request #39790 from aynugek/patch-2
refactor: Clean up code used to fetch website item stock details
2024-02-08 11:06:20 +05:30
ruthra kumar
28b0e988db Merge pull request #39798 from frappe/mergify/bp/version-14-hotfix/pr-39783
fix: cancelling cr/dr notes should update the linked Invoice status (backport #39783)
2024-02-08 10:00:54 +05:30
ruthra kumar
8d9b5764dd refactor(test): Forex Credit Note cancellation against Invoice
(cherry picked from commit 2f676ced5c)
2024-02-07 15:00:47 +00:00
ruthra kumar
dd74728568 refactor(test): assert Invoice status as well
(cherry picked from commit 33efe0d12d)
2024-02-07 15:00:47 +00:00
ruthra kumar
e97f30d8e2 test: Invoice status on Cr/Dr note cancellation
(cherry picked from commit 31a8c3bdc4)
2024-02-07 15:00:46 +00:00
ruthra kumar
33777a4d4c refactor: cancel Cr/Dr JE's on Sales/Purchase return cancel
(cherry picked from commit 0549535603)
2024-02-07 15:00:44 +00:00
Gursheen Kaur Anand
d62db9bb22 Merge pull request #39789 from GursheenK/duplicates-in-tax-category-bpv14
fix: remove duplicates from tax category map
2024-02-07 19:51:51 +05:30
mergify[bot]
df9d52d3ce fix: incorrect planned qty in PP (backport #39785) (#39792)
fix: incorrect planned qty in PP

(cherry picked from commit a8ebc94a36)

Co-authored-by: s-aga-r <sagarsharma.s312@gmail.com>
2024-02-07 19:26:14 +05:30
Gursheen Anand
d6a758d1f4 fix: accommodate for default rounding method in v14 2024-02-07 19:12:32 +05:30
mergify[bot]
de47e67dfa fix: set rate for PO created against BO (backport #39765) (#39766)
* fix: set rate for PO created against BO

(cherry picked from commit 0e5b4e5f07)

# Conflicts:
#	erpnext/manufacturing/doctype/blanket_order/blanket_order.py

* chore: `conflicts`

---------

Co-authored-by: s-aga-r <sagarsharma.s312@gmail.com>
2024-02-07 19:03:38 +05:30
Gursheen Anand
c56f3a58ab fix: remove duplicates from tax category map 2024-02-07 18:46:07 +05:30
Babuuu
e3591270c6 refactor: Clean up code used to fetch website item stock details 2024-02-07 13:12:14 +00:00
Gursheen Anand
e9c2f6d6f1 fix: message for subscription when no current inv 2024-02-05 11:05:45 +05:30
1342 changed files with 38542 additions and 26806 deletions

View File

@@ -9,6 +9,13 @@ trim_trailing_whitespace = true
charset = utf-8
# python, js indentation settings
[{*.py,*.js}]
[{*.py,*.js,*.vue,*.css,*.scss,*.html}]
indent_style = tab
indent_size = 4
max_line_length = 110
# JSON files - mostly doctype schema files
[{*.json}]
insert_final_newline = false
indent_style = space
indent_size = 2

View File

@@ -156,6 +156,7 @@
"onScan": true,
"html2canvas": true,
"extend_cscript": true,
"localforage": true
"localforage": true,
"Plaid": true
}
}

View File

@@ -28,4 +28,7 @@ b147b85e6ac19a9220cd1e2958a6ebd99373283a
494bd9ef78313436f0424b918f200dab8fc7c20b
# bulk format python code with black
baec607ff5905b1c67531096a9cf50ec7ff00a5d
baec607ff5905b1c67531096a9cf50ec7ff00a5d
# ruff
4d34b1ead73baf4c5430a2ecbe44b9e8468d7626

View File

@@ -21,7 +21,7 @@ jobs:
- uses: actions/setup-node@v3
with:
node-version: 14
node-version: 20
check-latest: true
- name: Check commit titles

View File

@@ -20,27 +20,60 @@ repos:
- id: check-yaml
- id: debug-statements
- repo: https://github.com/PyCQA/flake8
rev: 5.0.4
- repo: https://github.com/pre-commit/mirrors-prettier
rev: v2.7.1
hooks:
- id: flake8
additional_dependencies: [
'flake8-bugbear',
]
args: ['--config', '.github/helper/.flake8_strict']
exclude: ".*setup.py$"
- id: prettier
types_or: [javascript, vue, scss]
# Ignore any files that might contain jinja / bundles
exclude: |
(?x)^(
erpnext/public/dist/.*|
cypress/.*|
.*node_modules.*|
.*boilerplate.*|
erpnext/public/js/controllers/.*|
erpnext/templates/pages/order.js|
erpnext/templates/includes/.*|
.*/supplier_quotation.js|
.*/sales_taxes_and_charges_template.js|
.*/purchase_taxes_and_charges_template.js|
.*/subcontracting_order.js|
.*/landed_cost_voucher.js|
.*/payment_entry.js|
.*/loan_interest_accrual.js|
.*/loan_disbursement.js|
.*/loan_application.js|
.*/italy.js|
.*/sales_invoice.js|
.*/subcontracting_receipt.js|
.*/request_for_quotation.js|
.*/pos_profile.js|
.*/opportunity.js|
.*/quotation.js|
.*/sales_common.js|
.*/sales_order.js|
.*/pos_invoice.js|
.*/purchase_invoice.js|
.*/loan_repayment.js|
.*/material_request.js|
.*/purchase_receipt.js|
.*/delivery_note.js|
.*/loan.js|
.*/stock_entry.js|
.*/purchase_order.js|
.*/loan_write_off.js
)$
- repo: https://github.com/adityahase/black
rev: 9cb0a69f4d0030cdf687eddf314468b39ed54119
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.2.0
hooks:
- id: black
additional_dependencies: ['click==8.0.4']
- id: ruff
name: "Run ruff linter and apply fixes"
args: ["--fix"]
- repo: https://github.com/PyCQA/isort
rev: 5.12.0
hooks:
- id: isort
exclude: ".*setup.py$"
- id: ruff-format
name: "Format Python code"
ci:

View File

@@ -1,25 +1,13 @@
module.exports = {
parserPreset: 'conventional-changelog-conventionalcommits',
parserPreset: "conventional-changelog-conventionalcommits",
rules: {
'subject-empty': [2, 'never'],
'type-case': [2, 'always', 'lower-case'],
'type-empty': [2, 'never'],
'type-enum': [
"subject-empty": [2, "never"],
"type-case": [2, "always", "lower-case"],
"type-empty": [2, "never"],
"type-enum": [
2,
'always',
[
'build',
'chore',
'ci',
'docs',
'feat',
'fix',
'perf',
'refactor',
'revert',
'style',
'test',
],
"always",
["build", "chore", "ci", "docs", "feat", "fix", "perf", "refactor", "revert", "style", "test"],
],
},
};

View File

@@ -3,7 +3,7 @@ import inspect
import frappe
__version__ = "14.62.2"
__version__ = "14.70.2"
def get_default_company(user=None):
@@ -13,7 +13,7 @@ def get_default_company(user=None):
if not user:
user = frappe.session.user
companies = get_user_default_as_list(user, "company")
companies = get_user_default_as_list("company", user)
if companies:
default_company = companies[0]
else:
@@ -36,10 +36,8 @@ def get_default_cost_center(company):
if not frappe.flags.company_cost_center:
frappe.flags.company_cost_center = {}
if not company in frappe.flags.company_cost_center:
frappe.flags.company_cost_center[company] = frappe.get_cached_value(
"Company", company, "cost_center"
)
if company not in frappe.flags.company_cost_center:
frappe.flags.company_cost_center[company] = frappe.get_cached_value("Company", company, "cost_center")
return frappe.flags.company_cost_center[company]
@@ -47,7 +45,7 @@ def get_company_currency(company):
"""Returns the default company currency"""
if not frappe.flags.company_currency:
frappe.flags.company_currency = {}
if not company in frappe.flags.company_currency:
if company not in frappe.flags.company_currency:
frappe.flags.company_currency[company] = frappe.db.get_value(
"Company", company, "default_currency", cache=True
)
@@ -81,7 +79,7 @@ def is_perpetual_inventory_enabled(company):
if not hasattr(frappe.local, "enable_perpetual_inventory"):
frappe.local.enable_perpetual_inventory = {}
if not company in frappe.local.enable_perpetual_inventory:
if company not in frappe.local.enable_perpetual_inventory:
frappe.local.enable_perpetual_inventory[company] = (
frappe.get_cached_value("Company", company, "enable_perpetual_inventory") or 0
)
@@ -96,7 +94,7 @@ def get_default_finance_book(company=None):
if not hasattr(frappe.local, "default_finance_book"):
frappe.local.default_finance_book = {}
if not company in frappe.local.default_finance_book:
if company not in frappe.local.default_finance_book:
frappe.local.default_finance_book[company] = frappe.get_cached_value(
"Company", company, "default_finance_book"
)
@@ -108,7 +106,7 @@ def get_party_account_type(party_type):
if not hasattr(frappe.local, "party_account_types"):
frappe.local.party_account_types = {}
if not party_type in frappe.local.party_account_types:
if party_type not in frappe.local.party_account_types:
frappe.local.party_account_types[party_type] = (
frappe.db.get_value("Party Type", party_type, "account_type") or ""
)

View File

@@ -11,14 +11,14 @@ class ERPNextAddress(Address):
def validate(self):
self.validate_reference()
self.update_compnay_address()
super(ERPNextAddress, self).validate()
super().validate()
def link_address(self):
"""Link address based on owner"""
if self.is_your_company_address:
return
return super(ERPNextAddress, self).link_address()
return super().link_address()
def update_compnay_address(self):
for link in self.get("links"):
@@ -26,11 +26,11 @@ class ERPNextAddress(Address):
self.is_your_company_address = 1
def validate_reference(self):
if self.is_your_company_address and not [
row for row in self.links if row.link_doctype == "Company"
]:
if self.is_your_company_address and not [row for row in self.links if row.link_doctype == "Company"]:
frappe.throw(
_("Address needs to be linked to a Company. Please add a row for Company in the Links table."),
_(
"Address needs to be linked to a Company. Please add a row for Company in the Links table."
),
title=_("Company Not Linked"),
)

View File

@@ -1,4 +1,4 @@
frappe.provide('frappe.dashboards.chart_sources');
frappe.provide("frappe.dashboards.chart_sources");
frappe.dashboards.chart_sources["Account Balance Timeline"] = {
method: "erpnext.accounts.dashboard_chart_source.account_balance_timeline.account_balance_timeline.get",
@@ -9,14 +9,14 @@ frappe.dashboards.chart_sources["Account Balance Timeline"] = {
fieldtype: "Link",
options: "Company",
default: frappe.defaults.get_user_default("Company"),
reqd: 1
reqd: 1,
},
{
fieldname: "account",
label: __("Account"),
fieldtype: "Link",
options: "Account",
reqd: 1
reqd: 1,
},
]
],
};

View File

@@ -37,7 +37,7 @@ def get(
filters = frappe.parse_json(filters) or frappe.parse_json(chart.filters_json)
account = filters.get("account")
company = filters.get("company")
filters.get("company")
if not account and chart_name:
frappe.throw(
@@ -83,7 +83,6 @@ def build_result(account, dates, gl_entries):
# get balances in debit
for entry in gl_entries:
# entry date is after the current pointer, so move the pointer forward
while getdate(entry.posting_date) > result[date_index][0]:
date_index += 1
@@ -133,8 +132,6 @@ def get_dates_from_timegrain(from_date, to_date, timegrain):
dates = [get_period_ending(from_date, timegrain)]
while getdate(dates[-1]) < getdate(to_date):
date = get_period_ending(
add_to_date(dates[-1], years=years, months=months, days=days), timegrain
)
date = get_period_ending(add_to_date(dates[-1], years=years, months=months, days=days), timegrain)
dates.append(date)
return dates

View File

@@ -24,14 +24,10 @@ from erpnext.accounts.utils import get_account_currency
def validate_service_stop_date(doc):
"""Validates service_stop_date for Purchase Invoice and Sales Invoice"""
enable_check = (
"enable_deferred_revenue" if doc.doctype == "Sales Invoice" else "enable_deferred_expense"
)
enable_check = "enable_deferred_revenue" if doc.doctype == "Sales Invoice" else "enable_deferred_expense"
old_stop_dates = {}
old_doc = frappe.db.get_all(
"{0} Item".format(doc.doctype), {"parent": doc.name}, ["name", "service_stop_date"]
)
old_doc = frappe.db.get_all(f"{doc.doctype} Item", {"parent": doc.name}, ["name", "service_stop_date"])
for d in old_doc:
old_stop_dates[d.name] = d.service_stop_date or ""
@@ -62,16 +58,14 @@ def build_conditions(process_type, account, company):
)
if account:
conditions += "AND %s='%s'" % (deferred_account, account)
conditions += f"AND {deferred_account}='{account}'"
elif company:
conditions += f"AND p.company = {frappe.db.escape(company)}"
return conditions
def convert_deferred_expense_to_expense(
deferred_process, start_date=None, end_date=None, conditions=""
):
def convert_deferred_expense_to_expense(deferred_process, start_date=None, end_date=None, conditions=""):
# book the expense/income on the last day, but it will be trigger on the 1st of month at 12:00 AM
if not start_date:
@@ -81,16 +75,14 @@ def convert_deferred_expense_to_expense(
# check for the purchase invoice for which GL entries has to be done
invoices = frappe.db.sql_list(
"""
f"""
select distinct item.parent
from `tabPurchase Invoice Item` item, `tabPurchase Invoice` p
where item.service_start_date<=%s and item.service_end_date>=%s
and item.enable_deferred_expense = 1 and item.parent=p.name
and item.docstatus = 1 and ifnull(item.amount, 0) > 0
{0}
""".format(
conditions
),
{conditions}
""",
(end_date, start_date),
) # nosec
@@ -103,9 +95,7 @@ def convert_deferred_expense_to_expense(
send_mail(deferred_process)
def convert_deferred_revenue_to_income(
deferred_process, start_date=None, end_date=None, conditions=""
):
def convert_deferred_revenue_to_income(deferred_process, start_date=None, end_date=None, conditions=""):
# book the expense/income on the last day, but it will be trigger on the 1st of month at 12:00 AM
if not start_date:
@@ -115,16 +105,14 @@ def convert_deferred_revenue_to_income(
# check for the sales invoice for which GL entries has to be done
invoices = frappe.db.sql_list(
"""
f"""
select distinct item.parent
from `tabSales Invoice Item` item, `tabSales Invoice` p
where item.service_start_date<=%s and item.service_end_date>=%s
and item.enable_deferred_revenue = 1 and item.parent=p.name
and item.docstatus = 1 and ifnull(item.amount, 0) > 0
{0}
""".format(
conditions
),
{conditions}
""",
(end_date, start_date),
) # nosec
@@ -243,9 +231,7 @@ def calculate_monthly_amount(
already_booked_amount, already_booked_amount_in_account_currency = get_already_booked_amount(
doc, item
)
base_amount = flt(
item.base_net_amount - already_booked_amount, item.precision("base_net_amount")
)
base_amount = flt(item.base_net_amount - already_booked_amount, item.precision("base_net_amount"))
if account_currency == doc.company_currency:
amount = base_amount
else:
@@ -265,17 +251,13 @@ def calculate_amount(doc, item, last_gl_entry, total_days, total_booking_days, a
if account_currency == doc.company_currency:
amount = base_amount
else:
amount = flt(
item.net_amount * total_booking_days / flt(total_days), item.precision("net_amount")
)
amount = flt(item.net_amount * total_booking_days / flt(total_days), item.precision("net_amount"))
else:
already_booked_amount, already_booked_amount_in_account_currency = get_already_booked_amount(
doc, item
)
base_amount = flt(
item.base_net_amount - already_booked_amount, item.precision("base_net_amount")
)
base_amount = flt(item.base_net_amount - already_booked_amount, item.precision("base_net_amount"))
if account_currency == doc.company_currency:
amount = base_amount
else:
@@ -296,26 +278,22 @@ def get_already_booked_amount(doc, item):
gl_entries_details = frappe.db.sql(
"""
select sum({0}) as total_credit, sum({1}) as total_credit_in_account_currency, voucher_detail_no
select sum({}) as total_credit, sum({}) as total_credit_in_account_currency, voucher_detail_no
from `tabGL Entry` where company=%s and account=%s and voucher_type=%s and voucher_no=%s and voucher_detail_no=%s
and is_cancelled = 0
group by voucher_detail_no
""".format(
total_credit_debit, total_credit_debit_currency
),
""".format(total_credit_debit, total_credit_debit_currency),
(doc.company, item.get(deferred_account), doc.doctype, doc.name, item.name),
as_dict=True,
)
journal_entry_details = frappe.db.sql(
"""
SELECT sum(c.{0}) as total_credit, sum(c.{1}) as total_credit_in_account_currency, reference_detail_no
SELECT sum(c.{}) as total_credit, sum(c.{}) as total_credit_in_account_currency, reference_detail_no
FROM `tabJournal Entry` p , `tabJournal Entry Account` c WHERE p.name = c.parent and
p.company = %s and c.account=%s and c.reference_type=%s and c.reference_name=%s and c.reference_detail_no=%s
and p.docstatus < 2 group by reference_detail_no
""".format(
total_credit_debit, total_credit_debit_currency
),
""".format(total_credit_debit, total_credit_debit_currency),
(doc.company, item.get(deferred_account), doc.doctype, doc.name, item.name),
as_dict=True,
)
@@ -337,9 +315,7 @@ def get_already_booked_amount(doc, item):
def book_deferred_income_or_expense(doc, deferred_process, posting_date=None):
enable_check = (
"enable_deferred_revenue" if doc.doctype == "Sales Invoice" else "enable_deferred_expense"
)
enable_check = "enable_deferred_revenue" if doc.doctype == "Sales Invoice" else "enable_deferred_expense"
accounts_frozen_upto = frappe.db.get_single_value("Accounts Settings", "acc_frozen_upto")
@@ -440,9 +416,7 @@ def book_deferred_income_or_expense(doc, deferred_process, posting_date=None):
via_journal_entry = cint(
frappe.db.get_singles_value("Accounts Settings", "book_deferred_entries_via_journal_entry")
)
submit_journal_entry = cint(
frappe.db.get_singles_value("Accounts Settings", "submit_journal_entries")
)
submit_journal_entry = cint(frappe.db.get_singles_value("Accounts Settings", "submit_journal_entries"))
book_deferred_entries_based_on = frappe.db.get_singles_value(
"Accounts Settings", "book_deferred_entries_based_on"
)
@@ -462,9 +436,7 @@ def process_deferred_accounting(posting_date=None):
posting_date = today()
if not cint(
frappe.db.get_singles_value(
"Accounts Settings", "automatically_process_deferred_accounting_entry"
)
frappe.db.get_singles_value("Accounts Settings", "automatically_process_deferred_accounting_entry")
):
return
@@ -587,16 +559,13 @@ def book_revenue_via_journal_entry(
deferred_process=None,
submit="No",
):
if amount == 0:
return
journal_entry = frappe.new_doc("Journal Entry")
journal_entry.posting_date = posting_date
journal_entry.company = doc.company
journal_entry.voucher_type = (
"Deferred Revenue" if doc.doctype == "Sales Invoice" else "Deferred Expense"
)
journal_entry.voucher_type = "Deferred Revenue" if doc.doctype == "Sales Invoice" else "Deferred Expense"
journal_entry.process_deferred_accounting = deferred_process
debit_entry = {
@@ -645,7 +614,6 @@ def book_revenue_via_journal_entry(
def get_deferred_booking_accounts(doctype, voucher_detail_no, dr_or_cr):
if doctype == "Sales Invoice":
credit_account, debit_account = frappe.db.get_value(
"Sales Invoice Item",

View File

@@ -1,33 +1,32 @@
// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
frappe.ui.form.on('Account', {
setup: function(frm) {
frm.add_fetch('parent_account', 'report_type', 'report_type');
frm.add_fetch('parent_account', 'root_type', 'root_type');
frappe.ui.form.on("Account", {
setup: function (frm) {
frm.add_fetch("parent_account", "report_type", "report_type");
frm.add_fetch("parent_account", "root_type", "root_type");
},
onload: function(frm) {
frm.set_query('parent_account', function(doc) {
onload: function (frm) {
frm.set_query("parent_account", function (doc) {
return {
filters: {
"is_group": 1,
"company": doc.company
}
is_group: 1,
company: doc.company,
},
};
});
},
refresh: function(frm) {
frm.toggle_display('account_name', frm.is_new());
refresh: function (frm) {
frm.toggle_display("account_name", frm.is_new());
// hide fields if group
frm.toggle_display(['account_type', 'tax_rate'], cint(frm.doc.is_group) == 0);
frm.toggle_display(["account_type", "tax_rate"], cint(frm.doc.is_group) == 0);
// disable fields
frm.toggle_enable(['is_group', 'company'], false);
frm.toggle_enable(["is_group", "company"], false);
if (cint(frm.doc.is_group) == 0) {
frm.toggle_display('freeze_account', frm.doc.__onload
&& frm.doc.__onload.can_freeze_account);
frm.toggle_display("freeze_account", frm.doc.__onload && frm.doc.__onload.can_freeze_account);
}
// read-only for root accounts
@@ -38,79 +37,101 @@ frappe.ui.form.on('Account', {
} else {
// credit days and type if customer or supplier
frm.set_intro(null);
frm.trigger('account_type');
frm.trigger("account_type");
// show / hide convert buttons
frm.trigger('add_toolbar_buttons');
frm.trigger("add_toolbar_buttons");
}
if (frm.has_perm('write')) {
frm.add_custom_button(__('Merge Account'), function () {
frm.trigger("merge_account");
}, __('Actions'));
frm.add_custom_button(__('Update Account Name / Number'), function () {
frm.trigger("update_account_number");
}, __('Actions'));
if (frm.has_perm("write")) {
frm.add_custom_button(
__("Merge Account"),
function () {
frm.trigger("merge_account");
},
__("Actions")
);
frm.add_custom_button(
__("Update Account Name / Number"),
function () {
frm.trigger("update_account_number");
},
__("Actions")
);
}
}
},
account_type: function (frm) {
if (frm.doc.is_group == 0) {
frm.toggle_display(['tax_rate'], frm.doc.account_type == 'Tax');
frm.toggle_display('warehouse', frm.doc.account_type == 'Stock');
frm.toggle_display(["tax_rate"], frm.doc.account_type == "Tax");
frm.toggle_display("warehouse", frm.doc.account_type == "Stock");
}
},
add_toolbar_buttons: function(frm) {
frm.add_custom_button(__('Chart of Accounts'), () => {
frappe.set_route("Tree", "Account");
}, __('View'));
add_toolbar_buttons: function (frm) {
frm.add_custom_button(
__("Chart of Accounts"),
() => {
frappe.set_route("Tree", "Account");
},
__("View")
);
if (frm.doc.is_group == 1) {
frm.add_custom_button(__('Convert to Non-Group'), function () {
return frappe.call({
doc: frm.doc,
method: 'convert_group_to_ledger',
callback: function() {
frm.refresh();
}
});
}, __('Actions'));
frm.add_custom_button(
__("Convert to Non-Group"),
function () {
return frappe.call({
doc: frm.doc,
method: "convert_group_to_ledger",
callback: function () {
frm.refresh();
},
});
},
__("Actions")
);
} else if (cint(frm.doc.is_group) == 0 && frappe.boot.user.can_read.indexOf("GL Entry") !== -1) {
frm.add_custom_button(
__("General Ledger"),
function () {
frappe.route_options = {
account: frm.doc.name,
from_date: frappe.sys_defaults.year_start_date,
to_date: frappe.sys_defaults.year_end_date,
company: frm.doc.company,
};
frappe.set_route("query-report", "General Ledger");
},
__("View")
);
} else if (cint(frm.doc.is_group) == 0
&& frappe.boot.user.can_read.indexOf("GL Entry") !== -1) {
frm.add_custom_button(__('General Ledger'), function () {
frappe.route_options = {
"account": frm.doc.name,
"from_date": frappe.sys_defaults.year_start_date,
"to_date": frappe.sys_defaults.year_end_date,
"company": frm.doc.company
};
frappe.set_route("query-report", "General Ledger");
}, __('View'));
frm.add_custom_button(__('Convert to Group'), function () {
return frappe.call({
doc: frm.doc,
method: 'convert_ledger_to_group',
callback: function() {
frm.refresh();
}
});
}, __('Actions'));
frm.add_custom_button(
__("Convert to Group"),
function () {
return frappe.call({
doc: frm.doc,
method: "convert_ledger_to_group",
callback: function () {
frm.refresh();
},
});
},
__("Actions")
);
}
},
merge_account: function(frm) {
merge_account: function (frm) {
var d = new frappe.ui.Dialog({
title: __('Merge with Existing Account'),
title: __("Merge with Existing Account"),
fields: [
{
"label" : "Name",
"fieldname": "name",
"fieldtype": "Data",
"reqd": 1,
"default": frm.doc.name
}
label: "Name",
fieldname: "name",
fieldtype: "Data",
reqd: 1,
default: frm.doc.name,
},
],
primary_action: function() {
primary_action: function () {
var data = d.get_values();
frappe.call({
method: "erpnext.accounts.doctype.account.account.merge_account",
@@ -118,42 +139,45 @@ frappe.ui.form.on('Account', {
old: frm.doc.name,
new: data.name,
},
callback: function(r) {
if(!r.exc) {
if(r.message) {
callback: function (r) {
if (!r.exc) {
if (r.message) {
frappe.set_route("Form", "Account", r.message);
}
d.hide();
}
}
},
});
},
primary_action_label: __('Merge')
primary_action_label: __("Merge"),
});
d.show();
},
update_account_number: function(frm) {
update_account_number: function (frm) {
var d = new frappe.ui.Dialog({
title: __('Update Account Number / Name'),
title: __("Update Account Number / Name"),
fields: [
{
"label": "Account Name",
"fieldname": "account_name",
"fieldtype": "Data",
"reqd": 1,
"default": frm.doc.account_name
label: "Account Name",
fieldname: "account_name",
fieldtype: "Data",
reqd: 1,
default: frm.doc.account_name,
},
{
"label": "Account Number",
"fieldname": "account_number",
"fieldtype": "Data",
"default": frm.doc.account_number
}
label: "Account Number",
fieldname: "account_number",
fieldtype: "Data",
default: frm.doc.account_number,
},
],
primary_action: function() {
primary_action: function () {
var data = d.get_values();
if(data.account_number === frm.doc.account_number && data.account_name === frm.doc.account_name) {
if (
data.account_number === frm.doc.account_number &&
data.account_name === frm.doc.account_name
) {
d.hide();
return;
}
@@ -163,11 +187,11 @@ frappe.ui.form.on('Account', {
args: {
account_number: data.account_number,
account_name: data.account_name,
name: frm.doc.name
name: frm.doc.name,
},
callback: function(r) {
if(!r.exc) {
if(r.message) {
callback: function (r) {
if (!r.exc) {
if (r.message) {
frappe.set_route("Form", "Account", r.message);
} else {
frm.set_value("account_number", data.account_number);
@@ -175,11 +199,11 @@ frappe.ui.form.on('Account', {
}
d.hide();
}
}
},
});
},
primary_action_label: __('Update')
primary_action_label: __("Update"),
});
d.show();
}
},
});

View File

@@ -29,7 +29,7 @@ class Account(NestedSet):
if frappe.local.flags.ignore_update_nsm:
return
else:
super(Account, self).on_update()
super().on_update()
def onload(self):
frozen_accounts_modifier = frappe.db.get_value(
@@ -87,9 +87,7 @@ class Account(NestedSet):
def set_root_and_report_type(self):
if self.parent_account:
par = frappe.db.get_value(
"Account", self.parent_account, ["report_type", "root_type"], as_dict=1
)
par = frappe.db.get_value("Account", self.parent_account, ["report_type", "root_type"], as_dict=1)
if par.report_type:
self.report_type = par.report_type
@@ -144,9 +142,7 @@ class Account(NestedSet):
def validate_root_company_and_sync_account_to_children(self):
# ignore validation while creating new compnay or while syncing to child companies
if (
frappe.local.flags.ignore_root_company_validation or self.flags.ignore_root_company_validation
):
if frappe.local.flags.ignore_root_company_validation or self.flags.ignore_root_company_validation:
return
ancestors = get_root_company(self.company)
if ancestors:
@@ -341,7 +337,7 @@ class Account(NestedSet):
if self.check_gle_exists():
throw(_("Account with existing transaction can not be deleted"))
super(Account, self).on_trash(True)
super().on_trash(True)
@frappe.whitelist()
@@ -349,9 +345,8 @@ class Account(NestedSet):
def get_parent_account(doctype, txt, searchfield, start, page_len, filters):
return frappe.db.sql(
"""select name from tabAccount
where is_group = 1 and docstatus != 2 and company = %s
and %s like %s order by name limit %s offset %s"""
% ("%s", searchfield, "%s", "%s", "%s"),
where is_group = 1 and docstatus != 2 and company = {}
and {} like {} order by name limit {} offset {}""".format("%s", searchfield, "%s", "%s", "%s"),
(filters["company"], "%%%s%%" % txt, page_len, start),
as_list=1,
)
@@ -409,9 +404,7 @@ def update_account_number(name, account_name, account_number=None, from_descenda
if not account:
return
old_acc_name, old_acc_number = frappe.db.get_value(
"Account", name, ["account_name", "account_number"]
)
old_acc_name, old_acc_number = frappe.db.get_value("Account", name, ["account_name", "account_number"])
# check if account exists in parent company
ancestors = get_ancestors_of("Company", account.company)
@@ -519,7 +512,5 @@ def sync_update_account_number_in_child(
if old_acc_number:
filters["account_number"] = old_acc_number
for d in frappe.db.get_values(
"Account", filters=filters, fieldname=["company", "name"], as_dict=True
):
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)

View File

@@ -1,4 +1,4 @@
frappe.provide("frappe.treeview_settings")
frappe.provide("frappe.treeview_settings");
frappe.treeview_settings["Account"] = {
breadcrumb: "Accounts",
@@ -7,12 +7,12 @@ frappe.treeview_settings["Account"] = {
filters: [
{
fieldname: "company",
fieldtype:"Select",
fieldtype: "Select",
options: erpnext.utils.get_tree_options("company"),
label: __("Company"),
default: erpnext.utils.get_tree_default("company"),
on_change: function() {
var me = frappe.treeview_settings['Account'].treeview;
on_change: function () {
var me = frappe.treeview_settings["Account"].treeview;
var company = me.page.fields_dict.company.get_value();
if (!company) {
frappe.throw(__("Please set a Company"));
@@ -22,30 +22,36 @@ frappe.treeview_settings["Account"] = {
args: {
company: company,
},
callback: function(r) {
if(r.message) {
callback: function (r) {
if (r.message) {
let root_company = r.message.length ? r.message[0] : "";
me.page.fields_dict.root_company.set_value(root_company);
frappe.db.get_value("Company", {"name": company}, "allow_account_creation_against_child_company", (r) => {
frappe.flags.ignore_root_company_validation = r.allow_account_creation_against_child_company;
});
frappe.db.get_value(
"Company",
{ name: company },
"allow_account_creation_against_child_company",
(r) => {
frappe.flags.ignore_root_company_validation =
r.allow_account_creation_against_child_company;
}
);
}
}
},
});
}
},
},
{
fieldname: "root_company",
fieldtype:"Data",
fieldtype: "Data",
label: __("Root Company"),
hidden: true,
disable_onchange: true
}
disable_onchange: true,
},
],
root_label: "Accounts",
get_tree_nodes: 'erpnext.accounts.utils.get_children',
on_get_node: function(nodes, deep=false) {
get_tree_nodes: "erpnext.accounts.utils.get_children",
on_get_node: function (nodes, deep = false) {
if (frappe.boot.user.can_read.indexOf("GL Entry") == -1) return;
let accounts = [];
@@ -57,151 +63,231 @@ frappe.treeview_settings["Account"] = {
}
frappe.db.get_single_value("Accounts Settings", "show_balance_in_coa").then((value) => {
if(value) {
if (value) {
const get_balances = frappe.call({
method: 'erpnext.accounts.utils.get_account_balances',
method: "erpnext.accounts.utils.get_account_balances",
args: {
accounts: accounts,
company: cur_tree.args.company
company: cur_tree.args.company,
},
});
get_balances.then(r => {
get_balances.then((r) => {
if (!r.message || r.message.length == 0) return;
for (let account of r.message) {
const node = cur_tree.nodes && cur_tree.nodes[account.value];
if (!node || node.is_root) continue;
// show Dr if positive since balance is calculated as debit - credit else show Cr
const balance = account.balance_in_account_currency || account.balance;
const dr_or_cr = balance > 0 ? "Dr": "Cr";
const dr_or_cr = balance > 0 ? "Dr" : "Cr";
const format = (value, currency) => format_currency(Math.abs(value), currency);
if (account.balance!==undefined) {
node.parent && node.parent.find('.balance-area').remove();
$('<span class="balance-area pull-right">'
+ (account.balance_in_account_currency ?
(format(account.balance_in_account_currency, account.account_currency) + " / ") : "")
+ format(account.balance, account.company_currency)
+ " " + dr_or_cr
+ '</span>').insertBefore(node.$ul);
if (account.balance !== undefined) {
node.parent && node.parent.find(".balance-area").remove();
$(
'<span class="balance-area pull-right">' +
(account.balance_in_account_currency
? format(
account.balance_in_account_currency,
account.account_currency
) + " / "
: "") +
format(account.balance, account.company_currency) +
" " +
dr_or_cr +
"</span>"
).insertBefore(node.$ul);
}
}
});
}
});
},
add_tree_node: 'erpnext.accounts.utils.add_ac',
menu_items:[
add_tree_node: "erpnext.accounts.utils.add_ac",
menu_items: [
{
label: __('New Company'),
action: function() { frappe.new_doc("Company", true) },
condition: 'frappe.boot.user.can_create.indexOf("Company") !== -1'
}
label: __("New Company"),
action: function () {
frappe.new_doc("Company", true);
},
condition: 'frappe.boot.user.can_create.indexOf("Company") !== -1',
},
],
fields: [
{fieldtype:'Data', fieldname:'account_name', label:__('New Account Name'), reqd:true,
description: __("Name of new Account. Note: Please don't create accounts for Customers and Suppliers")},
{fieldtype:'Data', fieldname:'account_number', label:__('Account Number'),
description: __("Number of new Account, it will be included in the account name as a prefix")},
{fieldtype:'Check', fieldname:'is_group', label:__('Is Group'),
description: __('Further accounts can be made under Groups, but entries can be made against non-Groups')},
{fieldtype:'Select', fieldname:'root_type', label:__('Root Type'),
options: ['Asset', 'Liability', 'Equity', 'Income', 'Expense'].join('\n'),
depends_on: 'eval:doc.is_group && !doc.parent_account'},
{fieldtype:'Select', fieldname:'account_type', label:__('Account Type'),
options: frappe.get_meta("Account").fields.filter(d => d.fieldname=='account_type')[0].options,
description: __("Optional. This setting will be used to filter in various transactions.")
{
fieldtype: "Data",
fieldname: "account_name",
label: __("New Account Name"),
reqd: true,
description: __(
"Name of new Account. Note: Please don't create accounts for Customers and Suppliers"
),
},
{
fieldtype: "Data",
fieldname: "account_number",
label: __("Account Number"),
description: __("Number of new Account, it will be included in the account name as a prefix"),
},
{
fieldtype: "Check",
fieldname: "is_group",
label: __("Is Group"),
description: __(
"Further accounts can be made under Groups, but entries can be made against non-Groups"
),
},
{
fieldtype: "Select",
fieldname: "root_type",
label: __("Root Type"),
options: ["Asset", "Liability", "Equity", "Income", "Expense"].join("\n"),
depends_on: "eval:doc.is_group && !doc.parent_account",
},
{
fieldtype: "Select",
fieldname: "account_type",
label: __("Account Type"),
options: frappe.get_meta("Account").fields.filter((d) => d.fieldname == "account_type")[0]
.options,
description: __("Optional. This setting will be used to filter in various transactions."),
},
{
fieldtype: "Float",
fieldname: "tax_rate",
label: __("Tax Rate"),
depends_on: 'eval:doc.is_group==0&&doc.account_type=="Tax"',
},
{
fieldtype: "Link",
fieldname: "account_currency",
label: __("Currency"),
options: "Currency",
description: __("Optional. Sets company's default currency, if not specified."),
},
{fieldtype:'Float', fieldname:'tax_rate', label:__('Tax Rate'),
depends_on: 'eval:doc.is_group==0&&doc.account_type=="Tax"'},
{fieldtype:'Link', fieldname:'account_currency', label:__('Currency'), options:"Currency",
description: __("Optional. Sets company's default currency, if not specified.")}
],
ignore_fields:["parent_account"],
onload: function(treeview) {
frappe.treeview_settings['Account'].treeview = {};
$.extend(frappe.treeview_settings['Account'].treeview, treeview);
ignore_fields: ["parent_account"],
onload: function (treeview) {
frappe.treeview_settings["Account"].treeview = {};
$.extend(frappe.treeview_settings["Account"].treeview, treeview);
function get_company() {
return treeview.page.fields_dict.company.get_value();
}
// tools
treeview.page.add_inner_button(__("Chart of Cost Centers"), function() {
frappe.set_route('Tree', 'Cost Center', {company: get_company()});
}, __('View'));
treeview.page.add_inner_button(
__("Chart of Cost Centers"),
function () {
frappe.set_route("Tree", "Cost Center", { company: get_company() });
},
__("View")
);
treeview.page.add_inner_button(__("Opening Invoice Creation Tool"), function() {
frappe.set_route('Form', 'Opening Invoice Creation Tool', {company: get_company()});
}, __('View'));
treeview.page.add_inner_button(
__("Opening Invoice Creation Tool"),
function () {
frappe.set_route("Form", "Opening Invoice Creation Tool", { company: get_company() });
},
__("View")
);
treeview.page.add_inner_button(__("Period Closing Voucher"), function() {
frappe.set_route('List', 'Period Closing Voucher', {company: get_company()});
}, __('View'));
treeview.page.add_inner_button(
__("Period Closing Voucher"),
function () {
frappe.set_route("List", "Period Closing Voucher", { company: get_company() });
},
__("View")
);
treeview.page.add_inner_button(__("Journal Entry"), function() {
frappe.new_doc('Journal Entry', {company: get_company()});
}, __('Create'));
treeview.page.add_inner_button(__("Company"), function() {
frappe.new_doc('Company');
}, __('Create'));
treeview.page.add_inner_button(
__("Journal Entry"),
function () {
frappe.new_doc("Journal Entry", { company: get_company() });
},
__("Create")
);
treeview.page.add_inner_button(
__("Company"),
function () {
frappe.new_doc("Company");
},
__("Create")
);
// financial statements
for (let report of ['Trial Balance', 'General Ledger', 'Balance Sheet',
'Profit and Loss Statement', 'Cash Flow Statement', 'Accounts Payable', 'Accounts Receivable']) {
treeview.page.add_inner_button(__(report), function() {
frappe.set_route('query-report', report, {company: get_company()});
}, __('Financial Statements'));
for (let report of [
"Trial Balance",
"General Ledger",
"Balance Sheet",
"Profit and Loss Statement",
"Cash Flow Statement",
"Accounts Payable",
"Accounts Receivable",
]) {
treeview.page.add_inner_button(
__(report),
function () {
frappe.set_route("query-report", report, { company: get_company() });
},
__("Financial Statements")
);
}
},
post_render: function(treeview) {
frappe.treeview_settings['Account'].treeview["tree"] = treeview.tree;
treeview.page.set_primary_action(__("New"), function() {
let root_company = treeview.page.fields_dict.root_company.get_value();
post_render: function (treeview) {
frappe.treeview_settings["Account"].treeview["tree"] = treeview.tree;
treeview.page.set_primary_action(
__("New"),
function () {
let root_company = treeview.page.fields_dict.root_company.get_value();
if(root_company) {
frappe.throw(__("Please add the account to root level Company - {0}"), [root_company]);
} else {
treeview.new_node();
}
}, "add");
if (root_company) {
frappe.throw(__("Please add the account to root level Company - {0}"), [root_company]);
} else {
treeview.new_node();
}
},
"add"
);
},
toolbar: [
{
label:__("Add Child"),
condition: function(node) {
return frappe.boot.user.can_create.indexOf("Account") !== -1
&& (!frappe.treeview_settings['Account'].treeview.page.fields_dict.root_company.get_value()
|| frappe.flags.ignore_root_company_validation)
&& node.expandable && !node.hide_add;
label: __("Add Child"),
condition: function (node) {
return (
frappe.boot.user.can_create.indexOf("Account") !== -1 &&
(!frappe.treeview_settings[
"Account"
].treeview.page.fields_dict.root_company.get_value() ||
frappe.flags.ignore_root_company_validation) &&
node.expandable &&
!node.hide_add
);
},
click: function() {
var me = frappe.views.trees['Account'];
click: function () {
var me = frappe.views.trees["Account"];
me.new_node();
},
btnClass: "hidden-xs"
btnClass: "hidden-xs",
},
{
condition: function(node) {
return !node.root && frappe.boot.user.can_read.indexOf("GL Entry") !== -1
condition: function (node) {
return !node.root && frappe.boot.user.can_read.indexOf("GL Entry") !== -1;
},
label: __("View Ledger"),
click: function(node, btn) {
click: function (node, btn) {
frappe.route_options = {
"account": node.label,
"from_date": frappe.sys_defaults.year_start_date,
"to_date": frappe.sys_defaults.year_end_date,
"company": frappe.treeview_settings['Account'].treeview.page.fields_dict.company.get_value()
account: node.label,
from_date: frappe.sys_defaults.year_start_date,
to_date: frappe.sys_defaults.year_end_date,
company:
frappe.treeview_settings["Account"].treeview.page.fields_dict.company.get_value(),
};
frappe.set_route("query-report", "General Ledger");
},
btnClass: "hidden-xs"
}
btnClass: "hidden-xs",
},
],
extend_toolbar: true
}
extend_toolbar: true,
};

View File

@@ -31,7 +31,6 @@ def create_charts(
"tax_rate",
"account_currency",
]:
account_number = cstr(child.get("account_number")).strip()
account_name, account_name_in_db = add_suffix_if_duplicate(
account_name, account_number, accounts
@@ -39,7 +38,9 @@ def create_charts(
is_group = identify_is_group(child)
report_type = (
"Balance Sheet" if root_type in ["Asset", "Liability", "Equity"] else "Profit and Loss"
"Balance Sheet"
if root_type in ["Asset", "Liability", "Equity"]
else "Profit and Loss"
)
account = frappe.get_doc(
@@ -141,7 +142,7 @@ def get_chart(chart_template, existing_company=None):
for fname in os.listdir(path):
fname = frappe.as_unicode(fname)
if fname.endswith(".json"):
with open(os.path.join(path, fname), "r") as f:
with open(os.path.join(path, fname)) as f:
chart = f.read()
if chart and json.loads(chart).get("name") == chart_template:
return json.loads(chart).get("tree")
@@ -173,7 +174,7 @@ def get_charts_for_country(country, with_standard=False):
for fname in os.listdir(path):
fname = frappe.as_unicode(fname)
if (fname.startswith(country_code) or fname.startswith(country)) and fname.endswith(".json"):
with open(os.path.join(path, fname), "r") as f:
with open(os.path.join(path, fname)) as f:
_get_chart_name(f.read())
# if more than one charts, returned then add the standard
@@ -247,7 +248,13 @@ def validate_bank_account(coa, bank_account):
def _get_account_names(account_master):
for account_name, child in account_master.items():
if account_name not in ["account_number", "account_type", "root_type", "is_group", "tax_rate"]:
if account_name not in [
"account_number",
"account_type",
"root_type",
"is_group",
"tax_rate",
]:
accounts.append(account_name)
_get_account_names(child)

View File

@@ -26,7 +26,7 @@ def go():
default_account_types = get_default_account_types()
country_dirs = []
for basepath, folders, files in os.walk(path):
for basepath, _folders, _files in os.walk(path):
basename = os.path.basename(basepath)
if basename.startswith("l10n_"):
country_dirs.append(basename)
@@ -35,9 +35,7 @@ def go():
accounts, charts = {}, {}
country_path = os.path.join(path, country_dir)
manifest = ast.literal_eval(open(os.path.join(country_path, "__openerp__.py")).read())
data_files = (
manifest.get("data", []) + manifest.get("init_xml", []) + manifest.get("update_xml", [])
)
data_files = manifest.get("data", []) + manifest.get("init_xml", []) + manifest.get("update_xml", [])
files_path = [os.path.join(country_path, d) for d in data_files]
xml_roots = get_xml_roots(files_path)
csv_content = get_csv_contents(files_path)
@@ -90,10 +88,10 @@ def get_csv_contents(files_path):
fname = os.path.basename(filepath)
for file_type in ["account.account.template", "account.account.type", "account.chart.template"]:
if fname.startswith(file_type) and fname.endswith(".csv"):
with open(filepath, "r") as csvfile:
with open(filepath) as csvfile:
try:
csv_content.setdefault(file_type, []).append(read_csv_content(csvfile.read()))
except Exception as e:
except Exception:
continue
return csv_content
@@ -138,7 +136,7 @@ def get_account_types(root_list, csv_content, prefix=None):
if csv_content and csv_content[0][0] == "id":
for row in csv_content[1:]:
row_dict = dict(zip(csv_content[0], row))
row_dict = dict(zip(csv_content[0], row, strict=False))
data = {}
if row_dict.get("code") and account_type_map.get(row_dict["code"]):
data["account_type"] = account_type_map[row_dict["code"]]
@@ -150,7 +148,7 @@ def get_account_types(root_list, csv_content, prefix=None):
def make_maps_for_xml(xml_roots, account_types, country_dir):
"""make maps for `charts` and `accounts`"""
for model, root_list in xml_roots.items():
for _model, root_list in xml_roots.items():
for root in root_list:
for node in root[0].findall("record"):
if node.get("model") == "account.account.template":
@@ -186,7 +184,7 @@ def make_maps_for_xml(xml_roots, account_types, country_dir):
def make_maps_for_csv(csv_content, account_types, country_dir):
for content in csv_content.get("account.account.template", []):
for row in content[1:]:
data = dict(zip(content[0], row))
data = dict(zip(content[0], row, strict=False))
account = {
"name": data.get("name"),
"parent_id": data.get("parent_id:id") or data.get("parent_id/id"),
@@ -206,7 +204,7 @@ def make_maps_for_csv(csv_content, account_types, country_dir):
for content in csv_content.get("account.chart.template", []):
for row in content[1:]:
if row:
data = dict(zip(content[0], row))
data = dict(zip(content[0], row, strict=False))
charts.setdefault(data.get("id"), {}).update(
{
"account_root_id": data.get("account_root_id:id") or data.get("account_root_id/id"),
@@ -241,7 +239,7 @@ def make_charts():
if not src.get("name") or not src.get("account_root_id"):
continue
if not src["account_root_id"] in accounts:
if src["account_root_id"] not in accounts:
continue
filename = src["id"][5:] + "_" + chart_id
@@ -255,14 +253,20 @@ def make_charts():
for key, val in chart["tree"].items():
if key in ["name", "parent_id"]:
chart["tree"].pop(key)
if type(val) == dict:
if isinstance(val, dict):
val["root_type"] = ""
if chart:
fpath = os.path.join(
"erpnext", "erpnext", "accounts", "doctype", "account", "chart_of_accounts", filename + ".json"
"erpnext",
"erpnext",
"accounts",
"doctype",
"account",
"chart_of_accounts",
filename + ".json",
)
with open(fpath, "r") as chartfile:
with open(fpath) as chartfile:
old_content = chartfile.read()
if not old_content or (
json.loads(old_content).get("is_active", "No") == "No"

View File

@@ -260,28 +260,20 @@ class TestAccount(unittest.TestCase):
acc.insert()
self.assertTrue(
frappe.db.exists(
"Account", {"account_name": "Test Group Account", "company": "_Test Company 4"}
)
frappe.db.exists("Account", {"account_name": "Test Group Account", "company": "_Test Company 4"})
)
self.assertTrue(
frappe.db.exists(
"Account", {"account_name": "Test Group Account", "company": "_Test Company 5"}
)
frappe.db.exists("Account", {"account_name": "Test Group Account", "company": "_Test Company 5"})
)
# Try renaming child company account
acc_tc_5 = frappe.db.get_value(
"Account", {"account_name": "Test Group Account", "company": "_Test Company 5"}
)
self.assertRaises(
frappe.ValidationError, update_account_number, acc_tc_5, "Test Modified Account"
)
self.assertRaises(frappe.ValidationError, update_account_number, acc_tc_5, "Test Modified Account")
# Rename child company account with allow_account_creation_against_child_company enabled
frappe.db.set_value(
"Company", "_Test Company 5", "allow_account_creation_against_child_company", 1
)
frappe.db.set_value("Company", "_Test Company 5", "allow_account_creation_against_child_company", 1)
update_account_number(acc_tc_5, "Test Modified Account")
self.assertTrue(
@@ -290,9 +282,7 @@ class TestAccount(unittest.TestCase):
)
)
frappe.db.set_value(
"Company", "_Test Company 5", "allow_account_creation_against_child_company", 0
)
frappe.db.set_value("Company", "_Test Company 5", "allow_account_creation_against_child_company", 0)
to_delete = [
"Test Group Account - _TC3",
@@ -317,9 +307,7 @@ class TestAccount(unittest.TestCase):
self.assertEqual(acc.account_currency, "INR")
# Make a JV against this account
make_journal_entry(
"Test Currency Account - _TC", "Miscellaneous Expenses - _TC", 100, submit=True
)
make_journal_entry("Test Currency Account - _TC", "Miscellaneous Expenses - _TC", 100, submit=True)
acc.account_currency = "USD"
self.assertRaises(frappe.ValidationError, acc.save)

View File

@@ -17,16 +17,12 @@ class AccountClosingBalance(Document):
def make_closing_entries(closing_entries, voucher_name, company, closing_date):
accounting_dimensions = get_accounting_dimensions()
previous_closing_entries = get_previous_closing_entries(
company, closing_date, accounting_dimensions
)
previous_closing_entries = get_previous_closing_entries(company, closing_date, accounting_dimensions)
combined_entries = closing_entries + previous_closing_entries
merged_entries = aggregate_with_last_account_closing_balance(
combined_entries, accounting_dimensions
)
merged_entries = aggregate_with_last_account_closing_balance(combined_entries, accounting_dimensions)
for key, value in merged_entries.items():
for _key, value in merged_entries.items():
cle = frappe.new_doc("Account Closing Balance")
cle.update(value)
cle.update(value["dimensions"])

View File

@@ -1,74 +1,86 @@
// Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Accounting Dimension', {
refresh: function(frm) {
frm.set_query('document_type', () => {
frappe.ui.form.on("Accounting Dimension", {
refresh: function (frm) {
frm.set_query("document_type", () => {
let invalid_doctypes = frappe.model.core_doctypes_list;
invalid_doctypes.push('Accounting Dimension', 'Project',
'Cost Center', 'Accounting Dimension Detail', 'Company');
invalid_doctypes.push(
"Accounting Dimension",
"Project",
"Cost Center",
"Accounting Dimension Detail",
"Company"
);
return {
filters: {
name: ['not in', invalid_doctypes]
}
name: ["not in", invalid_doctypes],
},
};
});
frm.set_query("offsetting_account", "dimension_defaults", function(doc, cdt, cdn) {
frm.set_query("offsetting_account", "dimension_defaults", function (doc, cdt, cdn) {
let d = locals[cdt][cdn];
return {
filters: {
company: d.company,
root_type: ["in", ["Asset", "Liability"]],
is_group: 0
}
}
is_group: 0,
},
};
});
if (!frm.is_new()) {
frm.add_custom_button(__('Show {0}', [frm.doc.document_type]), function () {
frm.add_custom_button(__("Show {0}", [frm.doc.document_type]), function () {
frappe.set_route("List", frm.doc.document_type);
});
let button = frm.doc.disabled ? "Enable" : "Disable";
frm.add_custom_button(__(button), function() {
frm.set_value('disabled', 1 - frm.doc.disabled);
frm.add_custom_button(__(button), function () {
frm.set_value("disabled", 1 - frm.doc.disabled);
frappe.call({
method: "erpnext.accounts.doctype.accounting_dimension.accounting_dimension.disable_dimension",
args: {
doc: frm.doc
doc: frm.doc,
},
freeze: true,
callback: function(r) {
callback: function (r) {
let message = frm.doc.disabled ? "Dimension Disabled" : "Dimension Enabled";
frm.save();
frappe.show_alert({message:__(message), indicator:'green'});
}
frappe.show_alert({ message: __(message), indicator: "green" });
},
});
});
}
},
document_type: function(frm) {
document_type: function (frm) {
frm.set_value("label", frm.doc.document_type);
frm.set_value("fieldname", frappe.model.scrub(frm.doc.document_type));
frm.set_value('label', frm.doc.document_type);
frm.set_value('fieldname', frappe.model.scrub(frm.doc.document_type));
frappe.db.get_value('Accounting Dimension', {'document_type': frm.doc.document_type}, 'document_type', (r) => {
if (r && r.document_type) {
frm.set_df_property('document_type', 'description', "Document type is already set as dimension");
frappe.db.get_value(
"Accounting Dimension",
{ document_type: frm.doc.document_type },
"document_type",
(r) => {
if (r && r.document_type) {
frm.set_df_property(
"document_type",
"description",
"Document type is already set as dimension"
);
}
}
});
);
},
});
frappe.ui.form.on('Accounting Dimension Detail', {
dimension_defaults_add: function(frm, cdt, cdn) {
frappe.ui.form.on("Accounting Dimension Detail", {
dimension_defaults_add: function (frm, cdt, cdn) {
let row = locals[cdt][cdn];
row.reference_document = frm.doc.document_type;
}
},
});

View File

@@ -17,7 +17,8 @@ class AccountingDimension(Document):
self.set_fieldname_and_label()
def validate(self):
if self.document_type in core_doctypes_list + (
if self.document_type in (
*core_doctypes_list,
"Accounting Dimension",
"Project",
"Cost Center",
@@ -25,13 +26,10 @@ class AccountingDimension(Document):
"Company",
"Account",
):
msg = _("Not allowed to create accounting dimension for {0}").format(self.document_type)
frappe.throw(msg)
exists = frappe.db.get_value(
"Accounting Dimension", {"document_type": self.document_type}, ["name"]
)
exists = frappe.db.get_value("Accounting Dimension", {"document_type": self.document_type}, ["name"])
if exists and self.is_new():
frappe.throw(_("Document Type already used as a dimension"))
@@ -89,7 +87,6 @@ def make_dimension_in_accounting_doctypes(doc, doclist=None):
count = 0
for doctype in doclist:
if (doc_count + 1) % 2 == 0:
insert_after_field = "dimension_col_break"
else:
@@ -123,7 +120,7 @@ def add_dimension_to_budget_doctype(df, doc):
df.update(
{
"insert_after": "cost_center",
"depends_on": "eval:doc.budget_against == '{0}'".format(doc.document_type),
"depends_on": f"eval:doc.budget_against == '{doc.document_type}'",
}
)
@@ -157,19 +154,17 @@ def delete_accounting_dimension(doc):
frappe.db.sql(
"""
DELETE FROM `tabCustom Field`
WHERE fieldname = %s
AND dt IN (%s)"""
% ("%s", ", ".join(["%s"] * len(doclist))), # nosec
tuple([doc.fieldname] + doclist),
WHERE fieldname = {}
AND dt IN ({})""".format("%s", ", ".join(["%s"] * len(doclist))), # nosec
tuple([doc.fieldname, *doclist]),
)
frappe.db.sql(
"""
DELETE FROM `tabProperty Setter`
WHERE field_name = %s
AND doc_type IN (%s)"""
% ("%s", ", ".join(["%s"] * len(doclist))), # nosec
tuple([doc.fieldname] + doclist),
WHERE field_name = {}
AND doc_type IN ({})""".format("%s", ", ".join(["%s"] * len(doclist))), # nosec
tuple([doc.fieldname, *doclist]),
)
budget_against_property = frappe.get_doc("Property Setter", "Budget-budget_against-options")
@@ -218,7 +213,6 @@ def get_doctypes_with_dimensions():
def get_accounting_dimensions(as_list=True, filters=None):
if not filters:
filters = {"disabled": 0}
@@ -236,18 +230,19 @@ def get_accounting_dimensions(as_list=True, filters=None):
def get_checks_for_pl_and_bs_accounts():
dimensions = 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""",
as_dict=1,
)
if frappe.flags.accounting_dimensions_details is None:
# nosemgrep
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""",
as_dict=1,
)
return dimensions
return frappe.flags.accounting_dimensions_details
def get_dimension_with_children(doctype, dimensions):
if isinstance(dimensions, str):
dimensions = [dimensions]
@@ -255,9 +250,7 @@ def get_dimension_with_children(doctype, dimensions):
for dimension in dimensions:
lft, rgt = frappe.db.get_value(doctype, dimension, ["lft", "rgt"])
children = frappe.get_all(
doctype, filters={"lft": [">=", lft], "rgt": ["<=", rgt]}, order_by="lft"
)
children = frappe.get_all(doctype, filters={"lft": [">=", lft], "rgt": ["<=", rgt]}, order_by="lft")
all_dimensions += [c.name for c in children]
return all_dimensions

View File

@@ -78,6 +78,8 @@ class TestAccountingDimension(unittest.TestCase):
def tearDown(self):
disable_dimension()
frappe.flags.accounting_dimensions_details = None
frappe.flags.dimension_filter_map = None
def create_dimension():

View File

@@ -1,10 +1,9 @@
// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Accounting Dimension Filter', {
refresh: function(frm, cdt, cdn) {
let help_content =
`<table class="table table-bordered" style="background-color: var(--scrollbar-track-color);">
frappe.ui.form.on("Accounting Dimension Filter", {
refresh: function (frm, cdt, cdn) {
let help_content = `<table class="table table-bordered" style="background-color: var(--scrollbar-track-color);">
<tr><td>
<p>
<i class="fa fa-hand-right"></i>
@@ -13,67 +12,70 @@ frappe.ui.form.on('Accounting Dimension Filter', {
</td></tr>
</table>`;
frm.set_df_property('dimension_filter_help', 'options', help_content);
frm.set_df_property("dimension_filter_help", "options", help_content);
},
onload: function(frm) {
frm.set_query('applicable_on_account', 'accounts', function() {
onload: function (frm) {
frm.set_query("applicable_on_account", "accounts", function () {
return {
filters: {
'company': frm.doc.company
}
company: frm.doc.company,
},
};
});
frappe.db.get_list('Accounting Dimension',
{fields: ['document_type']}).then((res) => {
let options = ['Cost Center', 'Project'];
frappe.db.get_list("Accounting Dimension", { fields: ["document_type"] }).then((res) => {
let options = ["Cost Center", "Project"];
res.forEach((dimension) => {
options.push(dimension.document_type);
});
frm.set_df_property('accounting_dimension', 'options', options);
frm.set_df_property("accounting_dimension", "options", options);
});
frm.trigger('setup_filters');
frm.trigger("setup_filters");
},
setup_filters: function(frm) {
setup_filters: function (frm) {
let filters = {};
if (frm.doc.accounting_dimension) {
frappe.model.with_doctype(frm.doc.accounting_dimension, function() {
frappe.model.with_doctype(frm.doc.accounting_dimension, function () {
if (frappe.model.is_tree(frm.doc.accounting_dimension)) {
filters['is_group'] = 0;
filters["is_group"] = 0;
}
if (frappe.meta.has_field(frm.doc.accounting_dimension, 'company')) {
filters['company'] = frm.doc.company;
if (frappe.meta.has_field(frm.doc.accounting_dimension, "company")) {
filters["company"] = frm.doc.company;
}
frm.set_query('dimension_value', 'dimensions', function() {
frm.set_query("dimension_value", "dimensions", function () {
return {
filters: filters
filters: filters,
};
});
});
}
},
accounting_dimension: function(frm) {
accounting_dimension: function (frm) {
frm.clear_table("dimensions");
let row = frm.add_child("dimensions");
row.accounting_dimension = frm.doc.accounting_dimension;
frm.fields_dict["dimensions"].grid.update_docfield_property("dimension_value", "label", frm.doc.accounting_dimension);
frm.fields_dict["dimensions"].grid.update_docfield_property(
"dimension_value",
"label",
frm.doc.accounting_dimension
);
frm.refresh_field("dimensions");
frm.trigger('setup_filters');
frm.trigger("setup_filters");
},
});
frappe.ui.form.on('Allowed Dimension', {
dimensions_add: function(frm, cdt, cdn) {
frappe.ui.form.on("Allowed Dimension", {
dimensions_add: function (frm, cdt, cdn) {
let row = locals[cdt][cdn];
row.accounting_dimension = frm.doc.accounting_dimension;
frm.refresh_field("dimensions");
}
},
});

View File

@@ -38,37 +38,41 @@ class AccountingDimensionFilter(Document):
def get_dimension_filter_map():
filters = frappe.db.sql(
"""
SELECT
a.applicable_on_account, d.dimension_value, p.accounting_dimension,
p.allow_or_restrict, a.is_mandatory
FROM
`tabApplicable On Account` a, `tabAllowed Dimension` d,
`tabAccounting Dimension Filter` p
WHERE
p.name = a.parent
AND p.disabled = 0
AND p.name = d.parent
""",
as_dict=1,
)
dimension_filter_map = {}
for f in filters:
f.fieldname = scrub(f.accounting_dimension)
build_map(
dimension_filter_map,
f.fieldname,
f.applicable_on_account,
f.dimension_value,
f.allow_or_restrict,
f.is_mandatory,
if not frappe.flags.get("dimension_filter_map"):
# nosemgrep
filters = frappe.db.sql(
"""
SELECT
a.applicable_on_account, d.dimension_value, p.accounting_dimension,
p.allow_or_restrict, a.is_mandatory
FROM
`tabApplicable On Account` a, `tabAllowed Dimension` d,
`tabAccounting Dimension Filter` p
WHERE
p.name = a.parent
AND p.disabled = 0
AND p.name = d.parent
""",
as_dict=1,
)
return dimension_filter_map
dimension_filter_map = {}
for f in filters:
f.fieldname = scrub(f.accounting_dimension)
build_map(
dimension_filter_map,
f.fieldname,
f.applicable_on_account,
f.dimension_value,
f.allow_or_restrict,
f.is_mandatory,
)
frappe.flags.dimension_filter_map = dimension_filter_map
return frappe.flags.dimension_filter_map
def build_map(map_object, dimension, account, filter_value, allow_or_restrict, is_mandatory):

View File

@@ -47,6 +47,8 @@ class TestAccountingDimensionFilter(unittest.TestCase):
def tearDown(self):
disable_dimension_filter()
disable_dimension()
frappe.flags.accounting_dimensions_details = None
frappe.flags.dimension_filter_map = None
for si in self.invoice_list:
si.load_from_db()
@@ -55,9 +57,7 @@ class TestAccountingDimensionFilter(unittest.TestCase):
def create_accounting_dimension_filter():
if not frappe.db.get_value(
"Accounting Dimension Filter", {"accounting_dimension": "Cost Center"}
):
if not frappe.db.get_value("Accounting Dimension Filter", {"accounting_dimension": "Cost Center"}):
frappe.get_doc(
{
"doctype": "Accounting Dimension Filter",

View File

@@ -1,30 +1,33 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Accounting Period', {
onload: function(frm) {
if(frm.doc.closed_documents.length === 0 || (frm.doc.closed_documents.length === 1 && frm.doc.closed_documents[0].document_type == undefined)) {
frappe.ui.form.on("Accounting Period", {
onload: function (frm) {
if (
frm.doc.closed_documents.length === 0 ||
(frm.doc.closed_documents.length === 1 && frm.doc.closed_documents[0].document_type == undefined)
) {
frappe.call({
method: "get_doctypes_for_closing",
doc:frm.doc,
callback: function(r) {
if(r.message) {
doc: frm.doc,
callback: function (r) {
if (r.message) {
cur_frm.clear_table("closed_documents");
r.message.forEach(function(element) {
r.message.forEach(function (element) {
var c = frm.add_child("closed_documents");
c.document_type = element.document_type;
c.closed = element.closed;
});
refresh_field("closed_documents");
}
}
},
});
}
frm.set_query("document_type", "closed_documents", () => {
return {
query: "erpnext.controllers.queries.get_doctypes_for_closing",
}
};
});
}
},
});

View File

@@ -67,7 +67,10 @@ class AccountingPeriod(Document):
for doctype_for_closing in self.get_doctypes_for_closing():
self.append(
"closed_documents",
{"document_type": doctype_for_closing.document_type, "closed": doctype_for_closing.closed},
{
"document_type": doctype_for_closing.document_type,
"closed": doctype_for_closing.closed,
},
)

View File

@@ -34,9 +34,7 @@ class TestAccountingPeriod(unittest.TestCase):
ap1 = create_accounting_period(period_name="Test Accounting Period 2")
ap1.save()
doc = create_sales_invoice(
do_not_save=1, cost_center="_Test Company - _TC", warehouse="Stores - _TC"
)
doc = create_sales_invoice(do_not_save=1, cost_center="_Test Company - _TC", warehouse="Stores - _TC")
self.assertRaises(ClosedAccountingPeriod, doc.save)
def tearDown(self):

View File

@@ -1,8 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Accounts Settings', {
refresh: function(frm) {
}
frappe.ui.form.on("Accounts Settings", {
refresh: function (frm) {},
});

View File

@@ -1,8 +1,11 @@
frappe.ui.form.on('Accounts Settings', {
refresh: function(frm) {
frappe.ui.form.on("Accounts Settings", {
refresh: function (frm) {
frm.set_df_property("acc_frozen_upto", "label", "Books Closed Through");
frm.set_df_property("frozen_accounts_modifier", "label", "Role Allowed to Close Books & Make Changes to Closed Periods");
frm.set_df_property(
"frozen_accounts_modifier",
"label",
"Role Allowed to Close Books & Make Changes to Closed Periods"
);
frm.set_df_property("credit_controller", "label", "Credit Manager");
}
},
});

View File

@@ -1,41 +1,39 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.provide('erpnext.integrations');
frappe.provide("erpnext.integrations");
frappe.ui.form.on('Bank', {
onload: function(frm) {
frappe.ui.form.on("Bank", {
onload: function (frm) {
add_fields_to_mapping_table(frm);
},
refresh: function(frm) {
refresh: function (frm) {
add_fields_to_mapping_table(frm);
frappe.dynamic_link = { doc: frm.doc, fieldname: 'name', doctype: 'Bank' };
frappe.dynamic_link = { doc: frm.doc, fieldname: "name", doctype: "Bank" };
frm.toggle_display(['address_html','contact_html'], !frm.doc.__islocal);
frm.toggle_display(["address_html", "contact_html"], !frm.doc.__islocal);
if (frm.doc.__islocal) {
frm.set_df_property('address_and_contact', 'hidden', 1);
frm.set_df_property("address_and_contact", "hidden", 1);
frappe.contacts.clear_address_and_contact(frm);
}
else {
frm.set_df_property('address_and_contact', 'hidden', 0);
} else {
frm.set_df_property("address_and_contact", "hidden", 0);
frappe.contacts.render_address_and_contact(frm);
}
if (frm.doc.plaid_access_token) {
frm.add_custom_button(__('Refresh Plaid Link'), () => {
frm.add_custom_button(__("Refresh Plaid Link"), () => {
new erpnext.integrations.refreshPlaidLink(frm.doc.plaid_access_token);
});
}
}
},
});
let add_fields_to_mapping_table = function (frm) {
let options = [];
frappe.model.with_doctype("Bank Transaction", function() {
frappe.model.with_doctype("Bank Transaction", function () {
let meta = frappe.get_meta("Bank Transaction");
meta.fields.forEach(value => {
meta.fields.forEach((value) => {
if (!["Section Break", "Column Break"].includes(value.fieldtype)) {
options.push(value.fieldname);
}
@@ -43,30 +41,32 @@ let add_fields_to_mapping_table = function (frm) {
});
frm.fields_dict.bank_transaction_mapping.grid.update_docfield_property(
'bank_transaction_field', 'options', options
"bank_transaction_field",
"options",
options
);
};
erpnext.integrations.refreshPlaidLink = class refreshPlaidLink {
constructor(access_token) {
this.access_token = access_token;
this.plaidUrl = 'https://cdn.plaid.com/link/v2/stable/link-initialize.js';
this.plaidUrl = "https://cdn.plaid.com/link/v2/stable/link-initialize.js";
this.init_config();
}
async init_config() {
this.plaid_env = await frappe.db.get_single_value('Plaid Settings', 'plaid_env');
this.plaid_env = await frappe.db.get_single_value("Plaid Settings", "plaid_env");
this.token = await this.get_link_token_for_update();
this.init_plaid();
}
async get_link_token_for_update() {
const token = frappe.xcall(
'erpnext.erpnext_integrations.doctype.plaid_settings.plaid_settings.get_link_token_for_update',
"erpnext.erpnext_integrations.doctype.plaid_settings.plaid_settings.get_link_token_for_update",
{ access_token: this.access_token }
)
);
if (!token) {
frappe.throw(__('Cannot retrieve link token for update. Check Error Log for more information'));
frappe.throw(__("Cannot retrieve link token for update. Check Error Log for more information"));
}
return token;
}
@@ -93,13 +93,13 @@ erpnext.integrations.refreshPlaidLink = class refreshPlaidLink {
resolve();
return;
}
const el = document.createElement('script');
el.type = 'text/javascript';
const el = document.createElement("script");
el.type = "text/javascript";
el.async = true;
el.src = src;
el.addEventListener('load', resolve);
el.addEventListener('error', reject);
el.addEventListener('abort', reject);
el.addEventListener("load", resolve);
el.addEventListener("error", reject);
el.addEventListener("abort", reject);
document.head.appendChild(el);
});
}
@@ -108,20 +108,29 @@ erpnext.integrations.refreshPlaidLink = class refreshPlaidLink {
me.linkHandler = Plaid.create({
env: me.plaid_env,
token: me.token,
onSuccess: me.plaid_success
onSuccess: me.plaid_success,
});
}
onScriptError(error) {
frappe.msgprint(__("There was an issue connecting to Plaid's authentication server. Check browser console for more information"));
frappe.msgprint(
__(
"There was an issue connecting to Plaid's authentication server. Check browser console for more information"
)
);
console.log(error);
}
plaid_success(token, response) {
frappe.xcall('erpnext.erpnext_integrations.doctype.plaid_settings.plaid_settings.update_bank_account_ids', {
response: response,
}).then(() => {
frappe.show_alert({ message: __('Plaid Link Updated'), indicator: 'green' });
});
frappe
.xcall(
"erpnext.erpnext_integrations.doctype.plaid_settings.plaid_settings.update_bank_account_ids",
{
response: response,
}
)
.then(() => {
frappe.show_alert({ message: __("Plaid Link Updated"), indicator: "green" });
});
}
};

View File

@@ -1,45 +1,49 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Bank Account', {
setup: function(frm) {
frm.set_query("account", function() {
frappe.ui.form.on("Bank Account", {
setup: function (frm) {
frm.set_query("account", function () {
return {
filters: {
'account_type': 'Bank',
'company': frm.doc.company,
'is_group': 0
}
account_type: "Bank",
company: frm.doc.company,
is_group: 0,
},
};
});
frm.set_query("party_type", function() {
frm.set_query("party_type", function () {
return {
query: "erpnext.setup.doctype.party_type.party_type.get_party_type",
};
});
},
refresh: function(frm) {
frappe.dynamic_link = { doc: frm.doc, fieldname: 'name', doctype: 'Bank Account' }
refresh: function (frm) {
frappe.dynamic_link = { doc: frm.doc, fieldname: "name", doctype: "Bank Account" };
frm.toggle_display(['address_html','contact_html'], !frm.doc.__islocal);
frm.toggle_display(["address_html", "contact_html"], !frm.doc.__islocal);
if (frm.doc.__islocal) {
frappe.contacts.clear_address_and_contact(frm);
}
else {
} else {
frappe.contacts.render_address_and_contact(frm);
}
if (frm.doc.integration_id) {
frm.add_custom_button(__("Unlink external integrations"), function() {
frappe.confirm(__("This action will unlink this account from any external service integrating ERPNext with your bank accounts. It cannot be undone. Are you certain ?"), function() {
frm.set_value("integration_id", "");
});
frm.add_custom_button(__("Unlink external integrations"), function () {
frappe.confirm(
__(
"This action will unlink this account from any external service integrating ERPNext with your bank accounts. It cannot be undone. Are you certain ?"
),
function () {
frm.set_value("integration_id", "");
}
);
});
}
},
is_company_account: function(frm) {
frm.set_df_property('account', 'reqd', frm.doc.is_company_account);
}
is_company_account: function (frm) {
frm.set_df_property("account", "reqd", frm.doc.is_company_account);
},
});

View File

@@ -30,7 +30,9 @@ class BankAccount(Document):
def validate_account(self):
if self.account:
if accounts := frappe.db.get_all("Bank Account", filters={"account": self.account}, as_list=1):
if accounts := frappe.db.get_all(
"Bank Account", filters={"account": self.account, "name": ["!=", self.name]}, as_list=1
):
frappe.throw(
_("'{0}' account is already used by {1}. Use another account.").format(
frappe.bold(self.account),

View File

@@ -37,11 +37,11 @@ class TestBankAccount(unittest.TestCase):
try:
bank_account.validate_iban()
except ValidationError:
msg = "BankAccount.validate_iban() failed for valid IBAN {}".format(iban)
msg = f"BankAccount.validate_iban() failed for valid IBAN {iban}"
self.fail(msg=msg)
for not_iban in invalid_ibans:
bank_account.iban = not_iban
msg = "BankAccount.validate_iban() accepted invalid IBAN {}".format(not_iban)
msg = f"BankAccount.validate_iban() accepted invalid IBAN {not_iban}"
with self.assertRaises(ValidationError, msg=msg):
bank_account.validate_iban()

View File

@@ -1,8 +1,6 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Bank Account Subtype', {
refresh: function() {
}
frappe.ui.form.on("Bank Account Subtype", {
refresh: function () {},
});

View File

@@ -1,8 +1,7 @@
// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Bank Account Type', {
frappe.ui.form.on("Bank Account Type", {
// refresh: function(frm) {
// }
});

View File

@@ -2,80 +2,76 @@
// License: GNU General Public License v3. See license.txt
frappe.ui.form.on("Bank Clearance", {
setup: function(frm) {
setup: function (frm) {
frm.add_fetch("account", "account_currency", "account_currency");
frm.set_query("account", function() {
frm.set_query("account", function () {
return {
"filters": {
"account_type": ["in",["Bank","Cash"]],
"is_group": 0,
}
filters: {
account_type: ["in", ["Bank", "Cash"]],
is_group: 0,
},
};
});
frm.set_query("bank_account", function () {
return {
filters: {
'is_company_account': 1
is_company_account: 1,
},
};
});
},
onload: function(frm) {
let default_bank_account = frappe.defaults.get_user_default("Company")?
locals[":Company"][frappe.defaults.get_user_default("Company")]["default_bank_account"]: "";
onload: function (frm) {
let default_bank_account = frappe.defaults.get_user_default("Company")
? locals[":Company"][frappe.defaults.get_user_default("Company")]["default_bank_account"]
: "";
frm.set_value("account", default_bank_account);
frm.set_value("from_date", frappe.datetime.month_start());
frm.set_value("to_date", frappe.datetime.month_end());
},
refresh: function(frm) {
refresh: function (frm) {
frm.disable_save();
frm.add_custom_button(__('Get Payment Entries'), () =>
frm.trigger("get_payment_entries")
);
frm.add_custom_button(__("Get Payment Entries"), () => frm.trigger("get_payment_entries"));
frm.change_custom_button_type('Get Payment Entries', null, 'primary');
frm.change_custom_button_type("Get Payment Entries", null, "primary");
},
update_clearance_date: function(frm) {
update_clearance_date: function (frm) {
return frappe.call({
method: "update_clearance_date",
doc: frm.doc,
callback: function(r, rt) {
callback: function (r, rt) {
frm.refresh_field("payment_entries");
frm.refresh_fields();
if (!frm.doc.payment_entries.length) {
frm.change_custom_button_type('Get Payment Entries', null, 'primary');
frm.change_custom_button_type('Update Clearance Date', null, 'default');
frm.change_custom_button_type("Get Payment Entries", null, "primary");
frm.change_custom_button_type("Update Clearance Date", null, "default");
}
}
},
});
},
get_payment_entries: function(frm) {
get_payment_entries: function (frm) {
return frappe.call({
method: "get_payment_entries",
doc: frm.doc,
callback: function(r, rt) {
callback: function (r, rt) {
frm.refresh_field("payment_entries");
if (frm.doc.payment_entries.length) {
frm.add_custom_button(__('Update Clearance Date'), () =>
frm.add_custom_button(__("Update Clearance Date"), () =>
frm.trigger("update_clearance_date")
);
frm.change_custom_button_type('Get Payment Entries', null, 'default');
frm.change_custom_button_type('Update Clearance Date', null, 'primary');
frm.change_custom_button_type("Get Payment Entries", null, "default");
frm.change_custom_button_type("Update Clearance Date", null, "primary");
}
}
},
});
}
},
});

View File

@@ -27,7 +27,7 @@ class BankClearance(Document):
condition = "and (clearance_date IS NULL or clearance_date='0000-00-00')"
journal_entries = frappe.db.sql(
"""
f"""
select
"Journal Entry" as payment_document, t1.name as payment_entry,
t1.cheque_no as cheque_number, t1.cheque_date,
@@ -41,9 +41,7 @@ class BankClearance(Document):
and ifnull(t1.is_opening, 'No') = 'No' {condition}
group by t2.account, t1.name
order by t1.posting_date ASC, t1.name DESC
""".format(
condition=condition
),
""",
{"account": self.account, "from": self.from_date, "to": self.to_date},
as_dict=1,
)
@@ -52,7 +50,7 @@ class BankClearance(Document):
condition += "and bank_account = %(bank_account)s"
payment_entries = frappe.db.sql(
"""
f"""
select
"Payment Entry" as payment_document, name as payment_entry,
reference_no as cheque_number, reference_date as cheque_date,
@@ -67,9 +65,7 @@ class BankClearance(Document):
{condition}
order by
posting_date ASC, name DESC
""".format(
condition=condition
),
""",
{
"account": self.account,
"from": self.from_date,
@@ -132,11 +128,9 @@ class BankClearance(Document):
query = query.where(loan_repayment.clearance_date.isnull())
if frappe.db.has_column("Loan Repayment", "repay_from_salary"):
query = query.where((loan_repayment.repay_from_salary == 0))
query = query.where(loan_repayment.repay_from_salary == 0)
query = query.orderby(loan_repayment.posting_date).orderby(
loan_repayment.name, order=frappe.qb.desc
)
query = query.orderby(loan_repayment.posting_date).orderby(loan_repayment.name, order=frappe.qb.desc)
loan_repayments = query.run(as_dict=True)

View File

@@ -1,39 +1,39 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
cur_frm.add_fetch('bank_account','account','account');
cur_frm.add_fetch('bank_account','bank_account_no','bank_account_no');
cur_frm.add_fetch('bank_account','iban','iban');
cur_frm.add_fetch('bank_account','branch_code','branch_code');
cur_frm.add_fetch('bank','swift_number','swift_number');
cur_frm.add_fetch("bank_account", "account", "account");
cur_frm.add_fetch("bank_account", "bank_account_no", "bank_account_no");
cur_frm.add_fetch("bank_account", "iban", "iban");
cur_frm.add_fetch("bank_account", "branch_code", "branch_code");
cur_frm.add_fetch("bank", "swift_number", "swift_number");
frappe.ui.form.on('Bank Guarantee', {
setup: function(frm) {
frm.set_query("bank", function() {
return {
filters: {
company: frm.doc.company
}
};
});
frm.set_query("bank_account", function() {
frappe.ui.form.on("Bank Guarantee", {
setup: function (frm) {
frm.set_query("bank", function () {
return {
filters: {
company: frm.doc.company,
bank: frm.doc.bank
}
}
},
};
});
frm.set_query("project", function() {
frm.set_query("bank_account", function () {
return {
filters: {
customer: frm.doc.customer
}
company: frm.doc.company,
bank: frm.doc.bank,
},
};
});
frm.set_query("project", function () {
return {
filters: {
customer: frm.doc.customer,
},
};
});
},
bg_type: function(frm) {
bg_type: function (frm) {
if (frm.doc.bg_type == "Receiving") {
frm.set_value("reference_doctype", "Sales Order");
} else if (frm.doc.bg_type == "Providing") {
@@ -41,34 +41,33 @@ frappe.ui.form.on('Bank Guarantee', {
}
},
reference_docname: function(frm) {
reference_docname: function (frm) {
if (frm.doc.reference_docname && frm.doc.reference_doctype) {
let party_field = frm.doc.reference_doctype == "Sales Order" ? "customer" : "supplier";
frappe.call({
method: "erpnext.accounts.doctype.bank_guarantee.bank_guarantee.get_voucher_details",
args: {
"bank_guarantee_type": frm.doc.bg_type,
"reference_name": frm.doc.reference_docname
bank_guarantee_type: frm.doc.bg_type,
reference_name: frm.doc.reference_docname,
},
callback: function(r) {
callback: function (r) {
if (r.message) {
if (r.message[party_field]) frm.set_value(party_field, r.message[party_field]);
if (r.message.project) frm.set_value("project", r.message.project);
if (r.message.grand_total) frm.set_value("amount", r.message.grand_total);
}
}
},
});
}
},
start_date: function(frm) {
start_date: function (frm) {
var end_date = frappe.datetime.add_days(cur_frm.doc.start_date, cur_frm.doc.validity - 1);
cur_frm.set_value("end_date", end_date);
},
validity: function(frm) {
validity: function (frm) {
var end_date = frappe.datetime.add_days(cur_frm.doc.start_date, cur_frm.doc.validity - 1);
cur_frm.set_value("end_date", end_date);
}
},
});

View File

@@ -8,21 +8,22 @@ frappe.ui.form.on("Bank Reconciliation Tool", {
return {
filters: {
company: frm.doc.company,
'is_company_account': 1
is_company_account: 1,
},
};
});
let no_bank_transactions_text =
`<div class="text-muted text-center">${__("No Matching Bank Transactions Found")}</div>`
let no_bank_transactions_text = `<div class="text-muted text-center">${__(
"No Matching Bank Transactions Found"
)}</div>`;
set_field_options("no_bank_transactions", no_bank_transactions_text);
},
onload: function (frm) {
// Set default filter dates
let today = frappe.datetime.get_today()
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');
frm.trigger("bank_account");
},
filter_by_reference_date: function (frm) {
@@ -37,34 +38,27 @@ frappe.ui.form.on("Bank Reconciliation Tool", {
refresh: function (frm) {
frm.disable_save();
frappe.require("bank-reconciliation-tool.bundle.js", () =>
frm.trigger("make_reconciliation_tool")
);
frappe.require("bank-reconciliation-tool.bundle.js", () => frm.trigger("make_reconciliation_tool"));
frm.add_custom_button(__("Upload Bank Statement"), () =>
frappe.call({
method:
"erpnext.accounts.doctype.bank_statement_import.bank_statement_import.upload_bank_statement",
args: {
dt: frm.doc.doctype,
dn: frm.doc.name,
company: frm.doc.company,
bank_account: frm.doc.bank_account,
},
callback: function (r) {
if (!r.exc) {
var doc = frappe.model.sync(r.message);
frappe.set_route(
"Form",
doc[0].doctype,
doc[0].name
);
}
},
})
frappe.call({
method: "erpnext.accounts.doctype.bank_statement_import.bank_statement_import.upload_bank_statement",
args: {
dt: frm.doc.doctype,
dn: frm.doc.name,
company: frm.doc.company,
bank_account: frm.doc.bank_account,
},
callback: function (r) {
if (!r.exc) {
var doc = frappe.model.sync(r.message);
frappe.set_route("Form", doc[0].doctype, doc[0].name);
}
},
})
);
frm.add_custom_button(__('Auto Reconcile'), function() {
frm.add_custom_button(__("Auto Reconcile"), function () {
frappe.call({
method: "erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool.auto_reconcile_vouchers",
args: {
@@ -75,33 +69,22 @@ frappe.ui.form.on("Bank Reconciliation Tool", {
from_reference_date: frm.doc.from_reference_date,
to_reference_date: frm.doc.to_reference_date,
},
})
});
});
frm.add_custom_button(__('Get Unreconciled Entries'), function() {
frm.add_custom_button(__("Get Unreconciled Entries"), function () {
frm.trigger("make_reconciliation_tool");
});
frm.change_custom_button_type('Get Unreconciled Entries', null, 'primary');
frm.change_custom_button_type("Get Unreconciled Entries", null, "primary");
},
bank_account: function (frm) {
frappe.db.get_value(
"Bank Account",
frm.doc.bank_account,
"account",
(r) => {
frappe.db.get_value(
"Account",
r.account,
"account_currency",
(r) => {
frm.doc.account_currency = r.account_currency;
frm.trigger("render_chart");
}
);
}
);
frappe.db.get_value("Bank Account", frm.doc.bank_account, "account", (r) => {
frappe.db.get_value("Account", r.account, "account_currency", (r) => {
frm.doc.account_currency = r.account_currency;
frm.trigger("render_chart");
});
});
frm.trigger("get_account_opening_balance");
},
@@ -120,11 +103,7 @@ frappe.ui.form.on("Bank Reconciliation Tool", {
) {
frm.trigger("render_chart");
frm.trigger("render");
frappe.utils.scroll_to(
frm.get_field("reconciliation_tool_cards").$wrapper,
true,
30
);
frappe.utils.scroll_to(frm.get_field("reconciliation_tool_cards").$wrapper, true, 30);
}
});
}
@@ -133,11 +112,10 @@ frappe.ui.form.on("Bank Reconciliation Tool", {
get_account_opening_balance(frm) {
if (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",
method: "erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool.get_account_balance",
args: {
bank_account: frm.doc.bank_account,
till_date: frappe.datetime.add_days(frm.doc.bank_statement_from_date, -1)
till_date: frappe.datetime.add_days(frm.doc.bank_statement_from_date, -1),
},
callback: (response) => {
frm.set_value("account_opening_balance", response.message);
@@ -149,8 +127,7 @@ frappe.ui.form.on("Bank Reconciliation Tool", {
get_cleared_balance(frm) {
if (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",
method: "erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool.get_account_balance",
args: {
bank_account: frm.doc.bank_account,
till_date: frm.doc.bank_statement_to_date,
@@ -163,41 +140,30 @@ frappe.ui.form.on("Bank Reconciliation Tool", {
},
render_chart(frm) {
frm.cards_manager = new erpnext.accounts.bank_reconciliation.NumberCardManager(
{
$reconciliation_tool_cards: frm.get_field(
"reconciliation_tool_cards"
).$wrapper,
bank_statement_closing_balance:
frm.doc.bank_statement_closing_balance,
cleared_balance: frm.cleared_balance,
currency: frm.doc.account_currency,
}
);
frm.cards_manager = new erpnext.accounts.bank_reconciliation.NumberCardManager({
$reconciliation_tool_cards: frm.get_field("reconciliation_tool_cards").$wrapper,
bank_statement_closing_balance: frm.doc.bank_statement_closing_balance,
cleared_balance: frm.cleared_balance,
currency: frm.doc.account_currency,
});
},
render(frm) {
if (frm.doc.bank_account) {
frm.bank_reconciliation_data_table_manager = new erpnext.accounts.bank_reconciliation.DataTableManager(
{
frm.bank_reconciliation_data_table_manager =
new erpnext.accounts.bank_reconciliation.DataTableManager({
company: frm.doc.company,
bank_account: frm.doc.bank_account,
$reconciliation_tool_dt: frm.get_field(
"reconciliation_tool_dt"
).$wrapper,
$no_bank_transactions: frm.get_field(
"no_bank_transactions"
).$wrapper,
$reconciliation_tool_dt: frm.get_field("reconciliation_tool_dt").$wrapper,
$no_bank_transactions: frm.get_field("no_bank_transactions").$wrapper,
bank_statement_from_date: frm.doc.bank_statement_from_date,
bank_statement_to_date: frm.doc.bank_statement_to_date,
filter_by_reference_date: frm.doc.filter_by_reference_date,
from_reference_date: frm.doc.from_reference_date,
to_reference_date: frm.doc.to_reference_date,
bank_statement_closing_balance:
frm.doc.bank_statement_closing_balance,
bank_statement_closing_balance: frm.doc.bank_statement_closing_balance,
cards_manager: frm.cards_manager,
}
);
});
}
},
});

View File

@@ -61,9 +61,7 @@ def get_bank_transactions(bank_account, from_date=None, to_date=None):
def get_account_balance(bank_account, till_date):
# returns account balance till the specified date
account = frappe.db.get_value("Bank Account", bank_account, "account")
filters = frappe._dict(
{"account": account, "report_date": till_date, "include_pos_transactions": 1}
)
filters = frappe._dict({"account": account, "report_date": till_date, "include_pos_transactions": 1})
data = get_entries(filters)
balance_as_per_system = get_balance_on(filters["account"], filters["report_date"])
@@ -76,10 +74,7 @@ def get_account_balance(bank_account, till_date):
amounts_not_reflected_in_system = get_amounts_not_reflected_in_system(filters)
bank_bal = (
flt(balance_as_per_system)
- flt(total_debit)
+ flt(total_credit)
+ amounts_not_reflected_in_system
flt(balance_as_per_system) - flt(total_debit) + flt(total_credit) + amounts_not_reflected_in_system
)
return bank_bal
@@ -377,12 +372,13 @@ def auto_reconcile_vouchers(
)
transaction = frappe.get_doc("Bank Transaction", transaction.name)
account = frappe.db.get_value("Bank Account", transaction.bank_account, "account")
matched_trans = 0
for voucher in vouchers:
gl_entry = frappe.db.get_value(
"GL Entry",
dict(
account=account, voucher_type=voucher["payment_doctype"], voucher_no=voucher["payment_name"]
account=account,
voucher_type=voucher["payment_doctype"],
voucher_no=voucher["payment_name"],
),
["credit", "debit"],
as_dict=1,
@@ -731,7 +727,7 @@ def get_lr_matching_query(bank_account, exact_match, filters):
)
if frappe.db.has_column("Loan Repayment", "repay_from_salary"):
query = query.where((loan_repayment.repay_from_salary == 0))
query = query.where(loan_repayment.repay_from_salary == 0)
if exact_match:
query.where(loan_repayment.amount_paid == filters.get("amount"))
@@ -764,7 +760,7 @@ def get_pe_matching_query(
if cint(filter_by_reference_date):
filter_by_date = f"AND reference_date between '{from_reference_date}' and '{to_reference_date}'"
order_by = " reference_date"
if frappe.flags.auto_reconcile_vouchers == True:
if frappe.flags.auto_reconcile_vouchers is True:
filter_by_reference_no = f"AND reference_no = '{transaction.reference_number}'"
return f"""
SELECT
@@ -815,7 +811,7 @@ def get_je_matching_query(
if cint(filter_by_reference_date):
filter_by_date = f"AND je.cheque_date between '{from_reference_date}' and '{to_reference_date}'"
order_by = " je.cheque_date"
if frappe.flags.auto_reconcile_vouchers == True:
if frappe.flags.auto_reconcile_vouchers is True:
filter_by_reference_no = f"AND je.cheque_no = '{transaction.reference_number}'"
return f"""
SELECT

View File

@@ -17,11 +17,9 @@ frappe.ui.form.on("Bank Statement Import", {
frm.import_in_progress = false;
if (data_import !== frm.doc.name) return;
frappe.model.clear_doc("Bank Statement Import", frm.doc.name);
frappe.model
.with_doc("Bank Statement Import", frm.doc.name)
.then(() => {
frm.refresh();
});
frappe.model.with_doc("Bank Statement Import", frm.doc.name).then(() => {
frm.refresh();
});
});
frappe.realtime.on("data_import_progress", (data) => {
frm.import_in_progress = true;
@@ -48,20 +46,9 @@ frappe.ui.form.on("Bank Statement Import", {
: __("Updating {0} of {1}, {2}", message_args);
}
if (data.skipping) {
message = __(
"Skipping {0} of {1}, {2}",
[
data.current,
data.total,
eta_message,
]
);
message = __("Skipping {0} of {1}, {2}", [data.current, data.total, eta_message]);
}
frm.dashboard.show_progress(
__("Import Progress"),
percent,
message
);
frm.dashboard.show_progress(__("Import Progress"), percent, message);
frm.page.set_indicator(__("In Progress"), "orange");
// hide progress when complete
@@ -103,15 +90,12 @@ frappe.ui.form.on("Bank Statement Import", {
frm.trigger("show_report_error_button");
if (frm.doc.status === "Partial Success") {
frm.add_custom_button(__("Export Errored Rows"), () =>
frm.trigger("export_errored_rows")
);
frm.add_custom_button(__("Export Errored Rows"), () => frm.trigger("export_errored_rows"));
}
if (frm.doc.status.includes("Success")) {
frm.add_custom_button(
__("Go to {0} List", [__(frm.doc.reference_doctype)]),
() => frappe.set_route("List", frm.doc.reference_doctype)
frm.add_custom_button(__("Go to {0} List", [__(frm.doc.reference_doctype)]), () =>
frappe.set_route("List", frm.doc.reference_doctype)
);
}
},
@@ -128,13 +112,8 @@ frappe.ui.form.on("Bank Statement Import", {
frm.disable_save();
if (frm.doc.status !== "Success") {
if (!frm.is_new() && frm.has_import_file()) {
let label =
frm.doc.status === "Pending"
? __("Start Import")
: __("Retry");
frm.page.set_primary_action(label, () =>
frm.events.start_import(frm)
);
let label = frm.doc.status === "Pending" ? __("Start Import") : __("Retry");
frm.page.set_primary_action(label, () => frm.events.start_import(frm));
} else {
frm.page.set_primary_action(__("Save"), () => frm.save());
}
@@ -176,24 +155,24 @@ frappe.ui.form.on("Bank Statement Import", {
message =
successful_records.length > 1
? __(
"Successfully imported {0} records out of {1}. Click on Export Errored Rows, fix the errors and import again.",
message_args
)
"Successfully imported {0} records out of {1}. Click on Export Errored Rows, fix the errors and import again.",
message_args
)
: __(
"Successfully imported {0} record out of {1}. Click on Export Errored Rows, fix the errors and import again.",
message_args
);
"Successfully imported {0} record out of {1}. Click on Export Errored Rows, fix the errors and import again.",
message_args
);
} else {
message =
successful_records.length > 1
? __(
"Successfully updated {0} records out of {1}. Click on Export Errored Rows, fix the errors and import again.",
message_args
)
"Successfully updated {0} records out of {1}. Click on Export Errored Rows, fix the errors and import again.",
message_args
)
: __(
"Successfully updated {0} record out of {1}. Click on Export Errored Rows, fix the errors and import again.",
message_args
);
"Successfully updated {0} record out of {1}. Click on Export Errored Rows, fix the errors and import again.",
message_args
);
}
}
frm.dashboard.set_headline(message);
@@ -236,8 +215,7 @@ frappe.ui.form.on("Bank Statement Import", {
},
download_template() {
let method =
"/api/method/frappe.core.doctype.data_import.data_import.download_template";
let method = "/api/method/frappe.core.doctype.data_import.data_import.download_template";
open_url_post(method, {
doctype: "Bank Transaction",
@@ -250,7 +228,7 @@ frappe.ui.form.on("Bank Statement Import", {
"description",
"reference_number",
"bank_account",
"currency"
"currency",
],
},
});
@@ -321,10 +299,7 @@ frappe.ui.form.on("Bank Statement Import", {
show_import_preview(frm, preview_data) {
let import_log = JSON.parse(frm.doc.statement_import_log || "[]");
if (
frm.import_preview &&
frm.import_preview.doctype === frm.doc.reference_doctype
) {
if (frm.import_preview && frm.import_preview.doctype === frm.doc.reference_doctype) {
frm.import_preview.preview_data = preview_data;
frm.import_preview.import_log = import_log;
frm.import_preview.refresh();
@@ -340,19 +315,10 @@ frappe.ui.form.on("Bank Statement Import", {
frm,
events: {
remap_column(changed_map) {
let template_options = JSON.parse(
frm.doc.template_options || "{}"
);
template_options.column_to_field_map =
template_options.column_to_field_map || {};
Object.assign(
template_options.column_to_field_map,
changed_map
);
frm.set_value(
"template_options",
JSON.stringify(template_options)
);
let template_options = JSON.parse(frm.doc.template_options || "{}");
template_options.column_to_field_map = template_options.column_to_field_map || {};
Object.assign(template_options.column_to_field_map, changed_map);
frm.set_value("template_options", JSON.stringify(template_options));
frm.save().then(() => frm.trigger("import_file"));
},
},
@@ -386,8 +352,7 @@ frappe.ui.form.on("Bank Statement Import", {
let other_warnings = [];
for (let warning of warnings) {
if (warning.row) {
warnings_by_row[warning.row] =
warnings_by_row[warning.row] || [];
warnings_by_row[warning.row] = warnings_by_row[warning.row] || [];
warnings_by_row[warning.row].push(warning);
} else {
other_warnings.push(warning);
@@ -402,9 +367,7 @@ frappe.ui.form.on("Bank Statement Import", {
if (w.field) {
let label =
w.field.label +
(w.field.parent !== frm.doc.reference_doctype
? ` (${w.field.parent})`
: "");
(w.field.parent !== frm.doc.reference_doctype ? ` (${w.field.parent})` : "");
return `<li>${label}: ${w.message}</li>`;
}
return `<li>${w.message}</li>`;
@@ -423,10 +386,9 @@ frappe.ui.form.on("Bank Statement Import", {
.map((warning) => {
let header = "";
if (warning.col) {
let column_number = `<span class="text-uppercase">${__(
"Column {0}",
[warning.col]
)}</span>`;
let column_number = `<span class="text-uppercase">${__("Column {0}", [
warning.col,
])}</span>`;
let column_header = columns[warning.col].header_title;
header = `${column_number} (${column_header})`;
}
@@ -465,36 +427,28 @@ frappe.ui.form.on("Bank Statement Import", {
let html = "";
if (log.success) {
if (frm.doc.import_type === "Insert New Records") {
html = __(
"Successfully imported {0}", [
`<span class="underline">${frappe.utils.get_form_link(
frm.doc.reference_doctype,
log.docname,
true
)}<span>`,
]
);
html = __("Successfully imported {0}", [
`<span class="underline">${frappe.utils.get_form_link(
frm.doc.reference_doctype,
log.docname,
true
)}<span>`,
]);
} else {
html = __(
"Successfully updated {0}", [
`<span class="underline">${frappe.utils.get_form_link(
frm.doc.reference_doctype,
log.docname,
true
)}<span>`,
]
);
html = __("Successfully updated {0}", [
`<span class="underline">${frappe.utils.get_form_link(
frm.doc.reference_doctype,
log.docname,
true
)}<span>`,
]);
}
} else {
let messages = log.messages
.map(JSON.parse)
.map((m) => {
let title = m.title
? `<strong>${m.title}</strong>`
: "";
let message = m.message
? `<div>${m.message}</div>`
: "";
let title = m.title ? `<strong>${m.title}</strong>` : "";
let message = m.message ? `<div>${m.message}</div>` : "";
return title + message;
})
.join("");

View File

@@ -21,7 +21,7 @@ INVALID_VALUES = ("", None)
class BankStatementImport(DataImport):
def __init__(self, *args, **kwargs):
super(BankStatementImport, self).__init__(*args, **kwargs)
super().__init__(*args, **kwargs)
def validate(self):
doc_before_save = self.get_doc_before_save()
@@ -30,7 +30,6 @@ class BankStatementImport(DataImport):
or (doc_before_save and doc_before_save.import_file != self.import_file)
or (doc_before_save and doc_before_save.google_sheets_url != self.google_sheets_url)
):
template_options_dict = {}
column_to_field_map = {}
bank = frappe.get_doc("Bank", self.bank)
@@ -45,7 +44,6 @@ class BankStatementImport(DataImport):
self.validate_google_sheets_url()
def start_import(self):
preview = frappe.get_doc("Bank Statement Import", self.name).get_preview_from_template(
self.import_file, self.google_sheets_url
)
@@ -102,7 +100,7 @@ def download_errored_template(data_import_name):
def parse_data_from_template(raw_data):
data = []
for i, row in enumerate(raw_data):
for _i, row in enumerate(raw_data):
if all(v in INVALID_VALUES for v in row):
# empty row
continue
@@ -112,9 +110,7 @@ def parse_data_from_template(raw_data):
return data
def start_import(
data_import, bank_account, import_file_path, google_sheets_url, bank, template_options
):
def start_import(data_import, bank_account, import_file_path, google_sheets_url, bank, template_options):
"""This method runs in background job"""
update_mapping_db(bank, template_options)

View File

@@ -1,36 +1,34 @@
let imports_in_progress = [];
frappe.listview_settings['Bank Statement Import'] = {
frappe.listview_settings["Bank Statement Import"] = {
onload(listview) {
frappe.realtime.on('data_import_progress', data => {
frappe.realtime.on("data_import_progress", (data) => {
if (!imports_in_progress.includes(data.data_import)) {
imports_in_progress.push(data.data_import);
}
});
frappe.realtime.on('data_import_refresh', data => {
imports_in_progress = imports_in_progress.filter(
d => d !== data.data_import
);
frappe.realtime.on("data_import_refresh", (data) => {
imports_in_progress = imports_in_progress.filter((d) => d !== data.data_import);
listview.refresh();
});
},
get_indicator: function(doc) {
get_indicator: function (doc) {
var colors = {
'Pending': 'orange',
'Not Started': 'orange',
'Partial Success': 'orange',
'Success': 'green',
'In Progress': 'orange',
'Error': 'red'
Pending: "orange",
"Not Started": "orange",
"Partial Success": "orange",
Success: "green",
"In Progress": "orange",
Error: "red",
};
let status = doc.status;
if (imports_in_progress.includes(doc.name)) {
status = 'In Progress';
status = "In Progress";
}
if (status == 'Pending') {
status = 'Not Started';
if (status == "Pending") {
status = "Not Started";
}
return [__(status), colors[status], 'status,=,' + doc.status];
return [__(status), colors[status], "status,=," + doc.status];
},
hide_name_column: true
hide_name_column: true,
};

View File

@@ -1,5 +1,3 @@
from typing import Tuple, Union
import frappe
from frappe.utils import flt
from rapidfuzz import fuzz, process
@@ -19,7 +17,7 @@ class AutoMatchParty:
def get(self, key):
return self.__dict__.get(key, None)
def match(self) -> Union[Tuple, None]:
def match(self) -> tuple | None:
result = None
result = AutoMatchbyAccountIBAN(
bank_party_account_number=self.bank_party_account_number,
@@ -50,7 +48,7 @@ class AutoMatchbyAccountIBAN:
result = self.match_account_in_party()
return result
def match_account_in_party(self) -> Union[Tuple, None]:
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)
@@ -97,7 +95,7 @@ class AutoMatchbyPartyNameDescription:
def get(self, key):
return self.__dict__.get(key, None)
def match(self) -> Union[Tuple, None]:
def match(self) -> tuple | None:
# fuzzy search by customer/supplier & employee
if not (self.bank_party_name or self.description):
return None
@@ -105,7 +103,7 @@ class AutoMatchbyPartyNameDescription:
result = self.match_party_name_desc_in_party()
return result
def match_party_name_desc_in_party(self) -> Union[Tuple, None]:
def match_party_name_desc_in_party(self) -> tuple | None:
"""Fuzzy search party name and/or description against parties in the system"""
result = None
parties = get_parties_in_order(self.deposit)
@@ -130,7 +128,7 @@ class AutoMatchbyPartyNameDescription:
return result
def fuzzy_search_and_return_result(self, party, names, field) -> Union[Tuple, None]:
def fuzzy_search_and_return_result(self, party, names, field) -> tuple | None:
skip = False
result = process.extract(
query=self.get(field),
@@ -147,7 +145,7 @@ class AutoMatchbyPartyNameDescription:
party_name,
), skip
def process_fuzzy_result(self, result: Union[list, None]):
def process_fuzzy_result(self, result: list | None):
"""
If there are multiple valid close matches return None as result may be faulty.
Return the result only if one accurate match stands out.

View File

@@ -3,7 +3,7 @@
frappe.ui.form.on("Bank Transaction", {
onload(frm) {
frm.set_query("payment_document", "payment_entries", function() {
frm.set_query("payment_document", "payment_entries", function () {
const payment_doctypes = frm.events.get_payment_doctypes(frm);
return {
filters: {
@@ -23,7 +23,7 @@ frappe.ui.form.on("Bank Transaction", {
set_bank_statement_filter(frm);
},
setup: function(frm) {
setup: function (frm) {
frm.set_query("party_type", function () {
return {
filters: {
@@ -33,16 +33,10 @@ frappe.ui.form.on("Bank Transaction", {
});
},
get_payment_doctypes: function() {
get_payment_doctypes: function () {
// get payment doctypes from all the apps
return [
"Payment Entry",
"Journal Entry",
"Sales Invoice",
"Purchase Invoice",
"Bank Transaction",
];
}
return ["Payment Entry", "Journal Entry", "Sales Invoice", "Purchase Invoice", "Bank Transaction"];
},
});
frappe.ui.form.on("Bank Transaction Payments", {
@@ -54,10 +48,11 @@ frappe.ui.form.on("Bank Transaction Payments", {
const update_clearance_date = (frm, cdt, cdn) => {
if (frm.doc.docstatus === 1) {
frappe
.xcall(
"erpnext.accounts.doctype.bank_transaction.bank_transaction.unclear_reference_payment",
{ doctype: cdt, docname: cdn, bt_name: frm.doc.name }
)
.xcall("erpnext.accounts.doctype.bank_transaction.bank_transaction.unclear_reference_payment", {
doctype: cdt,
docname: cdn,
bt_name: frm.doc.name,
})
.then((e) => {
if (e == "success") {
frappe.show_alert({

View File

@@ -41,9 +41,10 @@ class BankTransaction(StatusUpdater):
else:
allocated_amount = 0.0
amount = abs(flt(self.withdrawal) - flt(self.deposit))
self.db_set("allocated_amount", flt(allocated_amount))
self.db_set("unallocated_amount", amount - flt(allocated_amount))
unallocated_amount = abs(flt(self.withdrawal) - flt(self.deposit)) - allocated_amount
self.db_set("allocated_amount", flt(allocated_amount, self.precision("allocated_amount")))
self.db_set("unallocated_amount", flt(unallocated_amount, self.precision("unallocated_amount")))
self.reload()
self.set_status(update=True)
@@ -185,9 +186,7 @@ def get_clearance_details(transaction, payment_entry):
"""
gl_bank_account = frappe.db.get_value("Bank Account", transaction.bank_account, "account")
gles = get_related_bank_gl_entries(payment_entry.payment_document, payment_entry.payment_entry)
bt_allocations = get_total_allocated_amount(
payment_entry.payment_document, payment_entry.payment_entry
)
bt_allocations = get_total_allocated_amount(payment_entry.payment_document, payment_entry.payment_entry)
unallocated_amount = min(
transaction.unallocated_amount,
@@ -285,7 +284,6 @@ def get_total_allocated_amount(doctype, docname):
def get_paid_amount(payment_entry, currency, gl_bank_account):
if payment_entry.payment_document in ["Payment Entry", "Sales Invoice", "Purchase Invoice"]:
paid_amount_field = "paid_amount"
if payment_entry.payment_document == "Payment Entry":
doc = frappe.get_doc("Payment Entry", payment_entry.payment_entry)
@@ -324,9 +322,7 @@ def get_paid_amount(payment_entry, currency, gl_bank_account):
)
elif payment_entry.payment_document == "Loan Repayment":
return frappe.db.get_value(
payment_entry.payment_document, payment_entry.payment_entry, "amount_paid"
)
return frappe.db.get_value(payment_entry.payment_document, payment_entry.payment_entry, "amount_paid")
elif payment_entry.payment_document == "Bank Transaction":
dep, wth = frappe.db.get_value(
@@ -336,9 +332,7 @@ def get_paid_amount(payment_entry, currency, gl_bank_account):
else:
frappe.throw(
"Please reconcile {0}: {1} manually".format(
payment_entry.payment_document, payment_entry.payment_entry
)
f"Please reconcile {payment_entry.payment_document}: {payment_entry.payment_entry} manually"
)

View File

@@ -1,15 +1,15 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
frappe.listview_settings['Bank Transaction'] = {
frappe.listview_settings["Bank Transaction"] = {
add_fields: ["unallocated_amount"],
get_indicator: function(doc) {
if(doc.docstatus == 2) {
get_indicator: function (doc) {
if (doc.docstatus == 2) {
return [__("Cancelled"), "red", "docstatus,=,2"];
} else if(flt(doc.unallocated_amount)<=0) {
} else if (flt(doc.unallocated_amount) <= 0) {
return [__("Reconciled"), "green", "unallocated_amount,=,0"];
} else if(flt(doc.unallocated_amount)>0) {
} else if (flt(doc.unallocated_amount) > 0) {
return [__("Unreconciled"), "orange", "unallocated_amount,>,0"];
}
}
},
};

View File

@@ -18,12 +18,12 @@ def upload_bank_statement():
fcontent = frappe.local.uploaded_file
fname = frappe.local.uploaded_filename
if frappe.safe_encode(fname).lower().endswith("csv".encode("utf-8")):
if frappe.safe_encode(fname).lower().endswith(b"csv"):
from frappe.utils.csvutils import read_csv_content
rows = read_csv_content(fcontent, False)
elif frappe.safe_encode(fname).lower().endswith("xlsx".encode("utf-8")):
elif frappe.safe_encode(fname).lower().endswith(b"xlsx"):
from frappe.utils.xlsxutils import read_xlsx_file_from_attached_file
rows = read_xlsx_file_from_attached_file(fcontent=fcontent)

View File

@@ -430,9 +430,7 @@ def add_vouchers(gl_account="_Test Bank - _TC"):
mode_of_payment = frappe.get_doc({"doctype": "Mode of Payment", "name": "Cash"})
if not frappe.db.get_value(
"Mode of Payment Account", {"company": "_Test Company", "parent": "Cash"}
):
if not frappe.db.get_value("Mode of Payment Account", {"company": "_Test Company", "parent": "Cash"}):
mode_of_payment.append("accounts", {"company": "_Test Company", "default_account": gl_account})
mode_of_payment.save()

View File

@@ -0,0 +1,100 @@
// Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on("Bisect Accounting Statements", {
onload(frm) {
frm.trigger("render_heatmap");
},
refresh(frm) {
frm.add_custom_button(__("Bisect Left"), () => {
frm.trigger("bisect_left");
});
frm.add_custom_button(__("Bisect Right"), () => {
frm.trigger("bisect_right");
});
frm.add_custom_button(__("Up"), () => {
frm.trigger("move_up");
});
frm.add_custom_button(__("Build Tree"), () => {
frm.trigger("build_tree");
});
},
render_heatmap(frm) {
let bisect_heatmap = frm.get_field("bisect_heatmap").$wrapper;
bisect_heatmap.addClass("bisect_heatmap_location");
// milliseconds in a day
let msiad = 24 * 60 * 60 * 1000;
let datapoints = {};
let fr_dt = new Date(frm.doc.from_date).getTime();
let to_dt = new Date(frm.doc.to_date).getTime();
let bisect_start = new Date(frm.doc.current_from_date).getTime();
let bisect_end = new Date(frm.doc.current_to_date).getTime();
for (let x = fr_dt; x <= to_dt; x += msiad) {
let epoch_in_seconds = x / 1000;
if (bisect_start <= x && x <= bisect_end) {
datapoints[epoch_in_seconds] = 1.0;
} else {
datapoints[epoch_in_seconds] = 0.0;
}
}
new frappe.Chart(".bisect_heatmap_location", {
type: "heatmap",
data: {
dataPoints: datapoints,
start: new Date(frm.doc.from_date),
end: new Date(frm.doc.to_date),
},
countLabel: "Bisecting",
discreteDomains: 1,
});
},
bisect_left(frm) {
frm.call({
doc: frm.doc,
method: "bisect_left",
freeze: true,
freeze_message: __("Bisecting Left ..."),
callback: (r) => {
frm.trigger("render_heatmap");
},
});
},
bisect_right(frm) {
frm.call({
doc: frm.doc,
freeze: true,
freeze_message: __("Bisecting Right ..."),
method: "bisect_right",
callback: (r) => {
frm.trigger("render_heatmap");
},
});
},
move_up(frm) {
frm.call({
doc: frm.doc,
freeze: true,
freeze_message: __("Moving up in tree ..."),
method: "move_up",
callback: (r) => {
frm.trigger("render_heatmap");
},
});
},
build_tree(frm) {
frm.call({
doc: frm.doc,
freeze: true,
freeze_message: __("Rebuilding BTree for period ..."),
method: "build_tree",
callback: (r) => {
frm.trigger("render_heatmap");
},
});
},
});

View File

@@ -0,0 +1,194 @@
{
"actions": [],
"allow_rename": 1,
"creation": "2023-09-15 21:28:28.054773",
"default_view": "List",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"section_break_cvfg",
"company",
"column_break_hcam",
"from_date",
"column_break_qxbi",
"to_date",
"column_break_iwny",
"algorithm",
"section_break_8ph9",
"current_node",
"section_break_ngid",
"bisect_heatmap",
"section_break_hmsy",
"bisecting_from",
"current_from_date",
"column_break_uqyd",
"bisecting_to",
"current_to_date",
"section_break_hbyo",
"heading_cppb",
"p_l_summary",
"column_break_aivo",
"balance_sheet_summary",
"b_s_summary",
"column_break_gvwx",
"difference_heading",
"difference"
],
"fields": [
{
"fieldname": "column_break_qxbi",
"fieldtype": "Column Break"
},
{
"fieldname": "from_date",
"fieldtype": "Datetime",
"label": "From Date"
},
{
"fieldname": "to_date",
"fieldtype": "Datetime",
"label": "To Date"
},
{
"default": "BFS",
"fieldname": "algorithm",
"fieldtype": "Select",
"label": "Algorithm",
"options": "BFS\nDFS"
},
{
"fieldname": "column_break_iwny",
"fieldtype": "Column Break"
},
{
"fieldname": "current_node",
"fieldtype": "Link",
"label": "Current Node",
"options": "Bisect Nodes"
},
{
"fieldname": "section_break_hmsy",
"fieldtype": "Section Break"
},
{
"fieldname": "current_from_date",
"fieldtype": "Datetime",
"read_only": 1
},
{
"fieldname": "current_to_date",
"fieldtype": "Datetime",
"read_only": 1
},
{
"fieldname": "column_break_uqyd",
"fieldtype": "Column Break"
},
{
"fieldname": "section_break_hbyo",
"fieldtype": "Section Break"
},
{
"fieldname": "p_l_summary",
"fieldtype": "Float",
"read_only": 1
},
{
"fieldname": "b_s_summary",
"fieldtype": "Float",
"read_only": 1
},
{
"fieldname": "difference",
"fieldtype": "Float",
"read_only": 1
},
{
"fieldname": "column_break_aivo",
"fieldtype": "Column Break"
},
{
"fieldname": "column_break_gvwx",
"fieldtype": "Column Break"
},
{
"fieldname": "company",
"fieldtype": "Link",
"label": "Company",
"options": "Company"
},
{
"fieldname": "column_break_hcam",
"fieldtype": "Column Break"
},
{
"fieldname": "section_break_ngid",
"fieldtype": "Section Break"
},
{
"fieldname": "section_break_8ph9",
"fieldtype": "Section Break",
"hidden": 1
},
{
"fieldname": "bisect_heatmap",
"fieldtype": "HTML",
"label": "Heatmap"
},
{
"fieldname": "heading_cppb",
"fieldtype": "Heading",
"label": "Profit and Loss Summary"
},
{
"fieldname": "balance_sheet_summary",
"fieldtype": "Heading",
"label": "Balance Sheet Summary"
},
{
"fieldname": "difference_heading",
"fieldtype": "Heading",
"label": "Difference"
},
{
"fieldname": "bisecting_from",
"fieldtype": "Heading",
"label": "Bisecting From"
},
{
"fieldname": "bisecting_to",
"fieldtype": "Heading",
"label": "Bisecting To"
},
{
"fieldname": "section_break_cvfg",
"fieldtype": "Section Break"
}
],
"hide_toolbar": 1,
"index_web_pages_for_search": 1,
"issingle": 1,
"links": [],
"modified": "2023-12-01 16:49:54.073890",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Bisect Accounting Statements",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"print": 1,
"read": 1,
"role": "Administrator",
"share": 1,
"write": 1
}
],
"read_only": 1,
"sort_field": "modified",
"sort_order": "DESC",
"states": []
}

View File

@@ -0,0 +1,206 @@
# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
import datetime
from collections import deque
from math import floor
import frappe
from dateutil.relativedelta import relativedelta
from frappe import _
from frappe.model.document import Document
from frappe.utils import getdate
from frappe.utils.data import guess_date_format
class BisectAccountingStatements(Document):
def validate(self):
self.validate_dates()
def validate_dates(self):
if getdate(self.from_date) > getdate(self.to_date):
frappe.throw(
_("From Date: {0} cannot be greater than To date: {1}").format(
frappe.bold(self.from_date), frappe.bold(self.to_date)
)
)
def bfs(self, from_date: datetime, to_date: datetime):
# Make Root node
node = frappe.new_doc("Bisect Nodes")
node.root = None
node.period_from_date = from_date
node.period_to_date = to_date
node.insert()
period_queue = deque([node])
while period_queue:
cur_node = period_queue.popleft()
delta = cur_node.period_to_date - cur_node.period_from_date
if delta.days == 0:
continue
else:
cur_floor = floor(delta.days / 2)
next_to_date = cur_node.period_from_date + relativedelta(days=+cur_floor)
left_node = frappe.new_doc("Bisect Nodes")
left_node.period_from_date = cur_node.period_from_date
left_node.period_to_date = next_to_date
left_node.root = cur_node.name
left_node.generated = False
left_node.insert()
cur_node.left_child = left_node.name
period_queue.append(left_node)
next_from_date = cur_node.period_from_date + relativedelta(days=+(cur_floor + 1))
right_node = frappe.new_doc("Bisect Nodes")
right_node.period_from_date = next_from_date
right_node.period_to_date = cur_node.period_to_date
right_node.root = cur_node.name
right_node.generated = False
right_node.insert()
cur_node.right_child = right_node.name
period_queue.append(right_node)
cur_node.save()
def dfs(self, from_date: datetime, to_date: datetime):
# Make Root node
node = frappe.new_doc("Bisect Nodes")
node.root = None
node.period_from_date = from_date
node.period_to_date = to_date
node.insert()
period_stack = [node]
while period_stack:
cur_node = period_stack.pop()
delta = cur_node.period_to_date - cur_node.period_from_date
if delta.days == 0:
continue
else:
cur_floor = floor(delta.days / 2)
next_to_date = cur_node.period_from_date + relativedelta(days=+cur_floor)
left_node = frappe.new_doc("Bisect Nodes")
left_node.period_from_date = cur_node.period_from_date
left_node.period_to_date = next_to_date
left_node.root = cur_node.name
left_node.generated = False
left_node.insert()
cur_node.left_child = left_node.name
period_stack.append(left_node)
next_from_date = cur_node.period_from_date + relativedelta(days=+(cur_floor + 1))
right_node = frappe.new_doc("Bisect Nodes")
right_node.period_from_date = next_from_date
right_node.period_to_date = cur_node.period_to_date
right_node.root = cur_node.name
right_node.generated = False
right_node.insert()
cur_node.right_child = right_node.name
period_stack.append(right_node)
cur_node.save()
@frappe.whitelist()
def build_tree(self):
frappe.db.delete("Bisect Nodes")
# Convert str to datetime format
dt_format = guess_date_format(self.from_date)
from_date = datetime.datetime.strptime(self.from_date, dt_format)
to_date = datetime.datetime.strptime(self.to_date, dt_format)
if self.algorithm == "BFS":
self.bfs(from_date, to_date)
if self.algorithm == "DFS":
self.dfs(from_date, to_date)
# set root as current node
root = frappe.db.get_all("Bisect Nodes", filters={"root": ["is", "not set"]})[0]
self.get_report_summary()
self.current_node = root.name
self.current_from_date = self.from_date
self.current_to_date = self.to_date
self.save()
def get_report_summary(self):
filters = {
"company": self.company,
"filter_based_on": "Date Range",
"period_start_date": self.current_from_date,
"period_end_date": self.current_to_date,
"periodicity": "Yearly",
}
pl_summary = frappe.get_doc("Report", "Profit and Loss Statement")
self.p_l_summary = pl_summary.execute_script_report(filters=filters)[5]
bs_summary = frappe.get_doc("Report", "Balance Sheet")
self.b_s_summary = bs_summary.execute_script_report(filters=filters)[5]
self.difference = abs(self.p_l_summary - self.b_s_summary)
def update_node(self):
current_node = frappe.get_doc("Bisect Nodes", self.current_node)
current_node.balance_sheet_summary = self.b_s_summary
current_node.profit_loss_summary = self.p_l_summary
current_node.difference = self.difference
current_node.generated = True
current_node.save()
def current_node_has_summary_info(self):
"Assertion method"
return frappe.db.get_value("Bisect Nodes", self.current_node, "generated")
def fetch_summary_info_from_current_node(self):
current_node = frappe.get_doc("Bisect Nodes", self.current_node)
self.p_l_summary = current_node.balance_sheet_summary
self.b_s_summary = current_node.profit_loss_summary
self.difference = abs(self.p_l_summary - self.b_s_summary)
def fetch_or_calculate(self):
if self.current_node_has_summary_info():
self.fetch_summary_info_from_current_node()
else:
self.get_report_summary()
self.update_node()
@frappe.whitelist()
def bisect_left(self):
if self.current_node is not None:
cur_node = frappe.get_doc("Bisect Nodes", self.current_node)
if cur_node.left_child is not None:
lft_node = frappe.get_doc("Bisect Nodes", cur_node.left_child)
self.current_node = cur_node.left_child
self.current_from_date = lft_node.period_from_date
self.current_to_date = lft_node.period_to_date
self.fetch_or_calculate()
self.save()
else:
frappe.msgprint(_("No more children on Left"))
@frappe.whitelist()
def bisect_right(self):
if self.current_node is not None:
cur_node = frappe.get_doc("Bisect Nodes", self.current_node)
if cur_node.right_child is not None:
rgt_node = frappe.get_doc("Bisect Nodes", cur_node.right_child)
self.current_node = cur_node.right_child
self.current_from_date = rgt_node.period_from_date
self.current_to_date = rgt_node.period_to_date
self.fetch_or_calculate()
self.save()
else:
frappe.msgprint(_("No more children on Right"))
@frappe.whitelist()
def move_up(self):
if self.current_node is not None:
cur_node = frappe.get_doc("Bisect Nodes", self.current_node)
if cur_node.root is not None:
root = frappe.get_doc("Bisect Nodes", cur_node.root)
self.current_node = cur_node.root
self.current_from_date = root.period_from_date
self.current_to_date = root.period_to_date
self.fetch_or_calculate()
self.save()
else:
frappe.msgprint(_("Reached Root"))

View File

@@ -0,0 +1,9 @@
# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
# import frappe
from frappe.tests.utils import FrappeTestCase
class TestBisectAccountingStatements(FrappeTestCase):
pass

View File

@@ -0,0 +1,8 @@
// Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
// frappe.ui.form.on("Bisect Nodes", {
// refresh(frm) {
// },
// });

View File

@@ -0,0 +1,97 @@
{
"actions": [],
"autoname": "autoincrement",
"creation": "2023-09-27 14:56:38.112462",
"default_view": "List",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"root",
"left_child",
"right_child",
"period_from_date",
"period_to_date",
"difference",
"balance_sheet_summary",
"profit_loss_summary",
"generated"
],
"fields": [
{
"fieldname": "root",
"fieldtype": "Link",
"label": "Root",
"options": "Bisect Nodes"
},
{
"fieldname": "left_child",
"fieldtype": "Link",
"label": "Left Child",
"options": "Bisect Nodes"
},
{
"fieldname": "right_child",
"fieldtype": "Link",
"label": "Right Child",
"options": "Bisect Nodes"
},
{
"fieldname": "period_from_date",
"fieldtype": "Datetime",
"label": "Period_from_date"
},
{
"fieldname": "period_to_date",
"fieldtype": "Datetime",
"label": "Period To Date"
},
{
"fieldname": "difference",
"fieldtype": "Float",
"label": "Difference"
},
{
"fieldname": "balance_sheet_summary",
"fieldtype": "Float",
"label": "Balance Sheet Summary"
},
{
"fieldname": "profit_loss_summary",
"fieldtype": "Float",
"label": "Profit and Loss Summary"
},
{
"default": "0",
"fieldname": "generated",
"fieldtype": "Check",
"label": "Generated"
}
],
"index_web_pages_for_search": 1,
"links": [],
"modified": "2023-12-01 17:46:12.437996",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Bisect Nodes",
"naming_rule": "Autoincrement",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "Administrator",
"share": 1,
"write": 1
}
],
"read_only": 1,
"sort_field": "modified",
"sort_order": "DESC",
"states": []
}

View File

@@ -0,0 +1,29 @@
# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
# import frappe
from frappe.model.document import Document
class BisectNodes(Document):
# begin: auto-generated types
# This code is auto-generated. Do not modify anything in this block.
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from frappe.types import DF
balance_sheet_summary: DF.Float
difference: DF.Float
generated: DF.Check
left_child: DF.Link | None
name: DF.Int | None
period_from_date: DF.Datetime | None
period_to_date: DF.Datetime | None
profit_loss_summary: DF.Float
right_child: DF.Link | None
root: DF.Link | None
# end: auto-generated types
pass

View File

@@ -0,0 +1,9 @@
# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
# import frappe
from frappe.tests.utils import FrappeTestCase
class TestBisectNodes(FrappeTestCase):
pass

View File

@@ -2,48 +2,48 @@
// For license information, please see license.txt
frappe.provide("erpnext.accounts.dimensions");
frappe.ui.form.on('Budget', {
onload: function(frm) {
frm.set_query("account", "accounts", function() {
frappe.ui.form.on("Budget", {
onload: function (frm) {
frm.set_query("account", "accounts", function () {
return {
filters: {
company: frm.doc.company,
report_type: "Profit and Loss",
is_group: 0
}
is_group: 0,
},
};
});
frm.set_query("monthly_distribution", function() {
frm.set_query("monthly_distribution", function () {
return {
filters: {
fiscal_year: frm.doc.fiscal_year
}
fiscal_year: frm.doc.fiscal_year,
},
};
});
erpnext.accounts.dimensions.setup_dimension_filters(frm, frm.doctype);
},
refresh: function(frm) {
frm.trigger("toggle_reqd_fields")
refresh: function (frm) {
frm.trigger("toggle_reqd_fields");
},
budget_against: function(frm) {
frm.trigger("set_null_value")
frm.trigger("toggle_reqd_fields")
budget_against: function (frm) {
frm.trigger("set_null_value");
frm.trigger("toggle_reqd_fields");
},
set_null_value: function(frm) {
if(frm.doc.budget_against == 'Cost Center') {
frm.set_value('project', null)
set_null_value: function (frm) {
if (frm.doc.budget_against == "Cost Center") {
frm.set_value("project", null);
} else {
frm.set_value('cost_center', null)
frm.set_value("cost_center", null);
}
},
toggle_reqd_fields: function(frm) {
frm.toggle_reqd("cost_center", frm.doc.budget_against=="Cost Center");
frm.toggle_reqd("project", frm.doc.budget_against=="Project");
}
toggle_reqd_fields: function (frm) {
frm.toggle_reqd("cost_center", frm.doc.budget_against == "Cost Center");
frm.toggle_reqd("project", frm.doc.budget_against == "Project");
},
});

View File

@@ -40,10 +40,11 @@ class Budget(Document):
select
b.name, ba.account from `tabBudget` b, `tabBudget Account` ba
where
ba.parent = b.name and b.docstatus < 2 and b.company = %s and %s=%s and
b.fiscal_year=%s and b.name != %s and ba.account in (%s) """
% ("%s", budget_against_field, "%s", "%s", "%s", ",".join(["%s"] * len(accounts))),
(self.company, budget_against, self.fiscal_year, self.name) + tuple(accounts),
ba.parent = b.name and b.docstatus < 2 and b.company = {} and {}={} and
b.fiscal_year={} and b.name != {} and ba.account in ({}) """.format(
"%s", budget_against_field, "%s", "%s", "%s", ",".join(["%s"] * len(accounts))
),
(self.company, budget_against, self.fiscal_year, self.name, *tuple(accounts)),
as_dict=1,
)
@@ -66,12 +67,14 @@ class Budget(Document):
if account_details.is_group:
frappe.throw(_("Budget cannot be assigned against Group Account {0}").format(d.account))
elif account_details.company != self.company:
frappe.throw(_("Account {0} does not belongs to company {1}").format(d.account, self.company))
frappe.throw(
_("Account {0} does not belongs to company {1}").format(d.account, self.company)
)
elif account_details.report_type != "Profit and Loss":
frappe.throw(
_("Budget cannot be assigned against {0}, as it's not an Income or Expense account").format(
d.account
)
_(
"Budget cannot be assigned against {0}, as it's not an Income or Expense account"
).format(d.account)
)
if d.account in account_list:
@@ -109,6 +112,8 @@ class Budget(Document):
def validate_expense_against_budget(args, expense_amount=0):
args = frappe._dict(args)
if not frappe.get_all("Budget", limit=1):
return
if args.get("company") and not args.fiscal_year:
args.fiscal_year = get_fiscal_year(args.get("posting_date"), company=args.get("company"))[0]
@@ -116,6 +121,9 @@ def validate_expense_against_budget(args, expense_amount=0):
"Company", args.get("company"), "exception_budget_approver_role"
)
if not frappe.get_cached_value("Budget", {"fiscal_year": args.fiscal_year, "company": args.company}): # nosec
return
if not args.account:
args.account = args.get("expense_account")
@@ -142,32 +150,26 @@ def validate_expense_against_budget(args, expense_amount=0):
if (
args.get(budget_against)
and args.account
and frappe.db.get_value("Account", {"name": args.account, "root_type": "Expense"})
and (frappe.get_cached_value("Account", args.account, "root_type") == "Expense")
):
doctype = dimension.get("document_type")
if frappe.get_cached_value("DocType", doctype, "is_tree"):
lft, rgt = frappe.db.get_value(doctype, args.get(budget_against), ["lft", "rgt"])
condition = """and exists(select name from `tab%s`
where lft<=%s and rgt>=%s and name=b.%s)""" % (
doctype,
lft,
rgt,
budget_against,
) # nosec
lft, rgt = frappe.get_cached_value(doctype, args.get(budget_against), ["lft", "rgt"])
condition = f"""and exists(select name from `tab{doctype}`
where lft<={lft} and rgt>={rgt} and name=b.{budget_against})""" # nosec
args.is_tree = True
else:
condition = "and b.%s=%s" % (budget_against, frappe.db.escape(args.get(budget_against)))
condition = f"and b.{budget_against}={frappe.db.escape(args.get(budget_against))}"
args.is_tree = False
args.budget_against_field = budget_against
args.budget_against_doctype = doctype
budget_records = frappe.db.sql(
"""
f"""
select
b.{budget_against_field} as budget_against, ba.budget_amount, b.monthly_distribution,
b.{budget_against} as budget_against, ba.budget_amount, b.monthly_distribution,
ifnull(b.applicable_on_material_request, 0) as for_material_request,
ifnull(applicable_on_purchase_order, 0) as for_purchase_order,
ifnull(applicable_on_booking_actual_expenses,0) as for_actual_expenses,
@@ -180,9 +182,7 @@ def validate_expense_against_budget(args, expense_amount=0):
b.name=ba.parent and b.fiscal_year=%s
and ba.account=%s and b.docstatus=1
{condition}
""".format(
condition=condition, budget_against_field=budget_against
),
""",
(args.fiscal_year, args.account),
as_dict=True,
) # nosec
@@ -194,12 +194,18 @@ def validate_expense_against_budget(args, expense_amount=0):
def validate_budget_records(args, budget_records, expense_amount):
for budget in budget_records:
if flt(budget.budget_amount):
amount = expense_amount or get_amount(args, budget)
yearly_action, monthly_action = get_actions(args, budget)
args["for_material_request"] = budget.for_material_request
args["for_purchase_order"] = budget.for_purchase_order
if yearly_action in ("Stop", "Warn"):
compare_expense_with_budget(
args, flt(budget.budget_amount), _("Annual"), yearly_action, budget.budget_against, amount
args,
flt(budget.budget_amount),
_("Annual"),
yearly_action,
budget.budget_against,
expense_amount,
)
if monthly_action in ["Stop", "Warn"]:
@@ -210,18 +216,32 @@ def validate_budget_records(args, budget_records, expense_amount):
args["month_end_date"] = get_last_day(args.posting_date)
compare_expense_with_budget(
args, budget_amount, _("Accumulated Monthly"), monthly_action, budget.budget_against, amount
args,
budget_amount,
_("Accumulated Monthly"),
monthly_action,
budget.budget_against,
expense_amount,
)
def compare_expense_with_budget(args, budget_amount, action_for, action, budget_against, amount=0):
actual_expense = get_actual_expense(args)
total_expense = actual_expense + amount
args.actual_expense, args.requested_amount, args.ordered_amount = get_actual_expense(args), 0, 0
if not amount:
args.requested_amount, args.ordered_amount = get_requested_amount(args), get_ordered_amount(args)
if args.get("doctype") == "Material Request" and args.for_material_request:
amount = args.requested_amount + args.ordered_amount
elif args.get("doctype") == "Purchase Order" and args.for_purchase_order:
amount = args.ordered_amount
total_expense = args.actual_expense + amount
if total_expense > budget_amount:
if actual_expense > budget_amount:
if args.actual_expense > budget_amount:
error_tense = _("is already")
diff = actual_expense - budget_amount
diff = args.actual_expense - budget_amount
else:
error_tense = _("will be")
diff = total_expense - budget_amount
@@ -238,9 +258,10 @@ def compare_expense_with_budget(args, budget_amount, action_for, action, budget_
frappe.bold(fmt_money(diff, currency=currency)),
)
if (
frappe.flags.exception_approver_role
and frappe.flags.exception_approver_role in frappe.get_roles(frappe.session.user)
msg += get_expense_breakup(args, currency, budget_against)
if frappe.flags.exception_approver_role and frappe.flags.exception_approver_role in frappe.get_roles(
frappe.session.user
):
action = "Warn"
@@ -250,6 +271,83 @@ def compare_expense_with_budget(args, budget_amount, action_for, action, budget_
frappe.msgprint(msg, indicator="orange", title=_("Budget Exceeded"))
def get_expense_breakup(args, currency, budget_against):
msg = "<hr>Total Expenses booked through - <ul>"
common_filters = frappe._dict(
{
args.budget_against_field: budget_against,
"account": args.account,
"company": args.company,
}
)
msg += (
"<li>"
+ frappe.utils.get_link_to_report(
"General Ledger",
label="Actual Expenses",
filters=common_filters.copy().update(
{
"from_date": frappe.get_cached_value("Fiscal Year", args.fiscal_year, "year_start_date"),
"to_date": frappe.get_cached_value("Fiscal Year", args.fiscal_year, "year_end_date"),
"is_cancelled": 0,
}
),
)
+ " - "
+ frappe.bold(fmt_money(args.actual_expense, currency=currency))
+ "</li>"
)
msg += (
"<li>"
+ frappe.utils.get_link_to_report(
"Material Request",
label="Material Requests",
report_type="Report Builder",
doctype="Material Request",
filters=common_filters.copy().update(
{
"status": [["!=", "Stopped"]],
"docstatus": 1,
"material_request_type": "Purchase",
"schedule_date": [["fiscal year", "2023-2024"]],
"item_code": args.item_code,
"per_ordered": [["<", 100]],
}
),
)
+ " - "
+ frappe.bold(fmt_money(args.requested_amount, currency=currency))
+ "</li>"
)
msg += (
"<li>"
+ frappe.utils.get_link_to_report(
"Purchase Order",
label="Unbilled Orders",
report_type="Report Builder",
doctype="Purchase Order",
filters=common_filters.copy().update(
{
"status": [["!=", "Closed"]],
"docstatus": 1,
"transaction_date": [["fiscal year", "2023-2024"]],
"item_code": args.item_code,
"per_billed": [["<", 100]],
}
),
)
+ " - "
+ frappe.bold(fmt_money(args.ordered_amount, currency=currency))
+ "</li></ul>"
)
return msg
def get_actions(args, budget):
yearly_action = budget.action_if_annual_budget_exceeded
monthly_action = budget.action_if_accumulated_monthly_budget_exceeded
@@ -265,31 +363,15 @@ def get_actions(args, budget):
return yearly_action, monthly_action
def get_amount(args, budget):
amount = 0
if args.get("doctype") == "Material Request" and budget.for_material_request:
amount = (
get_requested_amount(args, budget) + get_ordered_amount(args, budget) + get_actual_expense(args)
)
elif args.get("doctype") == "Purchase Order" and budget.for_purchase_order:
amount = get_ordered_amount(args, budget) + get_actual_expense(args)
return amount
def get_requested_amount(args, budget):
def get_requested_amount(args):
item_code = args.get("item_code")
condition = get_other_condition(args, budget, "Material Request")
condition = get_other_condition(args, "Material Request")
data = frappe.db.sql(
""" select ifnull((sum(child.stock_qty - child.ordered_qty) * rate), 0) as amount
from `tabMaterial Request Item` child, `tabMaterial Request` parent where parent.name = child.parent and
child.item_code = %s and parent.docstatus = 1 and child.stock_qty > child.ordered_qty and {0} and
parent.material_request_type = 'Purchase' and parent.status != 'Stopped'""".format(
condition
),
child.item_code = %s and parent.docstatus = 1 and child.stock_qty > child.ordered_qty and {} and
parent.material_request_type = 'Purchase' and parent.status != 'Stopped'""".format(condition),
item_code,
as_list=1,
)
@@ -297,17 +379,15 @@ def get_requested_amount(args, budget):
return data[0][0] if data else 0
def get_ordered_amount(args, budget):
def get_ordered_amount(args):
item_code = args.get("item_code")
condition = get_other_condition(args, budget, "Purchase Order")
condition = get_other_condition(args, "Purchase Order")
data = frappe.db.sql(
""" select ifnull(sum(child.amount - child.billed_amt), 0) as amount
f""" select ifnull(sum(child.amount - child.billed_amt), 0) as amount
from `tabPurchase Order Item` child, `tabPurchase Order` parent where
parent.name = child.parent and child.item_code = %s and parent.docstatus = 1 and child.amount > child.billed_amt
and parent.status != 'Closed' and {0}""".format(
condition
),
and parent.status != 'Closed' and {condition}""",
item_code,
as_list=1,
)
@@ -315,12 +395,12 @@ def get_ordered_amount(args, budget):
return data[0][0] if data else 0
def get_other_condition(args, budget, for_doc):
def get_other_condition(args, for_doc):
condition = "expense_account = '%s'" % (args.expense_account)
budget_against_field = args.get("budget_against_field")
if budget_against_field and args.get(budget_against_field):
condition += " and child.%s = '%s'" % (budget_against_field, args.get(budget_against_field))
condition += f" and child.{budget_against_field} = '{args.get(budget_against_field)}'"
if args.get("fiscal_year"):
date_field = "schedule_date" if for_doc == "Material Request" else "transaction_date"
@@ -328,12 +408,8 @@ def get_other_condition(args, budget, for_doc):
"Fiscal Year", args.get("fiscal_year"), ["year_start_date", "year_end_date"]
)
condition += """ and parent.%s
between '%s' and '%s' """ % (
date_field,
start_date,
end_date,
)
condition += f""" and parent.{date_field}
between '{start_date}' and '{end_date}' """
return condition
@@ -352,21 +428,17 @@ def get_actual_expense(args):
args.update(lft_rgt)
condition2 = """and exists(select name from `tab{doctype}`
condition2 = f"""and exists(select name from `tab{args.budget_against_doctype}`
where lft>=%(lft)s and rgt<=%(rgt)s
and name=gle.{budget_against_field})""".format(
doctype=args.budget_against_doctype, budget_against_field=budget_against_field # nosec
)
and name=gle.{budget_against_field})"""
else:
condition2 = """and exists(select name from `tab{doctype}`
where name=gle.{budget_against} and
gle.{budget_against} = %({budget_against})s)""".format(
doctype=args.budget_against_doctype, budget_against=budget_against_field
)
condition2 = f"""and exists(select name from `tab{args.budget_against_doctype}`
where name=gle.{budget_against_field} and
gle.{budget_against_field} = %({budget_against_field})s)"""
amount = flt(
frappe.db.sql(
"""
f"""
select sum(gle.debit) - sum(gle.credit)
from `tabGL Entry` gle
where
@@ -377,9 +449,7 @@ def get_actual_expense(args):
and gle.company=%(company)s
and gle.docstatus=1
{condition2}
""".format(
condition1=condition1, condition2=condition2
),
""",
(args),
)[0][0]
) # nosec

View File

@@ -41,9 +41,7 @@ class TestBudget(unittest.TestCase):
budget = make_budget(budget_against="Cost Center")
frappe.db.set_value(
"Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop"
)
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
jv = make_journal_entry(
"_Test Account Cost for Goods Sold - _TC",
@@ -63,9 +61,7 @@ class TestBudget(unittest.TestCase):
budget = make_budget(budget_against="Cost Center")
frappe.db.set_value(
"Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop"
)
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
jv = make_journal_entry(
"_Test Account Cost for Goods Sold - _TC",
@@ -97,9 +93,7 @@ class TestBudget(unittest.TestCase):
)
fiscal_year = get_fiscal_year(nowdate())[0]
frappe.db.set_value(
"Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop"
)
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
frappe.db.set_value("Budget", budget.name, "fiscal_year", fiscal_year)
mr = frappe.get_doc(
@@ -138,9 +132,7 @@ class TestBudget(unittest.TestCase):
)
fiscal_year = get_fiscal_year(nowdate())[0]
frappe.db.set_value(
"Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop"
)
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
frappe.db.set_value("Budget", budget.name, "fiscal_year", fiscal_year)
po = create_purchase_order(transaction_date=nowdate(), do_not_submit=True)
@@ -158,9 +150,7 @@ class TestBudget(unittest.TestCase):
budget = make_budget(budget_against="Project")
frappe.db.set_value(
"Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop"
)
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
project = frappe.get_value("Project", {"project_name": "_Test Project"})
@@ -223,7 +213,7 @@ class TestBudget(unittest.TestCase):
if month > 9:
month = 9
for i in range(month + 1):
for _i in range(month + 1):
jv = make_journal_entry(
"_Test Account Cost for Goods Sold - _TC",
"_Test Bank - _TC",
@@ -237,9 +227,7 @@ class TestBudget(unittest.TestCase):
frappe.db.get_value("GL Entry", {"voucher_type": "Journal Entry", "voucher_no": jv.name})
)
frappe.db.set_value(
"Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop"
)
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
self.assertRaises(BudgetError, jv.cancel)
@@ -255,7 +243,7 @@ class TestBudget(unittest.TestCase):
month = 9
project = frappe.get_value("Project", {"project_name": "_Test Project"})
for i in range(month + 1):
for _i in range(month + 1):
jv = make_journal_entry(
"_Test Account Cost for Goods Sold - _TC",
"_Test Bank - _TC",
@@ -270,9 +258,7 @@ class TestBudget(unittest.TestCase):
frappe.db.get_value("GL Entry", {"voucher_type": "Journal Entry", "voucher_no": jv.name})
)
frappe.db.set_value(
"Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop"
)
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
self.assertRaises(BudgetError, jv.cancel)
@@ -284,9 +270,7 @@ class TestBudget(unittest.TestCase):
set_total_expense_zero(nowdate(), "cost_center", "_Test Cost Center 2 - _TC")
budget = make_budget(budget_against="Cost Center", cost_center="_Test Company - _TC")
frappe.db.set_value(
"Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop"
)
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
jv = make_journal_entry(
"_Test Account Cost for Goods Sold - _TC",
@@ -316,9 +300,7 @@ class TestBudget(unittest.TestCase):
).insert(ignore_permissions=True)
budget = make_budget(budget_against="Cost Center", cost_center=cost_center)
frappe.db.set_value(
"Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop"
)
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
jv = make_journal_entry(
"_Test Account Cost for Goods Sold - _TC",
@@ -423,13 +405,11 @@ def make_budget(**args):
fiscal_year = get_fiscal_year(nowdate())[0]
if budget_against == "Project":
project_name = "{0}%".format("_Test Project/" + fiscal_year)
project_name = "{}%".format("_Test Project/" + fiscal_year)
budget_list = frappe.get_all("Budget", fields=["name"], filters={"name": ("like", project_name)})
else:
cost_center_name = "{0}%".format(cost_center or "_Test Cost Center - _TC/" + fiscal_year)
budget_list = frappe.get_all(
"Budget", fields=["name"], filters={"name": ("like", cost_center_name)}
)
cost_center_name = "{}%".format(cost_center or "_Test Cost Center - _TC/" + fiscal_year)
budget_list = frappe.get_all("Budget", fields=["name"], filters={"name": ("like", cost_center_name)})
for d in budget_list:
frappe.db.sql("delete from `tabBudget` where name = %(name)s", d)
frappe.db.sql("delete from `tabBudget Account` where parent = %(name)s", d)
@@ -451,24 +431,18 @@ def make_budget(**args):
budget.action_if_annual_budget_exceeded = "Stop"
budget.action_if_accumulated_monthly_budget_exceeded = "Ignore"
budget.budget_against = budget_against
budget.append(
"accounts", {"account": "_Test Account Cost for Goods Sold - _TC", "budget_amount": 200000}
)
budget.append("accounts", {"account": "_Test Account Cost for Goods Sold - _TC", "budget_amount": 200000})
if args.applicable_on_material_request:
budget.applicable_on_material_request = 1
budget.action_if_annual_budget_exceeded_on_mr = (
args.action_if_annual_budget_exceeded_on_mr or "Warn"
)
budget.action_if_annual_budget_exceeded_on_mr = args.action_if_annual_budget_exceeded_on_mr or "Warn"
budget.action_if_accumulated_monthly_budget_exceeded_on_mr = (
args.action_if_accumulated_monthly_budget_exceeded_on_mr or "Warn"
)
if args.applicable_on_purchase_order:
budget.applicable_on_purchase_order = 1
budget.action_if_annual_budget_exceeded_on_po = (
args.action_if_annual_budget_exceeded_on_po or "Warn"
)
budget.action_if_annual_budget_exceeded_on_po = args.action_if_annual_budget_exceeded_on_po or "Warn"
budget.action_if_accumulated_monthly_budget_exceeded_on_po = (
args.action_if_accumulated_monthly_budget_exceeded_on_po or "Warn"
)

View File

@@ -1,94 +1,42 @@
{
"allow_copy": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
"creation": "2016-05-16 11:54:09.286135",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "",
"editable_grid": 1,
"engine": "InnoDB",
"actions": [],
"creation": "2016-05-16 11:54:09.286135",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"account",
"budget_amount"
],
"fields": [
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "account",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Account",
"length": 0,
"no_copy": 0,
"options": "Account",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
"fieldname": "account",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Account",
"options": "Account",
"reqd": 1,
"search_index": 1
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "budget_amount",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Budget Amount",
"length": 0,
"no_copy": 0,
"options": "Company:company:default_currency",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
"fieldname": "budget_amount",
"fieldtype": "Currency",
"in_list_view": 1,
"label": "Budget Amount",
"options": "Company:company:default_currency",
"reqd": 1
}
],
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2017-01-02 17:02:53.339420",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Budget Account",
"name_case": "",
"owner": "Administrator",
"permissions": [],
"quick_entry": 1,
"read_only": 0,
"read_only_onload": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_seen": 0
],
"istable": 1,
"links": [],
"modified": "2024-03-04 15:43:27.016947",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Budget Account",
"owner": "Administrator",
"permissions": [],
"quick_entry": 1,
"sort_field": "modified",
"sort_order": "DESC",
"states": []
}

View File

@@ -1,6 +1,4 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Cash Flow Mapper', {
});
frappe.ui.form.on("Cash Flow Mapper", {});

View File

@@ -1,43 +1,45 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Cash Flow Mapping', {
refresh: function(frm) {
frappe.ui.form.on("Cash Flow Mapping", {
refresh: function (frm) {
frm.events.disable_unchecked_fields(frm);
},
reset_check_fields: function(frm) {
frm.fields.filter(field => field.df.fieldtype === 'Check')
.map(field => frm.set_df_property(field.df.fieldname, 'read_only', 0));
reset_check_fields: function (frm) {
frm.fields
.filter((field) => field.df.fieldtype === "Check")
.map((field) => frm.set_df_property(field.df.fieldname, "read_only", 0));
},
has_checked_field(frm) {
const val = frm.fields.filter(field => field.value === 1);
const val = frm.fields.filter((field) => field.value === 1);
return val.length ? 1 : 0;
},
_disable_unchecked_fields: function(frm) {
_disable_unchecked_fields: function (frm) {
// get value of clicked field
frm.fields.filter(field => field.value === 0)
.map(field => frm.set_df_property(field.df.fieldname, 'read_only', 1));
frm.fields
.filter((field) => field.value === 0)
.map((field) => frm.set_df_property(field.df.fieldname, "read_only", 1));
},
disable_unchecked_fields: function(frm) {
disable_unchecked_fields: function (frm) {
frm.events.reset_check_fields(frm);
const checked = frm.events.has_checked_field(frm);
if (checked) {
frm.events._disable_unchecked_fields(frm);
}
},
is_working_capital: function(frm) {
is_working_capital: function (frm) {
frm.events.disable_unchecked_fields(frm);
},
is_finance_cost: function(frm) {
is_finance_cost: function (frm) {
frm.events.disable_unchecked_fields(frm);
},
is_income_tax_liability: function(frm) {
is_income_tax_liability: function (frm) {
frm.events.disable_unchecked_fields(frm);
},
is_income_tax_expense: function(frm) {
is_income_tax_expense: function (frm) {
frm.events.disable_unchecked_fields(frm);
},
is_finance_cost_adjustment: function(frm) {
is_finance_cost_adjustment: function (frm) {
frm.events.disable_unchecked_fields(frm);
}
},
});

View File

@@ -1,6 +1,4 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Cash Flow Mapping Template', {
});
frappe.ui.form.on("Cash Flow Mapping Template", {});

View File

@@ -1,6 +1,4 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Cash Flow Mapping Template Details', {
});
frappe.ui.form.on("Cash Flow Mapping Template Details", {});

View File

@@ -1,11 +1,10 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
frappe.ui.form.on('Cashier Closing', {
setup: function(frm){
frappe.ui.form.on("Cashier Closing", {
setup: function (frm) {
if (frm.doc.user == "" || frm.doc.user == null) {
frm.doc.user = frappe.session.user;
}
}
},
});

View File

@@ -1,4 +1,4 @@
frappe.ui.form.on('Chart of Accounts Importer', {
frappe.ui.form.on("Chart of Accounts Importer", {
onload: function (frm) {
frm.set_value("company", "");
frm.set_value("import_file", "");
@@ -8,31 +8,34 @@ frappe.ui.form.on('Chart of Accounts Importer', {
frm.disable_save();
// make company mandatory
frm.set_df_property('company', 'reqd', frm.doc.company ? 0 : 1);
frm.set_df_property('import_file_section', 'hidden', frm.doc.company ? 0 : 1);
frm.set_df_property("company", "reqd", frm.doc.company ? 0 : 1);
frm.set_df_property("import_file_section", "hidden", frm.doc.company ? 0 : 1);
if (frm.doc.import_file) {
frappe.run_serially([
() => generate_tree_preview(frm),
() => create_import_button(frm),
() => frm.set_df_property('chart_preview', 'hidden', 0)
() => frm.set_df_property("chart_preview", "hidden", 0),
]);
}
frm.set_df_property('chart_preview', 'hidden',
$(frm.fields_dict['chart_tree'].wrapper).html()!="" ? 0 : 1);
frm.set_df_property(
"chart_preview",
"hidden",
$(frm.fields_dict["chart_tree"].wrapper).html() != "" ? 0 : 1
);
},
download_template: function(frm) {
download_template: function (frm) {
var d = new frappe.ui.Dialog({
title: __("Download Template"),
fields: [
{
label : "File Type",
label: "File Type",
fieldname: "file_type",
fieldtype: "Select",
reqd: 1,
options: ["Excel", "CSV"]
options: ["Excel", "CSV"],
},
{
label: "Template Type",
@@ -41,21 +44,27 @@ frappe.ui.form.on('Chart of Accounts Importer', {
reqd: 1,
options: ["Sample Template", "Blank Template"],
change: () => {
let template_type = d.get_value('template_type');
let template_type = d.get_value("template_type");
if (template_type === "Sample Template") {
d.set_df_property('template_type', 'description',
d.set_df_property(
"template_type",
"description",
`The Sample Template contains all the required accounts pre filled in the template.
You can add more accounts or change existing accounts in the template as per your choice.`);
You can add more accounts or change existing accounts in the template as per your choice.`
);
} else {
d.set_df_property('template_type', 'description',
d.set_df_property(
"template_type",
"description",
`The Blank Template contains just the account type and root type required to build the Chart
of Accounts. Please enter the account names and add more rows as per your requirement.`);
of Accounts. Please enter the account names and add more rows as per your requirement.`
);
}
}
},
},
{
label : "Company",
label: "Company",
fieldname: "company",
fieldtype: "Link",
reqd: 1,
@@ -63,25 +72,25 @@ frappe.ui.form.on('Chart of Accounts Importer', {
default: frm.doc.company,
},
],
primary_action: function() {
primary_action: function () {
let data = d.get_values();
if (!data.template_type) {
frappe.throw(__('Please select <b>Template Type</b> to download template'));
frappe.throw(__("Please select <b>Template Type</b> to download template"));
}
open_url_post(
'/api/method/erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.download_template',
"/api/method/erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.download_template",
{
file_type: data.file_type,
template_type: data.template_type,
company: data.company
company: data.company,
}
);
d.hide();
},
primary_action_label: __('Download')
primary_action_label: __("Download"),
});
d.show();
},
@@ -89,7 +98,7 @@ frappe.ui.form.on('Chart of Accounts Importer', {
import_file: function (frm) {
if (!frm.doc.import_file) {
frm.page.set_indicator("");
$(frm.fields_dict['chart_tree'].wrapper).empty(); // empty wrapper on removing file
$(frm.fields_dict["chart_tree"].wrapper).empty(); // empty wrapper on removing file
}
},
@@ -99,89 +108,97 @@ frappe.ui.form.on('Chart of Accounts Importer', {
frappe.call({
method: "erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.validate_company",
args: {
company: frm.doc.company
company: frm.doc.company,
},
callback: function(r) {
if(r.message===false) {
callback: function (r) {
if (r.message === false) {
frm.set_value("company", "");
frappe.throw(__("Transactions against the Company already exist! Chart of Accounts can only be imported for a Company with no transactions."));
frappe.throw(
__(
"Transactions against the Company already exist! Chart of Accounts can only be imported for a Company with no transactions."
)
);
} else {
frm.trigger("refresh");
}
}
},
});
}
}
},
});
var create_import_button = function(frm) {
frm.page.set_primary_action(__("Import"), function () {
var create_import_button = function (frm) {
frm.page
.set_primary_action(__("Import"), function () {
return frappe.call({
method: "erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.import_coa",
args: {
file_name: frm.doc.import_file,
company: frm.doc.company,
},
freeze: true,
freeze_message: __("Creating Accounts..."),
callback: function (r) {
if (!r.exc) {
clearInterval(frm.page["interval"]);
frm.page.set_indicator(__("Import Successful"), "blue");
create_reset_button(frm);
}
},
});
})
.addClass("btn btn-primary");
};
var create_reset_button = function (frm) {
frm.page
.set_primary_action(__("Reset"), function () {
frm.page.clear_primary_action();
delete frm.page["show_import_button"];
frm.reload_doc();
})
.addClass("btn btn-primary");
};
var validate_coa = function (frm) {
if (frm.doc.import_file) {
let parent = __("All Accounts");
return frappe.call({
method: "erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.import_coa",
method: "erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.get_coa",
args: {
file_name: frm.doc.import_file,
company: frm.doc.company
},
freeze: true,
freeze_message: __("Creating Accounts..."),
callback: function(r) {
if (!r.exc) {
clearInterval(frm.page["interval"]);
frm.page.set_indicator(__('Import Successful'), 'blue');
create_reset_button(frm);
}
}
});
}).addClass('btn btn-primary');
};
var create_reset_button = function(frm) {
frm.page.set_primary_action(__("Reset"), function () {
frm.page.clear_primary_action();
delete frm.page["show_import_button"];
frm.reload_doc();
}).addClass('btn btn-primary');
};
var validate_coa = function(frm) {
if (frm.doc.import_file) {
let parent = __('All Accounts');
return frappe.call({
'method': 'erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.get_coa',
'args': {
file_name: frm.doc.import_file,
parent: parent,
doctype: 'Chart of Accounts Importer',
doctype: "Chart of Accounts Importer",
file_type: frm.doc.file_type,
for_validate: 1
for_validate: 1,
},
callback: function(r) {
if (r.message['show_import_button']) {
frm.page['show_import_button'] = Boolean(r.message['show_import_button']);
callback: function (r) {
if (r.message["show_import_button"]) {
frm.page["show_import_button"] = Boolean(r.message["show_import_button"]);
}
}
},
});
}
};
var generate_tree_preview = function(frm) {
let parent = __('All Accounts');
$(frm.fields_dict['chart_tree'].wrapper).empty(); // empty wrapper to load new data
var generate_tree_preview = function (frm) {
let parent = __("All Accounts");
$(frm.fields_dict["chart_tree"].wrapper).empty(); // empty wrapper to load new data
// generate tree structure based on the csv data
return new frappe.ui.Tree({
parent: $(frm.fields_dict['chart_tree'].wrapper),
parent: $(frm.fields_dict["chart_tree"].wrapper),
label: parent,
expandable: true,
method: 'erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.get_coa',
method: "erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.get_coa",
args: {
file_name: frm.doc.import_file,
parent: parent,
doctype: 'Chart of Accounts Importer',
file_type: frm.doc.file_type
doctype: "Chart of Accounts Importer",
file_type: frm.doc.file_type,
},
onclick: function(node) {
onclick: function (node) {
parent = node.value;
}
},
});
};

View File

@@ -26,9 +26,7 @@ from erpnext.accounts.doctype.account.chart_of_accounts.chart_of_accounts import
class ChartofAccountsImporter(Document):
def validate(self):
if self.import_file:
get_coa(
"Chart of Accounts Importer", "All Accounts", file_name=self.import_file, for_validate=1
)
get_coa("Chart of Accounts Importer", "All Accounts", file_name=self.import_file, for_validate=1)
def validate_columns(data):
@@ -104,7 +102,7 @@ def generate_data_from_csv(file_doc, as_dict=False):
file_path = file_doc.get_full_path()
data = []
with open(file_path, "r") as in_file:
with open(file_path) as in_file:
csv_reader = list(csv.reader(in_file))
headers = csv_reader[0]
del csv_reader[0] # delete top row and headers row
@@ -203,10 +201,10 @@ def build_forest(data):
for row in data:
account_name, parent_account, account_number, parent_account_number = row[0:4]
if account_number:
account_name = "{} - {}".format(account_number, account_name)
account_name = f"{account_number} - {account_name}"
if parent_account_number:
parent_account_number = cstr(parent_account_number).strip()
parent_account = "{} - {}".format(parent_account_number, parent_account)
parent_account = f"{parent_account_number} - {parent_account}"
if parent_account == account_name == child:
return [parent_account]
@@ -218,7 +216,7 @@ def build_forest(data):
frappe.bold(parent_account)
)
)
return [child] + parent_account_list
return [child, *parent_account_list]
charts_map, paths = {}, []
@@ -238,12 +236,12 @@ def build_forest(data):
) = i
if not account_name:
error_messages.append("Row {0}: Please enter Account Name".format(line_no))
error_messages.append(f"Row {line_no}: Please enter Account Name")
name = account_name
if account_number:
account_number = cstr(account_number).strip()
account_name = "{} - {}".format(account_number, account_name)
account_name = f"{account_number} - {account_name}"
charts_map[account_name] = {}
charts_map[account_name]["account_name"] = name
@@ -340,9 +338,9 @@ def get_template(template_type, company):
def get_sample_template(writer, company):
currency = frappe.db.get_value("Company", company, "default_currency")
with open(os.path.join(os.path.dirname(__file__), "coa_sample_template.csv"), "r") as f:
with open(os.path.join(os.path.dirname(__file__), "coa_sample_template.csv")) as f:
for row in f:
row = row.strip().split(",") + [currency]
row = [*row.strip().split(","), currency]
writer.writerow(row)
return writer
@@ -451,7 +449,7 @@ def unset_existing_data(company):
"Purchase Taxes and Charges Template",
]:
frappe.db.sql(
'''delete from `tab{0}` where `company`="%s"'''.format(doctype) % (company) # nosec
f'''delete from `tab{doctype}` where `company`="%s"''' % (company) # nosec
)

View File

@@ -3,18 +3,20 @@
frappe.provide("erpnext.cheque_print");
frappe.ui.form.on('Cheque Print Template', {
refresh: function(frm) {
if(!frm.doc.__islocal) {
frm.add_custom_button(frm.doc.has_print_format?__("Update Print Format"):__("Create Print Format"),
function() {
frappe.ui.form.on("Cheque Print Template", {
refresh: function (frm) {
if (!frm.doc.__islocal) {
frm.add_custom_button(
frm.doc.has_print_format ? __("Update Print Format") : __("Create Print Format"),
function () {
erpnext.cheque_print.view_cheque_print(frm);
}).addClass("btn-primary");
}
).addClass("btn-primary");
$(frm.fields_dict.cheque_print_preview.wrapper).empty()
$(frm.fields_dict.cheque_print_preview.wrapper).empty();
var template = '<div style="position: relative; overflow-x: scroll;">\
var template =
'<div style="position: relative; overflow-x: scroll;">\
<div id="cheque_preview" style="width: {{ cheque_width }}cm; \
height: {{ cheque_height }}cm;\
background-repeat: no-repeat;\
@@ -48,30 +50,30 @@ frappe.ui.form.on('Cheque Print Template', {
</div>\
</div>';
$(frappe.render(template, frm.doc)).appendTo(frm.fields_dict.cheque_print_preview.wrapper)
$(frappe.render(template, frm.doc)).appendTo(frm.fields_dict.cheque_print_preview.wrapper);
if (frm.doc.scanned_cheque) {
$(frm.fields_dict.cheque_print_preview.wrapper).find("#cheque_preview").css('background-image', 'url(' + frm.doc.scanned_cheque + ')');
$(frm.fields_dict.cheque_print_preview.wrapper)
.find("#cheque_preview")
.css("background-image", "url(" + frm.doc.scanned_cheque + ")");
}
}
}
},
});
erpnext.cheque_print.view_cheque_print = function(frm) {
erpnext.cheque_print.view_cheque_print = function (frm) {
frappe.call({
method: "erpnext.accounts.doctype.cheque_print_template.cheque_print_template.create_or_update_cheque_print_format",
args:{
"template_name": frm.doc.name
args: {
template_name: frm.doc.name,
},
callback: function(r) {
callback: function (r) {
if (!r.exe && !frm.doc.has_print_format) {
var doc = frappe.model.sync(r.message);
frappe.set_route("Form", r.message.doctype, r.message.name);
} else {
frappe.msgprint(__("Print settings updated in respective print format"));
}
else {
frappe.msgprint(__("Print settings updated in respective print format"))
}
}
})
}
},
});
};

View File

@@ -31,71 +31,71 @@ def create_or_update_cheque_print_format(template_name):
cheque_print.html = """
<style>
.print-format {
.print-format {{
padding: 0px;
}
@media screen {
.print-format {
}}
@media screen {{
.print-format {{
padding: 0in;
}
}
}}
}}
</style>
<div style="position: relative; top:%(starting_position_from_top_edge)scm">
<div style="width:%(cheque_width)scm;height:%(cheque_height)scm;">
<span style="top:%(acc_pay_dist_from_top_edge)scm; left:%(acc_pay_dist_from_left_edge)scm;
<div style="position: relative; top:{starting_position_from_top_edge}cm">
<div style="width:{cheque_width}cm;height:{cheque_height}cm;">
<span style="top:{acc_pay_dist_from_top_edge}cm; left:{acc_pay_dist_from_left_edge}cm;
border-bottom: solid 1px;border-top:solid 1px; width:2cm;text-align: center; position: absolute;">
%(message_to_show)s
{message_to_show}
</span>
<span style="top:%(date_dist_from_top_edge)scm; left:%(date_dist_from_left_edge)scm;
<span style="top:{date_dist_from_top_edge}cm; left:{date_dist_from_left_edge}cm;
position: absolute;">
{{ frappe.utils.formatdate(doc.reference_date) or '' }}
{{{{ frappe.utils.formatdate(doc.reference_date) or '' }}}}
</span>
<span style="top:%(acc_no_dist_from_top_edge)scm;left:%(acc_no_dist_from_left_edge)scm;
<span style="top:{acc_no_dist_from_top_edge}cm;left:{acc_no_dist_from_left_edge}cm;
position: absolute; min-width: 6cm;">
{{ doc.account_no or '' }}
{{{{ doc.account_no or '' }}}}
</span>
<span style="top:%(payer_name_from_top_edge)scm;left: %(payer_name_from_left_edge)scm;
<span style="top:{payer_name_from_top_edge}cm;left: {payer_name_from_left_edge}cm;
position: absolute; min-width: 6cm;">
{{doc.party_name}}
{{{{doc.party_name}}}}
</span>
<span style="top:%(amt_in_words_from_top_edge)scm; left:%(amt_in_words_from_left_edge)scm;
position: absolute; display: block; width: %(amt_in_word_width)scm;
line-height:%(amt_in_words_line_spacing)scm; word-wrap: break-word;">
{{frappe.utils.money_in_words(doc.base_paid_amount or doc.base_received_amount)}}
<span style="top:{amt_in_words_from_top_edge}cm; left:{amt_in_words_from_left_edge}cm;
position: absolute; display: block; width: {amt_in_word_width}cm;
line-height:{amt_in_words_line_spacing}cm; word-wrap: break-word;">
{{{{frappe.utils.money_in_words(doc.base_paid_amount or doc.base_received_amount)}}}}
</span>
<span style="top:%(amt_in_figures_from_top_edge)scm;left: %(amt_in_figures_from_left_edge)scm;
<span style="top:{amt_in_figures_from_top_edge}cm;left: {amt_in_figures_from_left_edge}cm;
position: absolute; min-width: 4cm;">
{{doc.get_formatted("base_paid_amount") or doc.get_formatted("base_received_amount")}}
{{{{doc.get_formatted("base_paid_amount") or doc.get_formatted("base_received_amount")}}}}
</span>
<span style="top:%(signatory_from_top_edge)scm;left: %(signatory_from_left_edge)scm;
<span style="top:{signatory_from_top_edge}cm;left: {signatory_from_left_edge}cm;
position: absolute; min-width: 6cm;">
{{doc.company}}
{{{{doc.company}}}}
</span>
</div>
</div>""" % {
"starting_position_from_top_edge": doc.starting_position_from_top_edge
</div>""".format(
starting_position_from_top_edge=doc.starting_position_from_top_edge
if doc.cheque_size == "A4"
else 0.0,
"cheque_width": doc.cheque_width,
"cheque_height": doc.cheque_height,
"acc_pay_dist_from_top_edge": doc.acc_pay_dist_from_top_edge,
"acc_pay_dist_from_left_edge": doc.acc_pay_dist_from_left_edge,
"message_to_show": doc.message_to_show if doc.message_to_show else _("Account Pay Only"),
"date_dist_from_top_edge": doc.date_dist_from_top_edge,
"date_dist_from_left_edge": doc.date_dist_from_left_edge,
"acc_no_dist_from_top_edge": doc.acc_no_dist_from_top_edge,
"acc_no_dist_from_left_edge": doc.acc_no_dist_from_left_edge,
"payer_name_from_top_edge": doc.payer_name_from_top_edge,
"payer_name_from_left_edge": doc.payer_name_from_left_edge,
"amt_in_words_from_top_edge": doc.amt_in_words_from_top_edge,
"amt_in_words_from_left_edge": doc.amt_in_words_from_left_edge,
"amt_in_word_width": doc.amt_in_word_width,
"amt_in_words_line_spacing": doc.amt_in_words_line_spacing,
"amt_in_figures_from_top_edge": doc.amt_in_figures_from_top_edge,
"amt_in_figures_from_left_edge": doc.amt_in_figures_from_left_edge,
"signatory_from_top_edge": doc.signatory_from_top_edge,
"signatory_from_left_edge": doc.signatory_from_left_edge,
}
cheque_width=doc.cheque_width,
cheque_height=doc.cheque_height,
acc_pay_dist_from_top_edge=doc.acc_pay_dist_from_top_edge,
acc_pay_dist_from_left_edge=doc.acc_pay_dist_from_left_edge,
message_to_show=doc.message_to_show if doc.message_to_show else _("Account Pay Only"),
date_dist_from_top_edge=doc.date_dist_from_top_edge,
date_dist_from_left_edge=doc.date_dist_from_left_edge,
acc_no_dist_from_top_edge=doc.acc_no_dist_from_top_edge,
acc_no_dist_from_left_edge=doc.acc_no_dist_from_left_edge,
payer_name_from_top_edge=doc.payer_name_from_top_edge,
payer_name_from_left_edge=doc.payer_name_from_left_edge,
amt_in_words_from_top_edge=doc.amt_in_words_from_top_edge,
amt_in_words_from_left_edge=doc.amt_in_words_from_left_edge,
amt_in_word_width=doc.amt_in_word_width,
amt_in_words_line_spacing=doc.amt_in_words_line_spacing,
amt_in_figures_from_top_edge=doc.amt_in_figures_from_top_edge,
amt_in_figures_from_left_edge=doc.amt_in_figures_from_left_edge,
signatory_from_top_edge=doc.signatory_from_top_edge,
signatory_from_left_edge=doc.signatory_from_left_edge,
)
cheque_print.save(ignore_permissions=True)

View File

@@ -3,75 +3,80 @@
frappe.provide("erpnext.accounts");
frappe.ui.form.on('Cost Center', {
onload: function(frm) {
frm.set_query("parent_cost_center", function() {
frappe.ui.form.on("Cost Center", {
onload: function (frm) {
frm.set_query("parent_cost_center", function () {
return {
filters: {
company: frm.doc.company,
is_group: 1
}
}
is_group: 1,
},
};
});
},
refresh: function(frm) {
refresh: function (frm) {
if (!frm.is_new()) {
frm.add_custom_button(__('Update Cost Center Name / Number'), function () {
frm.add_custom_button(__("Update Cost Center Name / Number"), function () {
frm.trigger("update_cost_center_number");
});
}
let intro_txt = '';
let intro_txt = "";
let doc = frm.doc;
frm.toggle_display('cost_center_name', doc.__islocal);
frm.toggle_enable(['is_group', 'company'], doc.__islocal);
frm.toggle_display("cost_center_name", doc.__islocal);
frm.toggle_enable(["is_group", "company"], doc.__islocal);
if(!doc.__islocal && doc.is_group==1) {
intro_txt += __('Note: This Cost Center is a Group. Cannot make accounting entries against groups.');
if (!doc.__islocal && doc.is_group == 1) {
intro_txt += __(
"Note: This Cost Center is a Group. Cannot make accounting entries against groups."
);
}
frm.events.hide_unhide_group_ledger(frm);
frm.toggle_display('sb1', doc.is_group==0);
frm.toggle_display("sb1", doc.is_group == 0);
frm.set_intro(intro_txt);
if(!frm.doc.__islocal) {
frm.add_custom_button(__('Chart of Cost Centers'),
function() { frappe.set_route("Tree", "Cost Center"); });
if (!frm.doc.__islocal) {
frm.add_custom_button(__("Chart of Cost Centers"), function () {
frappe.set_route("Tree", "Cost Center");
});
frm.add_custom_button(__('Budget'),
function() { frappe.set_route("List", "Budget", {'cost_center': frm.doc.name}); });
frm.add_custom_button(__("Budget"), function () {
frappe.set_route("List", "Budget", { cost_center: frm.doc.name });
});
}
},
update_cost_center_number: function(frm) {
update_cost_center_number: function (frm) {
var d = new frappe.ui.Dialog({
title: __('Update Cost Center Name / Number'),
title: __("Update Cost Center Name / Number"),
fields: [
{
"label": "Cost Center Name",
"fieldname": "cost_center_name",
"fieldtype": "Data",
"reqd": 1,
"default": frm.doc.cost_center_name
label: "Cost Center Name",
fieldname: "cost_center_name",
fieldtype: "Data",
reqd: 1,
default: frm.doc.cost_center_name,
},
{
"label": "Cost Center Number",
"fieldname": "cost_center_number",
"fieldtype": "Data",
"default": frm.doc.cost_center_number
label: "Cost Center Number",
fieldname: "cost_center_number",
fieldtype: "Data",
default: frm.doc.cost_center_number,
},
{
"label": __("Merge with existing"),
"fieldname": "merge",
"fieldtype": "Check",
"default": 0
}
label: __("Merge with existing"),
fieldname: "merge",
fieldtype: "Check",
default: 0,
},
],
primary_action: function() {
primary_action: function () {
var data = d.get_values();
if(data.cost_center_name === frm.doc.cost_center_name && data.cost_center_number === frm.doc.cost_center_number) {
if (
data.cost_center_name === frm.doc.cost_center_name &&
data.cost_center_number === frm.doc.cost_center_number
) {
d.hide();
return;
}
@@ -83,12 +88,12 @@ frappe.ui.form.on('Cost Center', {
cost_center_name: data.cost_center_name,
cost_center_number: cstr(data.cost_center_number),
company: frm.doc.company,
merge: data.merge
merge: data.merge,
},
callback: function(r) {
callback: function (r) {
frappe.dom.unfreeze();
if(!r.exc) {
if(r.message) {
if (!r.exc) {
if (r.message) {
frappe.set_route("Form", "Cost Center", r.message);
} else {
me.frm.set_value("cost_center_name", data.cost_center_name);
@@ -96,44 +101,42 @@ frappe.ui.form.on('Cost Center', {
}
d.hide();
}
}
},
});
},
primary_action_label: __('Update')
primary_action_label: __("Update"),
});
d.show();
},
parent_cost_center(frm) {
if(!frm.doc.company) {
frappe.msgprint(__('Please enter company name first'));
if (!frm.doc.company) {
frappe.msgprint(__("Please enter company name first"));
}
},
hide_unhide_group_ledger(frm) {
let doc = frm.doc;
if (doc.is_group == 1) {
frm.add_custom_button(__('Convert to Non-Group'),
() => frm.events.convert_to_ledger(frm));
frm.add_custom_button(__("Convert to Non-Group"), () => frm.events.convert_to_ledger(frm));
} else if (doc.is_group == 0) {
frm.add_custom_button(__('Convert to Group'),
() => frm.events.convert_to_group(frm));
frm.add_custom_button(__("Convert to Group"), () => frm.events.convert_to_group(frm));
}
},
convert_to_group(frm) {
frm.call('convert_ledger_to_group').then(r => {
if(r.message === 1) {
frm.call("convert_ledger_to_group").then((r) => {
if (r.message === 1) {
frm.refresh();
}
});
},
convert_to_ledger(frm) {
frm.call('convert_group_to_ledger').then(r => {
if(r.message === 1) {
frm.call("convert_group_to_ledger").then((r) => {
if (r.message === 1) {
frm.refresh();
}
});
}
},
});

View File

@@ -125,7 +125,7 @@
"idx": 1,
"is_tree": 1,
"links": [],
"modified": "2022-01-31 13:22:58.916273",
"modified": "2024-04-24 10:55:54.083042",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Cost Center",
@@ -163,6 +163,15 @@
{
"read": 1,
"role": "Purchase User"
},
{
"email": 1,
"export": 1,
"print": 1,
"report": 1,
"role": "Employee",
"select": 1,
"share": 1
}
],
"search_fields": "parent_cost_center, is_group",

View File

@@ -15,9 +15,7 @@ class CostCenter(NestedSet):
def autoname(self):
from erpnext.accounts.utils import get_autoname_with_number
self.name = get_autoname_with_number(
self.cost_center_number, self.cost_center_name, self.company
)
self.name = get_autoname_with_number(self.cost_center_number, self.cost_center_name, self.company)
def validate(self):
self.validate_mandatory()
@@ -90,14 +88,14 @@ class CostCenter(NestedSet):
new_cost_center = get_name_with_abbr(newdn, self.company)
# Validate properties before merging
super(CostCenter, self).before_rename(olddn, new_cost_center, merge, "is_group")
super().before_rename(olddn, new_cost_center, merge, "is_group")
if not merge:
new_cost_center = get_name_with_number(new_cost_center, self.cost_center_number)
return new_cost_center
def after_rename(self, olddn, newdn, merge=False):
super(CostCenter, self).after_rename(olddn, newdn, merge)
super().after_rename(olddn, newdn, merge)
if not merge:
new_cost_center = frappe.db.get_value(

View File

@@ -1,54 +1,84 @@
frappe.treeview_settings["Cost Center"] = {
breadcrumb: "Accounts",
get_tree_root: false,
filters: [{
fieldname: "company",
fieldtype:"Select",
options: erpnext.utils.get_tree_options("company"),
label: __("Company"),
default: erpnext.utils.get_tree_default("company")
}],
root_label: "Cost Centers",
get_tree_nodes: 'erpnext.accounts.utils.get_children',
add_tree_node: 'erpnext.accounts.utils.add_cc',
menu_items:[
filters: [
{
label: __('New Company'),
action: function() { frappe.new_doc("Company", true) },
condition: 'frappe.boot.user.can_create.indexOf("Company") !== -1'
}
fieldname: "company",
fieldtype: "Select",
options: erpnext.utils.get_tree_options("company"),
label: __("Company"),
default: erpnext.utils.get_tree_default("company"),
},
],
fields:[
{fieldtype:'Data', fieldname:'cost_center_name', label:__('New Cost Center Name'), reqd:true},
{fieldtype:'Check', fieldname:'is_group', label:__('Is Group'),
description:__('Further cost centers can be made under Groups but entries can be made against non-Groups')},
{fieldtype:'Data', fieldname:'cost_center_number', label:__('Cost Center Number'),
description: __("Number of new Cost Center, it will be included in the cost center name as a prefix")}
root_label: "Cost Centers",
get_tree_nodes: "erpnext.accounts.utils.get_children",
add_tree_node: "erpnext.accounts.utils.add_cc",
menu_items: [
{
label: __("New Company"),
action: function () {
frappe.new_doc("Company", true);
},
condition: 'frappe.boot.user.can_create.indexOf("Company") !== -1',
},
],
ignore_fields:["parent_cost_center"],
onload: function(treeview) {
fields: [
{ fieldtype: "Data", fieldname: "cost_center_name", label: __("New Cost Center Name"), reqd: true },
{
fieldtype: "Check",
fieldname: "is_group",
label: __("Is Group"),
description: __(
"Further cost centers can be made under Groups but entries can be made against non-Groups"
),
},
{
fieldtype: "Data",
fieldname: "cost_center_number",
label: __("Cost Center Number"),
description: __(
"Number of new Cost Center, it will be included in the cost center name as a prefix"
),
},
],
ignore_fields: ["parent_cost_center"],
onload: function (treeview) {
function get_company() {
return treeview.page.fields_dict.company.get_value();
}
// tools
treeview.page.add_inner_button(__("Chart of Accounts"), function() {
frappe.set_route('Tree', 'Account', {company: get_company()});
}, __('View'));
treeview.page.add_inner_button(
__("Chart of Accounts"),
function () {
frappe.set_route("Tree", "Account", { company: get_company() });
},
__("View")
);
// make
treeview.page.add_inner_button(__("Budget List"), function() {
frappe.set_route('List', 'Budget', {company: get_company()});
}, __('Budget'));
treeview.page.add_inner_button(
__("Budget List"),
function () {
frappe.set_route("List", "Budget", { company: get_company() });
},
__("Budget")
);
treeview.page.add_inner_button(__("Monthly Distribution"), function() {
frappe.set_route('List', 'Monthly Distribution', {company: get_company()});
}, __('Budget'));
treeview.page.add_inner_button(
__("Monthly Distribution"),
function () {
frappe.set_route("List", "Monthly Distribution", { company: get_company() });
},
__("Budget")
);
treeview.page.add_inner_button(__("Budget Variance Report"), function() {
frappe.set_route('query-report', 'Budget Variance Report', {company: get_company()});
}, __('Budget'));
}
}
treeview.page.add_inner_button(
__("Budget Variance Report"),
function () {
frappe.set_route("query-report", "Budget Variance Report", { company: get_company() });
},
__("Budget")
);
},
};

View File

@@ -10,7 +10,6 @@ test_records = frappe.get_test_records("Cost Center")
class TestCostCenter(unittest.TestCase):
def test_cost_center_creation_against_child_node(self):
if not frappe.db.get_value("Cost Center", {"name": "_Test Cost Center 2 - _TC"}):
frappe.get_doc(test_records[1]).insert()

View File

@@ -1,19 +1,24 @@
// Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Cost Center Allocation', {
setup: function(frm) {
let filters = {"is_group": 0};
if (frm.doc.company) {
$.extend(filters, {
"company": frm.doc.company
});
}
frm.set_query('main_cost_center', function() {
frappe.ui.form.on("Cost Center Allocation", {
setup: function (frm) {
frm.set_query("main_cost_center", function () {
return {
filters: filters
filters: {
company: frm.doc.company,
is_group: 0,
},
};
});
}
frm.set_query("cost_center", "allocation_percentages", function () {
return {
filters: {
company: frm.doc.company,
is_group: 0,
},
};
});
},
});

View File

@@ -29,7 +29,7 @@ class InvalidDateError(frappe.ValidationError):
class CostCenterAllocation(Document):
def __init__(self, *args, **kwargs):
super(CostCenterAllocation, self).__init__(*args, **kwargs)
super().__init__(*args, **kwargs)
self._skip_from_date_validation = False
def validate(self):
@@ -44,9 +44,7 @@ class CostCenterAllocation(Document):
total_percentage = sum([d.percentage for d in self.get("allocation_percentages", [])])
if total_percentage != 100:
frappe.throw(
_("Total percentage against cost centers should be 100"), WrongPercentageAllocation
)
frappe.throw(_("Total percentage against cost centers should be 100"), WrongPercentageAllocation)
def validate_from_date_based_on_existing_gle(self):
# Check if GLE exists against the main cost center

View File

@@ -1,44 +1,41 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Coupon Code', {
setup: function(frm) {
frm.set_query("pricing_rule", function() {
frappe.ui.form.on("Coupon Code", {
setup: function (frm) {
frm.set_query("pricing_rule", function () {
return {
filters: [
["Pricing Rule","coupon_code_based", "=", "1"]
]
filters: [["Pricing Rule", "coupon_code_based", "=", "1"]],
};
});
},
coupon_name:function(frm){
if (frm.doc.__islocal===1) {
coupon_name: function (frm) {
if (frm.doc.__islocal === 1) {
frm.trigger("make_coupon_code");
}
},
coupon_type:function(frm){
if (frm.doc.__islocal===1) {
coupon_type: function (frm) {
if (frm.doc.__islocal === 1) {
frm.trigger("make_coupon_code");
}
},
make_coupon_code: function(frm) {
var coupon_name=frm.doc.coupon_name;
make_coupon_code: function (frm) {
var coupon_name = frm.doc.coupon_name;
var coupon_code;
if (frm.doc.coupon_type=='Gift Card') {
coupon_code=Math.random().toString(12).substring(2, 12).toUpperCase();
if (frm.doc.coupon_type == "Gift Card") {
coupon_code = Math.random().toString(12).substring(2, 12).toUpperCase();
} else if (frm.doc.coupon_type == "Promotional") {
coupon_name = coupon_name.replace(/\s/g, "");
coupon_code = coupon_name.toUpperCase().slice(0, 8);
}
else if(frm.doc.coupon_type=='Promotional'){
coupon_name=coupon_name.replace(/\s/g,'');
coupon_code=coupon_name.toUpperCase().slice(0,8);
}
frm.doc.coupon_code=coupon_code;
frm.refresh_field('coupon_code');
frm.doc.coupon_code = coupon_code;
frm.refresh_field("coupon_code");
},
refresh: function(frm) {
refresh: function (frm) {
if (frm.doc.pricing_rule) {
frm.add_custom_button(__("Add/Edit Coupon Conditions"), function(){
frm.add_custom_button(__("Add/Edit Coupon Conditions"), function () {
frappe.set_route("Form", "Pricing Rule", frm.doc.pricing_rule);
});
}
}
},
});

View File

@@ -1,28 +1,41 @@
// Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Currency Exchange Settings', {
service_provider: function(frm) {
if (frm.doc.service_provider == "exchangerate.host") {
let result = ['result'];
let params = {
date: '{transaction_date}',
from: '{from_currency}',
to: '{to_currency}'
};
add_param(frm, "https://api.exchangerate.host/convert", params, result);
} else if (frm.doc.service_provider == "frankfurter.app") {
let result = ['rates', '{to_currency}'];
let params = {
base: '{from_currency}',
symbols: '{to_currency}'
};
add_param(frm, "https://frankfurter.app/{transaction_date}", params, result);
}
}
frappe.ui.form.on("Currency Exchange Settings", {
service_provider: function (frm) {
frm.call({
method: "erpnext.accounts.doctype.currency_exchange_settings.currency_exchange_settings.get_api_endpoint",
args: {
service_provider: frm.doc.service_provider,
use_http: frm.doc.use_http,
},
callback: function (r) {
if (r && r.message) {
if (frm.doc.service_provider == "exchangerate.host") {
let result = ["result"];
let params = {
date: "{transaction_date}",
from: "{from_currency}",
to: "{to_currency}",
};
add_param(frm, r.message, params, result);
} else if (frm.doc.service_provider == "frankfurter.app") {
let result = ["rates", "{to_currency}"];
let params = {
base: "{from_currency}",
symbols: "{to_currency}",
};
add_param(frm, r.message, params, result);
}
}
},
});
},
use_http: function (frm) {
frm.trigger("service_provider");
},
});
function add_param(frm, api, params, result) {
var row;
frm.clear_table("req_params");
@@ -30,13 +43,13 @@ function add_param(frm, api, params, result) {
frm.doc.api_endpoint = api;
$.each(params, function(key, value) {
$.each(params, function (key, value) {
row = frm.add_child("req_params");
row.key = key;
row.value = value;
});
$.each(result, function(key, value) {
$.each(result, function (key, value) {
row = frm.add_child("result_key");
row.key = value;
});

View File

@@ -9,6 +9,7 @@
"disabled",
"service_provider",
"api_endpoint",
"use_http",
"access_key",
"url",
"column_break_3",
@@ -91,12 +92,19 @@
"fieldname": "access_key",
"fieldtype": "Data",
"label": "Access Key"
},
{
"default": "0",
"depends_on": "eval: doc.service_provider != \"Custom\"",
"fieldname": "use_http",
"fieldtype": "Check",
"label": "Use HTTP Protocol"
}
],
"index_web_pages_for_search": 1,
"issingle": 1,
"links": [],
"modified": "2023-10-04 15:30:25.333860",
"modified": "2024-03-18 08:32:26.895076",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Currency Exchange Settings",

View File

@@ -18,7 +18,6 @@ class CurrencyExchangeSettings(Document):
def set_parameters_and_result(self):
if self.service_provider == "exchangerate.host":
if not self.access_key:
frappe.throw(
_("Access Key is required for Service Provider: {0}").format(
@@ -29,7 +28,7 @@ class CurrencyExchangeSettings(Document):
self.set("result_key", [])
self.set("req_params", [])
self.api_endpoint = "https://api.exchangerate.host/convert"
self.api_endpoint = get_api_endpoint(self.service_provider, self.use_http)
self.append("result_key", {"key": "result"})
self.append("req_params", {"key": "access_key", "value": self.access_key})
self.append("req_params", {"key": "amount", "value": "1"})
@@ -40,7 +39,7 @@ class CurrencyExchangeSettings(Document):
self.set("result_key", [])
self.set("req_params", [])
self.api_endpoint = "https://frankfurter.app/{transaction_date}"
self.api_endpoint = get_api_endpoint(self.service_provider, self.use_http)
self.append("result_key", {"key": "rates"})
self.append("result_key", {"key": "{to_currency}"})
self.append("req_params", {"key": "base", "value": "{from_currency}"})
@@ -53,9 +52,7 @@ class CurrencyExchangeSettings(Document):
transaction_date=nowdate(), to_currency="INR", from_currency="USD"
)
api_url = self.api_endpoint.format(
transaction_date=nowdate(), to_currency="INR", from_currency="USD"
)
api_url = self.api_endpoint.format(transaction_date=nowdate(), to_currency="INR", from_currency="USD")
try:
response = requests.get(api_url, params=params)
@@ -75,7 +72,23 @@ class CurrencyExchangeSettings(Document):
]
except Exception:
frappe.throw(_("Invalid result key. Response:") + " " + response.text)
if not isinstance(value, (int, float)):
if not isinstance(value, int | float):
frappe.throw(_("Returned exchange rate is neither integer not float."))
self.url = response.url
@frappe.whitelist()
def get_api_endpoint(service_provider: str | None = None, use_http: bool = False):
if service_provider and service_provider in ["exchangerate.host", "frankfurter.app"]:
if service_provider == "exchangerate.host":
api = "api.exchangerate.host/convert"
elif service_provider == "frankfurter.app":
api = "frankfurter.app/{transaction_date}"
protocol = "https://"
if use_http:
protocol = "http://"
return protocol + api
return None

View File

@@ -9,7 +9,7 @@ frappe.ui.form.on("Dunning", {
docstatus: 1,
company: frm.doc.company,
outstanding_amount: [">", 0],
status: "Overdue"
status: "Overdue",
},
};
});
@@ -18,18 +18,14 @@ frappe.ui.form.on("Dunning", {
filters: {
company: frm.doc.company,
root_type: "Income",
is_group: 0
}
is_group: 0,
},
};
});
},
refresh: function (frm) {
frm.set_df_property("company", "read_only", frm.doc.__islocal ? 0 : 1);
frm.set_df_property(
"sales_invoice",
"read_only",
frm.doc.__islocal ? 0 : 1
);
frm.set_df_property("sales_invoice", "read_only", frm.doc.__islocal ? 0 : 1);
if (frm.doc.docstatus === 1 && frm.doc.status === "Unresolved") {
frm.add_custom_button(__("Resolve"), () => {
frm.set_value("status", "Resolved");
@@ -40,22 +36,27 @@ frappe.ui.form.on("Dunning", {
__("Payment"),
function () {
frm.events.make_payment_entry(frm);
},__("Create")
},
__("Create")
);
frm.page.set_inner_btn_group_as_primary(__("Create"));
}
if(frm.doc.docstatus > 0) {
frm.add_custom_button(__('Ledger'), function() {
frappe.route_options = {
"voucher_no": frm.doc.name,
"from_date": frm.doc.posting_date,
"to_date": frm.doc.posting_date,
"company": frm.doc.company,
"show_cancelled_entries": frm.doc.docstatus === 2
};
frappe.set_route("query-report", "General Ledger");
}, __('View'));
if (frm.doc.docstatus > 0) {
frm.add_custom_button(
__("Ledger"),
function () {
frappe.route_options = {
voucher_no: frm.doc.name,
from_date: frm.doc.posting_date,
to_date: frm.doc.posting_date,
company: frm.doc.company,
show_cancelled_entries: frm.doc.docstatus === 2,
};
frappe.set_route("query-report", "General Ledger");
},
__("View")
);
}
},
overdue_days: function (frm) {
@@ -86,8 +87,7 @@ frappe.ui.form.on("Dunning", {
get_dunning_letter_text: function (frm) {
if (frm.doc.dunning_type) {
frappe.call({
method:
"erpnext.accounts.doctype.dunning.dunning.get_dunning_letter_text",
method: "erpnext.accounts.doctype.dunning.dunning.get_dunning_letter_text",
args: {
dunning_type: frm.doc.dunning_type,
language: frm.doc.language,
@@ -129,26 +129,25 @@ frappe.ui.form.on("Dunning", {
},
calculate_overdue_days: function (frm) {
if (frm.doc.posting_date && frm.doc.due_date) {
const overdue_days = moment(frm.doc.posting_date).diff(
frm.doc.due_date,
"days"
);
const overdue_days = moment(frm.doc.posting_date).diff(frm.doc.due_date, "days");
frm.set_value("overdue_days", overdue_days);
}
},
calculate_interest_and_amount: function (frm) {
const interest_per_year = frm.doc.outstanding_amount * frm.doc.rate_of_interest / 100;
const interest_amount = flt((interest_per_year * cint(frm.doc.overdue_days)) / 365 || 0, precision('interest_amount'));
const dunning_amount = flt(interest_amount + frm.doc.dunning_fee, precision('dunning_amount'));
const grand_total = flt(frm.doc.outstanding_amount + dunning_amount, precision('grand_total'));
const interest_per_year = (frm.doc.outstanding_amount * frm.doc.rate_of_interest) / 100;
const interest_amount = flt(
(interest_per_year * cint(frm.doc.overdue_days)) / 365 || 0,
precision("interest_amount")
);
const dunning_amount = flt(interest_amount + frm.doc.dunning_fee, precision("dunning_amount"));
const grand_total = flt(frm.doc.outstanding_amount + dunning_amount, precision("grand_total"));
frm.set_value("interest_amount", interest_amount);
frm.set_value("dunning_amount", dunning_amount);
frm.set_value("grand_total", grand_total);
},
make_payment_entry: function (frm) {
return frappe.call({
method:
"erpnext.accounts.doctype.payment_entry.payment_entry.get_payment_entry",
method: "erpnext.accounts.doctype.payment_entry.payment_entry.get_payment_entry",
args: {
dt: frm.doc.doctype,
dn: frm.doc.name,

View File

@@ -1,8 +1,7 @@
// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Dunning Type', {
frappe.ui.form.on("Dunning Type", {
// refresh: function(frm) {
// }
});

View File

@@ -1,75 +1,79 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Exchange Rate Revaluation', {
setup: function(frm) {
frm.set_query("party_type", "accounts", function() {
frappe.ui.form.on("Exchange Rate Revaluation", {
setup: function (frm) {
frm.set_query("party_type", "accounts", function () {
return {
"filters": {
"name": ["in", Object.keys(frappe.boot.party_account_types)],
}
filters: {
name: ["in", Object.keys(frappe.boot.party_account_types)],
},
};
});
frm.set_query("account", "accounts", function(doc) {
frm.set_query("account", "accounts", function (doc) {
return {
"filters": {
"company": doc.company
}
filters: {
company: doc.company,
},
};
});
},
refresh: function(frm) {
if(frm.doc.docstatus==1) {
refresh: function (frm) {
if (frm.doc.docstatus == 1) {
frappe.call({
method: 'check_journal_entry_condition',
method: "check_journal_entry_condition",
doc: frm.doc,
callback: function(r) {
callback: function (r) {
if (r.message) {
frm.add_custom_button(__('Journal Entries'), function() {
return frm.events.make_jv(frm);
}, __('Create'));
frm.add_custom_button(
__("Journal Entries"),
function () {
return frm.events.make_jv(frm);
},
__("Create")
);
}
}
},
});
}
},
validate_rounding_loss: function(frm) {
validate_rounding_loss: function (frm) {
let allowance = frm.doc.rounding_loss_allowance;
if (!(allowance >= 0 && allowance < 1)) {
frappe.throw(__("Rounding Loss Allowance should be between 0 and 1"));
}
},
rounding_loss_allowance: function(frm) {
rounding_loss_allowance: function (frm) {
frm.events.validate_rounding_loss(frm);
},
validate: function(frm) {
validate: function (frm) {
frm.events.validate_rounding_loss(frm);
},
get_entries: function(frm, account) {
get_entries: function (frm, account) {
frappe.call({
method: "get_accounts_data",
doc: cur_frm.doc,
account: account,
callback: function(r){
callback: function (r) {
frappe.model.clear_table(frm.doc, "accounts");
if(r.message) {
if (r.message) {
r.message.forEach((d) => {
cur_frm.add_child("accounts",d);
cur_frm.add_child("accounts", d);
});
frm.events.get_total_gain_loss(frm);
refresh_field("accounts");
}
}
},
});
},
get_total_gain_loss: function(frm) {
if(!(frm.doc.accounts && frm.doc.accounts.length)) return;
get_total_gain_loss: function (frm) {
if (!(frm.doc.accounts && frm.doc.accounts.length)) return;
let total_gain_loss = 0;
frm.doc.accounts.forEach((d) => {
@@ -80,7 +84,7 @@ frappe.ui.form.on('Exchange Rate Revaluation', {
frm.refresh_fields();
},
make_jv : function(frm) {
make_jv: function (frm) {
let revaluation_journal = null;
let zero_balance_journal = null;
frappe.call({
@@ -88,66 +92,68 @@ frappe.ui.form.on('Exchange Rate Revaluation', {
doc: frm.doc,
freeze: true,
freeze_message: "Making Journal Entries...",
callback: function(r){
callback: function (r) {
if (r.message) {
let response = r.message;
if(response['revaluation_jv'] || response['zero_balance_jv']) {
if (response["revaluation_jv"] || response["zero_balance_jv"]) {
frappe.msgprint(__("Journals have been created"));
}
}
}
},
});
}
},
});
frappe.ui.form.on("Exchange Rate Revaluation Account", {
new_exchange_rate: function(frm, cdt, cdn) {
new_exchange_rate: function (frm, cdt, cdn) {
var row = frappe.get_doc(cdt, cdn);
row.new_balance_in_base_currency = flt(row.new_exchange_rate * flt(row.balance_in_account_currency),
precision("new_balance_in_base_currency", row));
row.new_balance_in_base_currency = flt(
row.new_exchange_rate * flt(row.balance_in_account_currency),
precision("new_balance_in_base_currency", row)
);
row.gain_loss = row.new_balance_in_base_currency - flt(row.balance_in_base_currency);
refresh_field("accounts");
frm.events.get_total_gain_loss(frm);
},
account: function(frm, cdt, cdn) {
account: function (frm, cdt, cdn) {
var row = locals[cdt][cdn];
if (row.account) {
get_account_details(frm, cdt, cdn);
}
},
party: function(frm, cdt, cdn) {
party: function (frm, cdt, cdn) {
var row = locals[cdt][cdn];
if (row.party && row.account) {
get_account_details(frm, cdt, cdn);
}
},
accounts_remove: function(frm) {
accounts_remove: function (frm) {
frm.events.get_total_gain_loss(frm);
}
},
});
var get_account_details = function(frm, cdt, cdn) {
var get_account_details = function (frm, cdt, cdn) {
var row = frappe.get_doc(cdt, cdn);
if(!frm.doc.company || !frm.doc.posting_date) {
if (!frm.doc.company || !frm.doc.posting_date) {
frappe.throw(__("Please select Company and Posting Date to getting entries"));
}
frappe.call({
method: "erpnext.accounts.doctype.exchange_rate_revaluation.exchange_rate_revaluation.get_account_details",
args:{
args: {
account: row.account,
company: frm.doc.company,
posting_date: frm.doc.posting_date,
party_type: row.party_type,
party: row.party,
rounding_loss_allowance: frm.doc.rounding_loss_allowance
rounding_loss_allowance: frm.doc.rounding_loss_allowance,
},
callback: function(r){
callback: function (r) {
$.extend(row, r.message);
refresh_field("accounts");
frm.events.get_total_gain_loss(frm);
}
},
});
};

View File

@@ -246,7 +246,6 @@ class ExchangeRateRevaluation(Document):
# Handle Accounts with '0' balance in Account/Base Currency
for d in [x for x in account_details if x.zero_balance]:
if d.balance != 0:
current_exchange_rate = new_exchange_rate = 0
@@ -259,7 +258,8 @@ class ExchangeRateRevaluation(Document):
new_balance_in_account_currency = 0
current_exchange_rate = (
calculate_exchange_rate_using_last_gle(company, d.account, d.party_type, d.party) or 0.0
calculate_exchange_rate_using_last_gle(company, d.account, d.party_type, d.party)
or 0.0
)
gain_loss = new_balance_in_account_currency - (
@@ -313,9 +313,7 @@ class ExchangeRateRevaluation(Document):
revaluation_jv = self.make_jv_for_revaluation()
if revaluation_jv:
frappe.msgprint(
f"Revaluation Journal: {get_link_to_form('Journal Entry', revaluation_jv.name)}"
)
frappe.msgprint(f"Revaluation Journal: {get_link_to_form('Journal Entry', revaluation_jv.name)}")
return {
"revaluation_jv": revaluation_jv.name if revaluation_jv else None,
@@ -372,7 +370,8 @@ class ExchangeRateRevaluation(Document):
journal_account.update(
{
dr_or_cr: flt(
abs(d.get("balance_in_account_currency")), d.precision("balance_in_account_currency")
abs(d.get("balance_in_account_currency")),
d.precision("balance_in_account_currency"),
),
reverse_dr_or_cr: 0,
"debit": 0,
@@ -498,7 +497,9 @@ class ExchangeRateRevaluation(Document):
abs(d.get("balance_in_account_currency")), d.precision("balance_in_account_currency")
),
"cost_center": erpnext.get_default_cost_center(self.company),
"exchange_rate": flt(d.get("current_exchange_rate"), d.precision("current_exchange_rate")),
"exchange_rate": flt(
d.get("current_exchange_rate"), d.precision("current_exchange_rate")
),
"reference_type": "Exchange Rate Revaluation",
"reference_name": self.name,
}
@@ -576,7 +577,7 @@ def calculate_exchange_rate_using_last_gle(company, account, party_type, party):
@frappe.whitelist()
def get_account_details(
company, posting_date, account, party_type=None, party=None, rounding_loss_allowance: float = None
company, posting_date, account, party_type=None, party=None, rounding_loss_allowance: float | None = None
):
if not (company and posting_date):
frappe.throw(_("Company and Posting Date is mandatory"))
@@ -589,7 +590,7 @@ def get_account_details(
frappe.throw(_("Party Type and Party is mandatory for {0} account").format(account_type))
account_details = {}
company_currency = erpnext.get_company_currency(company)
erpnext.get_company_currency(company)
account_details = {
"account_currency": account_currency,
@@ -603,24 +604,22 @@ def get_account_details(
rounding_loss_allowance=rounding_loss_allowance,
)
if account_balance and (
account_balance[0].balance or account_balance[0].balance_in_account_currency
):
account_with_new_balance = ExchangeRateRevaluation.calculate_new_account_balance(
if account_balance and (account_balance[0].balance or account_balance[0].balance_in_account_currency):
if account_with_new_balance := ExchangeRateRevaluation.calculate_new_account_balance(
company, posting_date, account_balance
)
row = account_with_new_balance[0]
account_details.update(
{
"balance_in_base_currency": row["balance_in_base_currency"],
"balance_in_account_currency": row["balance_in_account_currency"],
"current_exchange_rate": row["current_exchange_rate"],
"new_exchange_rate": row["new_exchange_rate"],
"new_balance_in_base_currency": row["new_balance_in_base_currency"],
"new_balance_in_account_currency": row["new_balance_in_account_currency"],
"zero_balance": row["zero_balance"],
"gain_loss": row["gain_loss"],
}
)
):
row = account_with_new_balance[0]
account_details.update(
{
"balance_in_base_currency": row["balance_in_base_currency"],
"balance_in_account_currency": row["balance_in_account_currency"],
"current_exchange_rate": row["current_exchange_rate"],
"new_exchange_rate": row["new_exchange_rate"],
"new_balance_in_base_currency": row["new_balance_in_base_currency"],
"new_balance_in_account_currency": row["new_balance_in_account_currency"],
"zero_balance": row["zero_balance"],
"gain_loss": row["gain_loss"],
}
)
return account_details

View File

@@ -1,21 +1,14 @@
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
import unittest
import frappe
from frappe import qb
from frappe.tests.utils import FrappeTestCase, change_settings
from frappe.utils import add_days, flt, today
from erpnext import get_default_cost_center
from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry
from erpnext.accounts.doctype.payment_entry.test_payment_entry import create_payment_entry
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
from erpnext.accounts.party import get_party_account
from erpnext.accounts.test.accounts_mixin import AccountsTestMixin
from erpnext.stock.doctype.item.test_item import create_item
class TestExchangeRateRevaluation(AccountsTestMixin, FrappeTestCase):
@@ -73,9 +66,7 @@ class TestExchangeRateRevaluation(AccountsTestMixin, FrappeTestCase):
err.extend("accounts", accounts)
row = err.accounts[0]
row.new_exchange_rate = 85
row.new_balance_in_base_currency = flt(
row.new_exchange_rate * flt(row.balance_in_account_currency)
)
row.new_balance_in_base_currency = flt(row.new_exchange_rate * flt(row.balance_in_account_currency))
row.gain_loss = row.new_balance_in_base_currency - flt(row.balance_in_base_currency)
err.set_total_gain_loss()
err = err.save().submit()
@@ -127,9 +118,9 @@ class TestExchangeRateRevaluation(AccountsTestMixin, FrappeTestCase):
pe.save().submit()
# Cancel the auto created gain/loss JE to simulate balance only in base currency
je = frappe.db.get_all(
"Journal Entry Account", filters={"reference_name": si.name}, pluck="parent"
)[0]
je = frappe.db.get_all("Journal Entry Account", filters={"reference_name": si.name}, pluck="parent")[
0
]
frappe.get_doc("Journal Entry", je).cancel()
err = frappe.new_doc("Exchange Rate Revaluation")
@@ -235,9 +226,9 @@ class TestExchangeRateRevaluation(AccountsTestMixin, FrappeTestCase):
self.assertEqual(flt(acc.debit, precision), 0.0)
self.assertEqual(flt(acc.credit, precision), 0.0)
row = [x for x in je.accounts if x.account == self.debtors_usd][0]
row = next(x for x in je.accounts if x.account == self.debtors_usd)
self.assertEqual(flt(row.credit_in_account_currency, precision), 5.0) # in USD
row = [x for x in je.accounts if x.account != self.debtors_usd][0]
row = next(x for x in je.accounts if x.account != self.debtors_usd)
self.assertEqual(flt(row.debit_in_account_currency, precision), 421.06) # in INR
# total_debit and total_credit will be 0.0, as JV is posting only to account currency fields
@@ -294,5 +285,5 @@ class TestExchangeRateRevaluation(AccountsTestMixin, FrappeTestCase):
"new_balance_in_account_currency": 100.0,
}
for key, val in expected_data.items():
for key, _val in expected_data.items():
self.assertEqual(expected_data.get(key), account_details.get(key))

View File

@@ -1,8 +1,6 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Finance Book', {
refresh: function(frm) {
}
frappe.ui.form.on("Finance Book", {
refresh: function (frm) {},
});

View File

@@ -1,17 +1,21 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
frappe.ui.form.on('Fiscal Year', {
onload: function(frm) {
if(frm.doc.__islocal) {
frm.set_value("year_start_date",
frappe.datetime.add_days(frappe.defaults.get_default("year_end_date"), 1));
frappe.ui.form.on("Fiscal Year", {
onload: function (frm) {
if (frm.doc.__islocal) {
frm.set_value(
"year_start_date",
frappe.datetime.add_days(frappe.defaults.get_default("year_end_date"), 1)
);
}
},
year_start_date: function(frm) {
year_start_date: function (frm) {
if (!frm.doc.is_short_year) {
let year_end_date =
frappe.datetime.add_days(frappe.datetime.add_months(frm.doc.year_start_date, 12), -1);
let year_end_date = frappe.datetime.add_days(
frappe.datetime.add_months(frm.doc.year_start_date, 12),
-1
);
frm.set_value("year_end_date", year_end_date);
}
},

View File

@@ -118,9 +118,17 @@
{
"read": 1,
"role": "Employee"
},
{
"read": 1,
"role": "Accounts Manager"
},
{
"read": 1,
"role": "Stock Manager"
}
],
"show_name_in_global_search": 1,
"sort_field": "name",
"sort_order": "DESC"
}
}

View File

@@ -98,9 +98,9 @@ class FiscalYear(Document):
if overlap:
frappe.throw(
_("Year start date or end date is overlapping with {0}. To avoid please set company").format(
existing.name
),
_(
"Year start date or end date is overlapping with {0}. To avoid please set company"
).format(existing.name),
frappe.NameError,
)
@@ -116,9 +116,9 @@ def check_duplicate_fiscal_year(doc):
not frappe.flags.in_test
):
frappe.throw(
_("Fiscal Year Start Date and Fiscal Year End Date are already set in Fiscal Year {0}").format(
fiscal_year
)
_(
"Fiscal Year Start Date and Fiscal Year End Date are already set in Fiscal Year {0}"
).format(fiscal_year)
)

View File

@@ -1,8 +1,8 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('GL Entry', {
refresh: function(frm) {
frm.page.btn_secondary.hide()
}
frappe.ui.form.on("GL Entry", {
refresh: function (frm) {
frm.page.btn_secondary.hide();
},
});

View File

@@ -174,7 +174,8 @@
"fieldname": "voucher_detail_no",
"fieldtype": "Data",
"label": "Voucher Detail No",
"read_only": 1
"read_only": 1,
"search_index": 1
},
{
"fieldname": "project",
@@ -256,7 +257,8 @@
"icon": "fa fa-list",
"idx": 1,
"in_create": 1,
"modified": "2020-04-07 16:22:33.766994",
"links": [],
"modified": "2024-03-19 18:30:49.613401",
"modified_by": "Administrator",
"module": "Accounts",
"name": "GL Entry",
@@ -288,5 +290,6 @@
"quick_entry": 1,
"search_fields": "voucher_no,account,posting_date,against_voucher",
"sort_field": "modified",
"sort_order": "DESC"
}
"sort_order": "DESC",
"states": []
}

View File

@@ -63,13 +63,18 @@ class GLEntry(Document):
]:
# Update outstanding amt on against voucher
if (
self.against_voucher_type in ["Journal Entry", "Sales Invoice", "Purchase Invoice", "Fees"]
self.against_voucher_type
in ["Journal Entry", "Sales Invoice", "Purchase Invoice", "Fees"]
and self.against_voucher
and self.flags.update_outstanding == "Yes"
and not frappe.flags.is_reverse_depr_entry
):
update_outstanding_amt(
self.account, self.party_type, self.party, self.against_voucher_type, self.against_voucher
self.account,
self.party_type,
self.party,
self.against_voucher_type,
self.against_voucher,
)
def check_mandatory(self):
@@ -127,7 +132,7 @@ class GLEntry(Document):
frappe.throw(msg, title=_("Missing Cost Center"))
def validate_dimensions_for_pl_and_bs(self):
account_type = frappe.db.get_value("Account", self.account, "report_type")
account_type = frappe.get_cached_value("Account", self.account, "report_type")
for dimension in get_checks_for_pl_and_bs_accounts():
if (
@@ -135,12 +140,13 @@ class GLEntry(Document):
and self.company == dimension.company
and dimension.mandatory_for_pl
and not dimension.disabled
and not self.is_cancelled
):
if not self.get(dimension.fieldname):
frappe.throw(
_("Accounting Dimension <b>{0}</b> is required for 'Profit and Loss' account {1}.").format(
dimension.label, self.account
)
_(
"Accounting Dimension <b>{0}</b> is required for 'Profit and Loss' account {1}."
).format(dimension.label, self.account)
)
if (
@@ -148,18 +154,19 @@ class GLEntry(Document):
and self.company == dimension.company
and dimension.mandatory_for_bs
and not dimension.disabled
and not self.is_cancelled
):
if not self.get(dimension.fieldname):
frappe.throw(
_("Accounting Dimension <b>{0}</b> is required for 'Balance Sheet' account {1}.").format(
dimension.label, self.account
)
_(
"Accounting Dimension <b>{0}</b> is required for 'Balance Sheet' account {1}."
).format(dimension.label, self.account)
)
def check_pl_account(self):
if (
self.is_opening == "Yes"
and frappe.db.get_value("Account", self.account, "report_type") == "Profit and Loss"
and frappe.get_cached_value("Account", self.account, "report_type") == "Profit and Loss"
and not self.is_cancelled
):
frappe.throw(
@@ -201,9 +208,7 @@ class GLEntry(Document):
if not self.cost_center:
return
is_group, company = frappe.get_cached_value(
"Cost Center", self.cost_center, ["is_group", "company"]
)
is_group, company = frappe.get_cached_value("Cost Center", self.cost_center, ["is_group", "company"])
if company != self.company:
frappe.throw(
@@ -252,7 +257,7 @@ class GLEntry(Document):
def validate_balance_type(account, adv_adj=False):
if not adv_adj and account:
balance_must_be = frappe.db.get_value("Account", account, "balance_must_be")
balance_must_be = frappe.get_cached_value("Account", account, "balance_must_be")
if balance_must_be:
balance = frappe.db.sql(
"""select sum(debit) - sum(credit)
@@ -272,31 +277,27 @@ def update_outstanding_amt(
account, party_type, party, against_voucher_type, against_voucher, on_cancel=False
):
if party_type and party:
party_condition = " and party_type={0} and party={1}".format(
party_condition = " and party_type={} and party={}".format(
frappe.db.escape(party_type), frappe.db.escape(party)
)
else:
party_condition = ""
if against_voucher_type == "Sales Invoice":
party_account = frappe.db.get_value(against_voucher_type, against_voucher, "debit_to")
account_condition = "and account in ({0}, {1})".format(
frappe.db.escape(account), frappe.db.escape(party_account)
)
party_account = frappe.get_cached_value(against_voucher_type, against_voucher, "debit_to")
account_condition = f"and account in ({frappe.db.escape(account)}, {frappe.db.escape(party_account)})"
else:
account_condition = " and account = {0}".format(frappe.db.escape(account))
account_condition = f" and account = {frappe.db.escape(account)}"
# get final outstanding amt
bal = flt(
frappe.db.sql(
"""
f"""
select sum(debit_in_account_currency) - sum(credit_in_account_currency)
from `tabGL Entry`
where against_voucher_type=%s and against_voucher=%s
and voucher_type != 'Invoice Discounting'
{0} {1}""".format(
party_condition, account_condition
),
{party_condition} {account_condition}""",
(against_voucher_type, against_voucher),
)[0][0]
or 0.0
@@ -307,12 +308,10 @@ def update_outstanding_amt(
elif against_voucher_type == "Journal Entry":
against_voucher_amount = flt(
frappe.db.sql(
"""
f"""
select sum(debit_in_account_currency) - sum(credit_in_account_currency)
from `tabGL Entry` where voucher_type = 'Journal Entry' and voucher_no = %s
and account = %s and (against_voucher is null or against_voucher='') {0}""".format(
party_condition
),
and account = %s and (against_voucher is null or against_voucher='') {party_condition}""",
(against_voucher, account),
)[0][0]
)
@@ -331,7 +330,9 @@ def update_outstanding_amt(
# Validation : Outstanding can not be negative for JV
if bal < 0 and not on_cancel:
frappe.throw(
_("Outstanding for {0} cannot be less than zero ({1})").format(against_voucher, fmt_money(bal))
_("Outstanding for {0} cannot be less than zero ({1})").format(
against_voucher, fmt_money(bal)
)
)
if against_voucher_type in ["Sales Invoice", "Purchase Invoice", "Fees"]:
@@ -347,7 +348,7 @@ def update_outstanding_amt(
def validate_frozen_account(account, adv_adj=None):
frozen_account = frappe.get_cached_value("Account", account, "freeze_account")
if frozen_account == "Yes" and not adv_adj:
frozen_accounts_modifier = frappe.db.get_value(
frozen_accounts_modifier = frappe.get_cached_value(
"Accounts Settings", None, "frozen_accounts_modifier"
)
@@ -404,7 +405,7 @@ def rename_temporarily_named_docs(doctype):
set_name_from_naming_options(frappe.get_meta(doctype).autoname, doc)
newname = doc.name
frappe.db.sql(
"UPDATE `tab{}` SET name = %s, to_rename = 0 where name = %s".format(doctype),
f"UPDATE `tab{doctype}` SET name = %s, to_rename = 0 where name = %s",
(newname, oldname),
auto_commit=True,
)

View File

@@ -14,9 +14,7 @@ from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journ
class TestGLEntry(unittest.TestCase):
def test_round_off_entry(self):
frappe.db.set_value("Company", "_Test Company", "round_off_account", "_Test Write Off - _TC")
frappe.db.set_value(
"Company", "_Test Company", "round_off_cost_center", "_Test Cost Center - _TC"
)
frappe.db.set_value("Company", "_Test Company", "round_off_cost_center", "_Test Cost Center - _TC")
jv = make_journal_entry(
"_Test Account Cost for Goods Sold - _TC",
@@ -73,7 +71,9 @@ class TestGLEntry(unittest.TestCase):
)
self.assertTrue(all(entry.to_rename == 0 for entry in new_gl_entries))
self.assertTrue(all(new.name != old.name for new, old in zip(gl_entries, new_gl_entries)))
self.assertTrue(
all(new.name != old.name for new, old in zip(gl_entries, new_gl_entries, strict=False))
)
new_naming_series_current_value = frappe.db.sql(
"SELECT current from tabSeries where name = %s", naming_series

View File

@@ -1,47 +1,49 @@
// Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Invoice Discounting', {
frappe.ui.form.on("Invoice Discounting", {
setup: (frm) => {
frm.set_query("sales_invoice", "invoices", (doc) => {
return {
"filters": {
"docstatus": 1,
"company": doc.company,
"outstanding_amount": [">", 0]
filters: {
docstatus: 1,
company: doc.company,
outstanding_amount: [">", 0],
},
};
});
frm.events.filter_accounts("bank_account", frm, [["account_type", "=", "Bank"]]);
frm.events.filter_accounts("bank_charges_account", frm, [["root_type", "=", "Expense"]]);
frm.events.filter_accounts("short_term_loan", frm, [["root_type", "=", "Liability"]]);
frm.events.filter_accounts("accounts_receivable_discounted", frm, [["account_type", "=", "Receivable"]]);
frm.events.filter_accounts("accounts_receivable_discounted", frm, [
["account_type", "=", "Receivable"],
]);
frm.events.filter_accounts("accounts_receivable_credit", frm, [["account_type", "=", "Receivable"]]);
frm.events.filter_accounts("accounts_receivable_unpaid", frm, [["account_type", "=", "Receivable"]]);
},
filter_accounts: (fieldname, frm, addl_filters) => {
let filters = [
["company", "=", frm.doc.company],
["is_group", "=", 0]
["is_group", "=", 0],
];
if(addl_filters){
filters = $.merge(filters , addl_filters);
if (addl_filters) {
filters = $.merge(filters, addl_filters);
}
frm.set_query(fieldname, () => { return { "filters": filters }; });
frm.set_query(fieldname, () => {
return { filters: filters };
});
},
refresh_filters: (frm) =>{
let invoice_accounts = Object.keys(frm.doc.invoices).map(function(key) {
refresh_filters: (frm) => {
let invoice_accounts = Object.keys(frm.doc.invoices).map(function (key) {
return frm.doc.invoices[key].debit_to;
});
let filters = [
["account_type", "=", "Receivable"],
["name", "not in", invoice_accounts]
["name", "not in", invoice_accounts],
];
frm.events.filter_accounts("accounts_receivable_credit", frm, filters);
frm.events.filter_accounts("accounts_receivable_discounted", frm, filters);
@@ -52,19 +54,19 @@ frappe.ui.form.on('Invoice Discounting', {
frm.events.show_general_ledger(frm);
if (frm.doc.docstatus === 0) {
frm.add_custom_button(__('Get Invoices'), function() {
frm.add_custom_button(__("Get Invoices"), function () {
frm.events.get_invoices(frm);
});
}
if (frm.doc.docstatus === 1 && frm.doc.status !== "Settled") {
if (frm.doc.status == "Sanctioned") {
frm.add_custom_button(__('Disburse Loan'), function() {
frm.add_custom_button(__("Disburse Loan"), function () {
frm.events.create_disbursement_entry(frm);
}).addClass("btn-primary");
}
if (frm.doc.status == "Disbursed") {
frm.add_custom_button(__('Close Loan'), function() {
frm.add_custom_button(__("Close Loan"), function () {
frm.events.close_loan(frm);
}).addClass("btn-primary");
}
@@ -92,119 +94,121 @@ frappe.ui.form.on('Invoice Discounting', {
calculate_total_amount: (frm) => {
let total_amount = 0.0;
for (let row of (frm.doc.invoices || [])) {
for (let row of frm.doc.invoices || []) {
total_amount += flt(row.outstanding_amount);
}
frm.set_value("total_amount", total_amount);
},
get_invoices: (frm) => {
var d = new frappe.ui.Dialog({
title: __('Get Invoices based on Filters'),
title: __("Get Invoices based on Filters"),
fields: [
{
"label": "Customer",
"fieldname": "customer",
"fieldtype": "Link",
"options": "Customer"
label: "Customer",
fieldname: "customer",
fieldtype: "Link",
options: "Customer",
},
{
"label": "From Date",
"fieldname": "from_date",
"fieldtype": "Date"
label: "From Date",
fieldname: "from_date",
fieldtype: "Date",
},
{
"label": "To Date",
"fieldname": "to_date",
"fieldtype": "Date"
label: "To Date",
fieldname: "to_date",
fieldtype: "Date",
},
{
"fieldname": "col_break",
"fieldtype": "Column Break",
fieldname: "col_break",
fieldtype: "Column Break",
},
{
"label": "Min Amount",
"fieldname": "min_amount",
"fieldtype": "Currency"
label: "Min Amount",
fieldname: "min_amount",
fieldtype: "Currency",
},
{
"label": "Max Amount",
"fieldname": "max_amount",
"fieldtype": "Currency"
}
label: "Max Amount",
fieldname: "max_amount",
fieldtype: "Currency",
},
],
primary_action: function() {
primary_action: function () {
var data = d.get_values();
frappe.call({
method: "erpnext.accounts.doctype.invoice_discounting.invoice_discounting.get_invoices",
args: {
filters: data
filters: data,
},
callback: function(r) {
if(!r.exc) {
callback: function (r) {
if (!r.exc) {
d.hide();
$.each(r.message, function(i, v) {
frm.doc.invoices = frm.doc.invoices.filter(row => row.sales_invoice);
$.each(r.message, function (i, v) {
frm.doc.invoices = frm.doc.invoices.filter((row) => row.sales_invoice);
let row = frm.add_child("invoices");
$.extend(row, v);
frm.events.refresh_filters(frm);
});
refresh_field("invoices");
}
}
},
});
},
primary_action_label: __('Get Invocies')
primary_action_label: __("Get Invocies"),
});
d.show();
},
create_disbursement_entry: (frm) => {
frappe.call({
method:"create_disbursement_entry",
method: "create_disbursement_entry",
doc: frm.doc,
callback: function(r) {
if(!r.exc){
callback: function (r) {
if (!r.exc) {
var doclist = frappe.model.sync(r.message);
frappe.set_route("Form", doclist[0].doctype, doclist[0].name);
}
}
},
});
},
close_loan: (frm) => {
frappe.call({
method:"close_loan",
method: "close_loan",
doc: frm.doc,
callback: function(r) {
if(!r.exc){
callback: function (r) {
if (!r.exc) {
var doclist = frappe.model.sync(r.message);
frappe.set_route("Form", doclist[0].doctype, doclist[0].name);
}
}
},
});
},
show_general_ledger: (frm) => {
if(frm.doc.docstatus > 0) {
cur_frm.add_custom_button(__('Accounting Ledger'), function() {
frappe.route_options = {
voucher_no: frm.doc.name,
from_date: frm.doc.posting_date,
to_date: moment(frm.doc.modified).format('YYYY-MM-DD'),
company: frm.doc.company,
group_by: "Group by Voucher (Consolidated)",
show_cancelled_entries: frm.doc.docstatus === 2
};
frappe.set_route("query-report", "General Ledger");
}, __("View"));
if (frm.doc.docstatus > 0) {
cur_frm.add_custom_button(
__("Accounting Ledger"),
function () {
frappe.route_options = {
voucher_no: frm.doc.name,
from_date: frm.doc.posting_date,
to_date: moment(frm.doc.modified).format("YYYY-MM-DD"),
company: frm.doc.company,
group_by: "Group by Voucher (Consolidated)",
show_cancelled_entries: frm.doc.docstatus === 2,
};
frappe.set_route("query-report", "General Ledger");
},
__("View")
);
}
}
},
});
frappe.ui.form.on('Discounted Invoice', {
frappe.ui.form.on("Discounted Invoice", {
sales_invoice: (frm) => {
frm.events.calculate_total_amount(frm);
frm.events.refresh_filters(frm);
@@ -212,5 +216,5 @@ frappe.ui.form.on('Discounted Invoice', {
invoices_remove: (frm) => {
frm.events.calculate_total_amount(frm);
frm.events.refresh_filters(frm);
}
},
});

View File

@@ -55,9 +55,7 @@ class InvoiceDiscounting(AccountsController):
frappe.throw(
_(
"Row({0}): Outstanding Amount cannot be greater than actual Outstanding Amount {1} in {2}"
).format(
record.idx, frappe.bold(actual_outstanding), frappe.bold(record.sales_invoice)
)
).format(record.idx, frappe.bold(actual_outstanding), frappe.bold(record.sales_invoice))
)
def calculate_total_amount(self):
@@ -77,7 +75,9 @@ class InvoiceDiscounting(AccountsController):
self.status = status
self.db_set("status", status)
for d in self.invoices:
frappe.get_doc("Sales Invoice", d.sales_invoice).set_status(update=True, update_modified=False)
frappe.get_doc("Sales Invoice", d.sales_invoice).set_status(
update=True, update_modified=False
)
else:
self.status = "Draft"
if self.docstatus == 1:

View File

@@ -1,21 +1,16 @@
frappe.listview_settings['Invoice Discounting'] = {
frappe.listview_settings["Invoice Discounting"] = {
add_fields: ["status"],
get_indicator: function(doc)
{
if(doc.status == "Draft") {
get_indicator: function (doc) {
if (doc.status == "Draft") {
return [__("Draft"), "red", "status,=,Draft"];
}
else if(doc.status == "Sanctioned") {
} else if (doc.status == "Sanctioned") {
return [__("Sanctioned"), "green", "status,=,Sanctioned"];
}
else if(doc.status == "Disbursed") {
} else if (doc.status == "Disbursed") {
return [__("Disbursed"), "blue", "status,=,Disbursed"];
}
else if(doc.status == "Settled") {
} else if (doc.status == "Settled") {
return [__("Settled"), "orange", "status,=,Settled"];
}
else if(doc.status == "Canceled") {
} else if (doc.status == "Canceled") {
return [__("Canceled"), "red", "status,=,Canceled"];
}
}
},
};

View File

@@ -75,8 +75,8 @@ class TestInvoiceDiscounting(unittest.TestCase):
gle = get_gl_entries("Invoice Discounting", inv_disc.name)
expected_gle = {inv.debit_to: [0.0, 200], self.ar_credit: [200, 0.0]}
for i, gle in enumerate(gle):
self.assertEqual([gle.debit, gle.credit], expected_gle.get(gle.account))
for _i, gle_value in enumerate(gle):
self.assertEqual([gle_value.debit, gle_value.credit], expected_gle.get(gle_value.account))
def test_loan_on_submit(self):
inv = create_sales_invoice(rate=300)
@@ -92,9 +92,7 @@ class TestInvoiceDiscounting(unittest.TestCase):
period=60,
)
self.assertEqual(inv_disc.status, "Sanctioned")
self.assertEqual(
inv_disc.loan_end_date, add_days(inv_disc.loan_start_date, inv_disc.loan_period)
)
self.assertEqual(inv_disc.loan_end_date, add_days(inv_disc.loan_start_date, inv_disc.loan_period))
def test_on_disbursed(self):
inv = create_sales_invoice(rate=500)
@@ -262,13 +260,9 @@ class TestInvoiceDiscounting(unittest.TestCase):
je_on_payment.submit()
self.assertEqual(je_on_payment.accounts[0].account, self.ar_discounted)
self.assertEqual(
je_on_payment.accounts[0].credit_in_account_currency, flt(inv.outstanding_amount)
)
self.assertEqual(je_on_payment.accounts[0].credit_in_account_currency, flt(inv.outstanding_amount))
self.assertEqual(je_on_payment.accounts[1].account, self.bank_account)
self.assertEqual(
je_on_payment.accounts[1].debit_in_account_currency, flt(inv.outstanding_amount)
)
self.assertEqual(je_on_payment.accounts[1].debit_in_account_currency, flt(inv.outstanding_amount))
inv.reload()
self.assertEqual(inv.outstanding_amount, 0)
@@ -304,13 +298,9 @@ class TestInvoiceDiscounting(unittest.TestCase):
je_on_payment.submit()
self.assertEqual(je_on_payment.accounts[0].account, self.ar_unpaid)
self.assertEqual(
je_on_payment.accounts[0].credit_in_account_currency, flt(inv.outstanding_amount)
)
self.assertEqual(je_on_payment.accounts[0].credit_in_account_currency, flt(inv.outstanding_amount))
self.assertEqual(je_on_payment.accounts[1].account, self.bank_account)
self.assertEqual(
je_on_payment.accounts[1].debit_in_account_currency, flt(inv.outstanding_amount)
)
self.assertEqual(je_on_payment.accounts[1].debit_in_account_currency, flt(inv.outstanding_amount))
inv.reload()
self.assertEqual(inv.outstanding_amount, 0)

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