Compare commits

...

189 Commits

Author SHA1 Message Date
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
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
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
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
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
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
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
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
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
11bddc14bb fix: Delete linked asset movement record on cancellation of purchase receipt/invoice 2024-02-20 12:23:16 +05:30
Gursheen Anand
e9c2f6d6f1 fix: message for subscription when no current inv 2024-02-05 11:05:45 +05:30
701 changed files with 29346 additions and 19545 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

@@ -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,6 +20,51 @@ repos:
- id: check-yaml
- id: debug-statements
- repo: https://github.com/pre-commit/mirrors-prettier
rev: v2.7.1
hooks:
- 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/PyCQA/flake8
rev: 5.0.4
hooks:

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.63.2"
__version__ = "14.63.3"
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:

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

@@ -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

@@ -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

@@ -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

@@ -236,14 +236,16 @@ 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):

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()

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

@@ -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

@@ -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

@@ -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

@@ -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

@@ -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

@@ -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

@@ -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

@@ -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

@@ -109,6 +109,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 +118,11 @@ 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,13 +149,13 @@ 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"])
lft, rgt = frappe.get_cached_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,

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

@@ -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

@@ -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

@@ -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

@@ -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

@@ -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,27 @@
// 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) {
frappe.ui.form.on("Currency Exchange Settings", {
service_provider: function (frm) {
if (frm.doc.service_provider == "exchangerate.host") {
let result = ['result'];
let result = ["result"];
let params = {
date: '{transaction_date}',
from: '{from_currency}',
to: '{to_currency}'
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 result = ["rates", "{to_currency}"];
let params = {
base: '{from_currency}',
symbols: '{to_currency}'
base: "{from_currency}",
symbols: "{to_currency}",
};
add_param(frm, "https://frankfurter.app/{transaction_date}", params, result);
}
}
},
});
function add_param(frm, api, params, result) {
var row;
frm.clear_table("req_params");
@@ -30,13 +29,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,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

@@ -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

@@ -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

@@ -127,7 +127,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 (
@@ -159,7 +159,7 @@ class GLEntry(Document):
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(
@@ -252,7 +252,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)
@@ -279,7 +279,7 @@ def update_outstanding_amt(
party_condition = ""
if against_voucher_type == "Sales Invoice":
party_account = frappe.db.get_value(against_voucher_type, against_voucher, "debit_to")
party_account = frappe.get_cached_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)
)
@@ -347,7 +347,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"
)

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

@@ -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

@@ -1,27 +1,49 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Item Tax Template', {
setup: function(frm) {
frm.set_query("tax_type", "taxes", function(doc) {
frappe.ui.form.on("Item Tax Template", {
setup: function (frm) {
frm.set_query("tax_type", "taxes", function (doc) {
return {
filters: [
['Account', 'company', '=', frm.doc.company],
['Account', 'is_group', '=', 0],
['Account', 'account_type', 'in', ['Tax', 'Chargeable', 'Income Account', 'Expense Account', 'Expenses Included In Valuation']]
]
}
["Account", "company", "=", frm.doc.company],
["Account", "is_group", "=", 0],
[
"Account",
"account_type",
"in",
[
"Tax",
"Chargeable",
"Income Account",
"Expense Account",
"Expenses Included In Valuation",
],
],
],
};
});
},
company: function (frm) {
frm.set_query("tax_type", "taxes", function(doc) {
frm.set_query("tax_type", "taxes", function (doc) {
return {
filters: [
['Account', 'company', '=', frm.doc.company],
['Account', 'is_group', '=', 0],
['Account', 'account_type', 'in', ['Tax', 'Chargeable', 'Income Account', 'Expense Account', 'Expenses Included In Valuation']]
]
}
["Account", "company", "=", frm.doc.company],
["Account", "is_group", "=", 0],
[
"Account",
"account_type",
"in",
[
"Tax",
"Chargeable",
"Income Account",
"Expense Account",
"Expenses Included In Valuation",
],
],
],
};
});
}
},
});

View File

@@ -4,39 +4,57 @@
frappe.provide("erpnext.accounts");
frappe.provide("erpnext.journal_entry");
frappe.ui.form.on("Journal Entry", {
setup: function(frm) {
setup: function (frm) {
frm.add_fetch("bank_account", "account", "account");
frm.ignore_doctypes_on_cancel_all = ["Sales Invoice", "Purchase Invoice", "Journal Entry", "Repost Payment Ledger", "Asset", "Asset Movement", "Repost Accounting Ledger", "Unreconcile Payment", "Unreconcile Payment Entries", "Bank Transaction"];
frm.ignore_doctypes_on_cancel_all = [
"Sales Invoice",
"Purchase Invoice",
"Journal Entry",
"Repost Payment Ledger",
"Asset",
"Asset Movement",
"Repost Accounting Ledger",
"Unreconcile Payment",
"Unreconcile Payment Entries",
"Bank Transaction",
];
},
refresh: function(frm) {
refresh: function (frm) {
erpnext.toggle_naming_series();
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": moment(frm.doc.modified).format('YYYY-MM-DD'),
"company": frm.doc.company,
"finance_book": frm.doc.finance_book,
"group_by": '',
"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: moment(frm.doc.modified).format("YYYY-MM-DD"),
company: frm.doc.company,
finance_book: frm.doc.finance_book,
group_by: "",
show_cancelled_entries: frm.doc.docstatus === 2,
};
frappe.set_route("query-report", "General Ledger");
},
__("View")
);
}
if(frm.doc.docstatus==1) {
frm.add_custom_button(__('Reverse Journal Entry'), function() {
return erpnext.journal_entry.reverse_journal_entry(frm);
}, __('Actions'));
if (frm.doc.docstatus == 1) {
frm.add_custom_button(
__("Reverse Journal Entry"),
function () {
return erpnext.journal_entry.reverse_journal_entry(frm);
},
__("Actions")
);
}
if (frm.doc.__islocal) {
frm.add_custom_button(__('Quick Entry'), function() {
frm.add_custom_button(__("Quick Entry"), function () {
return erpnext.journal_entry.quick_entry(frm);
});
}
@@ -44,52 +62,63 @@ frappe.ui.form.on("Journal Entry", {
// hide /unhide fields based on currency
erpnext.journal_entry.toggle_fields_based_on_currency(frm);
if ((frm.doc.voucher_type == "Inter Company Journal Entry") && (frm.doc.docstatus == 1) && (!frm.doc.inter_company_journal_entry_reference)) {
frm.add_custom_button(__("Create Inter Company Journal Entry"),
function() {
if (
frm.doc.voucher_type == "Inter Company Journal Entry" &&
frm.doc.docstatus == 1 &&
!frm.doc.inter_company_journal_entry_reference
) {
frm.add_custom_button(
__("Create Inter Company Journal Entry"),
function () {
frm.trigger("make_inter_company_journal_entry");
}, __('Make'));
},
__("Make")
);
}
erpnext.accounts.unreconcile_payment.add_unreconcile_btn(frm);
},
before_save: function(frm) {
if ((frm.doc.docstatus == 0) && (!frm.doc.is_system_generated)) {
let payment_entry_references = frm.doc.accounts.filter(elem => (elem.reference_type == "Payment Entry"));
before_save: function (frm) {
if (frm.doc.docstatus == 0 && !frm.doc.is_system_generated) {
let payment_entry_references = frm.doc.accounts.filter(
(elem) => elem.reference_type == "Payment Entry"
);
if (payment_entry_references.length > 0) {
let rows = payment_entry_references.map(x => "#"+x.idx);
frappe.throw(__("Rows: {0} have 'Payment Entry' as reference_type. This should not be set manually.", [frappe.utils.comma_and(rows)]));
let rows = payment_entry_references.map((x) => "#" + x.idx);
frappe.throw(
__("Rows: {0} have 'Payment Entry' as reference_type. This should not be set manually.", [
frappe.utils.comma_and(rows),
])
);
}
}
},
make_inter_company_journal_entry: function(frm) {
make_inter_company_journal_entry: function (frm) {
var d = new frappe.ui.Dialog({
title: __("Select Company"),
fields: [
{
'fieldname': 'company',
'fieldtype': 'Link',
'label': __('Company'),
'options': 'Company',
"get_query": function () {
fieldname: "company",
fieldtype: "Link",
label: __("Company"),
options: "Company",
get_query: function () {
return {
filters: [
["Company", "name", "!=", frm.doc.company]
]
filters: [["Company", "name", "!=", frm.doc.company]],
};
},
'reqd': 1
}
reqd: 1,
},
],
});
d.set_primary_action(__('Create'), function() {
d.set_primary_action(__("Create"), function () {
d.hide();
var args = d.get_values();
frappe.call({
args: {
"name": frm.doc.name,
"voucher_type": frm.doc.voucher_type,
"company": args.company
name: frm.doc.name,
voucher_type: frm.doc.voucher_type,
company: args.company,
},
method: "erpnext.accounts.doctype.journal_entry.journal_entry.make_inter_company_journal_entry",
callback: function (r) {
@@ -97,103 +126,106 @@ frappe.ui.form.on("Journal Entry", {
var doc = frappe.model.sync(r.message)[0];
frappe.set_route("Form", doc.doctype, doc.name);
}
}
},
});
});
d.show();
},
multi_currency: function(frm) {
multi_currency: function (frm) {
erpnext.journal_entry.toggle_fields_based_on_currency(frm);
},
posting_date: function(frm) {
if(!frm.doc.multi_currency || !frm.doc.posting_date) return;
posting_date: function (frm) {
if (!frm.doc.multi_currency || !frm.doc.posting_date) return;
$.each(frm.doc.accounts || [], function(i, row) {
$.each(frm.doc.accounts || [], function (i, row) {
erpnext.journal_entry.set_exchange_rate(frm, row.doctype, row.name);
})
});
},
company: function(frm) {
company: function (frm) {
frappe.call({
method: "frappe.client.get_value",
args: {
doctype: "Company",
filters: {"name": frm.doc.company},
fieldname: "cost_center"
filters: { name: frm.doc.company },
fieldname: "cost_center",
},
callback: function(r){
if(r.message){
$.each(frm.doc.accounts || [], function(i, jvd) {
callback: function (r) {
if (r.message) {
$.each(frm.doc.accounts || [], function (i, jvd) {
frappe.model.set_value(jvd.doctype, jvd.name, "cost_center", r.message.cost_center);
});
}
}
},
});
erpnext.accounts.dimensions.update_dimension(frm, frm.doctype);
},
voucher_type: function(frm){
voucher_type: function (frm) {
if (!frm.doc.company) return null;
if(!frm.doc.company) return null;
if((!(frm.doc.accounts || []).length) || ((frm.doc.accounts || []).length === 1 && !frm.doc.accounts[0].account)) {
if(in_list(["Bank Entry", "Cash Entry"], frm.doc.voucher_type)) {
if (
!(frm.doc.accounts || []).length ||
((frm.doc.accounts || []).length === 1 && !frm.doc.accounts[0].account)
) {
if (in_list(["Bank Entry", "Cash Entry"], frm.doc.voucher_type)) {
return frappe.call({
type: "GET",
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_default_bank_cash_account",
args: {
"account_type": (frm.doc.voucher_type=="Bank Entry" ?
"Bank" : (frm.doc.voucher_type=="Cash Entry" ? "Cash" : null)),
"company": frm.doc.company
account_type:
frm.doc.voucher_type == "Bank Entry"
? "Bank"
: frm.doc.voucher_type == "Cash Entry"
? "Cash"
: null,
company: frm.doc.company,
},
callback: function(r) {
if(r.message) {
callback: function (r) {
if (r.message) {
// If default company bank account not set
if(!$.isEmptyObject(r.message)){
if (!$.isEmptyObject(r.message)) {
update_jv_details(frm.doc, [r.message]);
}
}
}
},
});
}
}
},
from_template: function(frm){
if (frm.doc.from_template){
frappe.db.get_doc("Journal Entry Template", frm.doc.from_template)
.then((doc) => {
frappe.model.clear_table(frm.doc, "accounts");
frm.set_value({
"company": doc.company,
"voucher_type": doc.voucher_type,
"naming_series": doc.naming_series,
"is_opening": doc.is_opening,
"multi_currency": doc.multi_currency
})
update_jv_details(frm.doc, doc.accounts);
from_template: function (frm) {
if (frm.doc.from_template) {
frappe.db.get_doc("Journal Entry Template", frm.doc.from_template).then((doc) => {
frappe.model.clear_table(frm.doc, "accounts");
frm.set_value({
company: doc.company,
voucher_type: doc.voucher_type,
naming_series: doc.naming_series,
is_opening: doc.is_opening,
multi_currency: doc.multi_currency,
});
update_jv_details(frm.doc, doc.accounts);
});
}
}
},
});
var update_jv_details = function(doc, r) {
$.each(r, function(i, d) {
var update_jv_details = function (doc, r) {
$.each(r, function (i, d) {
var row = frappe.model.add_child(doc, "Journal Entry Account", "accounts");
frappe.model.set_value(row.doctype, row.name, "account", d.account)
frappe.model.set_value(row.doctype, row.name, "balance", d.balance)
frappe.model.set_value(row.doctype, row.name, "account", d.account);
});
refresh_field("accounts");
}
};
erpnext.accounts.JournalEntry = class JournalEntry extends frappe.ui.form.Controller {
onload() {
this.load_defaults();
this.setup_queries();
this.setup_balance_formatter();
erpnext.accounts.dimensions.setup_dimension_filters(this.frm, this.frm.doctype);
}
@@ -203,69 +235,67 @@ erpnext.accounts.JournalEntry = class JournalEntry extends frappe.ui.form.Contro
load_defaults() {
//this.frm.show_print_first = true;
if(this.frm.doc.__islocal && this.frm.doc.company) {
if (this.frm.doc.__islocal && this.frm.doc.company) {
frappe.model.set_default_values(this.frm.doc);
$.each(this.frm.doc.accounts || [], function(i, jvd) {
$.each(this.frm.doc.accounts || [], function (i, jvd) {
frappe.model.set_default_values(jvd);
});
var posting_date = this.frm.doc.posting_date;
if(!this.frm.doc.amended_from) this.frm.set_value('posting_date', posting_date || frappe.datetime.get_today());
if (!this.frm.doc.amended_from)
this.frm.set_value("posting_date", posting_date || frappe.datetime.get_today());
}
}
setup_queries() {
var me = this;
me.frm.set_query("account", "accounts", function(doc, cdt, cdn) {
me.frm.set_query("account", "accounts", function (doc, cdt, cdn) {
return erpnext.journal_entry.account_query(me.frm);
});
me.frm.set_query("party_type", "accounts", function(doc, cdt, cdn) {
me.frm.set_query("party_type", "accounts", function (doc, cdt, cdn) {
const row = locals[cdt][cdn];
return {
query: "erpnext.setup.doctype.party_type.party_type.get_party_type",
filters: {
'account': row.account
}
}
account: row.account,
},
};
});
me.frm.set_query("reference_name", "accounts", function(doc, cdt, cdn) {
me.frm.set_query("reference_name", "accounts", function (doc, cdt, cdn) {
var jvd = frappe.get_doc(cdt, cdn);
// journal entry
if(jvd.reference_type==="Journal Entry") {
if (jvd.reference_type === "Journal Entry") {
frappe.model.validate_missing(jvd, "account");
return {
query: "erpnext.accounts.doctype.journal_entry.journal_entry.get_against_jv",
filters: {
account: jvd.account,
party: jvd.party
}
party: jvd.party,
},
};
}
var out = {
filters: [
[jvd.reference_type, "docstatus", "=", 1]
]
filters: [[jvd.reference_type, "docstatus", "=", 1]],
};
if(in_list(["Sales Invoice", "Purchase Invoice"], jvd.reference_type)) {
if (in_list(["Sales Invoice", "Purchase Invoice"], jvd.reference_type)) {
out.filters.push([jvd.reference_type, "outstanding_amount", "!=", 0]);
// Filter by cost center
if(jvd.cost_center) {
if (jvd.cost_center) {
out.filters.push([jvd.reference_type, "cost_center", "in", ["", jvd.cost_center]]);
}
// account filter
frappe.model.validate_missing(jvd, "account");
var party_account_field = jvd.reference_type==="Sales Invoice" ? "debit_to": "credit_to";
var party_account_field = jvd.reference_type === "Sales Invoice" ? "debit_to" : "credit_to";
out.filters.push([jvd.reference_type, party_account_field, "=", jvd.account]);
}
if(in_list(["Sales Order", "Purchase Order"], jvd.reference_type)) {
if (in_list(["Sales Order", "Purchase Order"], jvd.reference_type)) {
// party_type and party mandatory
frappe.model.validate_missing(jvd, "party_type");
frappe.model.validate_missing(jvd, "party");
@@ -273,11 +303,11 @@ erpnext.accounts.JournalEntry = class JournalEntry extends frappe.ui.form.Contro
out.filters.push([jvd.reference_type, "per_billed", "<", 100]);
}
if(jvd.party_type && jvd.party) {
if (jvd.party_type && jvd.party) {
var party_field = "";
if(jvd.reference_type.indexOf("Sales")===0) {
if (jvd.reference_type.indexOf("Sales") === 0) {
var party_field = "customer";
} else if (jvd.reference_type.indexOf("Purchase")===0) {
} else if (jvd.reference_type.indexOf("Purchase") === 0) {
var party_field = "supplier";
}
@@ -288,64 +318,49 @@ erpnext.accounts.JournalEntry = class JournalEntry extends frappe.ui.form.Contro
return out;
});
}
setup_balance_formatter() {
const formatter = function(value, df, options, doc) {
var currency = frappe.meta.get_field_currency(df, doc);
var dr_or_cr = value ? ('<label>' + (value > 0.0 ? __("Dr") : __("Cr")) + '</label>') : "";
return "<div style='text-align: right'>"
+ ((value==null || value==="") ? "" : format_currency(Math.abs(value), currency))
+ " " + dr_or_cr
+ "</div>";
};
this.frm.fields_dict.accounts.grid.update_docfield_property('balance', 'formatter', formatter);
this.frm.fields_dict.accounts.grid.update_docfield_property('party_balance', 'formatter', formatter);
}
reference_name(doc, cdt, cdn) {
var d = frappe.get_doc(cdt, cdn);
if(d.reference_name) {
if (d.reference_type==="Purchase Invoice" && !flt(d.debit)) {
this.get_outstanding('Purchase Invoice', d.reference_name, doc.company, d);
} else if (d.reference_type==="Sales Invoice" && !flt(d.credit)) {
this.get_outstanding('Sales Invoice', d.reference_name, doc.company, d);
} else if (d.reference_type==="Journal Entry" && !flt(d.credit) && !flt(d.debit)) {
this.get_outstanding('Journal Entry', d.reference_name, doc.company, d);
if (d.reference_name) {
if (d.reference_type === "Purchase Invoice" && !flt(d.debit)) {
this.get_outstanding("Purchase Invoice", d.reference_name, doc.company, d);
} else if (d.reference_type === "Sales Invoice" && !flt(d.credit)) {
this.get_outstanding("Sales Invoice", d.reference_name, doc.company, d);
} else if (d.reference_type === "Journal Entry" && !flt(d.credit) && !flt(d.debit)) {
this.get_outstanding("Journal Entry", d.reference_name, doc.company, d);
}
}
}
get_outstanding(doctype, docname, company, child) {
var args = {
"doctype": doctype,
"docname": docname,
"party": child.party,
"account": child.account,
"account_currency": child.account_currency,
"company": company
}
doctype: doctype,
docname: docname,
party: child.party,
account: child.account,
account_currency: child.account_currency,
company: company,
};
return frappe.call({
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_outstanding",
args: { args: args},
callback: function(r) {
if(r.message) {
$.each(r.message, function(field, value) {
args: { args: args },
callback: function (r) {
if (r.message) {
$.each(r.message, function (field, value) {
frappe.model.set_value(child.doctype, child.name, field, value);
})
});
}
}
},
});
}
accounts_add(doc, cdt, cdn) {
var row = frappe.get_doc(cdt, cdn);
$.each(doc.accounts, function(i, d) {
if(d.account && d.party && d.party_type) {
$.each(doc.accounts, function (i, d) {
if (d.account && d.party && d.party_type) {
row.account = d.account;
row.party = d.party;
row.party_type = d.party_type;
@@ -353,8 +368,8 @@ erpnext.accounts.JournalEntry = class JournalEntry extends frappe.ui.form.Contro
});
// set difference
if(doc.difference) {
if(doc.difference > 0) {
if (doc.difference) {
if (doc.difference > 0) {
row.credit_in_account_currency = doc.difference;
row.credit = doc.difference;
} else {
@@ -364,132 +379,141 @@ erpnext.accounts.JournalEntry = class JournalEntry extends frappe.ui.form.Contro
}
cur_frm.cscript.update_totals(doc);
erpnext.accounts.dimensions.copy_dimension_from_first_row(this.frm, cdt, cdn, 'accounts');
erpnext.accounts.dimensions.copy_dimension_from_first_row(this.frm, cdt, cdn, "accounts");
}
};
cur_frm.script_manager.make(erpnext.accounts.JournalEntry);
cur_frm.cscript.update_totals = function(doc) {
var td=0.0; var tc =0.0;
cur_frm.cscript.update_totals = function (doc) {
var td = 0.0;
var tc = 0.0;
var accounts = doc.accounts || [];
for(var i in accounts) {
for (var i in accounts) {
td += flt(accounts[i].debit, precision("debit", accounts[i]));
tc += flt(accounts[i].credit, precision("credit", accounts[i]));
}
var doc = locals[doc.doctype][doc.name];
doc.total_debit = td;
doc.total_credit = tc;
doc.difference = flt((td - tc), precision("difference"));
refresh_many(['total_debit','total_credit','difference']);
}
doc.difference = flt(td - tc, precision("difference"));
refresh_many(["total_debit", "total_credit", "difference"]);
};
cur_frm.cscript.get_balance = function(doc,dt,dn) {
cur_frm.cscript.get_balance = function (doc, dt, dn) {
cur_frm.cscript.update_totals(doc);
cur_frm.call('get_balance', null, () => { cur_frm.refresh(); });
}
cur_frm.call("get_balance", null, () => {
cur_frm.refresh();
});
};
cur_frm.cscript.validate = function(doc,cdt,cdn) {
cur_frm.cscript.validate = function (doc, cdt, cdn) {
cur_frm.cscript.update_totals(doc);
}
};
frappe.ui.form.on("Journal Entry Account", {
party: function(frm, cdt, cdn) {
party: function (frm, cdt, cdn) {
var d = frappe.get_doc(cdt, cdn);
if(!d.account && d.party_type && d.party) {
if(!frm.doc.company) frappe.throw(__("Please select Company"));
if (!d.account && d.party_type && d.party) {
if (!frm.doc.company) frappe.throw(__("Please select Company"));
return frm.call({
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_party_account_and_balance",
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_party_account_and_currency",
child: d,
args: {
company: frm.doc.company,
party_type: d.party_type,
party: d.party,
cost_center: d.cost_center
}
},
});
}
},
cost_center: function(frm, dt, dn) {
erpnext.journal_entry.set_account_balance(frm, dt, dn);
cost_center: function (frm, dt, dn) {
erpnext.journal_entry.set_account_details(frm, dt, dn);
},
account: function(frm, dt, dn) {
erpnext.journal_entry.set_account_balance(frm, dt, dn);
account: function (frm, dt, dn) {
erpnext.journal_entry.set_account_details(frm, dt, dn);
},
debit_in_account_currency: function(frm, cdt, cdn) {
debit_in_account_currency: function (frm, cdt, cdn) {
erpnext.journal_entry.set_exchange_rate(frm, cdt, cdn);
},
credit_in_account_currency: function(frm, cdt, cdn) {
credit_in_account_currency: function (frm, cdt, cdn) {
erpnext.journal_entry.set_exchange_rate(frm, cdt, cdn);
},
debit: function(frm, dt, dn) {
debit: function (frm, dt, dn) {
cur_frm.cscript.update_totals(frm.doc);
},
credit: function(frm, dt, dn) {
credit: function (frm, dt, dn) {
cur_frm.cscript.update_totals(frm.doc);
},
exchange_rate: function(frm, cdt, cdn) {
exchange_rate: function (frm, cdt, cdn) {
var company_currency = frappe.get_doc(":Company", frm.doc.company).default_currency;
var row = locals[cdt][cdn];
if(row.account_currency == company_currency || !frm.doc.multi_currency) {
if (row.account_currency == company_currency || !frm.doc.multi_currency) {
frappe.model.set_value(cdt, cdn, "exchange_rate", 1);
}
erpnext.journal_entry.set_debit_credit_in_company_currency(frm, cdt, cdn);
}
})
},
});
frappe.ui.form.on("Journal Entry Account", "accounts_remove", function(frm) {
frappe.ui.form.on("Journal Entry Account", "accounts_remove", function (frm) {
cur_frm.cscript.update_totals(frm.doc);
});
$.extend(erpnext.journal_entry, {
toggle_fields_based_on_currency: function(frm) {
toggle_fields_based_on_currency: function (frm) {
var fields = ["currency_section", "account_currency", "exchange_rate", "debit", "credit"];
var grid = frm.get_field("accounts").grid;
if(grid) grid.set_column_disp(fields, frm.doc.multi_currency);
if (grid) grid.set_column_disp(fields, frm.doc.multi_currency);
// dynamic label
var field_label_map = {
"debit_in_account_currency": "Debit",
"credit_in_account_currency": "Credit"
debit_in_account_currency: "Debit",
credit_in_account_currency: "Credit",
};
$.each(field_label_map, function (fieldname, label) {
frm.fields_dict.accounts.grid.update_docfield_property(
fieldname,
'label',
frm.doc.multi_currency ? (label + " in Account Currency") : label
"label",
frm.doc.multi_currency ? label + " in Account Currency" : label
);
})
});
},
set_debit_credit_in_company_currency: function(frm, cdt, cdn) {
set_debit_credit_in_company_currency: function (frm, cdt, cdn) {
var row = locals[cdt][cdn];
frappe.model.set_value(cdt, cdn, "debit",
flt(flt(row.debit_in_account_currency)*row.exchange_rate, precision("debit", row)));
frappe.model.set_value(
cdt,
cdn,
"debit",
flt(flt(row.debit_in_account_currency) * row.exchange_rate, precision("debit", row))
);
frappe.model.set_value(cdt, cdn, "credit",
flt(flt(row.credit_in_account_currency)*row.exchange_rate, precision("credit", row)));
frappe.model.set_value(
cdt,
cdn,
"credit",
flt(flt(row.credit_in_account_currency) * row.exchange_rate, precision("credit", row))
);
cur_frm.cscript.update_totals(frm.doc);
},
set_exchange_rate: function(frm, cdt, cdn) {
set_exchange_rate: function (frm, cdt, cdn) {
var company_currency = frappe.get_doc(":Company", frm.doc.company).default_currency;
var row = locals[cdt][cdn];
if(row.account_currency == company_currency || !frm.doc.multi_currency) {
if (row.account_currency == company_currency || !frm.doc.multi_currency) {
row.exchange_rate = 1;
erpnext.journal_entry.set_debit_credit_in_company_currency(frm, cdt, cdn);
} else if (!row.exchange_rate || row.exchange_rate == 1 || row.account_type == "Bank") {
@@ -504,50 +528,70 @@ $.extend(erpnext.journal_entry, {
reference_name: cstr(row.reference_name),
debit: flt(row.debit_in_account_currency),
credit: flt(row.credit_in_account_currency),
exchange_rate: row.exchange_rate
exchange_rate: row.exchange_rate,
},
callback: function(r) {
if(r.message) {
callback: function (r) {
if (r.message) {
row.exchange_rate = r.message;
erpnext.journal_entry.set_debit_credit_in_company_currency(frm, cdt, cdn);
}
}
})
},
});
} else {
erpnext.journal_entry.set_debit_credit_in_company_currency(frm, cdt, cdn);
}
refresh_field("exchange_rate", cdn, "accounts");
},
quick_entry: function(frm) {
quick_entry: function (frm) {
var naming_series_options = frm.fields_dict.naming_series.df.options;
var naming_series_default = frm.fields_dict.naming_series.df.default || naming_series_options.split("\n")[0];
var naming_series_default =
frm.fields_dict.naming_series.df.default || naming_series_options.split("\n")[0];
var dialog = new frappe.ui.Dialog({
title: __("Quick Journal Entry"),
fields: [
{fieldtype: "Currency", fieldname: "debit", label: __("Amount"), reqd: 1},
{fieldtype: "Link", fieldname: "debit_account", label: __("Debit Account"), reqd: 1,
{ fieldtype: "Currency", fieldname: "debit", label: __("Amount"), reqd: 1 },
{
fieldtype: "Link",
fieldname: "debit_account",
label: __("Debit Account"),
reqd: 1,
options: "Account",
get_query: function() {
get_query: function () {
return erpnext.journal_entry.account_query(frm);
}
},
},
{fieldtype: "Link", fieldname: "credit_account", label: __("Credit Account"), reqd: 1,
{
fieldtype: "Link",
fieldname: "credit_account",
label: __("Credit Account"),
reqd: 1,
options: "Account",
get_query: function() {
get_query: function () {
return erpnext.journal_entry.account_query(frm);
}
},
},
{fieldtype: "Date", fieldname: "posting_date", label: __("Date"), reqd: 1,
default: frm.doc.posting_date},
{fieldtype: "Small Text", fieldname: "user_remark", label: __("User Remark")},
{fieldtype: "Select", fieldname: "naming_series", label: __("Series"), reqd: 1,
options: naming_series_options, default: naming_series_default},
]
{
fieldtype: "Date",
fieldname: "posting_date",
label: __("Date"),
reqd: 1,
default: frm.doc.posting_date,
},
{ fieldtype: "Small Text", fieldname: "user_remark", label: __("User Remark") },
{
fieldtype: "Select",
fieldname: "naming_series",
label: __("Series"),
reqd: 1,
options: naming_series_options,
default: naming_series_default,
},
],
});
dialog.set_primary_action(__("Save"), function() {
dialog.set_primary_action(__("Save"), function () {
var btn = this;
var values = dialog.get_values();
@@ -564,11 +608,21 @@ $.extend(erpnext.journal_entry, {
var debit_row = frm.fields_dict.accounts.grid.add_new_row();
frappe.model.set_value(debit_row.doctype, debit_row.name, "account", values.debit_account);
frappe.model.set_value(debit_row.doctype, debit_row.name, "debit_in_account_currency", values.debit);
frappe.model.set_value(
debit_row.doctype,
debit_row.name,
"debit_in_account_currency",
values.debit
);
var credit_row = frm.fields_dict.accounts.grid.add_new_row();
frappe.model.set_value(credit_row.doctype, credit_row.name, "account", values.credit_account);
frappe.model.set_value(credit_row.doctype, credit_row.name, "credit_in_account_currency", values.debit);
frappe.model.set_value(
credit_row.doctype,
credit_row.name,
"credit_in_account_currency",
values.debit
);
frm.save();
@@ -578,36 +632,36 @@ $.extend(erpnext.journal_entry, {
dialog.show();
},
account_query: function(frm) {
account_query: function (frm) {
var filters = {
company: frm.doc.company,
is_group: 0
is_group: 0,
};
if(!frm.doc.multi_currency) {
if (!frm.doc.multi_currency) {
$.extend(filters, {
account_currency: frappe.get_doc(":Company", frm.doc.company).default_currency
account_currency: frappe.get_doc(":Company", frm.doc.company).default_currency,
});
}
return { filters: filters };
},
reverse_journal_entry: function() {
reverse_journal_entry: function () {
frappe.model.open_mapped_doc({
method: "erpnext.accounts.doctype.journal_entry.journal_entry.make_reverse_journal_entry",
frm: cur_frm
})
frm: cur_frm,
});
},
});
$.extend(erpnext.journal_entry, {
set_account_balance: function(frm, dt, dn) {
set_account_details: function (frm, dt, dn) {
var d = locals[dt][dn];
if(d.account) {
if(!frm.doc.company) frappe.throw(__("Please select Company first"));
if(!frm.doc.posting_date) frappe.throw(__("Please select Posting Date first"));
if (d.account) {
if (!frm.doc.company) frappe.throw(__("Please select Company first"));
if (!frm.doc.posting_date) frappe.throw(__("Please select Posting Date first"));
return frappe.call({
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_account_balance_and_party_type",
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_account_details_and_party_type",
args: {
account: d.account,
date: frm.doc.posting_date,
@@ -615,15 +669,14 @@ $.extend(erpnext.journal_entry, {
debit: flt(d.debit_in_account_currency),
credit: flt(d.credit_in_account_currency),
exchange_rate: d.exchange_rate,
cost_center: d.cost_center
},
callback: function(r) {
if(r.message) {
callback: function (r) {
if (r.message) {
$.extend(d, r.message);
erpnext.journal_entry.set_debit_credit_in_company_currency(frm, dt, dn);
refresh_field('accounts');
refresh_field("accounts");
}
}
},
});
}
},

View File

@@ -68,7 +68,6 @@ class JournalEntry(AccountsController):
self.set_print_format_fields()
self.validate_credit_debit_note()
self.validate_empty_accounts_table()
self.set_account_and_party_balance()
self.validate_inter_company_accounts()
self.validate_depr_entry_voucher_type()
@@ -475,17 +474,28 @@ class JournalEntry(AccountsController):
elif d.party_type == "Supplier" and flt(d.credit) > 0:
frappe.throw(_("Row {0}: Advance against Supplier must be debit").format(d.idx))
def system_generated_gain_loss(self):
return (
self.voucher_type == "Exchange Gain Or Loss"
and self.multi_currency
and self.is_system_generated
)
def validate_against_jv(self):
for d in self.get("accounts"):
if d.reference_type == "Journal Entry":
account_root_type = frappe.db.get_value("Account", d.account, "root_type")
if account_root_type == "Asset" and flt(d.debit) > 0:
account_root_type = frappe.get_cached_value("Account", d.account, "root_type")
if account_root_type == "Asset" and flt(d.debit) > 0 and not self.system_generated_gain_loss():
frappe.throw(
_(
"Row #{0}: For {1}, you can select reference document only if account gets credited"
).format(d.idx, d.account)
)
elif account_root_type == "Liability" and flt(d.credit) > 0:
elif (
account_root_type == "Liability"
and flt(d.credit) > 0
and not self.system_generated_gain_loss()
):
frappe.throw(
_(
"Row #{0}: For {1}, you can select reference document only if account gets debited"
@@ -517,7 +527,7 @@ class JournalEntry(AccountsController):
for jvd in against_entries:
if flt(jvd[dr_or_cr]) > 0:
valid = True
if not valid:
if not valid and not self.system_generated_gain_loss():
frappe.throw(
_("Against Journal Entry {0} does not have any unmatched {1} entry").format(
d.reference_name, dr_or_cr
@@ -1065,21 +1075,6 @@ class JournalEntry(AccountsController):
if not self.get("accounts"):
frappe.throw(_("Accounts table cannot be blank."))
def set_account_and_party_balance(self):
account_balance = {}
party_balance = {}
for d in self.get("accounts"):
if d.account not in account_balance:
account_balance[d.account] = get_balance_on(account=d.account, date=self.posting_date)
if (d.party_type, d.party) not in party_balance:
party_balance[(d.party_type, d.party)] = get_balance_on(
party_type=d.party_type, party=d.party, date=self.posting_date, company=self.company
)
d.account_balance = account_balance[d.account]
d.party_balance = party_balance[(d.party_type, d.party)]
@frappe.whitelist()
def get_default_bank_cash_account(company, account_type=None, mode_of_payment=None, account=None):
@@ -1245,8 +1240,6 @@ def get_payment_entry(ref_doc, args):
"account_type": frappe.db.get_value("Account", args.get("party_account"), "account_type"),
"account_currency": args.get("party_account_currency")
or get_account_currency(args.get("party_account")),
"balance": get_balance_on(args.get("party_account")),
"party_balance": get_balance_on(party=args.get("party"), party_type=args.get("party_type")),
"exchange_rate": exchange_rate,
args.get("amount_field_party"): args.get("amount"),
"is_advance": args.get("is_advance"),
@@ -1394,30 +1387,23 @@ def get_outstanding(args):
@frappe.whitelist()
def get_party_account_and_balance(company, party_type, party, cost_center=None):
def get_party_account_and_currency(company, party_type, party):
if not frappe.has_permission("Account"):
frappe.msgprint(_("No Permission"), raise_exception=1)
account = get_party_account(party_type, party, company)
account_balance = get_balance_on(account=account, cost_center=cost_center)
party_balance = get_balance_on(
party_type=party_type, party=party, company=company, cost_center=cost_center
)
return {
"account": account,
"balance": account_balance,
"party_balance": party_balance,
"account_currency": frappe.db.get_value("Account", account, "account_currency"),
"account_currency": frappe.get_cached_value("Account", account, "account_currency"),
}
@frappe.whitelist()
def get_account_balance_and_party_type(
account, date, company, debit=None, credit=None, exchange_rate=None, cost_center=None
def get_account_details_and_party_type(
account, date, company, debit=None, credit=None, exchange_rate=None
):
"""Returns dict of account balance and party type to be set in Journal Entry on selection of account."""
"""Returns dict of account details and party type to be set in Journal Entry on selection of account."""
if not frappe.has_permission("Account"):
frappe.msgprint(_("No Permission"), raise_exception=1)
@@ -1437,7 +1423,6 @@ def get_account_balance_and_party_type(
party_type = ""
grid_values = {
"balance": get_balance_on(account, date, cost_center=cost_center),
"party_type": party_type,
"account_type": account_details.account_type,
"account_currency": account_details.account_currency or company_currency,

View File

@@ -1,12 +1,12 @@
frappe.listview_settings['Journal Entry'] = {
frappe.listview_settings["Journal Entry"] = {
add_fields: ["voucher_type", "posting_date", "total_debit", "company", "user_remark"],
get_indicator: function(doc) {
if(doc.docstatus==0) {
return [__("Draft", "red", "docstatus,=,0")]
} else if(doc.docstatus==2) {
return [__("Cancelled", "grey", "docstatus,=,2")]
get_indicator: function (doc) {
if (doc.docstatus == 0) {
return [__("Draft", "red", "docstatus,=,0")];
} else if (doc.docstatus == 2) {
return [__("Cancelled", "grey", "docstatus,=,2")];
} else {
return [__(doc.voucher_type), "blue", "voucher_type,=," + doc.voucher_type]
return [__(doc.voucher_type), "blue", "voucher_type,=," + doc.voucher_type];
}
}
},
};

View File

@@ -9,12 +9,10 @@
"field_order": [
"account",
"account_type",
"balance",
"col_break1",
"bank_account",
"party_type",
"party",
"party_balance",
"accounting_dimensions_section",
"cost_center",
"dimension_col_break",
@@ -63,17 +61,6 @@
"label": "Account Type",
"print_hide": 1
},
{
"fieldname": "balance",
"fieldtype": "Currency",
"label": "Account Balance",
"no_copy": 1,
"oldfieldname": "balance",
"oldfieldtype": "Data",
"options": "account_currency",
"print_hide": 1,
"read_only": 1
},
{
"default": ":Company",
"description": "If Income or Expense",
@@ -107,14 +94,6 @@
"label": "Party",
"options": "party_type"
},
{
"fieldname": "party_balance",
"fieldtype": "Currency",
"label": "Party Balance",
"options": "account_currency",
"print_hide": 1,
"read_only": 1
},
{
"fieldname": "currency_section",
"fieldtype": "Section Break",

View File

@@ -2,78 +2,82 @@
// For license information, please see license.txt
frappe.ui.form.on("Journal Entry Template", {
onload: function(frm) {
if(frm.is_new()) {
onload: function (frm) {
if (frm.is_new()) {
frappe.call({
type: "GET",
method: "erpnext.accounts.doctype.journal_entry_template.journal_entry_template.get_naming_series",
callback: function(r){
if(r.message) {
callback: function (r) {
if (r.message) {
frm.set_df_property("naming_series", "options", r.message.split("\n"));
frm.set_value("naming_series", r.message.split("\n")[0]);
frm.refresh_field("naming_series");
}
}
},
});
}
},
refresh: function(frm) {
refresh: function (frm) {
frappe.model.set_default_values(frm.doc);
frm.set_query("account" ,"accounts", function(){
frm.set_query("account", "accounts", function () {
var filters = {
company: frm.doc.company,
is_group: 0
is_group: 0,
};
if(!frm.doc.multi_currency) {
if (!frm.doc.multi_currency) {
$.extend(filters, {
account_currency: frappe.get_doc(":Company", frm.doc.company).default_currency
account_currency: frappe.get_doc(":Company", frm.doc.company).default_currency,
});
}
return { filters: filters };
});
},
voucher_type: function(frm) {
var add_accounts = function(doc, r) {
$.each(r, function(i, d) {
voucher_type: function (frm) {
var add_accounts = function (doc, r) {
$.each(r, function (i, d) {
var row = frappe.model.add_child(doc, "Journal Entry Template Account", "accounts");
row.account = d.account;
});
refresh_field("accounts");
};
if(!frm.doc.company) return;
if (!frm.doc.company) return;
frm.trigger("clear_child");
switch(frm.doc.voucher_type){
switch (frm.doc.voucher_type) {
case "Bank Entry":
case "Cash Entry":
frappe.call({
type: "GET",
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_default_bank_cash_account",
args: {
"account_type": (frm.doc.voucher_type=="Bank Entry" ?
"Bank" : (frm.doc.voucher_type=="Cash Entry" ? "Cash" : null)),
"company": frm.doc.company
account_type:
frm.doc.voucher_type == "Bank Entry"
? "Bank"
: frm.doc.voucher_type == "Cash Entry"
? "Cash"
: null,
company: frm.doc.company,
},
callback: function(r) {
if(r.message) {
callback: function (r) {
if (r.message) {
// If default company bank account not set
if(!$.isEmptyObject(r.message)){
if (!$.isEmptyObject(r.message)) {
add_accounts(frm.doc, [r.message]);
}
}
}
},
});
break;
default:
frm.trigger("clear_child");
}
},
clear_child: function(frm){
clear_child: function (frm) {
frappe.model.clear_table(frm.doc, "accounts");
frm.refresh_field("accounts");
}
},
});

View File

@@ -1,9 +1,9 @@
// Copyright (c) 2021, Wahni Green Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Ledger Merge', {
setup: function(frm) {
frappe.realtime.on('ledger_merge_refresh', ({ ledger_merge }) => {
frappe.ui.form.on("Ledger Merge", {
setup: function (frm) {
frappe.realtime.on("ledger_merge_refresh", ({ ledger_merge }) => {
if (ledger_merge !== frm.doc.name) return;
frappe.model.clear_doc(frm.doc.doctype, frm.doc.name);
frappe.model.with_doc(frm.doc.doctype, frm.doc.name).then(() => {
@@ -11,29 +11,29 @@ frappe.ui.form.on('Ledger Merge', {
});
});
frappe.realtime.on('ledger_merge_progress', data => {
frappe.realtime.on("ledger_merge_progress", (data) => {
if (data.ledger_merge !== frm.doc.name) return;
let message = __('Merging {0} of {1}', [data.current, data.total]);
let message = __("Merging {0} of {1}", [data.current, data.total]);
let percent = Math.floor((data.current * 100) / data.total);
frm.dashboard.show_progress(__('Merge Progress'), percent, message);
frm.page.set_indicator(__('In Progress'), 'orange');
frm.dashboard.show_progress(__("Merge Progress"), percent, message);
frm.page.set_indicator(__("In Progress"), "orange");
});
frm.set_query("account", function(doc) {
if (!doc.company) frappe.throw(__('Please set Company'));
if (!doc.root_type) frappe.throw(__('Please set Root Type'));
frm.set_query("account", function (doc) {
if (!doc.company) frappe.throw(__("Please set Company"));
if (!doc.root_type) frappe.throw(__("Please set Root Type"));
return {
filters: {
root_type: doc.root_type,
company: doc.company
}
company: doc.company,
},
};
});
frm.set_query('account', 'merge_accounts', function(doc) {
if (!doc.company) frappe.throw(__('Please set Company'));
if (!doc.root_type) frappe.throw(__('Please set Root Type'));
if (!doc.account) frappe.throw(__('Please set Account'));
frm.set_query("account", "merge_accounts", function (doc) {
if (!doc.company) frappe.throw(__("Please set Company"));
if (!doc.root_type) frappe.throw(__("Please set Root Type"));
if (!doc.account) frappe.throw(__("Please set Account"));
let acc = [doc.account];
frm.doc.merge_accounts.forEach((row) => {
acc.push(row.account);
@@ -43,86 +43,86 @@ frappe.ui.form.on('Ledger Merge', {
is_group: doc.is_group,
root_type: doc.root_type,
name: ["not in", acc],
company: doc.company
}
company: doc.company,
},
};
});
},
refresh: function(frm) {
refresh: function (frm) {
frm.page.hide_icon_group();
frm.trigger('set_merge_status');
frm.trigger('update_primary_action');
frm.trigger("set_merge_status");
frm.trigger("update_primary_action");
},
after_save: function(frm) {
after_save: function (frm) {
setTimeout(() => {
frm.trigger('update_primary_action');
frm.trigger("update_primary_action");
}, 500);
},
update_primary_action: function(frm) {
update_primary_action: function (frm) {
if (frm.is_dirty()) {
frm.enable_save();
return;
}
frm.disable_save();
if (frm.doc.status !== 'Success') {
if (frm.doc.status !== "Success") {
if (!frm.is_new()) {
let label = frm.doc.status === 'Pending' ? __('Start Merge') : __('Retry');
let label = frm.doc.status === "Pending" ? __("Start Merge") : __("Retry");
frm.page.set_primary_action(label, () => frm.events.start_merge(frm));
} else {
frm.page.set_primary_action(__('Save'), () => frm.save());
frm.page.set_primary_action(__("Save"), () => frm.save());
}
}
},
start_merge: function(frm) {
start_merge: function (frm) {
frm.call({
method: 'form_start_merge',
method: "form_start_merge",
args: { docname: frm.doc.name },
btn: frm.page.btn_primary
}).then(r => {
btn: frm.page.btn_primary,
}).then((r) => {
if (r.message === true) {
frm.disable_save();
}
});
},
set_merge_status: function(frm) {
set_merge_status: function (frm) {
if (frm.doc.status == "Pending") return;
let successful_records = 0;
frm.doc.merge_accounts.forEach((row) => {
if (row.merged) successful_records += 1;
});
let message_args = [successful_records, frm.doc.merge_accounts.length];
frm.dashboard.set_headline(__('Successfully merged {0} out of {1}.', message_args));
frm.dashboard.set_headline(__("Successfully merged {0} out of {1}.", message_args));
},
root_type: function(frm) {
frm.set_value('account', '');
frm.set_value('merge_accounts', []);
root_type: function (frm) {
frm.set_value("account", "");
frm.set_value("merge_accounts", []);
},
company: function(frm) {
frm.set_value('account', '');
frm.set_value('merge_accounts', []);
}
company: function (frm) {
frm.set_value("account", "");
frm.set_value("merge_accounts", []);
},
});
frappe.ui.form.on('Ledger Merge Accounts', {
merge_accounts_add: function(frm) {
frm.trigger('update_primary_action');
frappe.ui.form.on("Ledger Merge Accounts", {
merge_accounts_add: function (frm) {
frm.trigger("update_primary_action");
},
merge_accounts_remove: function(frm) {
frm.trigger('update_primary_action');
merge_accounts_remove: function (frm) {
frm.trigger("update_primary_action");
},
account: function(frm, cdt, cdn) {
account: function (frm, cdt, cdn) {
let row = frappe.get_doc(cdt, cdn);
row.account_name = row.account;
frm.refresh_field('merge_accounts');
frm.trigger('update_primary_action');
}
frm.refresh_field("merge_accounts");
frm.trigger("update_primary_action");
},
});

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('Loyalty Point Entry', {
refresh: function(frm) {
}
frappe.ui.form.on("Loyalty Point Entry", {
refresh: function (frm) {},
});

View File

@@ -3,30 +3,37 @@
frappe.provide("erpnext.accounts.dimensions");
frappe.ui.form.on('Loyalty Program', {
setup: function(frm) {
var help_content =
`<table class="table table-bordered" style="background-color: var(--scrollbar-track-color);">
frappe.ui.form.on("Loyalty Program", {
setup: function (frm) {
var help_content = `<table class="table table-bordered" style="background-color: var(--scrollbar-track-color);">
<tr><td>
<h4>
<i class="fa fa-hand-right"></i>
${__('Notes')}
${__("Notes")}
</h4>
<ul>
<li>
${__("Loyalty Points will be calculated from the spent done (via the Sales Invoice), based on collection factor mentioned.")}
${__(
"Loyalty Points will be calculated from the spent done (via the Sales Invoice), based on collection factor mentioned."
)}
</li>
<li>
${__("There can be multiple tiered collection factor based on the total spent. But the conversion factor for redemption will always be same for all the tier.")}
${__(
"There can be multiple tiered collection factor based on the total spent. But the conversion factor for redemption will always be same for all the tier."
)}
</li>
<li>
${__("In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent")}
${__(
"In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent"
)}
</li>
<li>
${__("If unlimited expiry for the Loyalty Points, keep the Expiry Duration empty or 0.")}
</li>
<li>
${__("If Auto Opt In is checked, then the customers will be automatically linked with the concerned Loyalty Program (on save)")}
${__(
"If Auto Opt In is checked, then the customers will be automatically linked with the concerned Loyalty Program (on save)"
)}
</li>
<li>
${__("One customer can be part of only single Loyalty Program.")}
@@ -37,14 +44,14 @@ frappe.ui.form.on('Loyalty Program', {
set_field_options("loyalty_program_help", help_content);
},
onload: function(frm) {
frm.set_query("expense_account", function(doc) {
onload: function (frm) {
frm.set_query("expense_account", function (doc) {
return {
filters: {
"root_type": "Expense",
'is_group': 0,
'company': doc.company
}
root_type: "Expense",
is_group: 0,
company: doc.company,
},
};
});
@@ -52,13 +59,15 @@ frappe.ui.form.on('Loyalty Program', {
erpnext.accounts.dimensions.setup_dimension_filters(frm, frm.doctype);
},
refresh: function(frm) {
refresh: function (frm) {
if (frm.doc.loyalty_program_type === "Single Tier Program" && frm.doc.collection_rules.length > 1) {
frappe.throw(__("Please select the Multiple Tier Program type for more than one collection rules."));
frappe.throw(
__("Please select the Multiple Tier Program type for more than one collection rules.")
);
}
},
company: function(frm) {
company: function (frm) {
erpnext.accounts.dimensions.update_dimension(frm, frm.doctype);
}
},
});

View File

@@ -1,16 +1,16 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
frappe.ui.form.on('Mode of Payment', {
setup: function(frm) {
frm.set_query("default_account", "accounts", function(doc, cdt, cdn) {
frappe.ui.form.on("Mode of Payment", {
setup: function (frm) {
frm.set_query("default_account", "accounts", function (doc, cdt, cdn) {
let d = locals[cdt][cdn];
return {
filters: [
['Account', 'account_type', 'in', 'Bank, Cash, Receivable'],
['Account', 'is_group', '=', 0],
['Account', 'company', '=', d.company]
]
["Account", "account_type", "in", "Bank, Cash, Receivable"],
["Account", "is_group", "=", 0],
["Account", "company", "=", d.company],
],
};
});
},

View File

@@ -1,16 +1,16 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
frappe.ui.form.on('Monthly Distribution', {
frappe.ui.form.on("Monthly Distribution", {
onload(frm) {
if(frm.doc.__islocal) {
return frm.call('get_months').then(() => {
frm.refresh_field('percentages');
if (frm.doc.__islocal) {
return frm.call("get_months").then(() => {
frm.refresh_field("percentages");
});
}
},
refresh(frm) {
frm.toggle_display('distribution_id', frm.doc.__islocal);
}
frm.toggle_display("distribution_id", frm.doc.__islocal);
},
});

View File

@@ -1,48 +1,52 @@
// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Opening Invoice Creation Tool', {
setup: function(frm) {
frm.set_query('party_type', 'invoices', function(doc, cdt, cdn) {
frappe.ui.form.on("Opening Invoice Creation Tool", {
setup: function (frm) {
frm.set_query("party_type", "invoices", function (doc, cdt, cdn) {
return {
filters: {
'name': ['in', 'Customer, Supplier']
}
name: ["in", "Customer, Supplier"],
},
};
});
if (frm.doc.company) {
frm.trigger('setup_company_filters');
frm.trigger("setup_company_filters");
}
frappe.realtime.on('opening_invoice_creation_progress', data => {
frappe.realtime.on("opening_invoice_creation_progress", (data) => {
if (!frm.doc.import_in_progress) {
frm.dashboard.reset();
frm.doc.import_in_progress = true;
}
if (data.count == data.total) {
setTimeout(() => {
frm.doc.import_in_progress = false;
frm.clear_table("invoices");
frm.refresh_fields();
frm.page.clear_indicator();
frm.dashboard.hide_progress();
frappe.msgprint(__("Opening {0} Invoices created", [frm.doc.invoice_type]));
}, 1500, data.title);
setTimeout(
() => {
frm.doc.import_in_progress = false;
frm.clear_table("invoices");
frm.refresh_fields();
frm.page.clear_indicator();
frm.dashboard.hide_progress();
frappe.msgprint(__("Opening {0} Invoices created", [frm.doc.invoice_type]));
},
1500,
data.title
);
return;
}
frm.dashboard.show_progress(data.title, (data.count / data.total) * 100, data.message);
frm.page.set_indicator(__('In Progress'), 'orange');
frm.page.set_indicator(__("In Progress"), "orange");
});
erpnext.accounts.dimensions.setup_dimension_filters(frm, frm.doctype);
},
refresh: function(frm) {
refresh: function (frm) {
frm.disable_save();
!frm.doc.import_in_progress && frm.trigger("make_dashboard");
frm.page.set_primary_action(__('Create Invoices'), () => {
frm.page.set_primary_action(__("Create Invoices"), () => {
let btn_primary = frm.page.btn_primary.get(0);
return frm.call({
doc: frm.doc,
@@ -58,100 +62,98 @@ frappe.ui.form.on('Opening Invoice Creation Tool', {
}
},
setup_company_filters: function(frm) {
frm.set_query('cost_center', 'invoices', function(doc, cdt, cdn) {
setup_company_filters: function (frm) {
frm.set_query("cost_center", "invoices", function (doc, cdt, cdn) {
return {
filters: {
'company': doc.company
}
company: doc.company,
},
};
});
frm.set_query('cost_center', function(doc) {
frm.set_query("cost_center", function (doc) {
return {
filters: {
'company': doc.company
}
company: doc.company,
},
};
});
frm.set_query('temporary_opening_account', 'invoices', function(doc, cdt, cdn) {
frm.set_query("temporary_opening_account", "invoices", function (doc, cdt, cdn) {
return {
filters: {
'company': doc.company
}
}
company: doc.company,
},
};
});
},
company: function(frm) {
company: function (frm) {
if (frm.doc.company) {
frm.trigger('setup_company_filters');
frm.trigger("setup_company_filters");
frappe.call({
method: 'erpnext.accounts.doctype.opening_invoice_creation_tool.opening_invoice_creation_tool.get_temporary_opening_account',
method: "erpnext.accounts.doctype.opening_invoice_creation_tool.opening_invoice_creation_tool.get_temporary_opening_account",
args: {
company: frm.doc.company
company: frm.doc.company,
},
callback: (r) => {
if (r.message) {
frm.doc.__onload.temporary_opening_account = r.message;
frm.trigger('update_invoice_table');
frm.trigger("update_invoice_table");
}
}
})
},
});
}
erpnext.accounts.dimensions.update_dimension(frm, frm.doctype);
},
invoice_type: function(frm) {
invoice_type: function (frm) {
$.each(frm.doc.invoices, (idx, row) => {
row.party_type = frm.doc.invoice_type == "Sales"? "Customer": "Supplier";
row.party_type = frm.doc.invoice_type == "Sales" ? "Customer" : "Supplier";
row.party = "";
});
frm.refresh_fields();
},
make_dashboard: function(frm) {
make_dashboard: function (frm) {
let max_count = frm.doc.__onload.max_count;
let opening_invoices_summary = frm.doc.__onload.opening_invoices_summary;
if(!$.isEmptyObject(opening_invoices_summary)) {
if (!$.isEmptyObject(opening_invoices_summary)) {
let section = frm.dashboard.add_section(
frappe.render_template('opening_invoice_creation_tool_dashboard', {
frappe.render_template("opening_invoice_creation_tool_dashboard", {
data: opening_invoices_summary,
max_count: max_count
max_count: max_count,
}),
__("Opening Invoices Summary")
);
section.on('click', '.invoice-link', function() {
let doctype = $(this).attr('data-type');
let company = $(this).attr('data-company');
frappe.set_route('List', doctype,
{'is_opening': 'Yes', 'company': company, 'docstatus': 1});
section.on("click", ".invoice-link", function () {
let doctype = $(this).attr("data-type");
let company = $(this).attr("data-company");
frappe.set_route("List", doctype, { is_opening: "Yes", company: company, docstatus: 1 });
});
frm.dashboard.show();
}
},
update_invoice_table: function(frm) {
update_invoice_table: function (frm) {
$.each(frm.doc.invoices, (idx, row) => {
if (!row.temporary_opening_account) {
row.temporary_opening_account = frm.doc.__onload.temporary_opening_account;
}
if(!row.cost_center) {
if (!row.cost_center) {
row.cost_center = frm.doc.cost_center;
}
row.party_type = frm.doc.invoice_type == "Sales"? "Customer": "Supplier";
row.party_type = frm.doc.invoice_type == "Sales" ? "Customer" : "Supplier";
});
}
},
});
frappe.ui.form.on('Opening Invoice Creation Tool Item', {
frappe.ui.form.on("Opening Invoice Creation Tool Item", {
invoices_add: (frm) => {
frm.trigger('update_invoice_table');
}
frm.trigger("update_invoice_table");
},
});

View File

@@ -1,33 +1,34 @@
// Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Party Link', {
refresh: function(frm) {
frm.set_query('primary_role', () => {
frappe.ui.form.on("Party Link", {
refresh: function (frm) {
frm.set_query("primary_role", () => {
return {
filters: {
name: ['in', ['Customer', 'Supplier']]
}
name: ["in", ["Customer", "Supplier"]],
},
};
});
frm.set_query('secondary_role', () => {
let party_types = Object.keys(frappe.boot.party_account_types)
.filter(p => p != frm.doc.primary_role);
frm.set_query("secondary_role", () => {
let party_types = Object.keys(frappe.boot.party_account_types).filter(
(p) => p != frm.doc.primary_role
);
return {
filters: {
name: ['in', party_types]
}
name: ["in", party_types],
},
};
});
},
primary_role(frm) {
frm.set_value('primary_party', '');
frm.set_value('secondary_role', '');
frm.set_value("primary_party", "");
frm.set_value("secondary_role", "");
},
secondary_role(frm) {
frm.set_value('secondary_party', '');
}
frm.set_value("secondary_party", "");
},
});

View File

@@ -335,7 +335,10 @@ class PaymentEntry(AccountsController):
)
def set_missing_ref_details(
self, force: bool = False, update_ref_details_only_for: list | None = None
self,
force: bool = False,
update_ref_details_only_for: list | None = None,
ref_exchange_rate: float | None = None,
) -> None:
for d in self.get("references"):
if d.allocated_amount:
@@ -347,6 +350,8 @@ class PaymentEntry(AccountsController):
ref_details = get_reference_details(
d.reference_doctype, d.reference_name, self.party_account_currency
)
if ref_exchange_rate:
ref_details.update({"exchange_rate": ref_exchange_rate})
for field, value in ref_details.items():
if d.exchange_gain_loss:

View File

@@ -1,14 +1,13 @@
frappe.listview_settings['Payment Entry'] = {
onload: function(listview) {
frappe.listview_settings["Payment Entry"] = {
onload: function (listview) {
if (listview.page.fields_dict.party_type) {
listview.page.fields_dict.party_type.get_query = function() {
listview.page.fields_dict.party_type.get_query = function () {
return {
"filters": {
"name": ["in", Object.keys(frappe.boot.party_account_types)],
}
filters: {
name: ["in", Object.keys(frappe.boot.party_account_types)],
},
};
};
}
}
},
};

View File

@@ -1,11 +1,11 @@
// Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
frappe.ui.form.on('Payment Gateway Account', {
frappe.ui.form.on("Payment Gateway Account", {
refresh(frm) {
erpnext.utils.check_payments_app();
if(!frm.doc.__islocal) {
frm.set_df_property('payment_gateway', 'read_only', 1);
if (!frm.doc.__islocal) {
frm.set_df_property("payment_gateway", "read_only", 1);
}
}
},
});

View File

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

View File

@@ -132,11 +132,12 @@ class PaymentLedgerEntry(Document):
def on_update(self):
adv_adj = self.flags.adv_adj
if not self.flags.from_repost:
self.validate_account_details()
self.validate_dimensions_for_pl_and_bs()
self.validate_allowed_dimensions()
validate_balance_type(self.account, adv_adj)
validate_frozen_account(self.account, adv_adj)
if not self.delinked:
self.validate_account_details()
self.validate_dimensions_for_pl_and_bs()
self.validate_allowed_dimensions()
validate_balance_type(self.account, adv_adj)
# update outstanding amount
if (

View File

@@ -1,61 +1,69 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Payment Order', {
setup: function(frm) {
frm.set_query("company_bank_account", function() {
frappe.ui.form.on("Payment Order", {
setup: function (frm) {
frm.set_query("company_bank_account", function () {
return {
filters: {
"is_company_account":1
}
}
is_company_account: 1,
},
};
});
frm.set_df_property('references', 'cannot_add_rows', true);
frm.set_df_property("references", "cannot_add_rows", true);
},
refresh: function(frm) {
refresh: function (frm) {
if (frm.doc.docstatus == 0) {
frm.add_custom_button(__('Payment Request'), function() {
frm.trigger("get_from_payment_request");
}, __("Get Payments from"));
frm.add_custom_button(
__("Payment Request"),
function () {
frm.trigger("get_from_payment_request");
},
__("Get Payments from")
);
frm.add_custom_button(__('Payment Entry'), function() {
frm.trigger("get_from_payment_entry");
}, __("Get Payments from"));
frm.add_custom_button(
__("Payment Entry"),
function () {
frm.trigger("get_from_payment_entry");
},
__("Get Payments from")
);
frm.trigger('remove_button');
frm.trigger("remove_button");
}
// payment Entry
if (frm.doc.docstatus===1 && frm.doc.payment_order_type==='Payment Request') {
frm.add_custom_button(__('Create Payment Entries'), function() {
if (frm.doc.docstatus === 1 && frm.doc.payment_order_type === "Payment Request") {
frm.add_custom_button(__("Create Payment Entries"), function () {
frm.trigger("make_payment_records");
});
}
},
remove_row_if_empty: function(frm) {
remove_row_if_empty: function (frm) {
// remove if first row is empty
if (frm.doc.references.length > 0 && !frm.doc.references[0].reference_name) {
frm.doc.references = [];
}
},
remove_button: function(frm) {
remove_button: function (frm) {
// remove custom button of order type that is not imported
let label = ["Payment Request", "Payment Entry"];
if (frm.doc.references.length > 0 && frm.doc.payment_order_type) {
label = label.reduce(x => {
x!= frm.doc.payment_order_type;
label = label.reduce((x) => {
x != frm.doc.payment_order_type;
return x;
});
frm.remove_custom_button(label, "Get from");
}
},
get_from_payment_entry: function(frm) {
get_from_payment_entry: function (frm) {
frm.trigger("remove_row_if_empty");
erpnext.utils.map_current_doc({
method: "erpnext.accounts.doctype.payment_entry.payment_entry.make_payment_order",
@@ -63,7 +71,7 @@ frappe.ui.form.on('Payment Order', {
target: frm,
date_field: "posting_date",
setters: {
party: frm.doc.supplier || ""
party: frm.doc.supplier || "",
},
get_query_filters: {
bank: frm.doc.bank,
@@ -71,70 +79,79 @@ frappe.ui.form.on('Payment Order', {
payment_type: ["!=", "Receive"],
bank_account: frm.doc.company_bank_account,
paid_from: frm.doc.account,
payment_order_status: ["=", "Initiated"]
}
payment_order_status: ["=", "Initiated"],
},
});
},
get_from_payment_request: function(frm) {
get_from_payment_request: function (frm) {
frm.trigger("remove_row_if_empty");
erpnext.utils.map_current_doc({
method: "erpnext.accounts.doctype.payment_request.payment_request.make_payment_order",
source_doctype: "Payment Request",
target: frm,
setters: {
party: frm.doc.supplier || ""
party: frm.doc.supplier || "",
},
get_query_filters: {
bank: frm.doc.bank,
docstatus: 1,
status: ["=", "Initiated"],
}
},
});
},
make_payment_records: function(frm){
make_payment_records: function (frm) {
var dialog = new frappe.ui.Dialog({
title: __("For Supplier"),
fields: [
{"fieldtype": "Link", "label": __("Supplier"), "fieldname": "supplier", "options":"Supplier",
"get_query": function () {
{
fieldtype: "Link",
label: __("Supplier"),
fieldname: "supplier",
options: "Supplier",
get_query: function () {
return {
query:"erpnext.accounts.doctype.payment_order.payment_order.get_supplier_query",
filters: {'parent': frm.doc.name}
}
}, "reqd": 1
query: "erpnext.accounts.doctype.payment_order.payment_order.get_supplier_query",
filters: { parent: frm.doc.name },
};
},
reqd: 1,
},
{"fieldtype": "Link", "label": __("Mode of Payment"), "fieldname": "mode_of_payment", "options":"Mode of Payment",
"get_query": function () {
{
fieldtype: "Link",
label: __("Mode of Payment"),
fieldname: "mode_of_payment",
options: "Mode of Payment",
get_query: function () {
return {
query:"erpnext.accounts.doctype.payment_order.payment_order.get_mop_query",
filters: {'parent': frm.doc.name}
}
}
}
]
query: "erpnext.accounts.doctype.payment_order.payment_order.get_mop_query",
filters: { parent: frm.doc.name },
};
},
},
],
});
dialog.set_primary_action(__("Submit"), function() {
dialog.set_primary_action(__("Submit"), function () {
var args = dialog.get_values();
if(!args) return;
if (!args) return;
return frappe.call({
method: "erpnext.accounts.doctype.payment_order.payment_order.make_payment_records",
args: {
"name": me.frm.doc.name,
"supplier": args.supplier,
"mode_of_payment": args.mode_of_payment
name: me.frm.doc.name,
supplier: args.supplier,
mode_of_payment: args.mode_of_payment,
},
freeze: true,
callback: function(r) {
callback: function (r) {
dialog.hide();
frm.refresh();
}
})
})
},
});
});
dialog.show();
},

View File

@@ -2,85 +2,82 @@
// For license information, please see license.txt
frappe.provide("erpnext.accounts");
erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationController extends frappe.ui.form.Controller {
erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationController extends (
frappe.ui.form.Controller
) {
onload() {
const default_company = frappe.defaults.get_default('company');
this.frm.set_value('company', default_company);
const default_company = frappe.defaults.get_default("company");
this.frm.set_value("company", default_company);
this.frm.set_value('party_type', '');
this.frm.set_value('party', '');
this.frm.set_value('receivable_payable_account', '');
this.frm.set_value("party_type", "");
this.frm.set_value("party", "");
this.frm.set_value("receivable_payable_account", "");
this.frm.set_query("party_type", () => {
return {
"filters": {
"name": ["in", Object.keys(frappe.boot.party_account_types)],
}
}
});
this.frm.set_query('receivable_payable_account', () => {
return {
filters: {
"company": this.frm.doc.company,
"is_group": 0,
"account_type": frappe.boot.party_account_types[this.frm.doc.party_type]
}
name: ["in", Object.keys(frappe.boot.party_account_types)],
},
};
});
this.frm.set_query('bank_cash_account', () => {
this.frm.set_query("receivable_payable_account", () => {
return {
filters:[
['Account', 'company', '=', this.frm.doc.company],
['Account', 'is_group', '=', 0],
['Account', 'account_type', 'in', ['Bank', 'Cash']]
]
filters: {
company: this.frm.doc.company,
is_group: 0,
account_type: frappe.boot.party_account_types[this.frm.doc.party_type],
},
};
});
this.frm.set_query("bank_cash_account", () => {
return {
filters: [
["Account", "company", "=", this.frm.doc.company],
["Account", "is_group", "=", 0],
["Account", "account_type", "in", ["Bank", "Cash"]],
],
};
});
this.frm.set_query("cost_center", () => {
return {
"filters": {
"company": this.frm.doc.company,
"is_group": 0
}
}
filters: {
company: this.frm.doc.company,
is_group: 0,
},
};
});
}
refresh() {
this.frm.disable_save();
this.frm.set_df_property('invoices', 'cannot_delete_rows', true);
this.frm.set_df_property('payments', 'cannot_delete_rows', true);
this.frm.set_df_property('allocation', 'cannot_delete_rows', true);
this.frm.set_df_property('invoices', 'cannot_add_rows', true);
this.frm.set_df_property('payments', 'cannot_add_rows', true);
this.frm.set_df_property('allocation', 'cannot_add_rows', true);
this.frm.set_df_property("invoices", "cannot_delete_rows", true);
this.frm.set_df_property("payments", "cannot_delete_rows", true);
this.frm.set_df_property("allocation", "cannot_delete_rows", true);
this.frm.set_df_property("invoices", "cannot_add_rows", true);
this.frm.set_df_property("payments", "cannot_add_rows", true);
this.frm.set_df_property("allocation", "cannot_add_rows", true);
if (this.frm.doc.receivable_payable_account) {
this.frm.add_custom_button(__('Get Unreconciled Entries'), () =>
this.frm.add_custom_button(__("Get Unreconciled Entries"), () =>
this.frm.trigger("get_unreconciled_entries")
);
this.frm.change_custom_button_type('Get Unreconciled Entries', null, 'primary');
this.frm.change_custom_button_type("Get Unreconciled Entries", null, "primary");
}
if (this.frm.doc.invoices.length && this.frm.doc.payments.length) {
this.frm.add_custom_button(__('Allocate'), () =>
this.frm.trigger("allocate")
);
this.frm.change_custom_button_type('Allocate', null, 'primary');
this.frm.change_custom_button_type('Get Unreconciled Entries', null, 'default');
this.frm.add_custom_button(__("Allocate"), () => this.frm.trigger("allocate"));
this.frm.change_custom_button_type("Allocate", null, "primary");
this.frm.change_custom_button_type("Get Unreconciled Entries", null, "default");
}
if (this.frm.doc.allocation.length) {
this.frm.add_custom_button(__('Reconcile'), () =>
this.frm.trigger("reconcile")
);
this.frm.change_custom_button_type('Reconcile', null, 'primary');
this.frm.change_custom_button_type('Get Unreconciled Entries', null, 'default');
this.frm.change_custom_button_type('Allocate', null, 'default');
this.frm.add_custom_button(__("Reconcile"), () => this.frm.trigger("reconcile"));
this.frm.change_custom_button_type("Reconcile", null, "primary");
this.frm.change_custom_button_type("Get Unreconciled Entries", null, "default");
this.frm.change_custom_button_type("Allocate", null, "default");
}
this.frm.trigger("set_query_for_dimension_filters");
@@ -89,31 +86,39 @@ erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationCo
if (this.frm.doc.receivable_payable_account) {
this.frm.call({
doc: this.frm.doc,
method: 'is_auto_process_enabled',
method: "is_auto_process_enabled",
callback: (r) => {
if (r.message) {
this.frm.call({
'method': "erpnext.accounts.doctype.process_payment_reconciliation.process_payment_reconciliation.is_any_doc_running",
"args": {
for_filter: {
company: this.frm.doc.company,
party_type: this.frm.doc.party_type,
party: this.frm.doc.party,
receivable_payable_account: this.frm.doc.receivable_payable_account
this.frm
.call({
method: "erpnext.accounts.doctype.process_payment_reconciliation.process_payment_reconciliation.is_any_doc_running",
args: {
for_filter: {
company: this.frm.doc.company,
party_type: this.frm.doc.party_type,
party: this.frm.doc.party,
receivable_payable_account: this.frm.doc.receivable_payable_account,
},
},
})
.then((r) => {
if (r.message) {
let doc_link = frappe.utils.get_form_link(
"Process Payment Reconciliation",
r.message,
true
);
let msg = __(
"Payment Reconciliation Job: {0} is running for this party. Can't reconcile now.",
[doc_link]
);
this.frm.dashboard.add_comment(msg, "yellow");
}
}
}).then(r => {
if (r.message) {
let doc_link = frappe.utils.get_form_link("Process Payment Reconciliation", r.message, true);
let msg = __("Payment Reconciliation Job: {0} is running for this party. Can't reconcile now.", [doc_link]);
this.frm.dashboard.add_comment(msg, "yellow");
}
});
});
}
}
},
});
}
}
set_query_for_dimension_filters() {
frappe.call({
@@ -123,29 +128,29 @@ erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationCo
},
callback: (r) => {
if (!r.exc && r.message) {
r.message.forEach(x => {
r.message.forEach((x) => {
this.frm.set_query(x.fieldname, () => {
return {
'filters': x.filters
filters: x.filters,
};
});
});
}
}
},
});
}
company() {
this.frm.set_value('party', '');
this.frm.set_value('receivable_payable_account', '');
this.frm.set_value("party", "");
this.frm.set_value("receivable_payable_account", "");
}
party_type() {
this.frm.set_value('party', '');
this.frm.set_value("party", "");
}
party() {
this.frm.set_value('receivable_payable_account', '');
this.frm.set_value("receivable_payable_account", "");
this.frm.trigger("clear_child_tables");
if (!this.frm.doc.receivable_payable_account && this.frm.doc.party_type && this.frm.doc.party) {
@@ -154,15 +159,14 @@ erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationCo
args: {
company: this.frm.doc.company,
party_type: this.frm.doc.party_type,
party: this.frm.doc.party
party: this.frm.doc.party,
},
callback: (r) => {
if (!r.exc && r.message) {
this.frm.set_value("receivable_payable_account", r.message);
}
this.frm.refresh();
}
},
});
}
}
@@ -180,7 +184,6 @@ erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationCo
this.frm.trigger("get_unreconciled_entries");
}
clear_child_tables() {
this.frm.clear_table("invoices");
this.frm.clear_table("payments");
@@ -192,52 +195,52 @@ erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationCo
this.frm.clear_table("allocation");
return this.frm.call({
doc: this.frm.doc,
method: 'get_unreconciled_entries',
method: "get_unreconciled_entries",
callback: () => {
if (!(this.frm.doc.payments.length || this.frm.doc.invoices.length)) {
frappe.throw({message: __("No Unreconciled Invoices and Payments found for this party and account")});
} else if (!(this.frm.doc.invoices.length)) {
frappe.throw({message: __("No Outstanding Invoices found for this party")});
} else if (!(this.frm.doc.payments.length)) {
frappe.throw({message: __("No Unreconciled Payments found for this party")});
frappe.throw({
message: __("No Unreconciled Invoices and Payments found for this party and account"),
});
} else if (!this.frm.doc.invoices.length) {
frappe.throw({ message: __("No Outstanding Invoices found for this party") });
} else if (!this.frm.doc.payments.length) {
frappe.throw({ message: __("No Unreconciled Payments found for this party") });
}
this.frm.refresh();
}
},
});
}
allocate() {
let payments = this.frm.fields_dict.payments.grid.get_selected_children();
if (!(payments.length)) {
if (!payments.length) {
payments = this.frm.doc.payments;
}
let invoices = this.frm.fields_dict.invoices.grid.get_selected_children();
if (!(invoices.length)) {
if (!invoices.length) {
invoices = this.frm.doc.invoices;
}
return this.frm.call({
doc: this.frm.doc,
method: 'allocate_entries',
method: "allocate_entries",
args: {
payments: payments,
invoices: invoices
invoices: invoices,
},
callback: () => {
this.frm.refresh();
}
},
});
}
reconcile() {
var show_dialog = this.frm.doc.allocation.filter(d => d.difference_amount);
var show_dialog = this.frm.doc.allocation.filter((d) => d.difference_amount);
if (show_dialog && show_dialog.length) {
this.data = [];
const dialog = new frappe.ui.Dialog({
title: __("Select Difference Account"),
size: 'extra-large',
size: "extra-large",
fields: [
{
fieldname: "allocation",
@@ -249,77 +252,89 @@ erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationCo
get_data: () => {
return this.data;
},
fields: [{
fieldtype:'Data',
fieldname:"docname",
in_list_view: 1,
hidden: 1
}, {
fieldtype:'Data',
fieldname:"reference_name",
label: __("Voucher No"),
in_list_view: 1,
read_only: 1
}, {
fieldtype:'Date',
fieldname:"gain_loss_posting_date",
label: __("Posting Date"),
in_list_view: 1,
reqd: 1,
}, {
fieldtype:'Link',
options: 'Account',
in_list_view: 1,
label: __("Difference Account"),
fieldname: 'difference_account',
reqd: 1,
get_query: () => {
return {
filters: {
company: this.frm.doc.company,
is_group: 0
}
}
}
}, {
fieldtype:'Currency',
in_list_view: 1,
label: __("Difference Amount"),
fieldname: 'difference_amount',
read_only: 1
}]
fields: [
{
fieldtype: "Data",
fieldname: "docname",
in_list_view: 1,
hidden: 1,
},
{
fieldtype: "Data",
fieldname: "reference_name",
label: __("Voucher No"),
in_list_view: 1,
read_only: 1,
},
{
fieldtype: "Date",
fieldname: "gain_loss_posting_date",
label: __("Posting Date"),
in_list_view: 1,
reqd: 1,
},
{
fieldtype: "Link",
options: "Account",
in_list_view: 1,
label: __("Difference Account"),
fieldname: "difference_account",
reqd: 1,
get_query: () => {
return {
filters: {
company: this.frm.doc.company,
is_group: 0,
},
};
},
},
{
fieldtype: "Currency",
in_list_view: 1,
label: __("Difference Amount"),
fieldname: "difference_amount",
read_only: 1,
},
],
},
{
fieldtype: 'HTML',
options: "<b> New Journal Entry will be posted for the difference amount </b>"
}
fieldtype: "HTML",
options: "<b> New Journal Entry will be posted for the difference amount </b>",
},
],
primary_action: () => {
const args = dialog.get_values()["allocation"];
args.forEach(d => {
frappe.model.set_value("Payment Reconciliation Allocation", d.docname,
"difference_account", d.difference_account);
frappe.model.set_value("Payment Reconciliation Allocation", d.docname,
"gain_loss_posting_date", d.gain_loss_posting_date);
args.forEach((d) => {
frappe.model.set_value(
"Payment Reconciliation Allocation",
d.docname,
"difference_account",
d.difference_account
);
frappe.model.set_value(
"Payment Reconciliation Allocation",
d.docname,
"gain_loss_posting_date",
d.gain_loss_posting_date
);
});
this.reconcile_payment_entries();
dialog.hide();
},
primary_action_label: __('Reconcile Entries')
primary_action_label: __("Reconcile Entries"),
});
this.frm.doc.allocation.forEach(d => {
this.frm.doc.allocation.forEach((d) => {
if (d.difference_amount) {
dialog.fields_dict.allocation.df.data.push({
'docname': d.name,
'reference_name': d.reference_name,
'difference_amount': d.difference_amount,
'difference_account': d.difference_account,
'gain_loss_posting_date': d.gain_loss_posting_date
docname: d.name,
reference_name: d.reference_name,
difference_amount: d.difference_amount,
difference_account: d.difference_account,
gain_loss_posting_date: d.gain_loss_posting_date,
});
}
});
@@ -335,41 +350,39 @@ erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationCo
reconcile_payment_entries() {
return this.frm.call({
doc: this.frm.doc,
method: 'reconcile',
method: "reconcile",
callback: () => {
this.frm.clear_table("allocation");
this.frm.refresh();
}
},
});
}
};
frappe.ui.form.on('Payment Reconciliation Allocation', {
allocated_amount: function(frm, cdt, cdn) {
frappe.ui.form.on("Payment Reconciliation Allocation", {
allocated_amount: function (frm, cdt, cdn) {
let row = locals[cdt][cdn];
// filter invoice
let invoice = frm.doc.invoices.filter((x) => (x.invoice_number == row.invoice_number));
let invoice = frm.doc.invoices.filter((x) => x.invoice_number == row.invoice_number);
// filter payment
let payment = frm.doc.payments.filter((x) => (x.reference_name == row.reference_name));
let payment = frm.doc.payments.filter((x) => x.reference_name == row.reference_name);
frm.call({
doc: frm.doc,
method: 'calculate_difference_on_allocation_change',
method: "calculate_difference_on_allocation_change",
args: {
payment_entry: payment,
invoice: invoice,
allocated_amount: row.allocated_amount
allocated_amount: row.allocated_amount,
},
callback: (r) => {
if (r.message) {
row.difference_amount = r.message;
frm.refresh();
}
}
},
});
}
},
});
extend_cscript(cur_frm.cscript, new erpnext.accounts.PaymentReconciliationController({frm: cur_frm}));
extend_cscript(cur_frm.cscript, new erpnext.accounts.PaymentReconciliationController({ frm: cur_frm }));

View File

@@ -566,7 +566,12 @@ class PaymentReconciliation(Document):
journals_map = frappe._dict(
frappe.db.get_all(
"Journal Entry Account",
filters={"parent": ("in", journals), "account": ("in", [self.receivable_payable_account])},
filters={
"parent": ("in", journals),
"account": ("in", [self.receivable_payable_account]),
"party_type": self.party_type,
"party": self.party,
},
fields=[
"parent as `name`",
"exchange_rate",

View File

@@ -56,6 +56,7 @@ class TestPaymentReconciliation(FrappeTestCase):
self.expense_account = "Cost of Goods Sold - _PR"
self.debit_to = "Debtors - _PR"
self.creditors = "Creditors - _PR"
self.cash = "Cash - _PR"
# create bank account
if frappe.db.exists("Account", "HDFC - _PR"):
@@ -486,6 +487,91 @@ class TestPaymentReconciliation(FrappeTestCase):
self.assertEqual(len(pr.get("invoices")), 0)
self.assertEqual(len(pr.get("payments")), 0)
def test_payment_against_foreign_currency_journal(self):
transaction_date = nowdate()
self.supplier = "_Test Supplier USD"
self.supplier2 = make_supplier("_Test Supplier2 USD", "USD")
amount = 100
exc_rate1 = 80
exc_rate2 = 83
je = frappe.new_doc("Journal Entry")
je.posting_date = transaction_date
je.company = self.company
je.user_remark = "test"
je.multi_currency = 1
je.set(
"accounts",
[
{
"account": self.creditors_usd,
"party_type": "Supplier",
"party": self.supplier,
"exchange_rate": exc_rate1,
"cost_center": self.cost_center,
"credit": amount * exc_rate1,
"credit_in_account_currency": amount,
},
{
"account": self.creditors_usd,
"party_type": "Supplier",
"party": self.supplier2,
"exchange_rate": exc_rate2,
"cost_center": self.cost_center,
"credit": amount * exc_rate2,
"credit_in_account_currency": amount,
},
{
"account": self.expense_account,
"cost_center": self.cost_center,
"debit": (amount * exc_rate1) + (amount * exc_rate2),
"debit_in_account_currency": (amount * exc_rate1) + (amount * exc_rate2),
},
],
)
je.save().submit()
pe = self.create_payment_entry(amount=amount, posting_date=transaction_date)
pe.payment_type = "Pay"
pe.party_type = "Supplier"
pe.party = self.supplier
pe.paid_to = self.creditors_usd
pe.paid_from = self.cash
pe.paid_amount = 8000
pe.received_amount = 100
pe.target_exchange_rate = exc_rate1
pe.paid_to_account_currency = "USD"
pe.save().submit()
pr = self.create_payment_reconciliation(party_is_customer=False)
pr.receivable_payable_account = self.creditors_usd
pr.minimum_invoice_amount = pr.maximum_invoice_amount = amount
pr.from_invoice_date = pr.to_invoice_date = transaction_date
pr.from_payment_date = pr.to_payment_date = transaction_date
pr.get_unreconciled_entries()
invoices = [x.as_dict() for x in pr.get("invoices")]
payments = [x.as_dict() for x in pr.get("payments")]
pr.allocate_entries(frappe._dict({"invoices": invoices, "payments": payments}))
# There should no difference_amount as the Journal and Payment have same exchange rate - 'exc_rate1'
for row in pr.allocation:
self.assertEqual(flt(row.get("difference_amount")), 0.0)
pr.reconcile()
# check PR tool output
self.assertEqual(len(pr.get("invoices")), 0)
self.assertEqual(len(pr.get("payments")), 0)
journals = frappe.db.get_all(
"Journal Entry Account",
filters={"reference_type": je.doctype, "reference_name": je.name, "docstatus": 1},
fields=["parent"],
)
self.assertEqual([], journals)
def test_journal_against_invoice(self):
transaction_date = nowdate()
amount = 100
@@ -1248,3 +1334,17 @@ def make_customer(customer_name, currency=None):
return customer.name
else:
return customer_name
def make_supplier(supplier_name, currency=None):
if not frappe.db.exists("Supplier", supplier_name):
supplier = frappe.new_doc("Supplier")
supplier.supplier_name = supplier_name
supplier.type = "Individual"
supplier.supplier_group = "Local"
if currency:
supplier.default_currency = currency
supplier.save()
return supplier.name
else:
return supplier_name

View File

@@ -1,83 +1,95 @@
cur_frm.add_fetch("payment_gateway_account", "payment_account", "payment_account")
cur_frm.add_fetch("payment_gateway_account", "payment_gateway", "payment_gateway")
cur_frm.add_fetch("payment_gateway_account", "message", "message")
cur_frm.add_fetch("payment_gateway_account", "payment_account", "payment_account");
cur_frm.add_fetch("payment_gateway_account", "payment_gateway", "payment_gateway");
cur_frm.add_fetch("payment_gateway_account", "message", "message");
frappe.ui.form.on("Payment Request", {
setup: function(frm) {
frm.set_query("party_type", function() {
setup: function (frm) {
frm.set_query("party_type", function () {
return {
query: "erpnext.setup.doctype.party_type.party_type.get_party_type",
};
});
}
})
},
});
frappe.ui.form.on("Payment Request", "onload", function(frm, dt, dn){
frappe.ui.form.on("Payment Request", "onload", function (frm, dt, dn) {
if (frm.doc.reference_doctype) {
frappe.call({
method:"erpnext.accounts.doctype.payment_request.payment_request.get_print_format_list",
args: {"ref_doctype": frm.doc.reference_doctype},
callback:function(r){
set_field_options("print_format", r.message["print_format"])
}
})
method: "erpnext.accounts.doctype.payment_request.payment_request.get_print_format_list",
args: { ref_doctype: frm.doc.reference_doctype },
callback: function (r) {
set_field_options("print_format", r.message["print_format"]);
},
});
}
})
});
frappe.ui.form.on("Payment Request", "refresh", function(frm) {
if(frm.doc.payment_request_type == 'Inward' && frm.doc.payment_channel !== "Phone" &&
!in_list(["Initiated", "Paid"], frm.doc.status) && !frm.doc.__islocal && frm.doc.docstatus==1){
frm.add_custom_button(__('Resend Payment Email'), function(){
frappe.ui.form.on("Payment Request", "refresh", function (frm) {
if (
frm.doc.payment_request_type == "Inward" &&
frm.doc.payment_channel !== "Phone" &&
!in_list(["Initiated", "Paid"], frm.doc.status) &&
!frm.doc.__islocal &&
frm.doc.docstatus == 1
) {
frm.add_custom_button(__("Resend Payment Email"), function () {
frappe.call({
method: "erpnext.accounts.doctype.payment_request.payment_request.resend_payment_email",
args: {"docname": frm.doc.name},
args: { docname: frm.doc.name },
freeze: true,
freeze_message: __("Sending"),
callback: function(r){
if(!r.exc) {
callback: function (r) {
if (!r.exc) {
frappe.msgprint(__("Message Sent"));
}
}
},
});
});
}
if((!frm.doc.payment_gateway_account || frm.doc.payment_request_type == "Outward") && frm.doc.status == "Initiated") {
frm.add_custom_button(__('Create Payment Entry'), function(){
if (
(!frm.doc.payment_gateway_account || frm.doc.payment_request_type == "Outward") &&
frm.doc.status == "Initiated"
) {
frm.add_custom_button(__("Create Payment Entry"), function () {
frappe.call({
method: "erpnext.accounts.doctype.payment_request.payment_request.make_payment_entry",
args: {"docname": frm.doc.name},
args: { docname: frm.doc.name },
freeze: true,
callback: function(r){
if(!r.exc) {
callback: function (r) {
if (!r.exc) {
var doc = frappe.model.sync(r.message);
frappe.set_route("Form", r.message.doctype, r.message.name);
}
}
},
});
}).addClass("btn-primary");
}
});
frappe.ui.form.on("Payment Request", "is_a_subscription", function(frm) {
frappe.ui.form.on("Payment Request", "is_a_subscription", function (frm) {
frm.toggle_reqd("payment_gateway_account", frm.doc.is_a_subscription);
frm.toggle_reqd("subscription_plans", frm.doc.is_a_subscription);
if (frm.doc.is_a_subscription && frm.doc.reference_doctype && frm.doc.reference_name) {
frappe.call({
method: "erpnext.accounts.doctype.payment_request.payment_request.get_subscription_details",
args: {"reference_doctype": frm.doc.reference_doctype, "reference_name": frm.doc.reference_name},
args: { reference_doctype: frm.doc.reference_doctype, reference_name: frm.doc.reference_name },
freeze: true,
callback: function(data){
if(!data.exc) {
$.each(data.message || [], function(i, v){
var d = frappe.model.add_child(frm.doc, "Subscription Plan Detail", "subscription_plans");
callback: function (data) {
if (!data.exc) {
$.each(data.message || [], function (i, v) {
var d = frappe.model.add_child(
frm.doc,
"Subscription Plan Detail",
"subscription_plans"
);
d.qty = v.qty;
d.plan = v.plan;
});
frm.refresh_field("subscription_plans");
}
}
},
});
}
});

View File

@@ -1,23 +1,19 @@
frappe.listview_settings['Payment Request'] = {
frappe.listview_settings["Payment Request"] = {
add_fields: ["status"],
get_indicator: function(doc) {
if(doc.status == "Draft") {
get_indicator: function (doc) {
if (doc.status == "Draft") {
return [__("Draft"), "gray", "status,=,Draft"];
}
if(doc.status == "Requested") {
if (doc.status == "Requested") {
return [__("Requested"), "green", "status,=,Requested"];
}
else if(doc.status == "Initiated") {
} else if (doc.status == "Initiated") {
return [__("Initiated"), "green", "status,=,Initiated"];
}
else if(doc.status == "Partially Paid") {
} else if (doc.status == "Partially Paid") {
return [__("Partially Paid"), "orange", "status,=,Partially Paid"];
}
else if(doc.status == "Paid") {
} else if (doc.status == "Paid") {
return [__("Paid"), "blue", "status,=,Paid"];
}
else if(doc.status == "Cancelled") {
} else if (doc.status == "Cancelled") {
return [__("Cancelled"), "red", "status,=,Cancelled"];
}
}
}
},
};

View File

@@ -1,22 +1,24 @@
// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Payment Term', {
frappe.ui.form.on("Payment Term", {
onload(frm) {
frm.trigger('set_dynamic_description');
frm.trigger("set_dynamic_description");
},
discount(frm) {
frm.trigger('set_dynamic_description');
frm.trigger("set_dynamic_description");
},
discount_type(frm) {
frm.trigger('set_dynamic_description');
frm.trigger("set_dynamic_description");
},
set_dynamic_description(frm) {
if (frm.doc.discount) {
let description = __("{0}% of total invoice value will be given as discount.", [frm.doc.discount]);
if (frm.doc.discount_type == 'Amount') {
let description = __("{0}% of total invoice value will be given as discount.", [
frm.doc.discount,
]);
if (frm.doc.discount_type == "Amount") {
description = __("{0} will be given as discount.", [fmt_money(frm.doc.discount)]);
}
frm.set_df_property("discount", "description", description);
}
}
},
});

View File

@@ -1,12 +1,18 @@
// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Payment Terms Template', {
refresh: function(frm) {
frm.fields_dict.terms.grid.toggle_reqd("payment_term", frm.doc.allocate_payment_based_on_payment_terms);
frappe.ui.form.on("Payment Terms Template", {
refresh: function (frm) {
frm.fields_dict.terms.grid.toggle_reqd(
"payment_term",
frm.doc.allocate_payment_based_on_payment_terms
);
},
allocate_payment_based_on_payment_terms: function(frm) {
frm.fields_dict.terms.grid.toggle_reqd("payment_term", frm.doc.allocate_payment_based_on_payment_terms);
}
allocate_payment_based_on_payment_terms: function (frm) {
frm.fields_dict.terms.grid.toggle_reqd(
"payment_term",
frm.doc.allocate_payment_based_on_payment_terms
);
},
});

View File

@@ -1,38 +1,41 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
frappe.ui.form.on('Period Closing Voucher', {
onload: function(frm) {
frappe.ui.form.on("Period Closing Voucher", {
onload: function (frm) {
if (!frm.doc.transaction_date) frm.doc.transaction_date = frappe.datetime.obj_to_str(new Date());
},
setup: function(frm) {
frm.set_query("closing_account_head", function() {
setup: function (frm) {
frm.set_query("closing_account_head", function () {
return {
filters: [
['Account', 'company', '=', frm.doc.company],
['Account', 'is_group', '=', '0'],
['Account', 'freeze_account', '=', 'No'],
['Account', 'root_type', 'in', 'Liability, Equity']
]
}
["Account", "company", "=", frm.doc.company],
["Account", "is_group", "=", "0"],
["Account", "freeze_account", "=", "No"],
["Account", "root_type", "in", "Liability, Equity"],
],
};
});
},
refresh: function(frm) {
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": moment(frm.doc.modified).format('YYYY-MM-DD'),
"company": frm.doc.company,
"group_by": "",
"show_cancelled_entries": frm.doc.docstatus === 2
};
frappe.set_route("query-report", "General Ledger");
}, "fa fa-table");
refresh: function (frm) {
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: moment(frm.doc.modified).format("YYYY-MM-DD"),
company: frm.doc.company,
group_by: "",
show_cancelled_entries: frm.doc.docstatus === 2,
};
frappe.set_route("query-report", "General Ledger");
},
"fa fa-table"
);
}
}
})
},
});

View File

@@ -1,36 +1,37 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('POS Closing Entry', {
onload: function(frm) {
frm.ignore_doctypes_on_cancel_all = ['POS Invoice Merge Log'];
frm.set_query("pos_profile", function(doc) {
frappe.ui.form.on("POS Closing Entry", {
onload: function (frm) {
frm.ignore_doctypes_on_cancel_all = ["POS Invoice Merge Log"];
frm.set_query("pos_profile", function (doc) {
return {
filters: { 'user': doc.user }
filters: { user: doc.user },
};
});
frm.set_query("user", function(doc) {
frm.set_query("user", function (doc) {
return {
query: "erpnext.accounts.doctype.pos_closing_entry.pos_closing_entry.get_cashiers",
filters: { 'parent': doc.pos_profile }
filters: { parent: doc.pos_profile },
};
});
frm.set_query("pos_opening_entry", function(doc) {
return { filters: { 'status': 'Open', 'docstatus': 1 } };
frm.set_query("pos_opening_entry", function (doc) {
return { filters: { status: "Open", docstatus: 1 } };
});
if (frm.doc.docstatus === 0 && !frm.doc.amended_from) frm.set_value("period_end_date", frappe.datetime.now_datetime());
if (frm.doc.docstatus === 0 && !frm.doc.amended_from)
frm.set_value("period_end_date", frappe.datetime.now_datetime());
frappe.realtime.on('closing_process_complete', async function(data) {
frappe.realtime.on("closing_process_complete", async function (data) {
await frm.reload_doc();
if (frm.doc.status == 'Failed' && frm.doc.error_message) {
if (frm.doc.status == "Failed" && frm.doc.error_message) {
frappe.msgprint({
title: __('POS Closing Failed'),
title: __("POS Closing Failed"),
message: frm.doc.error_message,
indicator: 'orange',
clear: true
indicator: "orange",
clear: true,
});
}
});
@@ -47,23 +48,23 @@ frappe.ui.form.on('POS Closing Entry', {
}
},
refresh: function(frm) {
if (frm.doc.docstatus == 1 && frm.doc.status == 'Failed') {
refresh: function (frm) {
if (frm.doc.docstatus == 1 && frm.doc.status == "Failed") {
const issue = '<a id="jump_to_error" style="text-decoration: underline;">issue</a>';
frm.dashboard.set_headline(
__('POS Closing failed while running in a background process. You can resolve the {0} and retry the process again.', [issue]));
__(
"POS Closing failed while running in a background process. You can resolve the {0} and retry the process again.",
[issue]
)
);
$('#jump_to_error').on('click', (e) => {
$("#jump_to_error").on("click", (e) => {
e.preventDefault();
frappe.utils.scroll_to(
cur_frm.get_field("error_message").$wrapper,
true,
30
);
frappe.utils.scroll_to(cur_frm.get_field("error_message").$wrapper, true, 30);
});
frm.add_custom_button(__('Retry'), function () {
frm.call('retry', {}, () => {
frm.add_custom_button(__("Retry"), function () {
frm.call("retry", {}, () => {
frm.reload_doc();
});
});
@@ -71,48 +72,54 @@ frappe.ui.form.on('POS Closing Entry', {
},
pos_opening_entry(frm) {
if (frm.doc.pos_opening_entry && frm.doc.period_start_date && frm.doc.period_end_date && frm.doc.user) {
if (
frm.doc.pos_opening_entry &&
frm.doc.period_start_date &&
frm.doc.period_end_date &&
frm.doc.user
) {
reset_values(frm);
frappe.run_serially([
() => frm.trigger("set_opening_amounts"),
() => frm.trigger("get_pos_invoices")
() => frm.trigger("get_pos_invoices"),
]);
}
},
set_opening_amounts(frm) {
return frappe.db.get_doc("POS Opening Entry", frm.doc.pos_opening_entry)
return frappe.db
.get_doc("POS Opening Entry", frm.doc.pos_opening_entry)
.then(({ balance_details }) => {
balance_details.forEach(detail => {
balance_details.forEach((detail) => {
frm.add_child("payment_reconciliation", {
mode_of_payment: detail.mode_of_payment,
opening_amount: detail.opening_amount,
expected_amount: detail.opening_amount
expected_amount: detail.opening_amount,
});
})
});
});
},
get_pos_invoices(frm) {
return frappe.call({
method: 'erpnext.accounts.doctype.pos_closing_entry.pos_closing_entry.get_pos_invoices',
method: "erpnext.accounts.doctype.pos_closing_entry.pos_closing_entry.get_pos_invoices",
args: {
start: frappe.datetime.get_datetime_as_string(frm.doc.period_start_date),
end: frappe.datetime.get_datetime_as_string(frm.doc.period_end_date),
pos_profile: frm.doc.pos_profile,
user: frm.doc.user
user: frm.doc.user,
},
callback: (r) => {
let pos_docs = r.message;
set_form_data(pos_docs, frm);
refresh_fields(frm);
set_html_data(frm);
}
},
});
},
before_save: async function(frm) {
frappe.dom.freeze(__('Processing Sales! Please Wait...'));
before_save: async function (frm) {
frappe.dom.freeze(__("Processing Sales! Please Wait..."));
frm.set_value("grand_total", 0);
frm.set_value("net_total", 0);
@@ -125,12 +132,12 @@ frappe.ui.form.on('POS Closing Entry', {
await Promise.all([
frappe.call({
method: 'erpnext.accounts.doctype.pos_closing_entry.pos_closing_entry.get_pos_invoices',
method: "erpnext.accounts.doctype.pos_closing_entry.pos_closing_entry.get_pos_invoices",
args: {
start: frappe.datetime.get_datetime_as_string(frm.doc.period_start_date),
end: frappe.datetime.get_datetime_as_string(frm.doc.period_end_date),
pos_profile: frm.doc.pos_profile,
user: frm.doc.user
user: frm.doc.user,
},
callback: (r) => {
let pos_invoices = r.message;
@@ -143,22 +150,22 @@ frappe.ui.form.on('POS Closing Entry', {
refresh_fields(frm);
set_html_data(frm);
}
}
})
])
},
}),
]);
frappe.dom.unfreeze();
}
},
});
frappe.ui.form.on('POS Closing Entry Detail', {
frappe.ui.form.on("POS Closing Entry Detail", {
closing_amount: (frm, cdt, cdn) => {
const row = locals[cdt][cdn];
frappe.model.set_value(cdt, cdn, "difference", flt(row.closing_amount - row.expected_amount));
}
})
},
});
function set_form_data(data, frm) {
data.forEach(d => {
data.forEach((d) => {
add_to_pos_transaction(d, frm);
frm.doc.grand_total += flt(d.grand_total);
frm.doc.net_total += flt(d.net_total);
@@ -173,13 +180,15 @@ function add_to_pos_transaction(d, frm) {
pos_invoice: d.name,
posting_date: d.posting_date,
grand_total: d.grand_total,
customer: d.customer
})
customer: d.customer,
});
}
function refresh_payments(d, frm) {
d.payments.forEach(p => {
const payment = frm.doc.payment_reconciliation.find(pay => pay.mode_of_payment === p.mode_of_payment);
d.payments.forEach((p) => {
const payment = frm.doc.payment_reconciliation.find(
(pay) => pay.mode_of_payment === p.mode_of_payment
);
if (p.account == d.account_for_change_amount) {
p.amount -= flt(d.change_amount);
}
@@ -191,25 +200,25 @@ function refresh_payments(d, frm) {
mode_of_payment: p.mode_of_payment,
opening_amount: 0,
expected_amount: p.amount,
closing_amount: 0
})
closing_amount: 0,
});
}
})
});
}
function refresh_taxes(d, frm) {
d.taxes.forEach(t => {
const tax = frm.doc.taxes.find(tx => tx.account_head === t.account_head && tx.rate === t.rate);
d.taxes.forEach((t) => {
const tax = frm.doc.taxes.find((tx) => tx.account_head === t.account_head && tx.rate === t.rate);
if (tax) {
tax.amount += flt(t.tax_amount);
} else {
frm.add_child("taxes", {
account_head: t.account_head,
rate: t.rate,
amount: t.tax_amount
})
amount: t.tax_amount,
});
}
})
});
}
function reset_values(frm) {
@@ -231,13 +240,13 @@ function refresh_fields(frm) {
}
function set_html_data(frm) {
if (frm.doc.docstatus === 1 && frm.doc.status == 'Submitted') {
if (frm.doc.docstatus === 1 && frm.doc.status == "Submitted") {
frappe.call({
method: "get_payment_reconciliation_details",
doc: frm.doc,
callback: (r) => {
frm.get_field("payment_reconciliation_details").$wrapper.html(r.message);
}
},
});
}
}

View File

@@ -2,16 +2,15 @@
// License: GNU General Public License v3. See license.txt
// render
frappe.listview_settings['POS Closing Entry'] = {
get_indicator: function(doc) {
frappe.listview_settings["POS Closing Entry"] = {
get_indicator: function (doc) {
var status_color = {
"Draft": "red",
"Submitted": "blue",
"Queued": "orange",
"Failed": "red",
"Cancelled": "red"
Draft: "red",
Submitted: "blue",
Queued: "orange",
Failed: "red",
Cancelled: "red",
};
return [__(doc.status), status_color[doc.status], "status,=,"+doc.status];
}
return [__(doc.status), status_color[doc.status], "status,=," + doc.status];
},
};

View File

@@ -2,40 +2,47 @@
// License: GNU General Public License v3. See license.txt
// render
frappe.listview_settings['POS Invoice'] = {
add_fields: ["customer", "customer_name", "base_grand_total", "outstanding_amount", "due_date", "company",
"currency", "is_return"],
get_indicator: function(doc) {
frappe.listview_settings["POS Invoice"] = {
add_fields: [
"customer",
"customer_name",
"base_grand_total",
"outstanding_amount",
"due_date",
"company",
"currency",
"is_return",
],
get_indicator: function (doc) {
var status_color = {
"Draft": "red",
"Unpaid": "orange",
"Paid": "green",
"Submitted": "blue",
"Consolidated": "green",
"Return": "darkgrey",
Draft: "red",
Unpaid: "orange",
Paid: "green",
Submitted: "blue",
Consolidated: "green",
Return: "darkgrey",
"Unpaid and Discounted": "orange",
"Overdue and Discounted": "red",
"Overdue": "red"
Overdue: "red",
};
return [__(doc.status), status_color[doc.status], "status,=,"+doc.status];
return [__(doc.status), status_color[doc.status], "status,=," + doc.status];
},
right_column: "grand_total",
onload: function(me) {
me.page.add_action_item('Make Merge Log', function() {
onload: function (me) {
me.page.add_action_item("Make Merge Log", function () {
const invoices = me.get_checked_items();
frappe.call({
method: "erpnext.accounts.doctype.pos_invoice.pos_invoice.make_merge_log",
freeze: true,
args:{
"invoices": invoices
args: {
invoices: invoices,
},
callback: function (r) {
if (r.message) {
var doc = frappe.model.sync(r.message)[0];
frappe.set_route("Form", doc.doctype, doc.name);
}
}
},
});
});
},

View File

@@ -1,21 +1,21 @@
// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('POS Invoice Merge Log', {
setup: function(frm) {
frm.set_query("pos_invoice", "pos_invoices", doc => {
frappe.ui.form.on("POS Invoice Merge Log", {
setup: function (frm) {
frm.set_query("pos_invoice", "pos_invoices", (doc) => {
return {
filters: {
'docstatus': 1,
'customer': doc.customer,
'consolidated_invoice': ''
}
}
docstatus: 1,
customer: doc.customer,
consolidated_invoice: "",
},
};
});
},
merge_invoices_based_on: function(frm) {
frm.set_value('customer', '');
frm.set_value('customer_group', '');
}
merge_invoices_based_on: function (frm) {
frm.set_value("customer", "");
frm.set_value("customer_group", "");
},
});

View File

@@ -1,56 +1,55 @@
// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('POS Opening Entry', {
frappe.ui.form.on("POS Opening Entry", {
setup(frm) {
if (frm.doc.docstatus == 0) {
frm.trigger('set_posting_date_read_only');
frm.set_value('period_start_date', frappe.datetime.now_datetime());
frm.set_value('user', frappe.session.user);
frm.trigger("set_posting_date_read_only");
frm.set_value("period_start_date", frappe.datetime.now_datetime());
frm.set_value("user", frappe.session.user);
}
frm.set_query("user", function(doc) {
frm.set_query("user", function (doc) {
return {
query: "erpnext.accounts.doctype.pos_closing_entry.pos_closing_entry.get_cashiers",
filters: { 'parent': doc.pos_profile }
filters: { parent: doc.pos_profile },
};
});
},
refresh(frm) {
// set default posting date / time
if(frm.doc.docstatus == 0) {
if(!frm.doc.posting_date) {
frm.set_value('posting_date', frappe.datetime.nowdate());
if (frm.doc.docstatus == 0) {
if (!frm.doc.posting_date) {
frm.set_value("posting_date", frappe.datetime.nowdate());
}
frm.trigger('set_posting_date_read_only');
frm.trigger("set_posting_date_read_only");
}
},
set_posting_date_read_only(frm) {
if(frm.doc.docstatus == 0 && frm.doc.set_posting_date) {
frm.set_df_property('posting_date', 'read_only', 0);
if (frm.doc.docstatus == 0 && frm.doc.set_posting_date) {
frm.set_df_property("posting_date", "read_only", 0);
} else {
frm.set_df_property('posting_date', 'read_only', 1);
frm.set_df_property("posting_date", "read_only", 1);
}
},
set_posting_date(frm) {
frm.trigger('set_posting_date_read_only');
frm.trigger("set_posting_date_read_only");
},
pos_profile: (frm) => {
if (frm.doc.pos_profile) {
frappe.db.get_doc("POS Profile", frm.doc.pos_profile)
.then(({ payments }) => {
if (payments.length) {
frm.doc.balance_details = [];
payments.forEach(({ mode_of_payment }) => {
frm.add_child("balance_details", { mode_of_payment });
})
frm.refresh_field("balance_details");
}
});
frappe.db.get_doc("POS Profile", frm.doc.pos_profile).then(({ payments }) => {
if (payments.length) {
frm.doc.balance_details = [];
payments.forEach(({ mode_of_payment }) => {
frm.add_child("balance_details", { mode_of_payment });
});
frm.refresh_field("balance_details");
}
});
}
}
},
});

View File

@@ -2,15 +2,14 @@
// License: GNU General Public License v3. See license.txt
// render
frappe.listview_settings['POS Opening Entry'] = {
get_indicator: function(doc) {
frappe.listview_settings["POS Opening Entry"] = {
get_indicator: function (doc) {
var status_color = {
"Draft": "red",
"Open": "orange",
"Closed": "green",
"Cancelled": "red"
Draft: "red",
Open: "orange",
Closed: "green",
Cancelled: "red",
};
return [__(doc.status), status_color[doc.status], "status,=,"+doc.status];
}
return [__(doc.status), status_color[doc.status], "status,=," + doc.status];
},
};

View File

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

View File

@@ -1,57 +1,91 @@
// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
let search_fields_datatypes = ['Data', 'Link', 'Dynamic Link', 'Long Text', 'Select', 'Small Text', 'Text', 'Text Editor'];
let do_not_include_fields = ["naming_series", "item_code", "item_name", "stock_uom", "asset_naming_series",
"default_material_request_type", "valuation_method", "warranty_period", "weight_uom", "batch_number_series",
"serial_no_series", "purchase_uom", "customs_tariff_number", "sales_uom", "deferred_revenue_account",
"deferred_expense_account", "quality_inspection_template", "route", "slideshow", "website_image_alt", "thumbnail",
"web_long_description"]
let search_fields_datatypes = [
"Data",
"Link",
"Dynamic Link",
"Long Text",
"Select",
"Small Text",
"Text",
"Text Editor",
];
let do_not_include_fields = [
"naming_series",
"item_code",
"item_name",
"stock_uom",
"asset_naming_series",
"default_material_request_type",
"valuation_method",
"warranty_period",
"weight_uom",
"batch_number_series",
"serial_no_series",
"purchase_uom",
"customs_tariff_number",
"sales_uom",
"deferred_revenue_account",
"deferred_expense_account",
"quality_inspection_template",
"route",
"slideshow",
"website_image_alt",
"thumbnail",
"web_long_description",
];
frappe.ui.form.on('POS Settings', {
onload: function(frm) {
frappe.ui.form.on("POS Settings", {
onload: function (frm) {
frm.trigger("get_invoice_fields");
frm.trigger("add_search_options");
},
get_invoice_fields: function(frm) {
get_invoice_fields: function (frm) {
frappe.model.with_doctype("POS Invoice", () => {
var fields = $.map(frappe.get_doc("DocType", "POS Invoice").fields, function(d) {
if (frappe.model.no_value_type.indexOf(d.fieldtype) === -1 || ['Button'].includes(d.fieldtype)) {
return { label: d.label + ' (' + d.fieldtype + ')', value: d.fieldname };
var fields = $.map(frappe.get_doc("DocType", "POS Invoice").fields, function (d) {
if (
frappe.model.no_value_type.indexOf(d.fieldtype) === -1 ||
["Button"].includes(d.fieldtype)
) {
return { label: d.label + " (" + d.fieldtype + ")", value: d.fieldname };
} else {
return null;
}
});
frm.fields_dict.invoice_fields.grid.update_docfield_property(
'fieldname', 'options', [""].concat(fields)
"fieldname",
"options",
[""].concat(fields)
);
});
},
add_search_options: function(frm) {
add_search_options: function (frm) {
frappe.model.with_doctype("Item", () => {
var fields = $.map(frappe.get_doc("DocType", "Item").fields, function(d) {
if (search_fields_datatypes.includes(d.fieldtype) && !(do_not_include_fields.includes(d.fieldname))) {
var fields = $.map(frappe.get_doc("DocType", "Item").fields, function (d) {
if (
search_fields_datatypes.includes(d.fieldtype) &&
!do_not_include_fields.includes(d.fieldname)
) {
return [d.label];
} else {
return null;
}
});
fields.unshift('');
frm.fields_dict.pos_search_fields.grid.update_docfield_property('field', 'options', fields);
fields.unshift("");
frm.fields_dict.pos_search_fields.grid.update_docfield_property("field", "options", fields);
});
}
},
});
frappe.ui.form.on("POS Search Fields", {
field: function(frm, doctype, name) {
field: function (frm, doctype, name) {
var doc = frappe.get_doc(doctype, name);
var df = $.map(frappe.get_doc("DocType", "Item").fields, function(d) {
var df = $.map(frappe.get_doc("DocType", "Item").fields, function (d) {
if (doc.field == d.label && search_fields_datatypes.includes(d.fieldtype)) {
return d;
} else {
@@ -61,13 +95,13 @@ frappe.ui.form.on("POS Search Fields", {
doc.fieldname = df.fieldname;
frm.refresh_field("fields");
}
},
});
frappe.ui.form.on("POS Field", {
fieldname: function(frm, doctype, name) {
fieldname: function (frm, doctype, name) {
var doc = frappe.get_doc(doctype, name);
var df = $.map(frappe.get_doc("DocType", "POS Invoice").fields, function(d) {
var df = $.map(frappe.get_doc("DocType", "POS Invoice").fields, function (d) {
return doc.fieldname == d.fieldname ? d : null;
})[0];
@@ -77,5 +111,5 @@ frappe.ui.form.on("POS Field", {
doc.fieldtype = df.fieldtype;
doc.default_value = df.default;
frm.refresh_field("fields");
}
},
});

View File

@@ -1,44 +1,43 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
frappe.ui.form.on('Pricing Rule', {
setup: function(frm) {
frm.fields_dict["for_price_list"].get_query = function(doc){
frappe.ui.form.on("Pricing Rule", {
setup: function (frm) {
frm.fields_dict["for_price_list"].get_query = function (doc) {
return {
filters: {
'selling': doc.selling,
'buying': doc.buying,
'currency': doc.currency
}
selling: doc.selling,
buying: doc.buying,
currency: doc.currency,
},
};
};
['items', 'item_groups', 'brands'].forEach(d => {
frm.fields_dict[d].grid.get_field('uom').get_query = function(doc, cdt, cdn){
["items", "item_groups", "brands"].forEach((d) => {
frm.fields_dict[d].grid.get_field("uom").get_query = function (doc, cdt, cdn) {
var row = locals[cdt][cdn];
return {
query:"erpnext.accounts.doctype.pricing_rule.pricing_rule.get_item_uoms",
filters: {'value': row[frappe.scrub(doc.apply_on)], apply_on: doc.apply_on}
}
query: "erpnext.accounts.doctype.pricing_rule.pricing_rule.get_item_uoms",
filters: { value: row[frappe.scrub(doc.apply_on)], apply_on: doc.apply_on },
};
};
})
});
},
onload: function(frm) {
if(frm.doc.__islocal && !frm.doc.applicable_for && (frm.doc.customer || frm.doc.supplier)) {
if(frm.doc.customer) {
onload: function (frm) {
if (frm.doc.__islocal && !frm.doc.applicable_for && (frm.doc.customer || frm.doc.supplier)) {
if (frm.doc.customer) {
frm.doc.applicable_for = "Customer";
frm.doc.selling = 1
frm.doc.selling = 1;
} else {
frm.doc.applicable_for = "Supplier";
frm.doc.buying = 1
frm.doc.buying = 1;
}
}
},
refresh: function(frm) {
var help_content =
`<table class="table table-bordered" style="background-color: var(--scrollbar-track-color);">
refresh: function (frm) {
var help_content = `<table class="table table-bordered" style="background-color: var(--scrollbar-track-color);">
<tr><td>
<h4>
<i class="fa fa-hand-right"></i>
@@ -97,61 +96,70 @@ frappe.ui.form.on('Pricing Rule', {
</td></tr>
</table>`;
frm.set_df_property('pricing_rule_help', 'options', help_content);
frm.set_df_property("pricing_rule_help", "options", help_content);
frm.events.set_options_for_applicable_for(frm);
frm.trigger("toggle_reqd_apply_on");
},
apply_on: function(frm) {
apply_on: function (frm) {
frm.trigger("toggle_reqd_apply_on");
},
toggle_reqd_apply_on: function(frm) {
toggle_reqd_apply_on: function (frm) {
const fields = {
'Item Code': 'items',
'Item Group': 'item_groups',
'Brand': 'brands'
}
"Item Code": "items",
"Item Group": "item_groups",
Brand: "brands",
};
for (var key in fields) {
frm.toggle_reqd(fields[key],
frm.doc.apply_on === key ? 1 : 0);
frm.toggle_reqd(fields[key], frm.doc.apply_on === key ? 1 : 0);
}
},
rate_or_discount: function(frm) {
if(frm.doc.rate_or_discount == 'Rate') {
frm.set_value('for_price_list', "");
rate_or_discount: function (frm) {
if (frm.doc.rate_or_discount == "Rate") {
frm.set_value("for_price_list", "");
}
},
selling: function(frm) {
selling: function (frm) {
frm.events.set_options_for_applicable_for(frm);
},
buying: function(frm) {
buying: function (frm) {
frm.events.set_options_for_applicable_for(frm);
},
//Dynamically change the description based on type of margin
margin_type: function(frm){
frm.set_df_property('margin_rate_or_amount', 'description', frm.doc.margin_type=='Percentage'?'In Percentage %':'In Amount');
margin_type: function (frm) {
frm.set_df_property(
"margin_rate_or_amount",
"description",
frm.doc.margin_type == "Percentage" ? "In Percentage %" : "In Amount"
);
},
set_options_for_applicable_for: function(frm) {
set_options_for_applicable_for: function (frm) {
var options = [""];
var applicable_for = frm.doc.applicable_for;
if(frm.doc.selling) {
options = $.merge(options, ["Customer", "Customer Group", "Territory", "Sales Partner", "Campaign"]);
if (frm.doc.selling) {
options = $.merge(options, [
"Customer",
"Customer Group",
"Territory",
"Sales Partner",
"Campaign",
]);
}
if(frm.doc.buying) {
if (frm.doc.buying) {
$.merge(options, ["Supplier", "Supplier Group"]);
}
set_field_options("applicable_for", options.join("\n"));
if(!in_list(options, applicable_for)) applicable_for = null;
if (!in_list(options, applicable_for)) applicable_for = null;
frm.set_value("applicable_for", applicable_for);
}
},
});

View File

@@ -1,53 +1,58 @@
// Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Process Deferred Accounting', {
setup: function(frm) {
frm.set_query("document_type", function() {
frappe.ui.form.on("Process Deferred Accounting", {
setup: function (frm) {
frm.set_query("document_type", function () {
return {
filters: {
'name': ['in', ['Sales Invoice', 'Purchase Invoice']]
}
name: ["in", ["Sales Invoice", "Purchase Invoice"]],
},
};
});
},
type: function(frm) {
type: function (frm) {
if (frm.doc.company && frm.doc.type) {
frm.set_query("account", function() {
frm.set_query("account", function () {
return {
filters: {
'company': frm.doc.company,
'root_type': frm.doc.type === 'Income' ? 'Liability' : 'Asset',
'is_group': 0
}
company: frm.doc.company,
root_type: frm.doc.type === "Income" ? "Liability" : "Asset",
is_group: 0,
},
};
});
}
},
validate: function() {
validate: function () {
return new Promise((resolve) => {
return frappe.db.get_single_value('Accounts Settings', 'automatically_process_deferred_accounting_entry')
.then(value => {
if(value) {
frappe.throw(__('Manual entry cannot be created! Disable automatic entry for deferred accounting in accounts settings and try again'));
return frappe.db
.get_single_value("Accounts Settings", "automatically_process_deferred_accounting_entry")
.then((value) => {
if (value) {
frappe.throw(
__(
"Manual entry cannot be created! Disable automatic entry for deferred accounting in accounts settings and try again"
)
);
}
resolve(value);
});
});
},
end_date: function(frm) {
end_date: function (frm) {
if (frm.doc.end_date && frm.doc.end_date < frm.doc.start_date) {
frappe.throw(__("End date cannot be before start date"));
}
},
onload: function(frm) {
onload: function (frm) {
if (frm.doc.posting_date && frm.doc.docstatus === 0) {
frm.set_value('start_date', frappe.datetime.add_months(frm.doc.posting_date, -1));
frm.set_value('end_date', frm.doc.posting_date);
frm.set_value("start_date", frappe.datetime.add_months(frm.doc.posting_date, -1));
frm.set_value("end_date", frm.doc.posting_date);
}
}
},
});

View File

@@ -2,129 +2,128 @@
// For license information, please see license.txt
frappe.ui.form.on("Process Payment Reconciliation", {
onload: function(frm) {
onload: function (frm) {
// set queries
frm.set_query("party_type", function() {
return {
"filters": {
"name": ["in", Object.keys(frappe.boot.party_account_types)],
}
}
});
frm.set_query('receivable_payable_account', function(doc) {
frm.set_query("party_type", function () {
return {
filters: {
"company": doc.company,
"is_group": 0,
"account_type": frappe.boot.party_account_types[doc.party_type]
}
name: ["in", Object.keys(frappe.boot.party_account_types)],
},
};
});
frm.set_query('cost_center', function(doc) {
frm.set_query("receivable_payable_account", function (doc) {
return {
filters: {
"company": doc.company,
"is_group": 0,
}
company: doc.company,
is_group: 0,
account_type: frappe.boot.party_account_types[doc.party_type],
},
};
});
frm.set_query('bank_cash_account', function(doc) {
frm.set_query("cost_center", function (doc) {
return {
filters:[
['Account', 'company', '=', doc.company],
['Account', 'is_group', '=', 0],
['Account', 'account_type', 'in', ['Bank', 'Cash']]
]
filters: {
company: doc.company,
is_group: 0,
},
};
});
frm.set_query("bank_cash_account", function (doc) {
return {
filters: [
["Account", "company", "=", doc.company],
["Account", "is_group", "=", 0],
["Account", "account_type", "in", ["Bank", "Cash"]],
],
};
});
},
refresh: function(frm) {
if (frm.doc.docstatus==1 && ['Queued', 'Paused'].find(x => x == frm.doc.status)) {
let execute_btn = __("Start / Resume")
refresh: function (frm) {
if (frm.doc.docstatus == 1 && ["Queued", "Paused"].find((x) => x == frm.doc.status)) {
let execute_btn = __("Start / Resume");
frm.add_custom_button(execute_btn, () => {
frm.call({
method: 'erpnext.accounts.doctype.process_payment_reconciliation.process_payment_reconciliation.trigger_job_for_doc',
method: "erpnext.accounts.doctype.process_payment_reconciliation.process_payment_reconciliation.trigger_job_for_doc",
args: {
docname: frm.doc.name
}
}).then(r => {
if(!r.exc) {
docname: frm.doc.name,
},
}).then((r) => {
if (!r.exc) {
frappe.show_alert(__("Job Started"));
frm.reload_doc();
}
});
});
}
if (frm.doc.docstatus==1 && ['Completed', 'Running', 'Paused', 'Partially Reconciled'].find(x => x == frm.doc.status)) {
if (
frm.doc.docstatus == 1 &&
["Completed", "Running", "Paused", "Partially Reconciled"].find((x) => x == frm.doc.status)
) {
frm.call({
'method': "erpnext.accounts.doctype.process_payment_reconciliation.process_payment_reconciliation.get_reconciled_count",
method: "erpnext.accounts.doctype.process_payment_reconciliation.process_payment_reconciliation.get_reconciled_count",
args: {
"docname": frm.docname,
}
}).then(r => {
docname: frm.docname,
},
}).then((r) => {
if (r.message) {
let progress = 0;
let description = "";
if (r.message.processed) {
progress = (r.message.processed/r.message.total) * 100;
description = r.message.processed + "/" + r.message.total + " processed";
progress = (r.message.processed / r.message.total) * 100;
description = r.message.processed + "/" + r.message.total + " processed";
} else if (r.message.total == 0 && frm.doc.status == "Completed") {
progress = 100;
}
frm.dashboard.add_progress('Reconciliation Progress', progress, description);
frm.dashboard.add_progress("Reconciliation Progress", progress, description);
}
})
});
}
if (frm.doc.docstatus==1 && frm.doc.status == 'Running') {
let execute_btn = __("Pause")
if (frm.doc.docstatus == 1 && frm.doc.status == "Running") {
let execute_btn = __("Pause");
frm.add_custom_button(execute_btn, () => {
frm.call({
'method': "erpnext.accounts.doctype.process_payment_reconciliation.process_payment_reconciliation.pause_job_for_doc",
method: "erpnext.accounts.doctype.process_payment_reconciliation.process_payment_reconciliation.pause_job_for_doc",
args: {
"docname": frm.docname,
}
}).then(r => {
docname: frm.docname,
},
}).then((r) => {
if (!r.exc) {
frappe.show_alert(__("Job Paused"));
frm.reload_doc()
frm.reload_doc();
}
});
});
}
},
company(frm) {
frm.set_value('party', '');
frm.set_value('receivable_payable_account', '');
frm.set_value("party", "");
frm.set_value("receivable_payable_account", "");
},
party_type(frm) {
frm.set_value('party', '');
frm.set_value("party", "");
},
party(frm) {
frm.set_value('receivable_payable_account', '');
frm.set_value("receivable_payable_account", "");
if (!frm.doc.receivable_payable_account && frm.doc.party_type && frm.doc.party) {
return frappe.call({
method: "erpnext.accounts.party.get_party_account",
args: {
company: frm.doc.company,
party_type: frm.doc.party_type,
party: frm.doc.party
party: frm.doc.party,
},
callback: (r) => {
if (!r.exc && r.message) {
frm.set_value("receivable_payable_account", r.message);
}
frm.refresh();
}
},
});
}
}
},
});

View File

@@ -1,15 +1,15 @@
frappe.listview_settings['Process Payment Reconciliation'] = {
frappe.listview_settings["Process Payment Reconciliation"] = {
add_fields: ["status"],
get_indicator: function(doc) {
get_indicator: function (doc) {
let colors = {
'Queued': 'orange',
'Paused': 'orange',
'Completed': 'green',
'Partially Reconciled': 'orange',
'Running': 'blue',
'Failed': 'red',
Queued: "orange",
Paused: "orange",
Completed: "green",
"Partially Reconciled": "orange",
Running: "blue",
Failed: "red",
};
let status = doc.status;
return [__(status), colors[status], 'status,=,'+status];
return [__(status), colors[status], "status,=," + status];
},
};

View File

@@ -3,15 +3,14 @@
frappe.ui.form.on("Process Payment Reconciliation Log", {
refresh(frm) {
if (['Completed', 'Running', 'Paused', 'Partially Reconciled'].find(x => x == frm.doc.status)) {
if (["Completed", "Running", "Paused", "Partially Reconciled"].find((x) => x == frm.doc.status)) {
let progress = 0;
if (frm.doc.reconciled_entries != 0) {
progress = frm.doc.reconciled_entries / frm.doc.total_allocations * 100;
} else if(frm.doc.total_allocations == 0 && frm.doc.status == "Completed"){
progress = (frm.doc.reconciled_entries / frm.doc.total_allocations) * 100;
} else if (frm.doc.total_allocations == 0 && frm.doc.status == "Completed") {
progress = 100;
}
frm.dashboard.add_progress(__('Reconciliation Progress'), progress);
frm.dashboard.add_progress(__("Reconciliation Progress"), progress);
}
},
});

View File

@@ -1,15 +1,15 @@
frappe.listview_settings['Process Payment Reconciliation Log'] = {
frappe.listview_settings["Process Payment Reconciliation Log"] = {
add_fields: ["status"],
get_indicator: function(doc) {
get_indicator: function (doc) {
var colors = {
'Partially Reconciled': 'orange',
'Paused': 'orange',
'Reconciled': 'green',
'Failed': 'red',
'Cancelled': 'red',
'Running': 'blue',
"Partially Reconciled": "orange",
Paused: "orange",
Reconciled: "green",
Failed: "red",
Cancelled: "red",
Running: "blue",
};
let status = doc.status;
return [__(status), colors[status], "status,=,"+status];
return [__(status), colors[status], "status,=," + status];
},
};

View File

@@ -1,153 +1,148 @@
// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Process Statement Of Accounts', {
view_properties: function(frm) {
frappe.route_options = {doc_type: 'Customer'};
frappe.ui.form.on("Process Statement Of Accounts", {
view_properties: function (frm) {
frappe.route_options = { doc_type: "Customer" };
frappe.set_route("Form", "Customize Form");
},
refresh: function(frm){
if(!frm.doc.__islocal) {
frm.add_custom_button(__('Send Emails'), function(){
refresh: function (frm) {
if (!frm.doc.__islocal) {
frm.add_custom_button(__("Send Emails"), function () {
frappe.call({
method: "erpnext.accounts.doctype.process_statement_of_accounts.process_statement_of_accounts.send_emails",
args: {
"document_name": frm.doc.name,
document_name: frm.doc.name,
},
callback: function(r) {
if(r && r.message) {
frappe.show_alert({message: __('Emails Queued'), indicator: 'blue'});
callback: function (r) {
if (r && r.message) {
frappe.show_alert({ message: __("Emails Queued"), indicator: "blue" });
} else {
frappe.msgprint(__("No Records for these settings."));
}
else{
frappe.msgprint(__('No Records for these settings.'))
}
}
},
});
});
frm.add_custom_button(__('Download'), function(){
frm.add_custom_button(__("Download"), function () {
var url = frappe.urllib.get_full_url(
'/api/method/erpnext.accounts.doctype.process_statement_of_accounts.process_statement_of_accounts.download_statements?'
+ 'document_name='+encodeURIComponent(frm.doc.name))
"/api/method/erpnext.accounts.doctype.process_statement_of_accounts.process_statement_of_accounts.download_statements?" +
"document_name=" +
encodeURIComponent(frm.doc.name)
);
$.ajax({
url: url,
type: 'GET',
success: function(result) {
if(jQuery.isEmptyObject(result)){
frappe.msgprint(__('No Records for these settings.'));
}
else{
type: "GET",
success: function (result) {
if (jQuery.isEmptyObject(result)) {
frappe.msgprint(__("No Records for these settings."));
} else {
window.location = url;
}
}
},
});
});
}
},
onload: function(frm) {
frm.set_query('currency', function(){
onload: function (frm) {
frm.set_query("currency", function () {
return {
filters: {
'enabled': 1
}
}
});
frm.set_query("account", function() {
return {
filters: {
'company': frm.doc.company
}
enabled: 1,
},
};
});
if(frm.doc.__islocal){
frm.set_value('from_date', frappe.datetime.add_months(frappe.datetime.get_today(), -1));
frm.set_value('to_date', frappe.datetime.get_today());
frm.set_query("account", function () {
return {
filters: {
company: frm.doc.company,
},
};
});
if (frm.doc.__islocal) {
frm.set_value("from_date", frappe.datetime.add_months(frappe.datetime.get_today(), -1));
frm.set_value("to_date", frappe.datetime.get_today());
}
},
report: function(frm){
report: function (frm) {
let filters = {
'company': frm.doc.company,
company: frm.doc.company,
};
if (frm.doc.report == "Accounts Receivable") {
filters["account_type"] = "Receivable";
}
if(frm.doc.report == 'Accounts Receivable'){
filters['account_type'] = 'Receivable';
}
frm.set_query("account", function() {
frm.set_query("account", function () {
return {
filters: filters
filters: filters,
};
});
},
customer_collection: function(frm){
frm.set_value('collection_name', '');
if(frm.doc.customer_collection){
frm.get_field('collection_name').set_label(frm.doc.customer_collection);
customer_collection: function (frm) {
frm.set_value("collection_name", "");
if (frm.doc.customer_collection) {
frm.get_field("collection_name").set_label(frm.doc.customer_collection);
}
},
frequency: function(frm){
if(frm.doc.frequency != ''){
frm.set_value('start_date', frappe.datetime.get_today());
}
else{
frm.set_value('start_date', '');
frequency: function (frm) {
if (frm.doc.frequency != "") {
frm.set_value("start_date", frappe.datetime.get_today());
} else {
frm.set_value("start_date", "");
}
},
fetch_customers: function(frm){
if(frm.doc.collection_name){
fetch_customers: function (frm) {
if (frm.doc.collection_name) {
frappe.call({
method: "erpnext.accounts.doctype.process_statement_of_accounts.process_statement_of_accounts.fetch_customers",
args: {
'customer_collection': frm.doc.customer_collection,
'collection_name': frm.doc.collection_name,
'primary_mandatory': frm.doc.primary_mandatory
customer_collection: frm.doc.customer_collection,
collection_name: frm.doc.collection_name,
primary_mandatory: frm.doc.primary_mandatory,
},
callback: function(r) {
if(!r.exc) {
if(r.message.length){
frm.clear_table('customers');
for (const customer of r.message){
var row = frm.add_child('customers');
callback: function (r) {
if (!r.exc) {
if (r.message.length) {
frm.clear_table("customers");
for (const customer of r.message) {
var row = frm.add_child("customers");
row.customer = customer.name;
row.primary_email = customer.primary_email;
row.billing_email = customer.billing_email;
}
frm.refresh_field('customers');
}
else{
frappe.throw(__('No Customers found with selected options.'));
frm.refresh_field("customers");
} else {
frappe.throw(__("No Customers found with selected options."));
}
}
}
},
});
} else {
frappe.throw("Enter " + frm.doc.customer_collection + " name.");
}
else {
frappe.throw('Enter ' + frm.doc.customer_collection + ' name.');
}
}
},
});
frappe.ui.form.on('Process Statement Of Accounts Customer', {
customer: function(frm, cdt, cdn){
frappe.ui.form.on("Process Statement Of Accounts Customer", {
customer: function (frm, cdt, cdn) {
var row = locals[cdt][cdn];
if (!row.customer){
if (!row.customer) {
return;
}
frappe.call({
method: 'erpnext.accounts.doctype.process_statement_of_accounts.process_statement_of_accounts.get_customer_emails',
method: "erpnext.accounts.doctype.process_statement_of_accounts.process_statement_of_accounts.get_customer_emails",
args: {
'customer_name': row.customer,
'primary_mandatory': frm.doc.primary_mandatory
customer_name: row.customer,
primary_mandatory: frm.doc.primary_mandatory,
},
callback: function(r){
if(!r.exe){
if(r.message.length){
frappe.model.set_value(cdt, cdn, "primary_email", r.message[0])
frappe.model.set_value(cdt, cdn, "billing_email", r.message[1])
}
else {
return
callback: function (r) {
if (!r.exe) {
if (r.message.length) {
frappe.model.set_value(cdt, cdn, "primary_email", r.message[0]);
frappe.model.set_value(cdt, cdn, "billing_email", r.message[1]);
} else {
return;
}
}
}
})
}
},
});
},
});

View File

@@ -397,11 +397,16 @@ def send_emails(document_name, from_scheduler=False, posting_date=None):
subject = frappe.render_template(doc.subject, context)
message = frappe.render_template(doc.body, context)
if doc.sender:
sender_email = frappe.db.get_value("Email Account", doc.sender, "email_id")
else:
sender_email = frappe.session.user
frappe.enqueue(
queue="short",
method=frappe.sendmail,
recipients=recipients,
sender=doc.sender or frappe.session.user,
sender=sender_email,
cc=cc,
subject=subject,
message=message,

View File

@@ -1,51 +1,56 @@
// Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Promotional Scheme', {
refresh: function(frm) {
frappe.ui.form.on("Promotional Scheme", {
refresh: function (frm) {
frm.trigger("set_options_for_applicable_for");
frm.trigger("toggle_reqd_apply_on");
},
selling: function(frm) {
selling: function (frm) {
frm.trigger("set_options_for_applicable_for");
},
buying: function(frm) {
buying: function (frm) {
frm.trigger("set_options_for_applicable_for");
},
set_options_for_applicable_for: function(frm) {
set_options_for_applicable_for: function (frm) {
var options = [""];
var applicable_for = frm.doc.applicable_for;
if(frm.doc.selling) {
options = $.merge(options, ["Customer", "Customer Group", "Territory", "Sales Partner", "Campaign"]);
if (frm.doc.selling) {
options = $.merge(options, [
"Customer",
"Customer Group",
"Territory",
"Sales Partner",
"Campaign",
]);
}
if(frm.doc.buying) {
if (frm.doc.buying) {
$.merge(options, ["Supplier", "Supplier Group"]);
}
set_field_options("applicable_for", options.join("\n"));
if(!in_list(options, applicable_for)) applicable_for = null;
if (!in_list(options, applicable_for)) applicable_for = null;
frm.set_value("applicable_for", applicable_for);
},
apply_on: function(frm) {
apply_on: function (frm) {
frm.trigger("toggle_reqd_apply_on");
},
toggle_reqd_apply_on: function(frm) {
toggle_reqd_apply_on: function (frm) {
const fields = {
'Item Code': 'items',
'Item Group': 'item_groups',
'Brand': 'brands'
"Item Code": "items",
"Item Group": "item_groups",
Brand: "brands",
};
for (var key in fields) {
frm.toggle_reqd(fields[key],
frm.doc.apply_on === key ? 1 : 0);
frm.toggle_reqd(fields[key], frm.doc.apply_on === key ? 1 : 0);
}
}
},
});

View File

@@ -22,6 +22,9 @@
"is_paid",
"is_return",
"return_against",
"update_outstanding_for_self",
"update_billed_amount_in_purchase_order",
"update_billed_amount_in_purchase_receipt",
"apply_tds",
"tax_withholding_category",
"amended_from",
@@ -410,6 +413,20 @@
"read_only": 1,
"search_index": 1
},
{
"default": "0",
"depends_on": "eval: doc.is_return",
"fieldname": "update_billed_amount_in_purchase_order",
"fieldtype": "Check",
"label": "Update Billed Amount in Purchase Order"
},
{
"default": "1",
"depends_on": "eval: doc.is_return",
"fieldname": "update_billed_amount_in_purchase_receipt",
"fieldtype": "Check",
"label": "Update Billed Amount in Purchase Receipt"
},
{
"fieldname": "section_addresses",
"fieldtype": "Section Break",
@@ -1588,13 +1605,21 @@
"fieldtype": "Check",
"label": "Use Transaction Date Exchange Rate",
"read_only": 1
},
{
"default": "1",
"depends_on": "eval: doc.is_return && doc.return_against",
"description": "Debit Note will update it's own outstanding amount, even if \"Return Against\" is specified.",
"fieldname": "update_outstanding_for_self",
"fieldtype": "Check",
"label": "Update Outstanding for Self"
}
],
"icon": "fa fa-file-text",
"idx": 204,
"is_submittable": 1,
"links": [],
"modified": "2023-11-03 15:47:30.319200",
"modified": "2024-03-11 14:46:30.298184",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice",

View File

@@ -3,7 +3,7 @@
import frappe
from frappe import _, throw
from frappe import _, qb, throw
from frappe.model.mapper import get_mapped_doc
from frappe.query_builder.functions import Sum
from frappe.utils import cint, cstr, flt, formatdate, get_link_to_form, getdate, nowdate
@@ -514,6 +514,11 @@ class PurchaseInvoice(BuyingController):
super(PurchaseInvoice, self).on_submit()
self.check_prev_docstatus()
if self.is_return and not self.update_billed_amount_in_purchase_order:
# NOTE status updating bypassed for is_return
self.status_updater = []
self.update_status_updater_args()
self.update_prevdoc_status()
@@ -570,13 +575,12 @@ class PurchaseInvoice(BuyingController):
self.db_set("repost_required", self.needs_repost)
def make_gl_entries(self, gl_entries=None, from_repost=False):
if not gl_entries:
gl_entries = self.get_gl_entries()
update_outstanding = "No" if (cint(self.is_paid) or self.write_off_account) else "Yes"
if self.docstatus == 1:
if not gl_entries:
gl_entries = self.get_gl_entries()
if gl_entries:
update_outstanding = "No" if (cint(self.is_paid) or self.write_off_account) else "Yes"
if self.docstatus == 1:
if gl_entries:
make_gl_entries(
gl_entries,
update_outstanding=update_outstanding,
@@ -584,29 +588,43 @@ class PurchaseInvoice(BuyingController):
from_repost=from_repost,
)
self.make_exchange_gain_loss_journal()
elif self.docstatus == 2:
provisional_entries = [a for a in gl_entries if a.voucher_type == "Purchase Receipt"]
make_reverse_gl_entries(voucher_type=self.doctype, voucher_no=self.name)
if provisional_entries:
for entry in provisional_entries:
frappe.db.set_value(
"GL Entry",
{"voucher_type": "Purchase Receipt", "voucher_detail_no": entry.voucher_detail_no},
"is_cancelled",
1,
)
if update_outstanding == "No":
update_outstanding_amt(
self.credit_to,
"Supplier",
self.supplier,
self.doctype,
self.return_against if cint(self.is_return) and self.return_against else self.name,
)
elif self.docstatus == 2 and cint(self.update_stock) and self.auto_accounting_for_stock:
elif self.docstatus == 2:
make_reverse_gl_entries(voucher_type=self.doctype, voucher_no=self.name)
self.cancel_provisional_entries()
self.update_supplier_outstanding(update_outstanding)
def cancel_provisional_entries(self):
rows = set()
purchase_receipts = set()
for d in self.items:
if d.purchase_receipt:
purchase_receipts.add(d.purchase_receipt)
rows.add(d.name)
if rows:
# cancel gl entries
gle = qb.DocType("GL Entry")
gle_update_query = (
qb.update(gle)
.set(gle.is_cancelled, 1)
.where(
(gle.voucher_type == "Purchase Receipt")
& (gle.voucher_no.isin(purchase_receipts))
& (gle.voucher_detail_no.isin(rows))
)
)
gle_update_query.run()
def update_supplier_outstanding(self, update_outstanding):
if update_outstanding == "No":
update_outstanding_amt(
self.credit_to,
"Supplier",
self.supplier,
self.doctype,
self.return_against if cint(self.is_return) and self.return_against else self.name,
)
def get_gl_entries(self, warehouse_account=None):
self.auto_accounting_for_stock = erpnext.is_perpetual_inventory_enabled(self.company)
@@ -658,6 +676,10 @@ class PurchaseInvoice(BuyingController):
)
if grand_total and not self.is_internal_transfer():
against_voucher = self.name
if self.is_return and self.return_against and not self.update_outstanding_for_self:
against_voucher = self.return_against
# Did not use base_grand_total to book rounding loss gle
gl_entries.append(
self.get_gl_dict(
@@ -671,7 +693,7 @@ class PurchaseInvoice(BuyingController):
"credit_in_account_currency": base_grand_total
if self.party_account_currency == self.company_currency
else grand_total,
"against_voucher": self.name,
"against_voucher": against_voucher,
"against_voucher_type": self.doctype,
"project": self.project,
"cost_center": self.cost_center,
@@ -715,8 +737,9 @@ class PurchaseInvoice(BuyingController):
"Company", self.company, "enable_provisional_accounting_for_non_stock_items"
)
)
purchase_receipt_doc_map = {}
self.provisional_enpenses_booked_in_pr = False
if provisional_accounting_for_non_stock_items:
self.get_provisional_accounts()
for item in self.get("items"):
if flt(item.base_net_amount):
@@ -853,34 +876,7 @@ class PurchaseInvoice(BuyingController):
dummy, amount = self.get_amount_and_base_amount(item, None)
if provisional_accounting_for_non_stock_items:
if item.purchase_receipt:
provisional_account = frappe.db.get_value(
"Purchase Receipt Item", item.pr_detail, "provisional_expense_account"
) or self.get_company_default("default_provisional_account")
purchase_receipt_doc = purchase_receipt_doc_map.get(item.purchase_receipt)
if not purchase_receipt_doc:
purchase_receipt_doc = frappe.get_doc("Purchase Receipt", item.purchase_receipt)
purchase_receipt_doc_map[item.purchase_receipt] = purchase_receipt_doc
# Post reverse entry for Stock-Received-But-Not-Billed if it is booked in Purchase Receipt
expense_booked_in_pr = frappe.db.get_value(
"GL Entry",
{
"is_cancelled": 0,
"voucher_type": "Purchase Receipt",
"voucher_no": item.purchase_receipt,
"voucher_detail_no": item.pr_detail,
"account": provisional_account,
},
["name"],
)
if expense_booked_in_pr:
# Intentionally passing purchase invoice item to handle partial billing
purchase_receipt_doc.add_provisional_gl_entry(
item, gl_entries, self.posting_date, provisional_account, reverse=1
)
self.make_provisional_gl_entry(gl_entries, item)
if not self.is_internal_transfer():
gl_entries.append(
@@ -977,6 +973,58 @@ class PurchaseInvoice(BuyingController):
if item.is_fixed_asset and item.landed_cost_voucher_amount:
self.update_gross_purchase_amount_for_linked_assets(item)
def get_provisional_accounts(self):
self.provisional_accounts = frappe._dict()
linked_purchase_receipts = set([d.purchase_receipt for d in self.items if d.purchase_receipt])
pr_items = frappe.get_all(
"Purchase Receipt Item",
filters={"parent": ("in", linked_purchase_receipts)},
fields=["name", "provisional_expense_account", "qty", "base_rate"],
)
default_provisional_account = self.get_company_default("default_provisional_account")
for item in pr_items:
self.provisional_accounts[item.name] = {
"provisional_account": item.provisional_expense_account or default_provisional_account,
"qty": item.qty,
"base_rate": item.base_rate,
}
def make_provisional_gl_entry(self, gl_entries, item):
if item.purchase_receipt:
if not self.provisional_enpenses_booked_in_pr:
pr_item = self.provisional_accounts.get(item.pr_detail, {})
provisional_account = pr_item.get("provisional_account")
pr_qty = pr_item.get("qty")
pr_base_rate = pr_item.get("base_rate")
# Post reverse entry for Stock-Received-But-Not-Billed if it is booked in Purchase Receipt
provision_gle_against_pr = frappe.db.get_value(
"GL Entry",
{
"is_cancelled": 0,
"voucher_type": "Purchase Receipt",
"voucher_no": item.purchase_receipt,
"voucher_detail_no": item.pr_detail,
"account": provisional_account,
},
["name"],
)
if provision_gle_against_pr:
self.provisional_enpenses_booked_in_pr = True
if self.provisional_enpenses_booked_in_pr:
purchase_receipt_doc = frappe.get_cached_doc("Purchase Receipt", item.purchase_receipt)
# Intentionally passing purchase invoice item to handle partial billing
purchase_receipt_doc.add_provisional_gl_entry(
item,
gl_entries,
self.posting_date,
provisional_account,
reverse=1,
item_amount=(min(item.qty, pr_qty) * pr_base_rate),
)
def update_gross_purchase_amount_for_linked_assets(self, item):
assets = frappe.db.get_all(
"Asset",
@@ -1264,6 +1312,10 @@ class PurchaseInvoice(BuyingController):
self.check_on_hold_or_closed_status()
if self.is_return and not self.update_billed_amount_in_purchase_order:
# NOTE status updating bypassed for is_return
self.status_updater = []
self.update_status_updater_args()
self.update_prevdoc_status()
@@ -1357,6 +1409,9 @@ class PurchaseInvoice(BuyingController):
frappe.throw(_("Supplier Invoice No exists in Purchase Invoice {0}").format(pi))
def update_billing_status_in_pr(self, update_modified=True):
if self.is_return and not self.update_billed_amount_in_purchase_receipt:
return
updated_pr = []
po_details = []

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