Compare commits

...

101 Commits

Author SHA1 Message Date
rohitwaghchaure
4a748f45c9 fix: linter issue 2024-03-12 15:28:33 +05:30
rohitwaghchaure
581c8b1a22 Merge branch 'version-15' into version-15-hotfix 2024-03-12 15:18:55 +05:30
mergify[bot]
478b988290 fix: negative stock error for the batch (backport #40389) (#40391)
fix: negative stock error for the batch (#40389)

(cherry picked from commit a419812864)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-03-12 14:55:34 +05:30
Gursheen Kaur Anand
c0b60413b6 Merge pull request #40393 from frappe/mergify/bp/version-15-hotfix/pr-40388
feat: add recursion qty field in promotional scheme (backport #40388)
2024-03-12 14:51:09 +05:30
Gursheen Anand
11f30e90ab test: pricing rule for product discounts
(cherry picked from commit 0ffc5cf012)
2024-03-12 08:59:40 +00:00
Gursheen Anand
5f4b23d4af feat: add recursion qty field in promotional scheme
(cherry picked from commit 7075c50b85)
2024-03-12 08:59:39 +00:00
mergify[bot]
9ce68deff5 fix: barcode field on line item not working (backport #40381) (#40384)
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:48:48 +05:30
mergify[bot]
32660abdc8 fix: Use serial/batch fields for delivery note return (backport #40374) (#40376)
fix: Use serial/batch fields for delivery note return (#40374)

fix: User serial/batch fields for delivery note return
(cherry picked from commit b9a8dd468b)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-03-11 17:27:02 +05:30
ruthra kumar
76fc420b21 Merge pull request #40375 from frappe/mergify/bp/version-15-hotfix/pr-40299
refactor: run qb directly instead of converting to sql (backport #40299)
2024-03-11 17:02:50 +05:30
ruthra kumar
c111ce9bf4 chore: replace parameter with qb conditions
(cherry picked from commit 0344ff2aac)
2024-03-11 11:15:43 +00:00
ruthra kumar
03bde07966 refactor: run qb directly instead of converting to sql
(cherry picked from commit 711b72b26c)
2024-03-11 11:15:43 +00:00
mergify[bot]
a195dd3c1f fix: MR Default Supplier search query (backport #40273) (#40351)
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:40 +05:30
mergify[bot]
7d3d2eb928 ci: add prettier to pre-commit (backport #40206) (#40362)
* ci: add prettier to pre-commit

(cherry picked from commit 2c16036ef3)

* style: format js files

---------

Co-authored-by: barredterra <14891507+barredterra@users.noreply.github.com>
Co-authored-by: Ankush Menat <ankush@frappe.io>
2024-03-11 10:47:18 +05:30
Deepesh Garg
5f789d9abe Merge pull request #40364 from frappe/mergify/bp/version-15-hotfix/pr-40344
fix: get_user_default_as_list args order (#40344)
2024-03-10 22:32:45 +05:30
Devin Slauenwhite
44ff607dcd fix: get_user_default_as_list args order
(cherry picked from commit ac1961b687)
2024-03-10 15:45:35 +00:00
Deepesh Garg
54fd9ec21e Merge pull request #40358 from frappe/mergify/bp/version-15-hotfix/pr-40323
fix: Filter for projects in Sales Cycle (#40323)
2024-03-10 21:11:55 +05:30
Deepesh Garg
399c5629f4 Merge pull request #40360 from frappe/mergify/bp/version-15-hotfix/pr-40325
fix: Sender email in process statements of accounts (#40325)
2024-03-10 19:57:06 +05:30
Deepesh Garg
953f64091a fix: Sender email in process statements of accounts
(cherry picked from commit 65a2f3d12c)
2024-03-10 13:58:04 +00:00
Deepesh Garg
173b3b85f6 fix: Filter for projects in Sales Cycle
(cherry picked from commit d0e0b66b2f)
2024-03-10 13:57:13 +00:00
Deepesh Garg
8b5afbbaca Merge pull request #40356 from frappe/mergify/bp/version-15-hotfix/pr-40355
fix: Blanket order rate getting changed on converting to order (#40355)
2024-03-10 19:26:24 +05:30
Deepesh Garg
df1a51e291 Merge pull request #40337 from frappe/mergify/bp/version-15-hotfix/pr-40334
fix: load ignored doctype and include Mode of Payment Account (#40334)
2024-03-10 19:25:09 +05:30
Deepesh Garg
d8c6eb0bf2 fix: Blanket order rate getting changed on converting to order
(cherry picked from commit 9702a65a0f)
2024-03-10 13:14:59 +00:00
ruthra kumar
b6e90c4973 Merge pull request #40354 from frappe/mergify/bp/version-15-hotfix/pr-39681
fix: incorrect advance paid in Sales/Purchase Order (backport #39681)
2024-03-10 17:15:15 +05:30
ruthra kumar
b8582db124 chore: resolve conflicts 2024-03-10 16:52:02 +05:30
ruthra kumar
d6a3b179ec refactor(test): make sure party has USD account
1. Don't reset 'party_account_currency' of SO/PO  upon Payment Entry
cancellation. This happens when there are no payments against a SO/PO

(cherry picked from commit e52c4c8f22)
2024-03-10 11:09:54 +00:00
ruthra kumar
6a5a941a5a fix: advance paid amount and ledger entries against SO/PO
(cherry picked from commit d9a0494fc3)

# Conflicts:
#	erpnext/accounts/utils.py
2024-03-10 11:09:53 +00:00
ruthra kumar
9317adfa33 refactor(test): use get_party_account for reference details section
(cherry picked from commit cb2529cec8)
2024-03-10 11:09:53 +00:00
ruthra kumar
d3039be5bc refactor(test): reference details will have account
(cherry picked from commit 158112896e)
2024-03-10 11:09:52 +00:00
ruthra kumar
6832908e92 fix: incorrect advance paid in Sales/Purchase Order
(cherry picked from commit 9d9b83362a)
2024-03-10 11:09:52 +00:00
Nihantra C. Patel
5fac50036a fix: load ignored doctype and include Mode of Payment Account (#40334)
(cherry picked from commit 68baa3612a)
2024-03-07 12:14:18 +00:00
Frappe PR Bot
3035dcab07 chore(release): Bumped to Version 15.16.2
## [15.16.2](https://github.com/frappe/erpnext/compare/v15.16.1...v15.16.2) (2024-03-07)

### Bug Fixes

* use serial/batch field for rejected items (backport [#40327](https://github.com/frappe/erpnext/issues/40327)) (backport [#40329](https://github.com/frappe/erpnext/issues/40329)) ([#40332](https://github.com/frappe/erpnext/issues/40332)) ([5af335d](5af335dc33))
2024-03-07 09:25:12 +00:00
mergify[bot]
5af335dc33 fix: use serial/batch field for rejected items (backport #40327) (backport #40329) (#40332)
fix: use serial/batch field for rejected items (backport #40327) (#40329)

fix: use serial/batch field for rejected items (#40327)

(cherry picked from commit 01856a6e9d)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
(cherry picked from commit 7ca72423b9)

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2024-03-07 14:53:29 +05:30
mergify[bot]
7ca72423b9 fix: use serial/batch field for rejected items (backport #40327) (#40329)
fix: use serial/batch field for rejected items (#40327)

(cherry picked from commit 01856a6e9d)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-03-07 14:36:59 +05:30
Raffael Meyer
9b4a1b0a69 Merge pull request #40321 from frappe/mergify/bp/version-15-hotfix/pr-40317
fix(Shipment Parcel): make length, width and height non-mandatory (backport #40317)
2024-03-06 19:49:56 +01:00
barredterra
1476196966 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:18 +00:00
Frappe PR Bot
643189a0ce chore(release): Bumped to Version 15.16.1
## [15.16.1](https://github.com/frappe/erpnext/compare/v15.16.0...v15.16.1) (2024-03-06)

### Bug Fixes

* batch no not copied while making Material Consumption entry (backport [#40290](https://github.com/frappe/erpnext/issues/40290)) (backport [#40300](https://github.com/frappe/erpnext/issues/40300)) ([#40303](https://github.com/frappe/erpnext/issues/40303)) ([f21918d](f21918d06c))
* not able to cancel purchase receipt for old subcontracting flow (backport [#40298](https://github.com/frappe/erpnext/issues/40298)) (backport [#40302](https://github.com/frappe/erpnext/issues/40302)) ([#40305](https://github.com/frappe/erpnext/issues/40305)) ([3814c5a](3814c5a54a))
* stock ledger balance qty for the batch (backport [#40274](https://github.com/frappe/erpnext/issues/40274)) (backport [#40301](https://github.com/frappe/erpnext/issues/40301)) ([#40304](https://github.com/frappe/erpnext/issues/40304)) ([539eb79](539eb794c0))
* use serial batch fields for subcontracting receipt (backport [#40311](https://github.com/frappe/erpnext/issues/40311)) (backport [#40315](https://github.com/frappe/erpnext/issues/40315)) ([#40316](https://github.com/frappe/erpnext/issues/40316)) ([e357497](e357497bcb))
2024-03-06 14:48:42 +00:00
mergify[bot]
e357497bcb fix: use serial batch fields for subcontracting receipt (backport #40311) (backport #40315) (#40316)
fix: use serial batch fields for subcontracting receipt (backport #40311) (#40315)

fix: use serial batch fields for subcontracting receipt (#40311)

(cherry picked from commit cef6291311)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
(cherry picked from commit 4b15c00b11)

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2024-03-06 20:17:30 +05:30
mergify[bot]
f21918d06c fix: batch no not copied while making Material Consumption entry (backport #40290) (backport #40300) (#40303)
fix: batch no not copied while making Material Consumption entry (backport #40290) (#40300)

fix: batch no not copied while making Material Consumption entry (#40290)

(cherry picked from commit 1eaa386657)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
(cherry picked from commit 6d1c144a66)

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2024-03-06 20:17:20 +05:30
mergify[bot]
539eb794c0 fix: stock ledger balance qty for the batch (backport #40274) (backport #40301) (#40304)
fix: stock ledger balance qty for the batch (backport #40274) (#40301)

fix: stock ledger balance qty for the batch (#40274)

(cherry picked from commit e178ffc3c1)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
(cherry picked from commit 62aefcef04)

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2024-03-06 20:17:09 +05:30
mergify[bot]
3814c5a54a fix: not able to cancel purchase receipt for old subcontracting flow (backport #40298) (backport #40302) (#40305)
fix: not able to cancel purchase receipt for old subcontracting flow (backport #40298) (#40302)

fix: not able to cancel purchase receipt for old subcontracting flow (#40298)

(cherry picked from commit 48da952fd7)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
(cherry picked from commit e0e80f7eed)

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2024-03-06 20:17:01 +05:30
mergify[bot]
4b15c00b11 fix: use serial batch fields for subcontracting receipt (backport #40311) (#40315)
fix: use serial batch fields for subcontracting receipt (#40311)

(cherry picked from commit cef6291311)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-03-06 19:59:21 +05:30
mergify[bot]
7001e0a820 fix(accounts): Allow setting Number of new Cost Center (backport #40212) (#40314)
fix(accounts): Allow setting Number of new Cost Center (#40212)

(cherry picked from commit a93d14b3f7)

Co-authored-by: Corentin Flr <10946971+cogk@users.noreply.github.com>
2024-03-06 19:49:42 +05:30
mergify[bot]
e0e80f7eed fix: not able to cancel purchase receipt for old subcontracting flow (backport #40298) (#40302)
fix: not able to cancel purchase receipt for old subcontracting flow (#40298)

(cherry picked from commit 48da952fd7)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-03-06 13:16:57 +05:30
mergify[bot]
62aefcef04 fix: stock ledger balance qty for the batch (backport #40274) (#40301)
fix: stock ledger balance qty for the batch (#40274)

(cherry picked from commit e178ffc3c1)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-03-06 13:06:19 +05:30
mergify[bot]
6d1c144a66 fix: batch no not copied while making Material Consumption entry (backport #40290) (#40300)
fix: batch no not copied while making Material Consumption entry (#40290)

(cherry picked from commit 1eaa386657)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-03-06 13:06:12 +05:30
Frappe PR Bot
eb9b2e896e chore(release): Bumped to Version 15.16.0
# [15.16.0](https://github.com/frappe/erpnext/compare/v15.15.0...v15.16.0) (2024-03-06)

### Bug Fixes

* allow editable accounting dimensions for repostable doctypes ([cd24a2a](cd24a2a05d))
* allow gain/loss for Journals against Journals ([d8cf6ba](d8cf6ba38d))
* check child rows before update ([e20c1ac](e20c1acb6e))
* disable editable account heads ([c55c0f7](c55c0f7173))
* do not allow to cancel incomplete reposting (backport [#40224](https://github.com/frappe/erpnext/issues/40224)) ([#40230](https://github.com/frappe/erpnext/issues/40230)) ([63209f4](63209f4eac))
* don't override reference exchange rate ([4513d83](4513d83f22))
* handle partial invoice against provisional entry ([87596e6](87596e6e29))
* ignore self on GL account validation for Bank Account ([1947a67](1947a67f3d))
* include Debit To/Credit To account while fetching advance ([23d7a1f](23d7a1fc76))
* incorrect exchange rate if JE has multi parties ([b785901](b785901efa))
* incorrect TCS on customer and suppliers with same name ([d74647d](d74647d5a5))
* make use of 'flt' to prevent really low precision exc gain/loss ([9057bff](9057bff786))
* make warning for previously existing SO an alert ([4f9b194](4f9b194fe9))
* over billing qty along with rate ([00d410c](00d410cc1d))
* **Project:** filter department by company ([13e3343](13e334398e))
* provisional reverse entry amount ([0182b95](0182b95230))
* rate change on changing of the qty (backport [#40241](https://github.com/frappe/erpnext/issues/40241)) ([#40243](https://github.com/frappe/erpnext/issues/40243)) ([1d42171](1d421713be))
* remove free item row only if pricing rule matches ([6352bfe](6352bfe34e))
* report path from the Item and Putaway Rule list (backport [#40190](https://github.com/frappe/erpnext/issues/40190)) ([#40266](https://github.com/frappe/erpnext/issues/40266)) ([c7b96df](c7b96df69c))
* serial no valuation rate (backport [#40221](https://github.com/frappe/erpnext/issues/40221)) ([#40223](https://github.com/frappe/erpnext/issues/40223)) ([85ae9ee](85ae9eee25))
* **setup:** avoid duplicate entry for Analytics role (backport [#40183](https://github.com/frappe/erpnext/issues/40183)) ([#40185](https://github.com/frappe/erpnext/issues/40185)) ([9cb8d33](9cb8d33923))
* test for repost accounting in JVs ([1634955](16349553c7))
* test for reposting pi ([6230bbc](6230bbc77d))
* uom wise price in sales or purchase transaction (backport [#40216](https://github.com/frappe/erpnext/issues/40216)) ([#40225](https://github.com/frappe/erpnext/issues/40225)) ([b398cc6](b398cc6579))

### Features

* add company filter to child table field ([0ede99b](0ede99b3cb))
* add patch for making repostable dimension fields editable ([4b57126](4b5712688a))
* allow on submit for selected fields ([6c3b5bb](6c3b5bb402))
* repost ledger button in JV ([e5eeb21](e5eeb216e8))
* update after submit in JV ([cdab3fa](cdab3fa970))
* validate before allowing repost ([8585cfc](8585cfc533))

### Performance Improvements

* serial and batch bundle valuation (reposting) (backport [#40255](https://github.com/frappe/erpnext/issues/40255)) ([#40262](https://github.com/frappe/erpnext/issues/40262)) ([93f3af7](93f3af7dba))
2024-03-06 03:31:25 +00:00
Deepesh Garg
5e89676d05 Merge pull request #40280 from frappe/version-15-hotfix
chore: release v15
2024-03-06 09:00:14 +05:30
ruthra kumar
50e49bef85 Merge pull request #40284 from frappe/mergify/bp/version-15-hotfix/pr-40278
fix: incorrect TCS on customer and suppliers with same name (backport #40278)
2024-03-05 15:48:25 +05:30
ruthra kumar
d74647d5a5 fix: incorrect TCS on customer and suppliers with same name
(cherry picked from commit 9904a9868c)
2024-03-05 09:54:46 +00:00
mergify[bot]
ee119f30fb chore: fixed fetch from (backport #40270) (#40275)
chore: fixed fetch from (#40270)

(cherry picked from commit 34051bc04f)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-03-05 14:32:36 +05:30
mergify[bot]
c7b96df69c fix: report path from the Item and Putaway Rule list (backport #40190) (#40266)
fix: report path from the Item and Putaway Rule list (#40190)

(cherry picked from commit 8e2f9787c1)

Co-authored-by: Nihantra C. Patel <141945075+Nihantra-Patel@users.noreply.github.com>
2024-03-04 20:03:42 +05:30
mergify[bot]
63209f4eac fix: do not allow to cancel incomplete reposting (backport #40224) (#40230)
* 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:21 +05:30
mergify[bot]
93f3af7dba perf: serial and batch bundle valuation (reposting) (backport #40255) (#40262)
* perf: serial and batch bundle valuation (reposting) (#40255)

perf: serial and batch bundle valuation
(cherry picked from commit 6379238893)

* chore: fix styles

* chore: fix linters

---------

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-03-04 13:13:49 +05:30
Gursheen Kaur Anand
0b1417e891 Merge pull request #40256 from GursheenK/editable-journals-v15
feat: editable journals v15
2024-03-04 11:15:41 +05:30
Gursheen Anand
16349553c7 fix: test for repost accounting in JVs 2024-03-04 00:25:57 +05:30
Gursheen Anand
4b5712688a feat: add patch for making repostable dimension fields editable 2024-03-04 00:25:54 +05:30
Gursheen Anand
cd24a2a05d fix: allow editable accounting dimensions for repostable doctypes 2024-03-04 00:24:32 +05:30
Gursheen Anand
c55c0f7173 fix: disable editable account heads 2024-03-04 00:24:26 +05:30
Gursheen Anand
6230bbc77d fix: test for reposting pi 2024-03-04 00:18:09 +05:30
Gursheen Anand
e20c1acb6e fix: check child rows before update 2024-03-04 00:18:09 +05:30
Gursheen Anand
6173654093 chore: correct typo 2024-03-04 00:18:09 +05:30
Gursheen Anand
b0be08f05d test: reposting entries for JV 2024-03-04 00:18:09 +05:30
Gursheen Anand
7aeb53a806 refactor: use qb for JV tests 2024-03-04 00:18:09 +05:30
Gursheen Anand
e5eeb216e8 feat: repost ledger button in JV 2024-03-04 00:18:09 +05:30
Gursheen Anand
8585cfc533 feat: validate before allowing repost 2024-03-04 00:18:04 +05:30
Gursheen Anand
a512ec7af5 refactor: better abstraction for controller code 2024-03-04 00:16:39 +05:30
Gursheen Anand
cdab3fa970 feat: update after submit in JV 2024-03-04 00:16:32 +05:30
Gursheen Anand
6c3b5bb402 feat: allow on submit for selected fields 2024-03-04 00:14:28 +05:30
Gursheen Anand
db7348a1de refactor: remove controller logic for setting balances 2024-03-04 00:13:32 +05:30
Gursheen Anand
84672e2275 refactor: exclude balances while setting currency 2024-03-04 00:13:32 +05:30
Gursheen Anand
c68939a0e0 refactor: exclude balance while setting acc details 2024-03-04 00:13:32 +05:30
Gursheen Anand
0c234e5c1a refactor: remove balance formatter 2024-03-04 00:13:32 +05:30
Gursheen Anand
689f277d13 refactor: remove balance fields from jv account 2024-03-04 00:11:23 +05:30
Gursheen Kaur Anand
328728e3a4 Merge pull request #40252 from frappe/mergify/bp/version-15-hotfix/pr-40250
fix(minor): company filter in cost center allocation (backport #40250)
2024-03-03 18:24:27 +05:30
Gursheen Anand
0ede99b3cb feat: add company filter to child table field
(cherry picked from commit 51909077bd)
2024-03-03 12:45:39 +00:00
Gursheen Kaur Anand
d130aadcf3 Merge pull request #40205 from frappe/mergify/bp/version-15-hotfix/pr-39584
fix: use receipt amount for reverse provisional entry (backport #39584)
2024-03-03 17:55:31 +05:30
mergify[bot]
1d421713be fix: rate change on changing of the qty (backport #40241) (#40243)
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:50:01 +05:30
ruthra kumar
0b091aaf14 Merge pull request #40239 from frappe/mergify/bp/version-15-hotfix/pr-40220
refactor: Gain/Loss Journal creation for Journals against Journals (backport #40220)
2024-03-02 15:57:18 +05:30
ruthra kumar
e5fdca7b05 test: gain/loss on Journals against Journals
(cherry picked from commit 8a5078b826)
2024-03-02 10:08:19 +00:00
ruthra kumar
d8cf6ba38d fix: allow gain/loss for Journals against Journals
(cherry picked from commit 5b67631d40)
2024-03-02 10:08:19 +00:00
ruthra kumar
9057bff786 fix: make use of 'flt' to prevent really low precision exc gain/loss
(cherry picked from commit 0aa72f841d)
2024-03-02 10:08:18 +00:00
Gursheen Anand
823abfd6e0 test: partial billing for provisional accounting
(cherry picked from commit c5770f2ecc)
2024-02-29 15:48:36 +00:00
Gursheen Anand
e55dc2a7c0 test: overbilling for provisional accounting
(cherry picked from commit ff3ca50a4b)
2024-02-29 15:48:36 +00:00
Gursheen Anand
00d410cc1d fix: over billing qty along with rate
(cherry picked from commit cc96d2b50c)
2024-02-29 15:48:36 +00:00
Gursheen Anand
87596e6e29 fix: handle partial invoice against provisional entry
(cherry picked from commit 2a46799188)
2024-02-29 15:48:36 +00:00
Gursheen Anand
0182b95230 fix: provisional reverse entry amount
(cherry picked from commit 3e59c66806)
2024-02-29 15:48:36 +00:00
Frappe PR Bot
23011df86b chore(release): Bumped to Version 15.15.0
# [15.15.0](https://github.com/frappe/erpnext/compare/v15.14.7...v15.15.0) (2024-02-28)

### Bug Fixes

* add flags for repost to ensure correct accounting from India Compliance App ([7d14ecf](7d14ecfcb8))
* amount label according to party type ([d541ba3](d541ba3e61))
* Cannot read properties of undefined (backport [#40081](https://github.com/frappe/erpnext/issues/40081)) ([#40083](https://github.com/frappe/erpnext/issues/40083)) ([53d943e](53d943ec70))
* capacity planning issue in the job card (backport [#40092](https://github.com/frappe/erpnext/issues/40092)) ([#40101](https://github.com/frappe/erpnext/issues/40101)) ([27703b5](27703b54bd))
* change label name ([824df72](824df72eeb))
* check for pricing rules on item ([32d9642](32d9642379))
* check_credit_limit on_update_after_submit of Sales Order ([83d7111](83d7111649))
* communication_date in party dashboards (backport [#40005](https://github.com/frappe/erpnext/issues/40005)) ([#40021](https://github.com/frappe/erpnext/issues/40021)) ([4269ef8](4269ef8c98))
* Completed Work Orders report not working ([ca03e9c](ca03e9cfd3))
* Cr/Dr notes with POS Payments ([2e07b03](2e07b03307))
* currency symbol in landed cost voucher and material request (backport [#40138](https://github.com/frappe/erpnext/issues/40138)) ([#40141](https://github.com/frappe/erpnext/issues/40141)) ([57bb031](57bb031602))
* Data too long for column 'serial_no' at row 1 (backport [#40098](https://github.com/frappe/erpnext/issues/40098)) ([#40139](https://github.com/frappe/erpnext/issues/40139)) ([9d19ec4](9d19ec43c8))
* default taxable value for item not found in item list ([7e43f6b](7e43f6b7e0))
* delete PLE containing invoice in against ([190bd45](190bd45bd7))
* do not make MR against raw materials of available sub assemblies (backport [#40085](https://github.com/frappe/erpnext/issues/40085)) ([#40087](https://github.com/frappe/erpnext/issues/40087)) ([cf5fa21](cf5fa210bb))
* Fiscal Year exception on demo data setup ([56ee843](56ee843233))
* incorrect item name in MR (backport [#40018](https://github.com/frappe/erpnext/issues/40018)) ([#40024](https://github.com/frappe/erpnext/issues/40024)) ([9f8f3db](9f8f3db953))
* Issues regarding asset cancellation and deletion ([8eb2f67](8eb2f67910))
* negative stock error while making stock reconciliation (backport [#40016](https://github.com/frappe/erpnext/issues/40016)) ([#40026](https://github.com/frappe/erpnext/issues/40026)) ([c964c45](c964c45f4e))
* on unreconciliation, update advance paid ([4d1f56c](4d1f56c4bd))
* only check for delinked PLEs ([a75a69a](a75a69a01e))
* only consider contributed qty towards achieved targets ([194f46b](194f46be57))
* parent warehouse checks in the production plan for sub-assemblies (backport [#40150](https://github.com/frappe/erpnext/issues/40150)) ([#40157](https://github.com/frappe/erpnext/issues/40157)) ([4784117](4784117a8f))
* remove cancelled payment entry from Payment Period Based On Invoice Date ([72da308](72da3083e6))
* remove cancelled payment entry from PPBOID report ([0be5203](0be520331c))
* remove config for default bank account in test ([36b442a](36b442a951))
* remove microsecond from posting datetime (backport [#40017](https://github.com/frappe/erpnext/issues/40017)) ([#40022](https://github.com/frappe/erpnext/issues/40022)) ([eaa3849](eaa3849df4))
* removed unwanted patch ([ee2d108](ee2d108bef))
* resolved conflict ([6928674](692867427c))
* resolved conflict ([a0c0ab7](a0c0ab7709))
* skip max discount validation for rate adjustment ([3b96aae](3b96aaeead))
* skip SO & DN validation for debit note ([cd42089](cd42089e20))
* Supplier users not able to see RFQ on the Portal (backport [#40161](https://github.com/frappe/erpnext/issues/40161)) ([#40165](https://github.com/frappe/erpnext/issues/40165)) ([6a63a6c](6a63a6c98a))
* timesheet per billed state edge case (backport [#40010](https://github.com/frappe/erpnext/issues/40010)) ([#40029](https://github.com/frappe/erpnext/issues/40029)) ([a543bf4](a543bf47ef))
* translatable columns in Sales Pipeline Analytics report ([1c5a7e2](1c5a7e29f2))
* type error for missing frm obj ([6b5e1cf](6b5e1cfeb7))
* unique gl account for plaid bank accounts ([65853da](65853da505))
* use correct variable name on hotfix branches ([0694fd1](0694fd19fd))
* use frm instead of cur_frm ([341f903](341f9030f5))
* use serial batch fields for packed items (backport [#40140](https://github.com/frappe/erpnext/issues/40140)) ([#40142](https://github.com/frappe/erpnext/issues/40142)) ([1860399](1860399ccb))

### Features

* show contributed qty in transaction summary ([38abfdb](38abfdb8ae))
* update billed amount in PO and PR ([e7e8149](e7e8149fbe))

### Performance Improvements

* new column Posting Datetime in SLE to optimize stock ledger related queries (backport [#39800](https://github.com/frappe/erpnext/issues/39800)) ([#40004](https://github.com/frappe/erpnext/issues/40004)) ([b9181e8](b9181e85dc))
2024-02-28 05:13:40 +00:00
Deepesh Garg
4291b9fa8d Merge pull request #40148 from frappe/version-15-hotfix
chore: release v15
2024-02-28 10:42:31 +05:30
Frappe PR Bot
792de1be03 chore(release): Bumped to Version 15.14.7
## [15.14.7](https://github.com/frappe/erpnext/compare/v15.14.6...v15.14.7) (2024-02-26)

### Bug Fixes

* Issues regarding asset cancellation and deletion ([6fc4dac](6fc4dac4db))
* removed unwanted patch ([3c98368](3c98368e45))
* resolved conflict ([fc565ec](fc565ecd99))
* resolved conflict ([d196aa5](d196aa5a36))
2024-02-26 07:33:28 +00:00
Nabin Hait
66156fcfa7 Merge pull request #40031 from frappe/mergify/bp/version-15/pr-39983
fix: Issues regarding asset cancellation and deletion (backport #39983)
2024-02-26 13:02:20 +05:30
Nabin Hait
fc565ecd99 fix: resolved conflict 2024-02-26 12:21:57 +05:30
Nabin Hait
d196aa5a36 fix: resolved conflict 2024-02-26 12:21:25 +05:30
Frappe PR Bot
f723d7b561 chore(release): Bumped to Version 15.14.6
## [15.14.6](https://github.com/frappe/erpnext/compare/v15.14.5...v15.14.6) (2024-02-22)

### Bug Fixes

* communication_date in party dashboards (backport [#40005](https://github.com/frappe/erpnext/issues/40005)) ([#40043](https://github.com/frappe/erpnext/issues/40043)) ([6662c32](6662c321a5))
2024-02-22 11:14:07 +00:00
mergify[bot]
6662c321a5 fix: communication_date in party dashboards (backport #40005) (#40043)
fix: accommodate for changed orderby statement

(cherry picked from commit 87df7ff717)

Co-authored-by: Gursheen Anand <gursheen@frappe.io>
2024-02-22 16:40:46 +05:30
Nabin Hait
3c98368e45 fix: removed unwanted patch
(cherry picked from commit 85471533e9)
2024-02-22 05:40:58 +00:00
Nabin Hait
6fc4dac4db fix: Issues regarding asset cancellation and deletion
(cherry picked from commit 17f85de6fb)

# Conflicts:
#	erpnext/assets/doctype/asset/depreciation.py
#	erpnext/assets/doctype/asset_capitalization/asset_capitalization.py
2024-02-22 05:40:57 +00:00
Frappe PR Bot
afc87a4486 chore(release): Bumped to Version 15.14.5
## [15.14.5](https://github.com/frappe/erpnext/compare/v15.14.4...v15.14.5) (2024-02-22)

### Bug Fixes

* check for pricing rules on item ([5084b9b](5084b9bd4b))
2024-02-22 05:38:47 +00:00
Deepesh Garg
5137966fe5 Merge pull request #40030 from frappe/mergify/bp/version-15/pr-40019
fix: TypeError for item pricing rules (#39999)
2024-02-22 11:07:32 +05:30
Gursheen Anand
5084b9bd4b fix: check for pricing rules on item
(cherry picked from commit ecd83b12ab)
(cherry picked from commit 32d9642379)
2024-02-22 05:36:43 +00:00
Frappe PR Bot
3d7e87185c chore(release): Bumped to Version 15.14.4
## [15.14.4](https://github.com/frappe/erpnext/compare/v15.14.3...v15.14.4) (2024-02-21)

### Bug Fixes

* 'NoneType' object is not iterable (backport [#39977](https://github.com/frappe/erpnext/issues/39977)) ([#39981](https://github.com/frappe/erpnext/issues/39981)) ([0f87ec1](0f87ec15ad))
* **Bank Transaction:** precision for `(un)allocated_amount` ([bf5d2f5](bf5d2f5fe4))
* batch filter not working in stock ledger report (backport [#39934](https://github.com/frappe/erpnext/issues/39934)) ([#39935](https://github.com/frappe/erpnext/issues/39935)) ([1513595](15135952fc))
* do not empty serial batch fields (backport [#39948](https://github.com/frappe/erpnext/issues/39948)) ([#39956](https://github.com/frappe/erpnext/issues/39956)) ([acd2e93](acd2e93f8c))
* fetch company terms ([14fe0af](14fe0af887))
* float division by zero ([b954bdf](b954bdfdf9))
* group node in warehouse filter in Item-wise Sales Register ([74819b8](74819b8e70))
* **Issue:** create communication ([f5d7fbd](f5d7fbdaf8))
* no need call for company method in sales invoice js ([bef38f7](bef38f74fe))
* not able to make purchase receipt ([3732946](37329469c3))
* party item code in Blanket Order ([518b22b](518b22bffc))
* reposting failed status not updated (backport [#39970](https://github.com/frappe/erpnext/issues/39970)) ([#39972](https://github.com/frappe/erpnext/issues/39972)) ([46f7569](46f7569a54))
* set batch created from bundle to batch field in stock transaction (backport [#39966](https://github.com/frappe/erpnext/issues/39966)) ([#39987](https://github.com/frappe/erpnext/issues/39987)) ([2ee51d3](2ee51d36ff))
* show active bom in the dropdown while making stock entry and MR (backport [#39974](https://github.com/frappe/erpnext/issues/39974)) ([#39976](https://github.com/frappe/erpnext/issues/39976)) ([7201448](720144898f))
* update_dimension is required and not need party account method ([a56d5b8](a56d5b805c))
* use serial batch fields not enabled for new stock entry ([40d4e32](40d4e3261e))
2024-02-21 05:29:45 +00:00
rohitwaghchaure
177110349d Merge pull request #39979 from frappe/version-15-hotfix
chore: release v15
2024-02-21 10:58:33 +05:30
627 changed files with 25739 additions and 21843 deletions

View File

@@ -9,6 +9,13 @@ trim_trailing_whitespace = true
charset = utf-8 charset = utf-8
# python, js indentation settings # python, js indentation settings
[{*.py,*.js}] [{*.py,*.js,*.vue,*.css,*.scss,*.html}]
indent_style = tab indent_style = tab
indent_size = 4 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

@@ -124,6 +124,7 @@
"beforeEach": true, "beforeEach": true,
"onScan": true, "onScan": true,
"extend_cscript": true, "extend_cscript": true,
"localforage": true "localforage": true,
"Plaid": true
} }
} }

View File

@@ -20,6 +20,23 @@ repos:
- id: check-yaml - id: check-yaml
- id: debug-statements - 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/.*
)$
- repo: https://github.com/pre-commit/mirrors-eslint - repo: https://github.com/pre-commit/mirrors-eslint
rev: v8.44.0 rev: v8.44.0
hooks: hooks:

View File

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

View File

@@ -3,7 +3,7 @@ import inspect
import frappe import frappe
__version__ = "15.14.3" __version__ = "15.16.2"
def get_default_company(user=None): def get_default_company(user=None):
@@ -13,7 +13,7 @@ def get_default_company(user=None):
if not user: if not user:
user = frappe.session.user user = frappe.session.user
companies = get_user_default_as_list(user, "company") companies = get_user_default_as_list("company", user)
if companies: if companies:
default_company = companies[0] default_company = companies[0]
else: 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"] = { frappe.dashboards.chart_sources["Account Balance Timeline"] = {
method: "erpnext.accounts.dashboard_chart_source.account_balance_timeline.account_balance_timeline.get", 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", fieldtype: "Link",
options: "Company", options: "Company",
default: frappe.defaults.get_user_default("Company"), default: frappe.defaults.get_user_default("Company"),
reqd: 1 reqd: 1,
}, },
{ {
fieldname: "account", fieldname: "account",
label: __("Account"), label: __("Account"),
fieldtype: "Link", fieldtype: "Link",
options: "Account", options: "Account",
reqd: 1 reqd: 1,
}, },
] ],
}; };

View File

@@ -26,19 +26,14 @@ frappe.ui.form.on("Account", {
frm.toggle_enable(["is_group", "company"], false); frm.toggle_enable(["is_group", "company"], false);
if (cint(frm.doc.is_group) == 0) { if (cint(frm.doc.is_group) == 0) {
frm.toggle_display( frm.toggle_display("freeze_account", frm.doc.__onload && frm.doc.__onload.can_freeze_account);
"freeze_account",
frm.doc.__onload && frm.doc.__onload.can_freeze_account
);
} }
// read-only for root accounts // read-only for root accounts
if (!frm.is_new()) { if (!frm.is_new()) {
if (!frm.doc.parent_account) { if (!frm.doc.parent_account) {
frm.set_read_only(); frm.set_read_only();
frm.set_intro( frm.set_intro(__("This is a root account and cannot be edited."));
__("This is a root account and cannot be edited.")
);
} else { } else {
// credit days and type if customer or supplier // credit days and type if customer or supplier
frm.set_intro(null); frm.set_intro(null);
@@ -80,27 +75,33 @@ frappe.ui.form.on("Account", {
); );
if (frm.doc.is_group == 1) { if (frm.doc.is_group == 1) {
frm.add_custom_button(__('Convert to Non-Group'), function () { frm.add_custom_button(
__("Convert to Non-Group"),
function () {
return frappe.call({ return frappe.call({
doc: frm.doc, doc: frm.doc,
method: 'convert_group_to_ledger', method: "convert_group_to_ledger",
callback: function() { callback: function () {
frm.refresh(); frm.refresh();
} },
}); });
}, __('Actions')); },
__("Actions")
} else if (cint(frm.doc.is_group) == 0 );
&& frappe.boot.user.can_read.indexOf("GL Entry") !== -1) { } else if (cint(frm.doc.is_group) == 0 && frappe.boot.user.can_read.indexOf("GL Entry") !== -1) {
frm.add_custom_button(__('General Ledger'), function () { frm.add_custom_button(
__("General Ledger"),
function () {
frappe.route_options = { frappe.route_options = {
"account": frm.doc.name, account: frm.doc.name,
"from_date": erpnext.utils.get_fiscal_year(frappe.datetime.get_today(), true)[1], from_date: erpnext.utils.get_fiscal_year(frappe.datetime.get_today(), true)[1],
"to_date": erpnext.utils.get_fiscal_year(frappe.datetime.get_today(), true)[2], to_date: erpnext.utils.get_fiscal_year(frappe.datetime.get_today(), true)[2],
"company": frm.doc.company company: frm.doc.company,
}; };
frappe.set_route("query-report", "General Ledger"); frappe.set_route("query-report", "General Ledger");
}, __('View')); },
__("View")
);
frm.add_custom_button( frm.add_custom_button(
__("Convert to Group"), __("Convert to Group"),
@@ -193,14 +194,8 @@ frappe.ui.form.on("Account", {
if (r.message) { if (r.message) {
frappe.set_route("Form", "Account", r.message); frappe.set_route("Form", "Account", r.message);
} else { } else {
frm.set_value( frm.set_value("account_number", data.account_number);
"account_number", frm.set_value("account_name", data.account_name);
data.account_number
);
frm.set_value(
"account_name",
data.account_name
);
} }
d.hide(); d.hide();
} }

View File

@@ -1,4 +1,4 @@
frappe.provide("frappe.treeview_settings") frappe.provide("frappe.treeview_settings");
frappe.treeview_settings["Account"] = { frappe.treeview_settings["Account"] = {
breadcrumb: "Accounts", breadcrumb: "Accounts",
@@ -7,12 +7,12 @@ frappe.treeview_settings["Account"] = {
filters: [ filters: [
{ {
fieldname: "company", fieldname: "company",
fieldtype:"Select", fieldtype: "Select",
options: erpnext.utils.get_tree_options("company"), options: erpnext.utils.get_tree_options("company"),
label: __("Company"), label: __("Company"),
default: erpnext.utils.get_tree_default("company"), default: erpnext.utils.get_tree_default("company"),
on_change: function() { on_change: function () {
var me = frappe.treeview_settings['Account'].treeview; var me = frappe.treeview_settings["Account"].treeview;
var company = me.page.fields_dict.company.get_value(); var company = me.page.fields_dict.company.get_value();
if (!company) { if (!company) {
frappe.throw(__("Please set a Company")); frappe.throw(__("Please set a Company"));
@@ -22,30 +22,36 @@ frappe.treeview_settings["Account"] = {
args: { args: {
company: company, company: company,
}, },
callback: function(r) { callback: function (r) {
if(r.message) { if (r.message) {
let root_company = r.message.length ? r.message[0] : ""; let root_company = r.message.length ? r.message[0] : "";
me.page.fields_dict.root_company.set_value(root_company); 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.db.get_value(
frappe.flags.ignore_root_company_validation = r.allow_account_creation_against_child_company; "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", fieldname: "root_company",
fieldtype:"Data", fieldtype: "Data",
label: __("Root Company"), label: __("Root Company"),
hidden: true, hidden: true,
disable_onchange: true disable_onchange: true,
} },
], ],
root_label: "Accounts", root_label: "Accounts",
get_tree_nodes: 'erpnext.accounts.utils.get_children', get_tree_nodes: "erpnext.accounts.utils.get_children",
on_get_node: function(nodes, deep=false) { on_get_node: function (nodes, deep = false) {
if (frappe.boot.user.can_read.indexOf("GL Entry") == -1) return; if (frappe.boot.user.can_read.indexOf("GL Entry") == -1) return;
let accounts = []; let accounts = [];
@@ -57,151 +63,231 @@ frappe.treeview_settings["Account"] = {
} }
frappe.db.get_single_value("Accounts Settings", "show_balance_in_coa").then((value) => { frappe.db.get_single_value("Accounts Settings", "show_balance_in_coa").then((value) => {
if(value) { if (value) {
const get_balances = frappe.call({ const get_balances = frappe.call({
method: 'erpnext.accounts.utils.get_account_balances', method: "erpnext.accounts.utils.get_account_balances",
args: { args: {
accounts: accounts, 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; if (!r.message || r.message.length == 0) return;
for (let account of r.message) { for (let account of r.message) {
const node = cur_tree.nodes && cur_tree.nodes[account.value]; const node = cur_tree.nodes && cur_tree.nodes[account.value];
if (!node || node.is_root) continue; if (!node || node.is_root) continue;
// show Dr if positive since balance is calculated as debit - credit else show Cr // show Dr if positive since balance is calculated as debit - credit else show Cr
const balance = account.balance_in_account_currency || account.balance; 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); const format = (value, currency) => format_currency(Math.abs(value), currency);
if (account.balance!==undefined) { if (account.balance !== undefined) {
node.parent && node.parent.find('.balance-area').remove(); node.parent && node.parent.find(".balance-area").remove();
$('<span class="balance-area pull-right">' $(
+ (account.balance_in_account_currency ? '<span class="balance-area pull-right">' +
(format(account.balance_in_account_currency, account.account_currency) + " / ") : "") (account.balance_in_account_currency
+ format(account.balance, account.company_currency) ? format(
+ " " + dr_or_cr account.balance_in_account_currency,
+ '</span>').insertBefore(node.$ul); account.account_currency
) + " / "
: "") +
format(account.balance, account.company_currency) +
" " +
dr_or_cr +
"</span>"
).insertBefore(node.$ul);
} }
} }
}); });
} }
}); });
}, },
add_tree_node: 'erpnext.accounts.utils.add_ac', add_tree_node: "erpnext.accounts.utils.add_ac",
menu_items:[ menu_items: [
{ {
label: __('New Company'), label: __("New Company"),
action: function() { frappe.new_doc("Company", true) }, action: function () {
condition: 'frappe.boot.user.can_create.indexOf("Company") !== -1' frappe.new_doc("Company", true);
} },
condition: 'frappe.boot.user.can_create.indexOf("Company") !== -1',
},
], ],
fields: [ 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",
{fieldtype:'Data', fieldname:'account_number', label:__('Account Number'), fieldname: "account_name",
description: __("Number of new Account, it will be included in the account name as a prefix")}, label: __("New Account Name"),
{fieldtype:'Check', fieldname:'is_group', label:__('Is Group'), reqd: true,
description: __('Further accounts can be made under Groups, but entries can be made against non-Groups')}, description: __(
{fieldtype:'Select', fieldname:'root_type', label:__('Root Type'), "Name of new Account. Note: Please don't create accounts for Customers and Suppliers"
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, fieldtype: "Data",
description: __("Optional. This setting will be used to filter in various transactions.") 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"], ignore_fields: ["parent_account"],
onload: function(treeview) { onload: function (treeview) {
frappe.treeview_settings['Account'].treeview = {}; frappe.treeview_settings["Account"].treeview = {};
$.extend(frappe.treeview_settings['Account'].treeview, treeview); $.extend(frappe.treeview_settings["Account"].treeview, treeview);
function get_company() { function get_company() {
return treeview.page.fields_dict.company.get_value(); return treeview.page.fields_dict.company.get_value();
} }
// tools // tools
treeview.page.add_inner_button(__("Chart of Cost Centers"), function() { treeview.page.add_inner_button(
frappe.set_route('Tree', 'Cost Center', {company: get_company()}); __("Chart of Cost Centers"),
}, __('View')); function () {
frappe.set_route("Tree", "Cost Center", { company: get_company() });
},
__("View")
);
treeview.page.add_inner_button(__("Opening Invoice Creation Tool"), function() { treeview.page.add_inner_button(
frappe.set_route('Form', 'Opening Invoice Creation Tool', {company: get_company()}); __("Opening Invoice Creation Tool"),
}, __('View')); function () {
frappe.set_route("Form", "Opening Invoice Creation Tool", { company: get_company() });
},
__("View")
);
treeview.page.add_inner_button(__("Period Closing Voucher"), function() { treeview.page.add_inner_button(
frappe.set_route('List', 'Period Closing Voucher', {company: get_company()}); __("Period Closing Voucher"),
}, __('View')); function () {
frappe.set_route("List", "Period Closing Voucher", { company: get_company() });
},
__("View")
);
treeview.page.add_inner_button(
treeview.page.add_inner_button(__("Journal Entry"), function() { __("Journal Entry"),
frappe.new_doc('Journal Entry', {company: get_company()}); function () {
}, __('Create')); frappe.new_doc("Journal Entry", { company: get_company() });
treeview.page.add_inner_button(__("Company"), function() { },
frappe.new_doc('Company'); __("Create")
}, __('Create')); );
treeview.page.add_inner_button(
__("Company"),
function () {
frappe.new_doc("Company");
},
__("Create")
);
// financial statements // financial statements
for (let report of ['Trial Balance', 'General Ledger', 'Balance Sheet', for (let report of [
'Profit and Loss Statement', 'Cash Flow Statement', 'Accounts Payable', 'Accounts Receivable']) { "Trial Balance",
treeview.page.add_inner_button(__(report), function() { "General Ledger",
frappe.set_route('query-report', report, {company: get_company()}); "Balance Sheet",
}, __('Financial Statements')); "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() });
}, },
post_render: function(treeview) { __("Financial Statements")
frappe.treeview_settings['Account'].treeview["tree"] = treeview.tree; );
treeview.page.set_primary_action(__("New"), function() { }
},
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(); let root_company = treeview.page.fields_dict.root_company.get_value();
if(root_company) { if (root_company) {
frappe.throw(__("Please add the account to root level Company - {0}"), [root_company]); frappe.throw(__("Please add the account to root level Company - {0}"), [root_company]);
} else { } else {
treeview.new_node(); treeview.new_node();
} }
}, "add"); },
"add"
);
}, },
toolbar: [ toolbar: [
{ {
label:__("Add Child"), label: __("Add Child"),
condition: function(node) { condition: function (node) {
return frappe.boot.user.can_create.indexOf("Account") !== -1 return (
&& (!frappe.treeview_settings['Account'].treeview.page.fields_dict.root_company.get_value() frappe.boot.user.can_create.indexOf("Account") !== -1 &&
|| frappe.flags.ignore_root_company_validation) (!frappe.treeview_settings[
&& node.expandable && !node.hide_add; "Account"
].treeview.page.fields_dict.root_company.get_value() ||
frappe.flags.ignore_root_company_validation) &&
node.expandable &&
!node.hide_add
);
}, },
click: function() { click: function () {
var me = frappe.views.trees['Account']; var me = frappe.views.trees["Account"];
me.new_node(); me.new_node();
}, },
btnClass: "hidden-xs" btnClass: "hidden-xs",
}, },
{ {
condition: function(node) { condition: function (node) {
return !node.root && frappe.boot.user.can_read.indexOf("GL Entry") !== -1 return !node.root && frappe.boot.user.can_read.indexOf("GL Entry") !== -1;
}, },
label: __("View Ledger"), label: __("View Ledger"),
click: function(node, btn) { click: function (node, btn) {
frappe.route_options = { frappe.route_options = {
"account": node.label, account: node.label,
"from_date": erpnext.utils.get_fiscal_year(frappe.datetime.get_today(), true)[1], from_date: erpnext.utils.get_fiscal_year(frappe.datetime.get_today(), true)[1],
"to_date": erpnext.utils.get_fiscal_year(frappe.datetime.get_today(), true)[2], to_date: erpnext.utils.get_fiscal_year(frappe.datetime.get_today(), true)[2],
"company": frappe.treeview_settings['Account'].treeview.page.fields_dict.company.get_value() company:
frappe.treeview_settings["Account"].treeview.page.fields_dict.company.get_value(),
}; };
frappe.set_route("query-report", "General Ledger"); 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 // Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt // For license information, please see license.txt
frappe.ui.form.on('Accounting Dimension', { frappe.ui.form.on("Accounting Dimension", {
refresh: function(frm) { refresh: function (frm) {
frm.set_query('document_type', () => { frm.set_query("document_type", () => {
let invalid_doctypes = frappe.model.core_doctypes_list; let invalid_doctypes = frappe.model.core_doctypes_list;
invalid_doctypes.push('Accounting Dimension', 'Project', invalid_doctypes.push(
'Cost Center', 'Accounting Dimension Detail', 'Company'); "Accounting Dimension",
"Project",
"Cost Center",
"Accounting Dimension Detail",
"Company"
);
return { return {
filters: { 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]; let d = locals[cdt][cdn];
return { return {
filters: { filters: {
company: d.company, company: d.company,
root_type: ["in", ["Asset", "Liability"]], root_type: ["in", ["Asset", "Liability"]],
is_group: 0 is_group: 0,
} },
} };
}); });
if (!frm.is_new()) { 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); frappe.set_route("List", frm.doc.document_type);
}); });
let button = frm.doc.disabled ? "Enable" : "Disable"; let button = frm.doc.disabled ? "Enable" : "Disable";
frm.add_custom_button(__(button), function() { frm.add_custom_button(__(button), function () {
frm.set_value("disabled", 1 - frm.doc.disabled);
frm.set_value('disabled', 1 - frm.doc.disabled);
frappe.call({ frappe.call({
method: "erpnext.accounts.doctype.accounting_dimension.accounting_dimension.disable_dimension", method: "erpnext.accounts.doctype.accounting_dimension.accounting_dimension.disable_dimension",
args: { args: {
doc: frm.doc doc: frm.doc,
}, },
freeze: true, freeze: true,
callback: function(r) { callback: function (r) {
let message = frm.doc.disabled ? "Dimension Disabled" : "Dimension Enabled"; let message = frm.doc.disabled ? "Dimension Disabled" : "Dimension Enabled";
frm.save(); 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); frappe.db.get_value(
frm.set_value('fieldname', frappe.model.scrub(frm.doc.document_type)); "Accounting Dimension",
{ document_type: frm.doc.document_type },
frappe.db.get_value('Accounting Dimension', {'document_type': frm.doc.document_type}, 'document_type', (r) => { "document_type",
(r) => {
if (r && r.document_type) { if (r && r.document_type) {
frm.set_df_property('document_type', 'description', "Document type is already set as dimension"); frm.set_df_property(
"document_type",
"description",
"Document type is already set as dimension"
);
} }
}); }
);
}, },
}); });
frappe.ui.form.on('Accounting Dimension Detail', { frappe.ui.form.on("Accounting Dimension Detail", {
dimension_defaults_add: function(frm, cdt, cdn) { dimension_defaults_add: function (frm, cdt, cdn) {
let row = locals[cdt][cdn]; let row = locals[cdt][cdn];
row.reference_document = frm.doc.document_type; row.reference_document = frm.doc.document_type;
} },
}); });

View File

@@ -11,6 +11,10 @@ from frappe.model import core_doctypes_list
from frappe.model.document import Document from frappe.model.document import Document
from frappe.utils import cstr from frappe.utils import cstr
from erpnext.accounts.doctype.repost_accounting_ledger.repost_accounting_ledger import (
get_allowed_types_from_settings,
)
class AccountingDimension(Document): class AccountingDimension(Document):
# begin: auto-generated types # begin: auto-generated types
@@ -106,6 +110,7 @@ def make_dimension_in_accounting_doctypes(doc, doclist=None):
doc_count = len(get_accounting_dimensions()) doc_count = len(get_accounting_dimensions())
count = 0 count = 0
repostable_doctypes = get_allowed_types_from_settings()
for doctype in doclist: for doctype in doclist:
@@ -121,6 +126,7 @@ def make_dimension_in_accounting_doctypes(doc, doclist=None):
"options": doc.document_type, "options": doc.document_type,
"insert_after": insert_after_field, "insert_after": insert_after_field,
"owner": "Administrator", "owner": "Administrator",
"allow_on_submit": 1 if doctype in repostable_doctypes else 0,
} }
meta = frappe.get_meta(doctype, cached=False) meta = frappe.get_meta(doctype, cached=False)

View File

@@ -1,10 +1,9 @@
// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors // Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt // For license information, please see license.txt
frappe.ui.form.on('Accounting Dimension Filter', { frappe.ui.form.on("Accounting Dimension Filter", {
refresh: function(frm, cdt, cdn) { refresh: function (frm, cdt, cdn) {
let help_content = let help_content = `<table class="table table-bordered" style="background-color: var(--scrollbar-track-color);">
`<table class="table table-bordered" style="background-color: var(--scrollbar-track-color);">
<tr><td> <tr><td>
<p> <p>
<i class="fa fa-hand-right"></i> <i class="fa fa-hand-right"></i>
@@ -13,62 +12,65 @@ frappe.ui.form.on('Accounting Dimension Filter', {
</td></tr> </td></tr>
</table>`; </table>`;
frm.set_df_property('dimension_filter_help', 'options', help_content); frm.set_df_property("dimension_filter_help", "options", help_content);
}, },
onload: function(frm) { onload: function (frm) {
frm.set_query('applicable_on_account', 'accounts', function() { frm.set_query("applicable_on_account", "accounts", function () {
return { return {
filters: { filters: {
'company': frm.doc.company company: frm.doc.company,
} },
}; };
}); });
frappe.db.get_list('Accounting Dimension', frappe.db.get_list("Accounting Dimension", { fields: ["document_type"] }).then((res) => {
{fields: ['document_type']}).then((res) => { let options = ["Cost Center", "Project"];
let options = ['Cost Center', 'Project'];
res.forEach((dimension) => { res.forEach((dimension) => {
options.push(dimension.document_type); 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 = {}; let filters = {};
if (frm.doc.accounting_dimension) { 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)) { 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')) { if (frappe.meta.has_field(frm.doc.accounting_dimension, "company")) {
filters['company'] = frm.doc.company; filters["company"] = frm.doc.company;
} }
frm.set_query('dimension_value', 'dimensions', function() { frm.set_query("dimension_value", "dimensions", function () {
return { return {
filters: filters filters: filters,
}; };
}); });
}); });
} }
}, },
accounting_dimension: function(frm) { accounting_dimension: function (frm) {
frm.clear_table("dimensions"); frm.clear_table("dimensions");
let row = frm.add_child("dimensions"); let row = frm.add_child("dimensions");
row.accounting_dimension = frm.doc.accounting_dimension; 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.refresh_field("dimensions");
frm.trigger('setup_filters'); frm.trigger("setup_filters");
}, },
apply_restriction_on_values: function(frm) { apply_restriction_on_values: function (frm) {
/** If restriction on values is not applied, we should set "allow_or_restrict" to "Restrict" with an empty allowed dimension table. /** If restriction on values is not applied, we should set "allow_or_restrict" to "Restrict" with an empty allowed dimension table.
* Hence it's not "restricted" on any value. * Hence it's not "restricted" on any value.
*/ */
@@ -77,13 +79,13 @@ frappe.ui.form.on('Accounting Dimension Filter', {
frm.clear_table("dimensions"); frm.clear_table("dimensions");
frm.refresh_field("dimensions"); frm.refresh_field("dimensions");
} }
} },
}); });
frappe.ui.form.on('Allowed Dimension', { frappe.ui.form.on("Allowed Dimension", {
dimensions_add: function(frm, cdt, cdn) { dimensions_add: function (frm, cdt, cdn) {
let row = locals[cdt][cdn]; let row = locals[cdt][cdn];
row.accounting_dimension = frm.doc.accounting_dimension; row.accounting_dimension = frm.doc.accounting_dimension;
frm.refresh_field("dimensions"); frm.refresh_field("dimensions");
} },
}); });

View File

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

View File

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

View File

@@ -1,8 +1,11 @@
frappe.ui.form.on("Accounts Settings", {
frappe.ui.form.on('Accounts Settings', { refresh: function (frm) {
refresh: function(frm) {
frm.set_df_property("acc_frozen_upto", "label", "Books Closed Through"); 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"); frm.set_df_property("credit_controller", "label", "Credit Manager");
} },
}); });

View File

@@ -1,38 +1,36 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors // Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt // For license information, please see license.txt
frappe.provide('erpnext.integrations'); frappe.provide("erpnext.integrations");
frappe.ui.form.on('Bank', { frappe.ui.form.on("Bank", {
onload: function(frm) { onload: function (frm) {
add_fields_to_mapping_table(frm); add_fields_to_mapping_table(frm);
}, },
refresh: function(frm) { refresh: function (frm) {
add_fields_to_mapping_table(frm); add_fields_to_mapping_table(frm);
frm.toggle_display(['address_html','contact_html'], !frm.doc.__islocal); frm.toggle_display(["address_html", "contact_html"], !frm.doc.__islocal);
if (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); frappe.contacts.clear_address_and_contact(frm);
} } else {
else { frm.set_df_property("address_and_contact", "hidden", 0);
frm.set_df_property('address_and_contact', 'hidden', 0);
frappe.contacts.render_address_and_contact(frm); frappe.contacts.render_address_and_contact(frm);
} }
if (frm.doc.plaid_access_token) { 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); new erpnext.integrations.refreshPlaidLink(frm.doc.plaid_access_token);
}); });
} }
} },
}); });
let add_fields_to_mapping_table = function (frm) { let add_fields_to_mapping_table = function (frm) {
let options = []; let options = [];
frappe.model.with_doctype("Bank Transaction", function() { frappe.model.with_doctype("Bank Transaction", function () {
let meta = frappe.get_meta("Bank Transaction"); let meta = frappe.get_meta("Bank Transaction");
meta.fields.forEach(value => { meta.fields.forEach((value) => {
if (!["Section Break", "Column Break"].includes(value.fieldtype)) { if (!["Section Break", "Column Break"].includes(value.fieldtype)) {
options.push(value.fieldname); options.push(value.fieldname);
} }
@@ -40,30 +38,32 @@ let add_fields_to_mapping_table = function (frm) {
}); });
frm.fields_dict.bank_transaction_mapping.grid.update_docfield_property( 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 { erpnext.integrations.refreshPlaidLink = class refreshPlaidLink {
constructor(access_token) { constructor(access_token) {
this.access_token = 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(); this.init_config();
} }
async 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.token = await this.get_link_token_for_update();
this.init_plaid(); this.init_plaid();
} }
async get_link_token_for_update() { async get_link_token_for_update() {
const token = frappe.xcall( 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 } { access_token: this.access_token }
) );
if (!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; return token;
} }
@@ -90,35 +90,45 @@ erpnext.integrations.refreshPlaidLink = class refreshPlaidLink {
resolve(); resolve();
return; return;
} }
const el = document.createElement('script'); const el = document.createElement("script");
el.type = 'text/javascript'; el.type = "text/javascript";
el.async = true; el.async = true;
el.src = src; el.src = src;
el.addEventListener('load', resolve); el.addEventListener("load", resolve);
el.addEventListener('error', reject); el.addEventListener("error", reject);
el.addEventListener('abort', reject); el.addEventListener("abort", reject);
document.head.appendChild(el); document.head.appendChild(el);
}); });
} }
onScriptLoaded(me) { onScriptLoaded(me) {
me.linkHandler = Plaid.create({ // eslint-disable-line no-undef me.linkHandler = Plaid.create({
// eslint-disable-line no-undef
env: me.plaid_env, env: me.plaid_env,
token: me.token, token: me.token,
onSuccess: me.plaid_success onSuccess: me.plaid_success,
}); });
} }
onScriptError(error) { 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); console.log(error);
} }
plaid_success(token, response) { plaid_success(token, response) {
frappe.xcall('erpnext.erpnext_integrations.doctype.plaid_settings.plaid_settings.update_bank_account_ids', { frappe
.xcall(
"erpnext.erpnext_integrations.doctype.plaid_settings.plaid_settings.update_bank_account_ids",
{
response: response, response: response,
}).then(() => { }
frappe.show_alert({ message: __('Plaid Link Updated'), indicator: 'green' }); )
.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 // Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt // For license information, please see license.txt
frappe.ui.form.on('Bank Account', { frappe.ui.form.on("Bank Account", {
setup: function(frm) { setup: function (frm) {
frm.set_query("account", function() { frm.set_query("account", function () {
return { return {
filters: { filters: {
'account_type': 'Bank', account_type: "Bank",
'company': frm.doc.company, company: frm.doc.company,
'is_group': 0 is_group: 0,
} },
}; };
}); });
frm.set_query("party_type", function() { frm.set_query("party_type", function () {
return { return {
query: "erpnext.setup.doctype.party_type.party_type.get_party_type", query: "erpnext.setup.doctype.party_type.party_type.get_party_type",
}; };
}); });
}, },
refresh: function(frm) { refresh: function (frm) {
frappe.dynamic_link = { doc: frm.doc, fieldname: 'name', doctype: 'Bank Account' } 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) { if (frm.doc.__islocal) {
frappe.contacts.clear_address_and_contact(frm); frappe.contacts.clear_address_and_contact(frm);
} } else {
else {
frappe.contacts.render_address_and_contact(frm); frappe.contacts.render_address_and_contact(frm);
} }
if (frm.doc.integration_id) { if (frm.doc.integration_id) {
frm.add_custom_button(__("Unlink external integrations"), function() { 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() { 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.set_value("integration_id", "");
}); }
);
}); });
} }
}, },
is_company_account: function(frm) { is_company_account: function (frm) {
frm.set_df_property('account', 'reqd', frm.doc.is_company_account); frm.set_df_property("account", "reqd", frm.doc.is_company_account);
} },
}); });

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -9,7 +9,6 @@ from frappe import _
from frappe.model.document import Document from frappe.model.document import Document
from frappe.query_builder.custom import ConstantColumn from frappe.query_builder.custom import ConstantColumn
from frappe.utils import cint, flt from frappe.utils import cint, flt
from pypika.terms import Parameter
from erpnext import get_default_cost_center from erpnext import get_default_cost_center
from erpnext.accounts.doctype.bank_transaction.bank_transaction import get_total_allocated_amount from erpnext.accounts.doctype.bank_transaction.bank_transaction import get_total_allocated_amount
@@ -509,6 +508,18 @@ def check_matching(
to_reference_date, to_reference_date,
): ):
exact_match = True if "exact_match" in document_types else False exact_match = True if "exact_match" in document_types else False
common_filters = frappe._dict(
{
"amount": transaction.unallocated_amount,
"payment_type": "Receive" if transaction.deposit > 0.0 else "Pay",
"reference_no": transaction.reference_number,
"party_type": transaction.party_type,
"party": transaction.party,
"bank_account": bank_account,
}
)
queries = get_queries( queries = get_queries(
bank_account, bank_account,
company, company,
@@ -520,20 +531,12 @@ def check_matching(
from_reference_date, from_reference_date,
to_reference_date, to_reference_date,
exact_match, exact_match,
common_filters,
) )
filters = {
"amount": transaction.unallocated_amount,
"payment_type": "Receive" if transaction.deposit > 0.0 else "Pay",
"reference_no": transaction.reference_number,
"party_type": transaction.party_type,
"party": transaction.party,
"bank_account": bank_account,
}
matching_vouchers = [] matching_vouchers = []
for query in queries: for query in queries:
matching_vouchers.extend(frappe.db.sql(query, filters, as_dict=True)) matching_vouchers.extend(query.run(as_dict=True))
return ( return (
sorted(matching_vouchers, key=lambda x: x["rank"], reverse=True) if matching_vouchers else [] sorted(matching_vouchers, key=lambda x: x["rank"], reverse=True) if matching_vouchers else []
@@ -551,6 +554,7 @@ def get_queries(
from_reference_date, from_reference_date,
to_reference_date, to_reference_date,
exact_match, exact_match,
common_filters,
): ):
# get queries to get matching vouchers # get queries to get matching vouchers
account_from_to = "paid_to" if transaction.deposit > 0.0 else "paid_from" account_from_to = "paid_to" if transaction.deposit > 0.0 else "paid_from"
@@ -571,6 +575,7 @@ def get_queries(
filter_by_reference_date, filter_by_reference_date,
from_reference_date, from_reference_date,
to_reference_date, to_reference_date,
common_filters,
) )
or [] or []
) )
@@ -590,6 +595,7 @@ def get_matching_queries(
filter_by_reference_date, filter_by_reference_date,
from_reference_date, from_reference_date,
to_reference_date, to_reference_date,
common_filters,
): ):
queries = [] queries = []
currency = get_account_currency(bank_account) currency = get_account_currency(bank_account)
@@ -604,6 +610,7 @@ def get_matching_queries(
filter_by_reference_date, filter_by_reference_date,
from_reference_date, from_reference_date,
to_reference_date, to_reference_date,
common_filters,
) )
queries.append(query) queries.append(query)
@@ -616,16 +623,17 @@ def get_matching_queries(
filter_by_reference_date, filter_by_reference_date,
from_reference_date, from_reference_date,
to_reference_date, to_reference_date,
common_filters,
) )
queries.append(query) queries.append(query)
if transaction.deposit > 0.0 and "sales_invoice" in document_types: if transaction.deposit > 0.0 and "sales_invoice" in document_types:
query = get_si_matching_query(exact_match, currency) query = get_si_matching_query(exact_match, currency, common_filters)
queries.append(query) queries.append(query)
if transaction.withdrawal > 0.0: if transaction.withdrawal > 0.0:
if "purchase_invoice" in document_types: if "purchase_invoice" in document_types:
query = get_pi_matching_query(exact_match, currency) query = get_pi_matching_query(exact_match, currency, common_filters)
queries.append(query) queries.append(query)
if "bank_transaction" in document_types: if "bank_transaction" in document_types:
@@ -680,7 +688,7 @@ def get_bt_matching_query(exact_match, transaction):
.where(amount_condition) .where(amount_condition)
.where(bt.docstatus == 1) .where(bt.docstatus == 1)
) )
return str(query) return query
def get_pe_matching_query( def get_pe_matching_query(
@@ -692,6 +700,7 @@ def get_pe_matching_query(
filter_by_reference_date, filter_by_reference_date,
from_reference_date, from_reference_date,
to_reference_date, to_reference_date,
common_filters,
): ):
# get matching payment entries query # get matching payment entries query
to_from = "to" if transaction.deposit > 0.0 else "from" to_from = "to" if transaction.deposit > 0.0 else "from"
@@ -734,7 +743,7 @@ def get_pe_matching_query(
.where(pe.docstatus == 1) .where(pe.docstatus == 1)
.where(pe.payment_type.isin([payment_type, "Internal Transfer"])) .where(pe.payment_type.isin([payment_type, "Internal Transfer"]))
.where(pe.clearance_date.isnull()) .where(pe.clearance_date.isnull())
.where(getattr(pe, account_from_to) == Parameter("%(bank_account)s")) .where(getattr(pe, account_from_to) == common_filters.bank_account)
.where(amount_condition) .where(amount_condition)
.where(filter_by_date) .where(filter_by_date)
.orderby(pe.reference_date if cint(filter_by_reference_date) else pe.posting_date) .orderby(pe.reference_date if cint(filter_by_reference_date) else pe.posting_date)
@@ -743,7 +752,7 @@ def get_pe_matching_query(
if frappe.flags.auto_reconcile_vouchers == True: if frappe.flags.auto_reconcile_vouchers == True:
query = query.where(ref_condition) query = query.where(ref_condition)
return str(query) return query
def get_je_matching_query( def get_je_matching_query(
@@ -754,6 +763,7 @@ def get_je_matching_query(
filter_by_reference_date, filter_by_reference_date,
from_reference_date, from_reference_date,
to_reference_date, to_reference_date,
common_filters,
): ):
# get matching journal entry query # get matching journal entry query
# We have mapping at the bank level # We have mapping at the bank level
@@ -793,7 +803,7 @@ def get_je_matching_query(
.where(je.docstatus == 1) .where(je.docstatus == 1)
.where(je.voucher_type != "Opening Entry") .where(je.voucher_type != "Opening Entry")
.where(je.clearance_date.isnull()) .where(je.clearance_date.isnull())
.where(jea.account == Parameter("%(bank_account)s")) .where(jea.account == common_filters.bank_account)
.where(amount_equality if exact_match else getattr(jea, amount_field) > 0.0) .where(amount_equality if exact_match else getattr(jea, amount_field) > 0.0)
.where(je.docstatus == 1) .where(je.docstatus == 1)
.where(filter_by_date) .where(filter_by_date)
@@ -803,19 +813,19 @@ def get_je_matching_query(
if frappe.flags.auto_reconcile_vouchers == True: if frappe.flags.auto_reconcile_vouchers == True:
query = query.where(ref_condition) query = query.where(ref_condition)
return str(query) return query
def get_si_matching_query(exact_match, currency): def get_si_matching_query(exact_match, currency, common_filters):
# get matching sales invoice query # get matching sales invoice query
si = frappe.qb.DocType("Sales Invoice") si = frappe.qb.DocType("Sales Invoice")
sip = frappe.qb.DocType("Sales Invoice Payment") sip = frappe.qb.DocType("Sales Invoice Payment")
amount_equality = sip.amount == Parameter("%(amount)s") amount_equality = sip.amount == common_filters.amount
amount_rank = frappe.qb.terms.Case().when(amount_equality, 1).else_(0) amount_rank = frappe.qb.terms.Case().when(amount_equality, 1).else_(0)
amount_condition = amount_equality if exact_match else sip.amount > 0.0 amount_condition = amount_equality if exact_match else sip.amount > 0.0
party_condition = si.customer == Parameter("%(party)s") party_condition = si.customer == common_filters.party
party_rank = frappe.qb.terms.Case().when(party_condition, 1).else_(0) party_rank = frappe.qb.terms.Case().when(party_condition, 1).else_(0)
query = ( query = (
@@ -836,23 +846,23 @@ def get_si_matching_query(exact_match, currency):
) )
.where(si.docstatus == 1) .where(si.docstatus == 1)
.where(sip.clearance_date.isnull()) .where(sip.clearance_date.isnull())
.where(sip.account == Parameter("%(bank_account)s")) .where(sip.account == common_filters.bank_account)
.where(amount_condition) .where(amount_condition)
.where(si.currency == currency) .where(si.currency == currency)
) )
return str(query) return query
def get_pi_matching_query(exact_match, currency): def get_pi_matching_query(exact_match, currency, common_filters):
# get matching purchase invoice query when they are also used as payment entries (is_paid) # get matching purchase invoice query when they are also used as payment entries (is_paid)
purchase_invoice = frappe.qb.DocType("Purchase Invoice") purchase_invoice = frappe.qb.DocType("Purchase Invoice")
amount_equality = purchase_invoice.paid_amount == Parameter("%(amount)s") amount_equality = purchase_invoice.paid_amount == common_filters.amount
amount_rank = frappe.qb.terms.Case().when(amount_equality, 1).else_(0) amount_rank = frappe.qb.terms.Case().when(amount_equality, 1).else_(0)
amount_condition = amount_equality if exact_match else purchase_invoice.paid_amount > 0.0 amount_condition = amount_equality if exact_match else purchase_invoice.paid_amount > 0.0
party_condition = purchase_invoice.supplier == Parameter("%(party)s") party_condition = purchase_invoice.supplier == common_filters.party
party_rank = frappe.qb.terms.Case().when(party_condition, 1).else_(0) party_rank = frappe.qb.terms.Case().when(party_condition, 1).else_(0)
query = ( query = (
@@ -872,9 +882,9 @@ def get_pi_matching_query(exact_match, currency):
.where(purchase_invoice.docstatus == 1) .where(purchase_invoice.docstatus == 1)
.where(purchase_invoice.is_paid == 1) .where(purchase_invoice.is_paid == 1)
.where(purchase_invoice.clearance_date.isnull()) .where(purchase_invoice.clearance_date.isnull())
.where(purchase_invoice.cash_bank_account == Parameter("%(bank_account)s")) .where(purchase_invoice.cash_bank_account == common_filters.bank_account)
.where(amount_condition) .where(amount_condition)
.where(purchase_invoice.currency == currency) .where(purchase_invoice.currency == currency)
) )
return str(query) return query

View File

@@ -7,9 +7,7 @@ frappe.ui.form.on("Bank Statement Import", {
frm.import_in_progress = false; frm.import_in_progress = false;
if (data_import !== frm.doc.name) return; if (data_import !== frm.doc.name) return;
frappe.model.clear_doc("Bank Statement Import", frm.doc.name); frappe.model.clear_doc("Bank Statement Import", frm.doc.name);
frappe.model frappe.model.with_doc("Bank Statement Import", frm.doc.name).then(() => {
.with_doc("Bank Statement Import", frm.doc.name)
.then(() => {
frm.refresh(); frm.refresh();
}); });
}); });
@@ -38,20 +36,9 @@ frappe.ui.form.on("Bank Statement Import", {
: __("Updating {0} of {1}, {2}", message_args); : __("Updating {0} of {1}, {2}", message_args);
} }
if (data.skipping) { if (data.skipping) {
message = __( message = __("Skipping {0} of {1}, {2}", [data.current, data.total, eta_message]);
"Skipping {0} of {1}, {2}",
[
data.current,
data.total,
eta_message,
]
);
} }
frm.dashboard.show_progress( frm.dashboard.show_progress(__("Import Progress"), percent, message);
__("Import Progress"),
percent,
message
);
frm.page.set_indicator(__("In Progress"), "orange"); frm.page.set_indicator(__("In Progress"), "orange");
// hide progress when complete // hide progress when complete
@@ -93,15 +80,12 @@ frappe.ui.form.on("Bank Statement Import", {
frm.trigger("show_report_error_button"); frm.trigger("show_report_error_button");
if (frm.doc.status === "Partial Success") { if (frm.doc.status === "Partial Success") {
frm.add_custom_button(__("Export Errored Rows"), () => frm.add_custom_button(__("Export Errored Rows"), () => frm.trigger("export_errored_rows"));
frm.trigger("export_errored_rows")
);
} }
if (frm.doc.status.includes("Success")) { if (frm.doc.status.includes("Success")) {
frm.add_custom_button( frm.add_custom_button(__("Go to {0} List", [__(frm.doc.reference_doctype)]), () =>
__("Go to {0} List", [__(frm.doc.reference_doctype)]), frappe.set_route("List", frm.doc.reference_doctype)
() => frappe.set_route("List", frm.doc.reference_doctype)
); );
} }
}, },
@@ -118,13 +102,8 @@ frappe.ui.form.on("Bank Statement Import", {
frm.disable_save(); frm.disable_save();
if (frm.doc.status !== "Success") { if (frm.doc.status !== "Success") {
if (!frm.is_new() && frm.has_import_file()) { if (!frm.is_new() && frm.has_import_file()) {
let label = let label = frm.doc.status === "Pending" ? __("Start Import") : __("Retry");
frm.doc.status === "Pending" frm.page.set_primary_action(label, () => frm.events.start_import(frm));
? __("Start Import")
: __("Retry");
frm.page.set_primary_action(label, () =>
frm.events.start_import(frm)
);
} else { } else {
frm.page.set_primary_action(__("Save"), () => frm.save()); frm.page.set_primary_action(__("Save"), () => frm.save());
} }
@@ -226,8 +205,7 @@ frappe.ui.form.on("Bank Statement Import", {
}, },
download_template() { download_template() {
let method = let method = "/api/method/frappe.core.doctype.data_import.data_import.download_template";
"/api/method/frappe.core.doctype.data_import.data_import.download_template";
open_url_post(method, { open_url_post(method, {
doctype: "Bank Transaction", doctype: "Bank Transaction",
@@ -240,7 +218,7 @@ frappe.ui.form.on("Bank Statement Import", {
"description", "description",
"reference_number", "reference_number",
"bank_account", "bank_account",
"currency" "currency",
], ],
}, },
}); });
@@ -311,10 +289,7 @@ frappe.ui.form.on("Bank Statement Import", {
show_import_preview(frm, preview_data) { show_import_preview(frm, preview_data) {
let import_log = JSON.parse(frm.doc.statement_import_log || "[]"); let import_log = JSON.parse(frm.doc.statement_import_log || "[]");
if ( if (frm.import_preview && frm.import_preview.doctype === frm.doc.reference_doctype) {
frm.import_preview &&
frm.import_preview.doctype === frm.doc.reference_doctype
) {
frm.import_preview.preview_data = preview_data; frm.import_preview.preview_data = preview_data;
frm.import_preview.import_log = import_log; frm.import_preview.import_log = import_log;
frm.import_preview.refresh(); frm.import_preview.refresh();
@@ -330,19 +305,10 @@ frappe.ui.form.on("Bank Statement Import", {
frm, frm,
events: { events: {
remap_column(changed_map) { remap_column(changed_map) {
let template_options = JSON.parse( let template_options = JSON.parse(frm.doc.template_options || "{}");
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);
template_options.column_to_field_map = frm.set_value("template_options", JSON.stringify(template_options));
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")); frm.save().then(() => frm.trigger("import_file"));
}, },
}, },
@@ -376,8 +342,7 @@ frappe.ui.form.on("Bank Statement Import", {
let other_warnings = []; let other_warnings = [];
for (let warning of warnings) { for (let warning of warnings) {
if (warning.row) { 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); warnings_by_row[warning.row].push(warning);
} else { } else {
other_warnings.push(warning); other_warnings.push(warning);
@@ -392,9 +357,7 @@ frappe.ui.form.on("Bank Statement Import", {
if (w.field) { if (w.field) {
let label = let label =
w.field.label + w.field.label +
(w.field.parent !== frm.doc.reference_doctype (w.field.parent !== frm.doc.reference_doctype ? ` (${w.field.parent})` : "");
? ` (${w.field.parent})`
: "");
return `<li>${label}: ${w.message}</li>`; return `<li>${label}: ${w.message}</li>`;
} }
return `<li>${w.message}</li>`; return `<li>${w.message}</li>`;
@@ -413,10 +376,9 @@ frappe.ui.form.on("Bank Statement Import", {
.map((warning) => { .map((warning) => {
let header = ""; let header = "";
if (warning.col) { if (warning.col) {
let column_number = `<span class="text-uppercase">${__( let column_number = `<span class="text-uppercase">${__("Column {0}", [
"Column {0}", warning.col,
[warning.col] ])}</span>`;
)}</span>`;
let column_header = columns[warning.col].header_title; let column_header = columns[warning.col].header_title;
header = `${column_number} (${column_header})`; header = `${column_number} (${column_header})`;
} }
@@ -455,36 +417,28 @@ frappe.ui.form.on("Bank Statement Import", {
let html = ""; let html = "";
if (log.success) { if (log.success) {
if (frm.doc.import_type === "Insert New Records") { if (frm.doc.import_type === "Insert New Records") {
html = __( html = __("Successfully imported {0}", [
"Successfully imported {0}", [
`<span class="underline">${frappe.utils.get_form_link( `<span class="underline">${frappe.utils.get_form_link(
frm.doc.reference_doctype, frm.doc.reference_doctype,
log.docname, log.docname,
true true
)}<span>`, )}<span>`,
] ]);
);
} else { } else {
html = __( html = __("Successfully updated {0}", [
"Successfully updated {0}", [
`<span class="underline">${frappe.utils.get_form_link( `<span class="underline">${frappe.utils.get_form_link(
frm.doc.reference_doctype, frm.doc.reference_doctype,
log.docname, log.docname,
true true
)}<span>`, )}<span>`,
] ]);
);
} }
} else { } else {
let messages = log.messages let messages = log.messages
.map(JSON.parse) .map(JSON.parse)
.map((m) => { .map((m) => {
let title = m.title let title = m.title ? `<strong>${m.title}</strong>` : "";
? `<strong>${m.title}</strong>` let message = m.message ? `<div>${m.message}</div>` : "";
: "";
let message = m.message
? `<div>${m.message}</div>`
: "";
return title + message; return title + message;
}) })
.join(""); .join("");

View File

@@ -1,36 +1,34 @@
let imports_in_progress = []; let imports_in_progress = [];
frappe.listview_settings['Bank Statement Import'] = { frappe.listview_settings["Bank Statement Import"] = {
onload(listview) { onload(listview) {
frappe.realtime.on('data_import_progress', data => { frappe.realtime.on("data_import_progress", (data) => {
if (!imports_in_progress.includes(data.data_import)) { if (!imports_in_progress.includes(data.data_import)) {
imports_in_progress.push(data.data_import); imports_in_progress.push(data.data_import);
} }
}); });
frappe.realtime.on('data_import_refresh', data => { frappe.realtime.on("data_import_refresh", (data) => {
imports_in_progress = imports_in_progress.filter( imports_in_progress = imports_in_progress.filter((d) => d !== data.data_import);
d => d !== data.data_import
);
listview.refresh(); listview.refresh();
}); });
}, },
get_indicator: function(doc) { get_indicator: function (doc) {
var colors = { var colors = {
'Pending': 'orange', Pending: "orange",
'Not Started': 'orange', "Not Started": "orange",
'Partial Success': 'orange', "Partial Success": "orange",
'Success': 'green', Success: "green",
'In Progress': 'orange', "In Progress": "orange",
'Error': 'red' Error: "red",
}; };
let status = doc.status; let status = doc.status;
if (imports_in_progress.includes(doc.name)) { if (imports_in_progress.includes(doc.name)) {
status = 'In Progress'; status = "In Progress";
} }
if (status == 'Pending') { if (status == "Pending") {
status = 'Not Started'; 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", { frappe.ui.form.on("Bank Transaction", {
onload(frm) { 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); const payment_doctypes = frm.events.get_payment_doctypes(frm);
return { return {
filters: { filters: {
@@ -23,7 +23,7 @@ frappe.ui.form.on("Bank Transaction", {
set_bank_statement_filter(frm); set_bank_statement_filter(frm);
}, },
setup: function(frm) { setup: function (frm) {
frm.set_query("party_type", function () { frm.set_query("party_type", function () {
return { return {
filters: { 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 // get payment doctypes from all the apps
return [ return ["Payment Entry", "Journal Entry", "Sales Invoice", "Purchase Invoice", "Bank Transaction"];
"Payment Entry", },
"Journal Entry",
"Sales Invoice",
"Purchase Invoice",
"Bank Transaction",
];
}
}); });
frappe.ui.form.on("Bank Transaction Payments", { 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) => { const update_clearance_date = (frm, cdt, cdn) => {
if (frm.doc.docstatus === 1) { if (frm.doc.docstatus === 1) {
frappe frappe
.xcall( .xcall("erpnext.accounts.doctype.bank_transaction.bank_transaction.unclear_reference_payment", {
"erpnext.accounts.doctype.bank_transaction.bank_transaction.unclear_reference_payment", doctype: cdt,
{ doctype: cdt, docname: cdn, bt_name: frm.doc.name } docname: cdn,
) bt_name: frm.doc.name,
})
.then((e) => { .then((e) => {
if (e == "success") { if (e == "success") {
frappe.show_alert({ frappe.show_alert({

View File

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

View File

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

View File

@@ -1,11 +1,10 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors // Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt // License: GNU General Public License v3. See license.txt
frappe.ui.form.on('Cashier Closing', { frappe.ui.form.on("Cashier Closing", {
setup: function (frm) {
setup: function(frm){
if (frm.doc.user == "" || frm.doc.user == null) { if (frm.doc.user == "" || frm.doc.user == null) {
frm.doc.user = frappe.session.user; 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) { onload: function (frm) {
frm.set_value("company", ""); frm.set_value("company", "");
frm.set_value("import_file", ""); frm.set_value("import_file", "");
@@ -8,31 +8,34 @@ frappe.ui.form.on('Chart of Accounts Importer', {
frm.disable_save(); frm.disable_save();
// make company mandatory // make company mandatory
frm.set_df_property('company', 'reqd', 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); frm.set_df_property("import_file_section", "hidden", frm.doc.company ? 0 : 1);
if (frm.doc.import_file) { if (frm.doc.import_file) {
frappe.run_serially([ frappe.run_serially([
() => generate_tree_preview(frm), () => generate_tree_preview(frm),
() => create_import_button(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.set_df_property(
$(frm.fields_dict['chart_tree'].wrapper).html()!="" ? 0 : 1); "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({ var d = new frappe.ui.Dialog({
title: __("Download Template"), title: __("Download Template"),
fields: [ fields: [
{ {
label : "File Type", label: "File Type",
fieldname: "file_type", fieldname: "file_type",
fieldtype: "Select", fieldtype: "Select",
reqd: 1, reqd: 1,
options: ["Excel", "CSV"] options: ["Excel", "CSV"],
}, },
{ {
label: "Template Type", label: "Template Type",
@@ -41,21 +44,27 @@ frappe.ui.form.on('Chart of Accounts Importer', {
reqd: 1, reqd: 1,
options: ["Sample Template", "Blank Template"], options: ["Sample Template", "Blank Template"],
change: () => { change: () => {
let template_type = d.get_value('template_type'); let template_type = d.get_value("template_type");
if (template_type === "Sample Template") { 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. `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 { } 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 `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", fieldname: "company",
fieldtype: "Link", fieldtype: "Link",
reqd: 1, reqd: 1,
@@ -63,25 +72,25 @@ frappe.ui.form.on('Chart of Accounts Importer', {
default: frm.doc.company, default: frm.doc.company,
}, },
], ],
primary_action: function() { primary_action: function () {
let data = d.get_values(); let data = d.get_values();
if (!data.template_type) { 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( 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, file_type: data.file_type,
template_type: data.template_type, template_type: data.template_type,
company: data.company company: data.company,
} }
); );
d.hide(); d.hide();
}, },
primary_action_label: __('Download') primary_action_label: __("Download"),
}); });
d.show(); d.show();
}, },
@@ -89,7 +98,7 @@ frappe.ui.form.on('Chart of Accounts Importer', {
import_file: function (frm) { import_file: function (frm) {
if (!frm.doc.import_file) { if (!frm.doc.import_file) {
frm.page.set_indicator(""); 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({ frappe.call({
method: "erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.validate_company", method: "erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.validate_company",
args: { args: {
company: frm.doc.company company: frm.doc.company,
}, },
callback: function(r) { callback: function (r) {
if(r.message===false) { if (r.message === false) {
frm.set_value("company", ""); 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 { } else {
frm.trigger("refresh"); frm.trigger("refresh");
} }
} },
}); });
} }
} },
}); });
var create_import_button = function(frm) { var create_import_button = function (frm) {
frm.page.set_primary_action(__("Import"), function () { frm.page
.set_primary_action(__("Import"), function () {
return frappe.call({ 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.import_coa",
args: { args: {
file_name: frm.doc.import_file, file_name: frm.doc.import_file,
company: frm.doc.company company: frm.doc.company,
}, },
freeze: true, freeze: true,
freeze_message: __("Creating Accounts..."), freeze_message: __("Creating Accounts..."),
callback: function(r) { callback: function (r) {
if (!r.exc) { if (!r.exc) {
clearInterval(frm.page["interval"]); clearInterval(frm.page["interval"]);
frm.page.set_indicator(__('Import Successful'), 'blue'); frm.page.set_indicator(__("Import Successful"), "blue");
create_reset_button(frm); create_reset_button(frm);
} }
} },
}); });
}).addClass('btn btn-primary'); })
.addClass("btn btn-primary");
}; };
var create_reset_button = function(frm) { var create_reset_button = function (frm) {
frm.page.set_primary_action(__("Reset"), function () { frm.page
.set_primary_action(__("Reset"), function () {
frm.page.clear_primary_action(); frm.page.clear_primary_action();
delete frm.page["show_import_button"]; delete frm.page["show_import_button"];
frm.reload_doc(); frm.reload_doc();
}).addClass('btn btn-primary'); })
.addClass("btn btn-primary");
}; };
var validate_coa = function(frm) { var validate_coa = function (frm) {
if (frm.doc.import_file) { if (frm.doc.import_file) {
let parent = __('All Accounts'); let parent = __("All Accounts");
return frappe.call({ return frappe.call({
'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,
for_validate: 1
},
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
// generate tree structure based on the csv data
return new frappe.ui.Tree({
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',
args: { args: {
file_name: frm.doc.import_file, file_name: frm.doc.import_file,
parent: parent, parent: parent,
doctype: 'Chart of Accounts Importer', doctype: "Chart of Accounts Importer",
file_type: frm.doc.file_type file_type: frm.doc.file_type,
for_validate: 1,
}, },
onclick: function(node) { callback: function (r) {
parent = node.value; 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
// generate tree structure based on the csv data
return new frappe.ui.Tree({
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",
args: {
file_name: frm.doc.import_file,
parent: parent,
doctype: "Chart of Accounts Importer",
file_type: frm.doc.file_type,
},
onclick: function (node) {
parent = node.value;
},
}); });
}; };

View File

@@ -3,18 +3,20 @@
frappe.provide("erpnext.cheque_print"); frappe.provide("erpnext.cheque_print");
frappe.ui.form.on('Cheque Print Template', { frappe.ui.form.on("Cheque Print Template", {
refresh: function(frm) { refresh: function (frm) {
if(!frm.doc.__islocal) { if (!frm.doc.__islocal) {
frm.add_custom_button(frm.doc.has_print_format?__("Update Print Format"):__("Create Print Format"), frm.add_custom_button(
function() { frm.doc.has_print_format ? __("Update Print Format") : __("Create Print Format"),
function () {
erpnext.cheque_print.view_cheque_print(frm); 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 =
var template = '<div style="position: relative; overflow-x: scroll;">\ '<div style="position: relative; overflow-x: scroll;">\
<div id="cheque_preview" style="width: {{ cheque_width }}cm; \ <div id="cheque_preview" style="width: {{ cheque_width }}cm; \
height: {{ cheque_height }}cm;\ height: {{ cheque_height }}cm;\
background-repeat: no-repeat;\ background-repeat: no-repeat;\
@@ -48,30 +50,30 @@ frappe.ui.form.on('Cheque Print Template', {
</div>\ </div>\
</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) { 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({ frappe.call({
method: "erpnext.accounts.doctype.cheque_print_template.cheque_print_template.create_or_update_cheque_print_format", method: "erpnext.accounts.doctype.cheque_print_template.cheque_print_template.create_or_update_cheque_print_format",
args:{ args: {
"template_name": frm.doc.name template_name: frm.doc.name,
}, },
callback: function(r) { callback: function (r) {
if (!r.exe && !frm.doc.has_print_format) { if (!r.exe && !frm.doc.has_print_format) {
var doc = frappe.model.sync(r.message); var doc = frappe.model.sync(r.message);
frappe.set_route("Form", r.message.doctype, r.message.name); 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.provide("erpnext.accounts");
frappe.ui.form.on("Cost Center", {
onload: function (frm) {
frappe.ui.form.on('Cost Center', { frm.set_query("parent_cost_center", function () {
onload: function(frm) {
frm.set_query("parent_cost_center", function() {
return { return {
filters: { filters: {
company: frm.doc.company, company: frm.doc.company,
is_group: 1 is_group: 1,
} },
} };
}); });
}, },
refresh: function(frm) { refresh: function (frm) {
if (!frm.is_new()) { 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"); frm.trigger("update_cost_center_number");
}); });
} }
let intro_txt = ''; let intro_txt = "";
let doc = frm.doc; let doc = frm.doc;
frm.toggle_display('cost_center_name', doc.__islocal); frm.toggle_display("cost_center_name", doc.__islocal);
frm.toggle_enable(['is_group', 'company'], doc.__islocal); frm.toggle_enable(["is_group", "company"], doc.__islocal);
if(!doc.__islocal && doc.is_group==1) { if (!doc.__islocal && doc.is_group == 1) {
intro_txt += __('Note: This Cost Center is a Group. Cannot make accounting entries against groups.'); intro_txt += __(
"Note: This Cost Center is a Group. Cannot make accounting entries against groups."
);
} }
frm.events.hide_unhide_group_ledger(frm); 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); frm.set_intro(intro_txt);
if(!frm.doc.__islocal) { if (!frm.doc.__islocal) {
frm.add_custom_button(__('Chart of Cost Centers'), frm.add_custom_button(__("Chart of Cost Centers"), function () {
function() { frappe.set_route("Tree", "Cost Center"); }); frappe.set_route("Tree", "Cost Center");
});
frm.add_custom_button(__('Budget'), frm.add_custom_button(__("Budget"), function () {
function() { frappe.set_route("List", "Budget", {'cost_center': frm.doc.name}); }); 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({ var d = new frappe.ui.Dialog({
title: __('Update Cost Center Name / Number'), title: __("Update Cost Center Name / Number"),
fields: [ fields: [
{ {
"label": "Cost Center Name", label: "Cost Center Name",
"fieldname": "cost_center_name", fieldname: "cost_center_name",
"fieldtype": "Data", fieldtype: "Data",
"reqd": 1, reqd: 1,
"default": frm.doc.cost_center_name default: frm.doc.cost_center_name,
}, },
{ {
"label": "Cost Center Number", label: "Cost Center Number",
"fieldname": "cost_center_number", fieldname: "cost_center_number",
"fieldtype": "Data", fieldtype: "Data",
"default": frm.doc.cost_center_number default: frm.doc.cost_center_number,
}, },
{ {
"label": __("Merge with existing"), label: __("Merge with existing"),
"fieldname": "merge", fieldname: "merge",
"fieldtype": "Check", fieldtype: "Check",
"default": 0 default: 0,
} },
], ],
primary_action: function() { primary_action: function () {
let data = d.get_values(); let 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(); d.hide();
return; return;
} }
@@ -83,12 +88,12 @@ frappe.ui.form.on('Cost Center', {
cost_center_name: data.cost_center_name, cost_center_name: data.cost_center_name,
cost_center_number: cstr(data.cost_center_number), cost_center_number: cstr(data.cost_center_number),
company: frm.doc.company, company: frm.doc.company,
merge: data.merge merge: data.merge,
}, },
callback: function(r) { callback: function (r) {
frappe.dom.unfreeze(); frappe.dom.unfreeze();
if(!r.exc) { if (!r.exc) {
if(r.message) { if (r.message) {
frappe.set_route("Form", "Cost Center", r.message); frappe.set_route("Form", "Cost Center", r.message);
} else { } else {
frm.set_value("cost_center_name", data.cost_center_name); frm.set_value("cost_center_name", data.cost_center_name);
@@ -96,44 +101,42 @@ frappe.ui.form.on('Cost Center', {
} }
d.hide(); d.hide();
} }
} },
}); });
}, },
primary_action_label: __('Update') primary_action_label: __("Update"),
}); });
d.show(); d.show();
}, },
parent_cost_center(frm) { parent_cost_center(frm) {
if(!frm.doc.company) { if (!frm.doc.company) {
frappe.msgprint(__('Please enter company name first')); frappe.msgprint(__("Please enter company name first"));
} }
}, },
hide_unhide_group_ledger(frm) { hide_unhide_group_ledger(frm) {
let doc = frm.doc; let doc = frm.doc;
if (doc.is_group == 1) { if (doc.is_group == 1) {
frm.add_custom_button(__('Convert to Non-Group'), frm.add_custom_button(__("Convert to Non-Group"), () => frm.events.convert_to_ledger(frm));
() => frm.events.convert_to_ledger(frm));
} else if (doc.is_group == 0) { } else if (doc.is_group == 0) {
frm.add_custom_button(__('Convert to Group'), frm.add_custom_button(__("Convert to Group"), () => frm.events.convert_to_group(frm));
() => frm.events.convert_to_group(frm));
} }
}, },
convert_to_group(frm) { convert_to_group(frm) {
frm.call('convert_ledger_to_group').then(r => { frm.call("convert_ledger_to_group").then((r) => {
if(r.message === 1) { if (r.message === 1) {
frm.refresh(); frm.refresh();
} }
}); });
}, },
convert_to_ledger(frm) { convert_to_ledger(frm) {
frm.call('convert_group_to_ledger').then(r => { frm.call("convert_group_to_ledger").then((r) => {
if(r.message === 1) { if (r.message === 1) {
frm.refresh(); frm.refresh();
} }
}); });
} },
}); });

View File

@@ -41,7 +41,7 @@
"in_list_view": 1, "in_list_view": 1,
"in_standard_filter": 1, "in_standard_filter": 1,
"label": "Cost Center Number", "label": "Cost Center Number",
"read_only": 1 "read_only_depends_on": "eval:!doc.__islocal"
}, },
{ {
"fieldname": "parent_cost_center", "fieldname": "parent_cost_center",

View File

@@ -1,54 +1,84 @@
frappe.treeview_settings["Cost Center"] = { frappe.treeview_settings["Cost Center"] = {
breadcrumb: "Accounts", breadcrumb: "Accounts",
get_tree_root: false, get_tree_root: false,
filters: [{ filters: [
{
fieldname: "company", fieldname: "company",
fieldtype:"Select", fieldtype: "Select",
options: erpnext.utils.get_tree_options("company"), options: erpnext.utils.get_tree_options("company"),
label: __("Company"), label: __("Company"),
default: erpnext.utils.get_tree_default("company") default: erpnext.utils.get_tree_default("company"),
}], },
],
root_label: "Cost Centers", root_label: "Cost Centers",
get_tree_nodes: 'erpnext.accounts.utils.get_children', get_tree_nodes: "erpnext.accounts.utils.get_children",
add_tree_node: 'erpnext.accounts.utils.add_cc', add_tree_node: "erpnext.accounts.utils.add_cc",
menu_items:[ menu_items: [
{ {
label: __('New Company'), label: __("New Company"),
action: function() { frappe.new_doc("Company", true) }, action: function () {
condition: 'frappe.boot.user.can_create.indexOf("Company") !== -1' frappe.new_doc("Company", true);
} },
condition: 'frappe.boot.user.can_create.indexOf("Company") !== -1',
},
], ],
fields:[ fields: [
{fieldtype:'Data', fieldname:'cost_center_name', label:__('New Cost Center Name'), reqd:true}, { 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: "Check",
{fieldtype:'Data', fieldname:'cost_center_number', label:__('Cost Center Number'), fieldname: "is_group",
description: __("Number of new Cost Center, it will be included in the cost center name as a prefix")} 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"], ignore_fields: ["parent_cost_center"],
onload: function(treeview) { onload: function (treeview) {
function get_company() { function get_company() {
return treeview.page.fields_dict.company.get_value(); return treeview.page.fields_dict.company.get_value();
} }
// tools // tools
treeview.page.add_inner_button(__("Chart of Accounts"), function() { treeview.page.add_inner_button(
frappe.set_route('Tree', 'Account', {company: get_company()}); __("Chart of Accounts"),
}, __('View')); function () {
frappe.set_route("Tree", "Account", { company: get_company() });
},
__("View")
);
// make // make
treeview.page.add_inner_button(__("Budget List"), function() { treeview.page.add_inner_button(
frappe.set_route('List', 'Budget', {company: get_company()}); __("Budget List"),
}, __('Budget')); function () {
frappe.set_route("List", "Budget", { company: get_company() });
},
__("Budget")
);
treeview.page.add_inner_button(__("Monthly Distribution"), function() { treeview.page.add_inner_button(
frappe.set_route('List', 'Monthly Distribution', {company: get_company()}); __("Monthly Distribution"),
}, __('Budget')); function () {
frappe.set_route("List", "Monthly Distribution", { company: get_company() });
},
__("Budget")
);
treeview.page.add_inner_button(__("Budget Variance Report"), function() { treeview.page.add_inner_button(
frappe.set_route('query-report', 'Budget Variance Report', {company: get_company()}); __("Budget Variance Report"),
}, __('Budget')); 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 // Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt // For license information, please see license.txt
frappe.ui.form.on('Cost Center Allocation', { frappe.ui.form.on("Cost Center Allocation", {
setup: function(frm) { setup: function (frm) {
let filters = {"is_group": 0}; frm.set_query("main_cost_center", function () {
if (frm.doc.company) {
$.extend(filters, {
"company": frm.doc.company
});
}
frm.set_query('main_cost_center', function() {
return { 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 // Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt // For license information, please see license.txt
frappe.ui.form.on('Coupon Code', { frappe.ui.form.on("Coupon Code", {
setup: function(frm) { setup: function (frm) {
frm.set_query("pricing_rule", function() { frm.set_query("pricing_rule", function () {
return { return {
filters: [ filters: [["Pricing Rule", "coupon_code_based", "=", "1"]],
["Pricing Rule","coupon_code_based", "=", "1"]
]
}; };
}); });
}, },
coupon_name:function(frm){ coupon_name: function (frm) {
if (frm.doc.__islocal===1) { if (frm.doc.__islocal === 1) {
frm.trigger("make_coupon_code"); frm.trigger("make_coupon_code");
} }
}, },
coupon_type:function(frm){ coupon_type: function (frm) {
if (frm.doc.__islocal===1) { if (frm.doc.__islocal === 1) {
frm.trigger("make_coupon_code"); frm.trigger("make_coupon_code");
} }
}, },
make_coupon_code: function(frm) { make_coupon_code: function (frm) {
var coupon_name=frm.doc.coupon_name; var coupon_name = frm.doc.coupon_name;
var coupon_code; var coupon_code;
if (frm.doc.coupon_type=='Gift Card') { if (frm.doc.coupon_type == "Gift Card") {
coupon_code=Math.random().toString(12).substring(2, 12).toUpperCase(); 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'){ frm.doc.coupon_code = coupon_code;
coupon_name=coupon_name.replace(/\s/g,''); frm.refresh_field("coupon_code");
coupon_code=coupon_name.toUpperCase().slice(0,8);
}
frm.doc.coupon_code=coupon_code;
frm.refresh_field('coupon_code');
}, },
refresh: function(frm) { refresh: function (frm) {
if (frm.doc.pricing_rule) { 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); 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 // Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt // For license information, please see license.txt
frappe.ui.form.on('Currency Exchange Settings', { frappe.ui.form.on("Currency Exchange Settings", {
service_provider: function(frm) { service_provider: function (frm) {
if (frm.doc.service_provider == "exchangerate.host") { if (frm.doc.service_provider == "exchangerate.host") {
let result = ['result']; let result = ["result"];
let params = { let params = {
date: '{transaction_date}', date: "{transaction_date}",
from: '{from_currency}', from: "{from_currency}",
to: '{to_currency}' to: "{to_currency}",
}; };
add_param(frm, "https://api.exchangerate.host/convert", params, result); add_param(frm, "https://api.exchangerate.host/convert", params, result);
} else if (frm.doc.service_provider == "frankfurter.app") { } else if (frm.doc.service_provider == "frankfurter.app") {
let result = ['rates', '{to_currency}']; let result = ["rates", "{to_currency}"];
let params = { let params = {
base: '{from_currency}', base: "{from_currency}",
symbols: '{to_currency}' symbols: "{to_currency}",
}; };
add_param(frm, "https://frankfurter.app/{transaction_date}", params, result); add_param(frm, "https://frankfurter.app/{transaction_date}", params, result);
} }
} },
}); });
function add_param(frm, api, params, result) { function add_param(frm, api, params, result) {
var row; var row;
frm.clear_table("req_params"); frm.clear_table("req_params");
@@ -30,13 +29,13 @@ function add_param(frm, api, params, result) {
frm.doc.api_endpoint = api; frm.doc.api_endpoint = api;
$.each(params, function(key, value) { $.each(params, function (key, value) {
row = frm.add_child("req_params"); row = frm.add_child("req_params");
row.key = key; row.key = key;
row.value = value; row.value = value;
}); });
$.each(result, function(key, value) { $.each(result, function (key, value) {
row = frm.add_child("result_key"); row = frm.add_child("result_key");
row.key = value; row.key = value;
}); });

View File

@@ -10,7 +10,7 @@ frappe.ui.form.on("Dunning", {
company: frm.doc.company, company: frm.doc.company,
customer: frm.doc.customer, customer: frm.doc.customer,
outstanding_amount: [">", 0], outstanding_amount: [">", 0],
status: "Overdue" status: "Overdue",
}, },
}; };
}); });
@@ -19,16 +19,16 @@ frappe.ui.form.on("Dunning", {
filters: { filters: {
company: frm.doc.company, company: frm.doc.company,
root_type: "Income", root_type: "Income",
is_group: 0 is_group: 0,
} },
}; };
}); });
frm.set_query("cost_center", () => { frm.set_query("cost_center", () => {
return { return {
filters: { filters: {
company: frm.doc.company, company: frm.doc.company,
is_group: 0 is_group: 0,
} },
}; };
}); });
@@ -51,7 +51,8 @@ frappe.ui.form.on("Dunning", {
__("Payment"), __("Payment"),
function () { function () {
frm.events.make_payment_entry(frm); frm.events.make_payment_entry(frm);
}, __("Create") },
__("Create")
); );
frm.page.set_inner_btn_group_as_primary(__("Create")); frm.page.set_inner_btn_group_as_primary(__("Create"));
} }
@@ -69,7 +70,7 @@ frappe.ui.form.on("Dunning", {
get_query_filters: { get_query_filters: {
docstatus: 1, docstatus: 1,
status: "Overdue", status: "Overdue",
company: frm.doc.company company: frm.doc.company,
}, },
allow_child_item_selection: true, allow_child_item_selection: true,
child_fieldname: "payment_schedule", child_fieldname: "payment_schedule",
@@ -78,9 +79,12 @@ frappe.ui.form.on("Dunning", {
}); });
} }
frappe.dynamic_link = { doc: frm.doc, fieldname: 'customer', doctype: 'Customer' }; frappe.dynamic_link = { doc: frm.doc, fieldname: "customer", doctype: "Customer" };
frm.toggle_display("customer_name", (frm.doc.customer_name && frm.doc.customer_name !== frm.doc.customer)); frm.toggle_display(
"customer_name",
frm.doc.customer_name && frm.doc.customer_name !== frm.doc.customer
);
}, },
// When multiple companies are set up. in case company name is changed set default company address // When multiple companies are set up. in case company name is changed set default company address
company: function (frm) { company: function (frm) {
@@ -90,8 +94,8 @@ frappe.ui.form.on("Dunning", {
args: { name: frm.doc.company, existing_address: frm.doc.company_address || "" }, args: { name: frm.doc.company, existing_address: frm.doc.company_address || "" },
debounce: 2000, debounce: 2000,
callback: function (r) { callback: function (r) {
frm.set_value("company_address", r && r.message || ""); frm.set_value("company_address", (r && r.message) || "");
} },
}); });
if (frm.fields_dict.currency) { if (frm.fields_dict.currency) {
@@ -125,16 +129,16 @@ frappe.ui.form.on("Dunning", {
transaction_date: frm.doc.posting_date, transaction_date: frm.doc.posting_date,
from_currency: frm.doc.currency, from_currency: frm.doc.currency,
to_currency: company_currency, to_currency: company_currency,
args: "for_selling" args: "for_selling",
}, },
freeze: true, freeze: true,
freeze_message: __("Fetching exchange rates ..."), freeze_message: __("Fetching exchange rates ..."),
callback: function(r) { callback: function (r) {
const exchange_rate = flt(r.message); const exchange_rate = flt(r.message);
if (exchange_rate != frm.doc.conversion_rate) { if (exchange_rate != frm.doc.conversion_rate) {
frm.set_value("conversion_rate", exchange_rate); frm.set_value("conversion_rate", exchange_rate);
} }
} },
}); });
} else { } else {
frm.trigger("conversion_rate"); frm.trigger("conversion_rate");
@@ -166,8 +170,7 @@ frappe.ui.form.on("Dunning", {
get_dunning_letter_text: function (frm) { get_dunning_letter_text: function (frm) {
if (frm.doc.dunning_type) { if (frm.doc.dunning_type) {
frappe.call({ frappe.call({
method: method: "erpnext.accounts.doctype.dunning.dunning.get_dunning_letter_text",
"erpnext.accounts.doctype.dunning.dunning.get_dunning_letter_text",
args: { args: {
dunning_type: frm.doc.dunning_type, dunning_type: frm.doc.dunning_type,
language: frm.doc.language, language: frm.doc.language,
@@ -204,10 +207,7 @@ frappe.ui.form.on("Dunning", {
calculate_overdue_days: function (frm) { calculate_overdue_days: function (frm) {
frm.doc.overdue_payments.forEach((row) => { frm.doc.overdue_payments.forEach((row) => {
if (frm.doc.posting_date && row.due_date) { if (frm.doc.posting_date && row.due_date) {
const overdue_days = moment(frm.doc.posting_date).diff( const overdue_days = moment(frm.doc.posting_date).diff(row.due_date, "days");
row.due_date,
"days"
);
frappe.model.set_value(row.doctype, row.name, "overdue_days", overdue_days); frappe.model.set_value(row.doctype, row.name, "overdue_days", overdue_days);
} }
}); });
@@ -215,15 +215,16 @@ frappe.ui.form.on("Dunning", {
calculate_interest: function (frm) { calculate_interest: function (frm) {
frm.doc.overdue_payments.forEach((row) => { frm.doc.overdue_payments.forEach((row) => {
const interest_per_day = frm.doc.rate_of_interest / 100 / 365; const interest_per_day = frm.doc.rate_of_interest / 100 / 365;
const interest = flt((interest_per_day * row.overdue_days * row.outstanding), precision("interest", row)); const interest = flt(
interest_per_day * row.overdue_days * row.outstanding,
precision("interest", row)
);
frappe.model.set_value(row.doctype, row.name, "interest", interest); frappe.model.set_value(row.doctype, row.name, "interest", interest);
}); });
}, },
calculate_totals: function (frm) { calculate_totals: function (frm) {
const total_interest = frm.doc.overdue_payments const total_interest = frm.doc.overdue_payments.reduce((prev, cur) => prev + cur.interest, 0);
.reduce((prev, cur) => prev + cur.interest, 0); const total_outstanding = frm.doc.overdue_payments.reduce((prev, cur) => prev + cur.outstanding, 0);
const total_outstanding = frm.doc.overdue_payments
.reduce((prev, cur) => prev + cur.outstanding, 0);
const dunning_amount = total_interest + frm.doc.dunning_fee; const dunning_amount = total_interest + frm.doc.dunning_fee;
const base_dunning_amount = dunning_amount * frm.doc.conversion_rate; const base_dunning_amount = dunning_amount * frm.doc.conversion_rate;
const grand_total = total_outstanding + dunning_amount; const grand_total = total_outstanding + dunning_amount;
@@ -240,8 +241,7 @@ frappe.ui.form.on("Dunning", {
}, },
make_payment_entry: function (frm) { make_payment_entry: function (frm) {
return frappe.call({ return frappe.call({
method: method: "erpnext.accounts.doctype.payment_entry.payment_entry.get_payment_entry",
"erpnext.accounts.doctype.payment_entry.payment_entry.get_payment_entry",
args: { args: {
dt: frm.doc.doctype, dt: frm.doc.doctype,
dn: frm.doc.name, dn: frm.doc.name,
@@ -257,5 +257,5 @@ frappe.ui.form.on("Dunning", {
frappe.ui.form.on("Overdue Payment", { frappe.ui.form.on("Overdue Payment", {
interest: function (frm) { interest: function (frm) {
frm.trigger("calculate_totals"); frm.trigger("calculate_totals");
} },
}); });

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -4,39 +4,82 @@
frappe.provide("erpnext.accounts"); frappe.provide("erpnext.accounts");
frappe.provide("erpnext.journal_entry"); frappe.provide("erpnext.journal_entry");
frappe.ui.form.on("Journal Entry", { frappe.ui.form.on("Journal Entry", {
setup: function(frm) { setup: function (frm) {
frm.add_fetch("bank_account", "account", "account"); 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', 'Asset Depreciation Schedule', "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",
"Asset Depreciation Schedule",
"Repost Accounting Ledger",
"Unreconcile Payment",
"Unreconcile Payment Entries",
"Bank Transaction",
];
}, },
refresh: function(frm) { refresh: function (frm) {
erpnext.toggle_naming_series(); erpnext.toggle_naming_series();
if(frm.doc.docstatus > 0) { if (frm.doc.repost_required && frm.doc.docstatus === 1) {
frm.add_custom_button(__('Ledger'), function() { frm.set_intro(
frappe.route_options = { __(
"voucher_no": frm.doc.name, "Accounting entries for this Journal Entry need to be reposted. Please click on 'Repost' button to update."
"from_date": frm.doc.posting_date, )
"to_date": moment(frm.doc.modified).format('YYYY-MM-DD'), );
"company": frm.doc.company, frm.add_custom_button(__("Repost Accounting Entries"), () => {
"finance_book": frm.doc.finance_book, frm.call({
"group_by": '', doc: frm.doc,
"show_cancelled_entries": frm.doc.docstatus === 2 method: "repost_accounting_entries",
}; freeze: true,
frappe.set_route("query-report", "General Ledger"); freeze_message: __("Reposting..."),
}, __('View')); callback: (r) => {
if (!r.exc) {
frappe.msgprint(__("Accounting Entries are reposted."));
frm.refresh();
}
},
});
})
.removeClass("btn-default")
.addClass("btn-warning");
} }
if(frm.doc.docstatus==1) { if (frm.doc.docstatus > 0) {
frm.add_custom_button(__('Reverse Journal Entry'), function() { 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); return erpnext.journal_entry.reverse_journal_entry(frm);
}, __('Actions')); },
__("Actions")
);
} }
if (frm.doc.__islocal) { 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); return erpnext.journal_entry.quick_entry(frm);
}); });
} }
@@ -44,52 +87,63 @@ frappe.ui.form.on("Journal Entry", {
// hide /unhide fields based on currency // hide /unhide fields based on currency
erpnext.journal_entry.toggle_fields_based_on_currency(frm); 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)) { if (
frm.add_custom_button(__("Create Inter Company Journal Entry"), frm.doc.voucher_type == "Inter Company Journal Entry" &&
function() { 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"); frm.trigger("make_inter_company_journal_entry");
}, __('Make')); },
__("Make")
);
} }
erpnext.accounts.unreconcile_payment.add_unreconcile_btn(frm); erpnext.accounts.unreconcile_payment.add_unreconcile_btn(frm);
}, },
before_save: function(frm) { before_save: function (frm) {
if ((frm.doc.docstatus == 0) && (!frm.doc.is_system_generated)) { if (frm.doc.docstatus == 0 && !frm.doc.is_system_generated) {
let payment_entry_references = frm.doc.accounts.filter(elem => (elem.reference_type == "Payment Entry")); let payment_entry_references = frm.doc.accounts.filter(
(elem) => elem.reference_type == "Payment Entry"
);
if (payment_entry_references.length > 0) { if (payment_entry_references.length > 0) {
let rows = payment_entry_references.map(x => "#"+x.idx); 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)])); 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({ var d = new frappe.ui.Dialog({
title: __("Select Company"), title: __("Select Company"),
fields: [ fields: [
{ {
'fieldname': 'company', fieldname: "company",
'fieldtype': 'Link', fieldtype: "Link",
'label': __('Company'), label: __("Company"),
'options': 'Company', options: "Company",
"get_query": function () { get_query: function () {
return { return {
filters: [ filters: [["Company", "name", "!=", frm.doc.company]],
["Company", "name", "!=", frm.doc.company]
]
}; };
}, },
'reqd': 1 reqd: 1,
} },
], ],
}); });
d.set_primary_action(__('Create'), function() { d.set_primary_action(__("Create"), function () {
d.hide(); d.hide();
var args = d.get_values(); var args = d.get_values();
frappe.call({ frappe.call({
args: { args: {
"name": frm.doc.name, name: frm.doc.name,
"voucher_type": frm.doc.voucher_type, voucher_type: frm.doc.voucher_type,
"company": args.company company: args.company,
}, },
method: "erpnext.accounts.doctype.journal_entry.journal_entry.make_inter_company_journal_entry", method: "erpnext.accounts.doctype.journal_entry.journal_entry.make_inter_company_journal_entry",
callback: function (r) { callback: function (r) {
@@ -97,103 +151,106 @@ frappe.ui.form.on("Journal Entry", {
var doc = frappe.model.sync(r.message)[0]; var doc = frappe.model.sync(r.message)[0];
frappe.set_route("Form", doc.doctype, doc.name); frappe.set_route("Form", doc.doctype, doc.name);
} }
} },
}); });
}); });
d.show(); d.show();
}, },
multi_currency: function(frm) { multi_currency: function (frm) {
erpnext.journal_entry.toggle_fields_based_on_currency(frm); erpnext.journal_entry.toggle_fields_based_on_currency(frm);
}, },
posting_date: function(frm) { posting_date: function (frm) {
if(!frm.doc.multi_currency || !frm.doc.posting_date) return; 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); erpnext.journal_entry.set_exchange_rate(frm, row.doctype, row.name);
}) });
}, },
company: function(frm) { company: function (frm) {
frappe.call({ frappe.call({
method: "frappe.client.get_value", method: "frappe.client.get_value",
args: { args: {
doctype: "Company", doctype: "Company",
filters: {"name": frm.doc.company}, filters: { name: frm.doc.company },
fieldname: "cost_center" fieldname: "cost_center",
}, },
callback: function(r){ callback: function (r) {
if(r.message){ if (r.message) {
$.each(frm.doc.accounts || [], function(i, jvd) { $.each(frm.doc.accounts || [], function (i, jvd) {
frappe.model.set_value(jvd.doctype, jvd.name, "cost_center", r.message.cost_center); frappe.model.set_value(jvd.doctype, jvd.name, "cost_center", r.message.cost_center);
}); });
} }
} },
}); });
erpnext.accounts.dimensions.update_dimension(frm, frm.doctype); 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 ||
if((!(frm.doc.accounts || []).length) || ((frm.doc.accounts || []).length === 1 && !frm.doc.accounts[0].account)) { ((frm.doc.accounts || []).length === 1 && !frm.doc.accounts[0].account)
if(in_list(["Bank Entry", "Cash Entry"], frm.doc.voucher_type)) { ) {
if (in_list(["Bank Entry", "Cash Entry"], frm.doc.voucher_type)) {
return frappe.call({ return frappe.call({
type: "GET", type: "GET",
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_default_bank_cash_account", method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_default_bank_cash_account",
args: { args: {
"account_type": (frm.doc.voucher_type=="Bank Entry" ? account_type:
"Bank" : (frm.doc.voucher_type=="Cash Entry" ? "Cash" : null)), frm.doc.voucher_type == "Bank Entry"
"company": frm.doc.company ? "Bank"
: frm.doc.voucher_type == "Cash Entry"
? "Cash"
: null,
company: frm.doc.company,
}, },
callback: function(r) { callback: function (r) {
if(r.message) { if (r.message) {
// If default company bank account not set // If default company bank account not set
if(!$.isEmptyObject(r.message)){ if (!$.isEmptyObject(r.message)) {
update_jv_details(frm.doc, [r.message]); update_jv_details(frm.doc, [r.message]);
} }
} }
} },
}); });
} }
} }
}, },
from_template: function(frm){ from_template: function (frm) {
if (frm.doc.from_template){ if (frm.doc.from_template) {
frappe.db.get_doc("Journal Entry Template", frm.doc.from_template) frappe.db.get_doc("Journal Entry Template", frm.doc.from_template).then((doc) => {
.then((doc) => {
frappe.model.clear_table(frm.doc, "accounts"); frappe.model.clear_table(frm.doc, "accounts");
frm.set_value({ frm.set_value({
"company": doc.company, company: doc.company,
"voucher_type": doc.voucher_type, voucher_type: doc.voucher_type,
"naming_series": doc.naming_series, naming_series: doc.naming_series,
"is_opening": doc.is_opening, is_opening: doc.is_opening,
"multi_currency": doc.multi_currency multi_currency: doc.multi_currency,
}) });
update_jv_details(frm.doc, doc.accounts); update_jv_details(frm.doc, doc.accounts);
}); });
} }
} },
}); });
var update_jv_details = function(doc, r) { var update_jv_details = function (doc, r) {
$.each(r, function(i, d) { $.each(r, function (i, d) {
var row = frappe.model.add_child(doc, "Journal Entry Account", "accounts"); 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, "account", d.account);
frappe.model.set_value(row.doctype, row.name, "balance", d.balance)
}); });
refresh_field("accounts"); refresh_field("accounts");
} };
erpnext.accounts.JournalEntry = class JournalEntry extends frappe.ui.form.Controller { erpnext.accounts.JournalEntry = class JournalEntry extends frappe.ui.form.Controller {
onload() { onload() {
this.load_defaults(); this.load_defaults();
this.setup_queries(); this.setup_queries();
this.setup_balance_formatter();
erpnext.accounts.dimensions.setup_dimension_filters(this.frm, this.frm.doctype); erpnext.accounts.dimensions.setup_dimension_filters(this.frm, this.frm.doctype);
} }
@@ -203,69 +260,67 @@ erpnext.accounts.JournalEntry = class JournalEntry extends frappe.ui.form.Contro
load_defaults() { load_defaults() {
//this.frm.show_print_first = true; //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); 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); frappe.model.set_default_values(jvd);
}); });
var posting_date = this.frm.doc.posting_date; 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() { setup_queries() {
var me = this; 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); 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]; const row = locals[cdt][cdn];
return { return {
query: "erpnext.setup.doctype.party_type.party_type.get_party_type", query: "erpnext.setup.doctype.party_type.party_type.get_party_type",
filters: { 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); var jvd = frappe.get_doc(cdt, cdn);
// journal entry // journal entry
if(jvd.reference_type==="Journal Entry") { if (jvd.reference_type === "Journal Entry") {
frappe.model.validate_missing(jvd, "account"); frappe.model.validate_missing(jvd, "account");
return { return {
query: "erpnext.accounts.doctype.journal_entry.journal_entry.get_against_jv", query: "erpnext.accounts.doctype.journal_entry.journal_entry.get_against_jv",
filters: { filters: {
account: jvd.account, account: jvd.account,
party: jvd.party party: jvd.party,
} },
}; };
} }
var out = { var out = {
filters: [ filters: [[jvd.reference_type, "docstatus", "=", 1]],
[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]); out.filters.push([jvd.reference_type, "outstanding_amount", "!=", 0]);
// Filter by cost center // Filter by cost center
if(jvd.cost_center) { if (jvd.cost_center) {
out.filters.push([jvd.reference_type, "cost_center", "in", ["", jvd.cost_center]]); out.filters.push([jvd.reference_type, "cost_center", "in", ["", jvd.cost_center]]);
} }
// account filter // account filter
frappe.model.validate_missing(jvd, "account"); 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]); 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 // party_type and party mandatory
frappe.model.validate_missing(jvd, "party_type"); frappe.model.validate_missing(jvd, "party_type");
frappe.model.validate_missing(jvd, "party"); frappe.model.validate_missing(jvd, "party");
@@ -273,11 +328,11 @@ erpnext.accounts.JournalEntry = class JournalEntry extends frappe.ui.form.Contro
out.filters.push([jvd.reference_type, "per_billed", "<", 100]); out.filters.push([jvd.reference_type, "per_billed", "<", 100]);
} }
if(jvd.party_type && jvd.party) { if (jvd.party_type && jvd.party) {
let party_field = ""; let party_field = "";
if(jvd.reference_type.indexOf("Sales")===0) { if (jvd.reference_type.indexOf("Sales") === 0) {
party_field = "customer"; party_field = "customer";
} else if (jvd.reference_type.indexOf("Purchase")===0) { } else if (jvd.reference_type.indexOf("Purchase") === 0) {
party_field = "supplier"; party_field = "supplier";
} }
@@ -288,64 +343,49 @@ erpnext.accounts.JournalEntry = class JournalEntry extends frappe.ui.form.Contro
return out; 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) { reference_name(doc, cdt, cdn) {
var d = frappe.get_doc(cdt, cdn); var d = frappe.get_doc(cdt, cdn);
if(d.reference_name) { if (d.reference_name) {
if (d.reference_type==="Purchase Invoice" && !flt(d.debit)) { if (d.reference_type === "Purchase Invoice" && !flt(d.debit)) {
this.get_outstanding('Purchase Invoice', d.reference_name, doc.company, d); this.get_outstanding("Purchase Invoice", d.reference_name, doc.company, d);
} else if (d.reference_type==="Sales Invoice" && !flt(d.credit)) { } else if (d.reference_type === "Sales Invoice" && !flt(d.credit)) {
this.get_outstanding('Sales Invoice', d.reference_name, doc.company, d); this.get_outstanding("Sales Invoice", d.reference_name, doc.company, d);
} else if (d.reference_type==="Journal Entry" && !flt(d.credit) && !flt(d.debit)) { } else if (d.reference_type === "Journal Entry" && !flt(d.credit) && !flt(d.debit)) {
this.get_outstanding('Journal Entry', d.reference_name, doc.company, d); this.get_outstanding("Journal Entry", d.reference_name, doc.company, d);
} }
} }
} }
get_outstanding(doctype, docname, company, child) { get_outstanding(doctype, docname, company, child) {
var args = { var args = {
"doctype": doctype, doctype: doctype,
"docname": docname, docname: docname,
"party": child.party, party: child.party,
"account": child.account, account: child.account,
"account_currency": child.account_currency, account_currency: child.account_currency,
"company": company company: company,
} };
return frappe.call({ return frappe.call({
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_outstanding", method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_outstanding",
args: { args: args}, args: { args: args },
callback: function(r) { callback: function (r) {
if(r.message) { if (r.message) {
$.each(r.message, function(field, value) { $.each(r.message, function (field, value) {
frappe.model.set_value(child.doctype, child.name, field, value); frappe.model.set_value(child.doctype, child.name, field, value);
}) });
}
} }
},
}); });
} }
accounts_add(doc, cdt, cdn) { accounts_add(doc, cdt, cdn) {
var row = frappe.get_doc(cdt, cdn); var row = frappe.get_doc(cdt, cdn);
$.each(doc.accounts, function(i, d) { $.each(doc.accounts, function (i, d) {
if(d.account && d.party && d.party_type) { if (d.account && d.party && d.party_type) {
row.account = d.account; row.account = d.account;
row.party = d.party; row.party = d.party;
row.party_type = d.party_type; row.party_type = d.party_type;
@@ -353,8 +393,8 @@ erpnext.accounts.JournalEntry = class JournalEntry extends frappe.ui.form.Contro
}); });
// set difference // set difference
if(doc.difference) { if (doc.difference) {
if(doc.difference > 0) { if (doc.difference > 0) {
row.credit_in_account_currency = doc.difference; row.credit_in_account_currency = doc.difference;
row.credit = doc.difference; row.credit = doc.difference;
} else { } else {
@@ -364,132 +404,141 @@ erpnext.accounts.JournalEntry = class JournalEntry extends frappe.ui.form.Contro
} }
cur_frm.cscript.update_totals(doc); 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.script_manager.make(erpnext.accounts.JournalEntry);
cur_frm.cscript.update_totals = function(doc) { cur_frm.cscript.update_totals = function (doc) {
var td=0.0; var tc =0.0; var td = 0.0;
var tc = 0.0;
var accounts = doc.accounts || []; var accounts = doc.accounts || [];
for(var i in accounts) { for (var i in accounts) {
td += flt(accounts[i].debit, precision("debit", accounts[i])); td += flt(accounts[i].debit, precision("debit", accounts[i]));
tc += flt(accounts[i].credit, precision("credit", accounts[i])); tc += flt(accounts[i].credit, precision("credit", accounts[i]));
} }
doc = locals[doc.doctype][doc.name]; doc = locals[doc.doctype][doc.name];
doc.total_debit = td; doc.total_debit = td;
doc.total_credit = tc; doc.total_credit = tc;
doc.difference = flt((td - tc), precision("difference")); doc.difference = flt(td - tc, precision("difference"));
refresh_many(['total_debit','total_credit','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.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); cur_frm.cscript.update_totals(doc);
} };
frappe.ui.form.on("Journal Entry Account", { frappe.ui.form.on("Journal Entry Account", {
party: function(frm, cdt, cdn) { party: function (frm, cdt, cdn) {
var d = frappe.get_doc(cdt, cdn); var d = frappe.get_doc(cdt, cdn);
if(!d.account && d.party_type && d.party) { if (!d.account && d.party_type && d.party) {
if(!frm.doc.company) frappe.throw(__("Please select Company")); if (!frm.doc.company) frappe.throw(__("Please select Company"));
return frm.call({ 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, child: d,
args: { args: {
company: frm.doc.company, company: frm.doc.company,
party_type: d.party_type, party_type: d.party_type,
party: d.party, party: d.party,
cost_center: d.cost_center },
}
}); });
} }
}, },
cost_center: function(frm, dt, dn) { cost_center: function (frm, dt, dn) {
erpnext.journal_entry.set_account_balance(frm, dt, dn); erpnext.journal_entry.set_account_details(frm, dt, dn);
}, },
account: function(frm, dt, dn) { account: function (frm, dt, dn) {
erpnext.journal_entry.set_account_balance(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); 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); 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); cur_frm.cscript.update_totals(frm.doc);
}, },
credit: function(frm, dt, dn) { credit: function (frm, dt, dn) {
cur_frm.cscript.update_totals(frm.doc); 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 company_currency = frappe.get_doc(":Company", frm.doc.company).default_currency;
var row = locals[cdt][cdn]; 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); frappe.model.set_value(cdt, cdn, "exchange_rate", 1);
} }
erpnext.journal_entry.set_debit_credit_in_company_currency(frm, cdt, cdn); 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); cur_frm.cscript.update_totals(frm.doc);
}); });
$.extend(erpnext.journal_entry, { $.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 fields = ["currency_section", "account_currency", "exchange_rate", "debit", "credit"];
var grid = frm.get_field("accounts").grid; 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 // dynamic label
var field_label_map = { var field_label_map = {
"debit_in_account_currency": "Debit", debit_in_account_currency: "Debit",
"credit_in_account_currency": "Credit" credit_in_account_currency: "Credit",
}; };
$.each(field_label_map, function (fieldname, label) { $.each(field_label_map, function (fieldname, label) {
frm.fields_dict.accounts.grid.update_docfield_property( frm.fields_dict.accounts.grid.update_docfield_property(
fieldname, fieldname,
'label', "label",
frm.doc.multi_currency ? (label + " in Account Currency") : 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]; var row = locals[cdt][cdn];
frappe.model.set_value(cdt, cdn, "debit", frappe.model.set_value(
flt(flt(row.debit_in_account_currency)*row.exchange_rate, precision("debit", row))); cdt,
cdn,
"debit",
flt(flt(row.debit_in_account_currency) * row.exchange_rate, precision("debit", row))
);
frappe.model.set_value(cdt, cdn, "credit", frappe.model.set_value(
flt(flt(row.credit_in_account_currency)*row.exchange_rate, precision("credit", row))); cdt,
cdn,
"credit",
flt(flt(row.credit_in_account_currency) * row.exchange_rate, precision("credit", row))
);
cur_frm.cscript.update_totals(frm.doc); 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 company_currency = frappe.get_doc(":Company", frm.doc.company).default_currency;
var row = locals[cdt][cdn]; 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; row.exchange_rate = 1;
erpnext.journal_entry.set_debit_credit_in_company_currency(frm, cdt, cdn); 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") { } else if (!row.exchange_rate || row.exchange_rate == 1 || row.account_type == "Bank") {
@@ -504,50 +553,70 @@ $.extend(erpnext.journal_entry, {
reference_name: cstr(row.reference_name), reference_name: cstr(row.reference_name),
debit: flt(row.debit_in_account_currency), debit: flt(row.debit_in_account_currency),
credit: flt(row.credit_in_account_currency), credit: flt(row.credit_in_account_currency),
exchange_rate: row.exchange_rate exchange_rate: row.exchange_rate,
}, },
callback: function(r) { callback: function (r) {
if(r.message) { if (r.message) {
row.exchange_rate = r.message; row.exchange_rate = r.message;
erpnext.journal_entry.set_debit_credit_in_company_currency(frm, cdt, cdn); erpnext.journal_entry.set_debit_credit_in_company_currency(frm, cdt, cdn);
} }
} },
}) });
} else { } else {
erpnext.journal_entry.set_debit_credit_in_company_currency(frm, cdt, cdn); erpnext.journal_entry.set_debit_credit_in_company_currency(frm, cdt, cdn);
} }
refresh_field("exchange_rate", cdn, "accounts"); 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_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({ var dialog = new frappe.ui.Dialog({
title: __("Quick Journal Entry"), title: __("Quick Journal Entry"),
fields: [ fields: [
{fieldtype: "Currency", fieldname: "debit", label: __("Amount"), reqd: 1}, { fieldtype: "Currency", fieldname: "debit", label: __("Amount"), reqd: 1 },
{fieldtype: "Link", fieldname: "debit_account", label: __("Debit Account"), reqd: 1, {
fieldtype: "Link",
fieldname: "debit_account",
label: __("Debit Account"),
reqd: 1,
options: "Account", options: "Account",
get_query: function() { get_query: function () {
return erpnext.journal_entry.account_query(frm); 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", options: "Account",
get_query: function() { get_query: function () {
return erpnext.journal_entry.account_query(frm); 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: "Date",
{fieldtype: "Select", fieldname: "naming_series", label: __("Series"), reqd: 1, fieldname: "posting_date",
options: naming_series_options, default: naming_series_default}, 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 btn = this;
var values = dialog.get_values(); var values = dialog.get_values();
@@ -564,11 +633,21 @@ $.extend(erpnext.journal_entry, {
var debit_row = frm.fields_dict.accounts.grid.add_new_row(); 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, "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(); 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, "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(); frm.save();
@@ -578,36 +657,39 @@ $.extend(erpnext.journal_entry, {
dialog.show(); dialog.show();
}, },
account_query: function(frm) { account_query: function (frm) {
var filters = { var filters = {
company: frm.doc.company, company: frm.doc.company,
is_group: 0 is_group: 0,
}; };
if(!frm.doc.multi_currency) { if (!frm.doc.multi_currency) {
$.extend(filters, { $.extend(filters, {
account_currency: ['in', [frappe.get_doc(":Company", frm.doc.company).default_currency, null]] account_currency: [
"in",
[frappe.get_doc(":Company", frm.doc.company).default_currency, null],
],
}); });
} }
return { filters: filters }; return { filters: filters };
}, },
reverse_journal_entry: function() { reverse_journal_entry: function () {
frappe.model.open_mapped_doc({ frappe.model.open_mapped_doc({
method: "erpnext.accounts.doctype.journal_entry.journal_entry.make_reverse_journal_entry", method: "erpnext.accounts.doctype.journal_entry.journal_entry.make_reverse_journal_entry",
frm: cur_frm frm: cur_frm,
}) });
}, },
}); });
$.extend(erpnext.journal_entry, { $.extend(erpnext.journal_entry, {
set_account_balance: function(frm, dt, dn) { set_account_details: function (frm, dt, dn) {
var d = locals[dt][dn]; var d = locals[dt][dn];
if(d.account) { if (d.account) {
if(!frm.doc.company) frappe.throw(__("Please select Company first")); if (!frm.doc.company) frappe.throw(__("Please select Company first"));
if(!frm.doc.posting_date) frappe.throw(__("Please select Posting Date first")); if (!frm.doc.posting_date) frappe.throw(__("Please select Posting Date first"));
return frappe.call({ 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: { args: {
account: d.account, account: d.account,
date: frm.doc.posting_date, date: frm.doc.posting_date,
@@ -615,15 +697,14 @@ $.extend(erpnext.journal_entry, {
debit: flt(d.debit_in_account_currency), debit: flt(d.debit_in_account_currency),
credit: flt(d.credit_in_account_currency), credit: flt(d.credit_in_account_currency),
exchange_rate: d.exchange_rate, exchange_rate: d.exchange_rate,
cost_center: d.cost_center
}, },
callback: function(r) { callback: function (r) {
if(r.message) { if (r.message) {
$.extend(d, r.message); $.extend(d, r.message);
erpnext.journal_entry.set_debit_credit_in_company_currency(frm, dt, dn); erpnext.journal_entry.set_debit_credit_in_company_currency(frm, dt, dn);
refresh_field('accounts'); refresh_field("accounts");
}
} }
},
}); });
} }
}, },

View File

@@ -64,7 +64,8 @@
"stock_entry", "stock_entry",
"subscription_section", "subscription_section",
"auto_repeat", "auto_repeat",
"amended_from" "amended_from",
"repost_required"
], ],
"fields": [ "fields": [
{ {
@@ -543,6 +544,15 @@
"label": "Is System Generated", "label": "Is System Generated",
"no_copy": 1, "no_copy": 1,
"read_only": 1 "read_only": 1
},
{
"default": "0",
"fieldname": "repost_required",
"fieldtype": "Check",
"hidden": 1,
"label": "Repost Required",
"print_hide": 1,
"read_only": 1
} }
], ],
"icon": "fa fa-file-text", "icon": "fa fa-file-text",

View File

@@ -13,6 +13,10 @@ from erpnext.accounts.deferred_revenue import get_deferred_booking_accounts
from erpnext.accounts.doctype.invoice_discounting.invoice_discounting import ( from erpnext.accounts.doctype.invoice_discounting.invoice_discounting import (
get_party_account_based_on_invoice_discounting, get_party_account_based_on_invoice_discounting,
) )
from erpnext.accounts.doctype.repost_accounting_ledger.repost_accounting_ledger import (
validate_docs_for_deferred_accounting,
validate_docs_for_voucher_types,
)
from erpnext.accounts.doctype.tax_withholding_category.tax_withholding_category import ( from erpnext.accounts.doctype.tax_withholding_category.tax_withholding_category import (
get_party_tax_withholding_details, get_party_tax_withholding_details,
) )
@@ -140,7 +144,6 @@ class JournalEntry(AccountsController):
self.set_print_format_fields() self.set_print_format_fields()
self.validate_credit_debit_note() self.validate_credit_debit_note()
self.validate_empty_accounts_table() self.validate_empty_accounts_table()
self.set_account_and_party_balance()
self.validate_inter_company_accounts() self.validate_inter_company_accounts()
self.validate_depr_entry_voucher_type() self.validate_depr_entry_voucher_type()
@@ -150,6 +153,10 @@ class JournalEntry(AccountsController):
if not self.title: if not self.title:
self.title = self.get_title() self.title = self.get_title()
def validate_for_repost(self):
validate_docs_for_voucher_types(["Journal Entry"])
validate_docs_for_deferred_accounting([self.name], [])
def submit(self): def submit(self):
if len(self.accounts) > 100: if len(self.accounts) > 100:
msgprint(_("The task has been enqueued as a background job."), alert=True) msgprint(_("The task has been enqueued as a background job."), alert=True)
@@ -173,6 +180,15 @@ class JournalEntry(AccountsController):
self.update_inter_company_jv() self.update_inter_company_jv()
self.update_invoice_discounting() self.update_invoice_discounting()
def on_update_after_submit(self):
if hasattr(self, "repost_required"):
self.needs_repost = self.check_if_fields_updated(
fields_to_check=[], child_tables={"accounts": []}
)
if self.needs_repost:
self.validate_for_repost()
self.db_set("repost_required", self.needs_repost)
def on_cancel(self): def on_cancel(self):
# References for this Journal are removed on the `on_cancel` event in accounts_controller # References for this Journal are removed on the `on_cancel` event in accounts_controller
super(JournalEntry, self).on_cancel() super(JournalEntry, self).on_cancel()
@@ -559,17 +575,28 @@ class JournalEntry(AccountsController):
elif d.party_type == "Supplier" and flt(d.credit) > 0: elif d.party_type == "Supplier" and flt(d.credit) > 0:
frappe.throw(_("Row {0}: Advance against Supplier must be debit").format(d.idx)) 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): def validate_against_jv(self):
for d in self.get("accounts"): for d in self.get("accounts"):
if d.reference_type == "Journal Entry": if d.reference_type == "Journal Entry":
account_root_type = frappe.get_cached_value("Account", d.account, "root_type") account_root_type = frappe.get_cached_value("Account", d.account, "root_type")
if account_root_type == "Asset" and flt(d.debit) > 0: if account_root_type == "Asset" and flt(d.debit) > 0 and not self.system_generated_gain_loss():
frappe.throw( frappe.throw(
_( _(
"Row #{0}: For {1}, you can select reference document only if account gets credited" "Row #{0}: For {1}, you can select reference document only if account gets credited"
).format(d.idx, d.account) ).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( frappe.throw(
_( _(
"Row #{0}: For {1}, you can select reference document only if account gets debited" "Row #{0}: For {1}, you can select reference document only if account gets debited"
@@ -601,7 +628,7 @@ class JournalEntry(AccountsController):
for jvd in against_entries: for jvd in against_entries:
if flt(jvd[dr_or_cr]) > 0: if flt(jvd[dr_or_cr]) > 0:
valid = True valid = True
if not valid: if not valid and not self.system_generated_gain_loss():
frappe.throw( frappe.throw(
_("Against Journal Entry {0} does not have any unmatched {1} entry").format( _("Against Journal Entry {0} does not have any unmatched {1} entry").format(
d.reference_name, dr_or_cr d.reference_name, dr_or_cr
@@ -1149,21 +1176,6 @@ class JournalEntry(AccountsController):
if not self.get("accounts"): if not self.get("accounts"):
frappe.throw(_("Accounts table cannot be blank.")) 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() @frappe.whitelist()
def get_default_bank_cash_account(company, account_type=None, mode_of_payment=None, account=None): def get_default_bank_cash_account(company, account_type=None, mode_of_payment=None, account=None):
@@ -1329,8 +1341,6 @@ def get_payment_entry(ref_doc, args):
"account_type": frappe.get_cached_value("Account", args.get("party_account"), "account_type"), "account_type": frappe.get_cached_value("Account", args.get("party_account"), "account_type"),
"account_currency": args.get("party_account_currency") "account_currency": args.get("party_account_currency")
or get_account_currency(args.get("party_account")), 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, "exchange_rate": exchange_rate,
args.get("amount_field_party"): args.get("amount"), args.get("amount_field_party"): args.get("amount"),
"is_advance": args.get("is_advance"), "is_advance": args.get("is_advance"),
@@ -1478,30 +1488,23 @@ def get_outstanding(args):
@frappe.whitelist() @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"): if not frappe.has_permission("Account"):
frappe.msgprint(_("No Permission"), raise_exception=1) frappe.msgprint(_("No Permission"), raise_exception=1)
account = get_party_account(party_type, party, company) 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 { return {
"account": account, "account": account,
"balance": account_balance,
"party_balance": party_balance,
"account_currency": frappe.get_cached_value("Account", account, "account_currency"), "account_currency": frappe.get_cached_value("Account", account, "account_currency"),
} }
@frappe.whitelist() @frappe.whitelist()
def get_account_balance_and_party_type( def get_account_details_and_party_type(
account, date, company, debit=None, credit=None, exchange_rate=None, cost_center=None 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"): if not frappe.has_permission("Account"):
frappe.msgprint(_("No Permission"), raise_exception=1) frappe.msgprint(_("No Permission"), raise_exception=1)
@@ -1521,7 +1524,6 @@ def get_account_balance_and_party_type(
party_type = "" party_type = ""
grid_values = { grid_values = {
"balance": get_balance_on(account, date, cost_center=cost_center),
"party_type": party_type, "party_type": party_type,
"account_type": account_details.account_type, "account_type": account_details.account_type,
"account_currency": account_details.account_currency or company_currency, "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"], add_fields: ["voucher_type", "posting_date", "total_debit", "company", "user_remark"],
get_indicator: function(doc) { get_indicator: function (doc) {
if(doc.docstatus==0) { if (doc.docstatus == 0) {
return [__("Draft", "red", "docstatus,=,0")] return [__("Draft", "red", "docstatus,=,0")];
} else if(doc.docstatus==2) { } else if (doc.docstatus == 2) {
return [__("Cancelled", "grey", "docstatus,=,2")] return [__("Cancelled", "grey", "docstatus,=,2")];
} else { } else {
return [__(doc.voucher_type), "blue", "voucher_type,=," + doc.voucher_type] return [__(doc.voucher_type), "blue", "voucher_type,=," + doc.voucher_type];
}
} }
},
}; };

View File

@@ -166,43 +166,37 @@ class TestJournalEntry(unittest.TestCase):
jv.get("accounts")[1].credit_in_account_currency = 5000 jv.get("accounts")[1].credit_in_account_currency = 5000
jv.submit() jv.submit()
gl_entries = frappe.db.sql( self.voucher_no = jv.name
"""select account, account_currency, debit, credit,
debit_in_account_currency, credit_in_account_currency
from `tabGL Entry` where voucher_type='Journal Entry' and voucher_no=%s
order by account asc""",
jv.name,
as_dict=1,
)
self.assertTrue(gl_entries) self.fields = [
"account",
"account_currency",
"debit",
"debit_in_account_currency",
"credit",
"credit_in_account_currency",
]
expected_values = { self.expected_gle = [
"_Test Bank USD - _TC": { {
"account_currency": "USD", "account": "_Test Bank - _TC",
"debit": 5000,
"debit_in_account_currency": 100,
"credit": 0,
"credit_in_account_currency": 0,
},
"_Test Bank - _TC": {
"account_currency": "INR", "account_currency": "INR",
"debit": 0, "debit": 0,
"debit_in_account_currency": 0, "debit_in_account_currency": 0,
"credit": 5000, "credit": 5000,
"credit_in_account_currency": 5000, "credit_in_account_currency": 5000,
}, },
} {
"account": "_Test Bank USD - _TC",
"account_currency": "USD",
"debit": 5000,
"debit_in_account_currency": 100,
"credit": 0,
"credit_in_account_currency": 0,
},
]
for field in ( self.check_gl_entries()
"account_currency",
"debit",
"debit_in_account_currency",
"credit",
"credit_in_account_currency",
):
for i, gle in enumerate(gl_entries):
self.assertEqual(expected_values[gle.account][field], gle[field])
# cancel # cancel
jv.cancel() jv.cancel()
@@ -228,43 +222,37 @@ class TestJournalEntry(unittest.TestCase):
rjv.posting_date = nowdate() rjv.posting_date = nowdate()
rjv.submit() rjv.submit()
gl_entries = frappe.db.sql( self.voucher_no = rjv.name
"""select account, account_currency, debit, credit,
debit_in_account_currency, credit_in_account_currency
from `tabGL Entry` where voucher_type='Journal Entry' and voucher_no=%s
order by account asc""",
rjv.name,
as_dict=1,
)
self.assertTrue(gl_entries) self.fields = [
"account",
"account_currency",
"debit",
"credit",
"debit_in_account_currency",
"credit_in_account_currency",
]
expected_values = { self.expected_gle = [
"_Test Bank USD - _TC": { {
"account": "_Test Bank USD - _TC",
"account_currency": "USD", "account_currency": "USD",
"debit": 0, "debit": 0,
"debit_in_account_currency": 0, "debit_in_account_currency": 0,
"credit": 5000, "credit": 5000,
"credit_in_account_currency": 100, "credit_in_account_currency": 100,
}, },
"Sales - _TC": { {
"account": "Sales - _TC",
"account_currency": "INR", "account_currency": "INR",
"debit": 5000, "debit": 5000,
"debit_in_account_currency": 5000, "debit_in_account_currency": 5000,
"credit": 0, "credit": 0,
"credit_in_account_currency": 0, "credit_in_account_currency": 0,
}, },
} ]
for field in ( self.check_gl_entries()
"account_currency",
"debit",
"debit_in_account_currency",
"credit",
"credit_in_account_currency",
):
for i, gle in enumerate(gl_entries):
self.assertEqual(expected_values[gle.account][field], gle[field])
def test_disallow_change_in_account_currency_for_a_party(self): def test_disallow_change_in_account_currency_for_a_party(self):
# create jv in USD # create jv in USD
@@ -344,23 +332,25 @@ class TestJournalEntry(unittest.TestCase):
jv.insert() jv.insert()
jv.submit() jv.submit()
expected_values = { self.voucher_no = jv.name
"_Test Cash - _TC": {"cost_center": cost_center},
"_Test Bank - _TC": {"cost_center": cost_center},
}
gl_entries = frappe.db.sql( self.fields = [
"""select account, cost_center, debit, credit "account",
from `tabGL Entry` where voucher_type='Journal Entry' and voucher_no=%s "cost_center",
order by account asc""", ]
jv.name,
as_dict=1,
)
self.assertTrue(gl_entries) self.expected_gle = [
{
"account": "_Test Bank - _TC",
"cost_center": cost_center,
},
{
"account": "_Test Cash - _TC",
"cost_center": cost_center,
},
]
for gle in gl_entries: self.check_gl_entries()
self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center)
def test_jv_with_project(self): def test_jv_with_project(self):
from erpnext.projects.doctype.project.test_project import make_project from erpnext.projects.doctype.project.test_project import make_project
@@ -387,23 +377,22 @@ class TestJournalEntry(unittest.TestCase):
jv.insert() jv.insert()
jv.submit() jv.submit()
expected_values = { self.voucher_no = jv.name
"_Test Cash - _TC": {"project": project_name},
"_Test Bank - _TC": {"project": project_name},
}
gl_entries = frappe.db.sql( self.fields = ["account", "project"]
"""select account, project, debit, credit
from `tabGL Entry` where voucher_type='Journal Entry' and voucher_no=%s
order by account asc""",
jv.name,
as_dict=1,
)
self.assertTrue(gl_entries) self.expected_gle = [
{
"account": "_Test Bank - _TC",
"project": project_name,
},
{
"account": "_Test Cash - _TC",
"project": project_name,
},
]
for gle in gl_entries: self.check_gl_entries()
self.assertEqual(expected_values[gle.account]["project"], gle.project)
def test_jv_account_and_party_balance_with_cost_centre(self): def test_jv_account_and_party_balance_with_cost_centre(self):
from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
@@ -426,6 +415,79 @@ class TestJournalEntry(unittest.TestCase):
account_balance = get_balance_on(account="_Test Bank - _TC", cost_center=cost_center) account_balance = get_balance_on(account="_Test Bank - _TC", cost_center=cost_center)
self.assertEqual(expected_account_balance, account_balance) self.assertEqual(expected_account_balance, account_balance)
def test_repost_accounting_entries(self):
from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
# Configure Repost Accounting Ledger for JVs
settings = frappe.get_doc("Repost Accounting Ledger Settings")
if not [x for x in settings.allowed_types if x.document_type == "Journal Entry"]:
settings.append("allowed_types", {"document_type": "Journal Entry", "allowed": True})
settings.save()
# Create JV with defaut cost center - _Test Cost Center
jv = make_journal_entry("_Test Cash - _TC", "_Test Bank - _TC", 100, save=False)
jv.multi_currency = 0
jv.submit()
# Check GL entries before reposting
self.voucher_no = jv.name
self.fields = [
"account",
"debit_in_account_currency",
"credit_in_account_currency",
"cost_center",
]
self.expected_gle = [
{
"account": "_Test Bank - _TC",
"debit_in_account_currency": 0,
"credit_in_account_currency": 100,
"cost_center": "_Test Cost Center - _TC",
},
{
"account": "_Test Cash - _TC",
"debit_in_account_currency": 100,
"credit_in_account_currency": 0,
"cost_center": "_Test Cost Center - _TC",
},
]
self.check_gl_entries()
# Change cost center for bank account - _Test Cost Center for BS Account
create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company")
jv.accounts[1].cost_center = "_Test Cost Center for BS Account - _TC"
jv.save()
# Check if repost flag gets set on update after submit
self.assertTrue(jv.repost_required)
jv.repost_accounting_entries()
# Check GL entries after reposting
jv.load_from_db()
self.expected_gle[0]["cost_center"] = "_Test Cost Center for BS Account - _TC"
self.check_gl_entries()
def check_gl_entries(self):
gl = frappe.qb.DocType("GL Entry")
query = frappe.qb.from_(gl)
for field in self.fields:
query = query.select(gl[field])
query = query.where(
(gl.voucher_type == "Journal Entry")
& (gl.voucher_no == self.voucher_no)
& (gl.is_cancelled == 0)
).orderby(gl.account)
gl_entries = query.run(as_dict=True)
for i in range(len(self.expected_gle)):
for field in self.fields:
self.assertEqual(self.expected_gle[i][field], gl_entries[i][field])
def make_journal_entry( def make_journal_entry(
account1, account1,

View File

@@ -9,12 +9,10 @@
"field_order": [ "field_order": [
"account", "account",
"account_type", "account_type",
"balance",
"col_break1", "col_break1",
"bank_account", "bank_account",
"party_type", "party_type",
"party", "party",
"party_balance",
"accounting_dimensions_section", "accounting_dimensions_section",
"cost_center", "cost_center",
"dimension_col_break", "dimension_col_break",
@@ -64,17 +62,7 @@
"print_hide": 1 "print_hide": 1
}, },
{ {
"fieldname": "balance", "allow_on_submit": 1,
"fieldtype": "Currency",
"label": "Account Balance",
"no_copy": 1,
"oldfieldname": "balance",
"oldfieldtype": "Data",
"options": "account_currency",
"print_hide": 1,
"read_only": 1
},
{
"default": ":Company", "default": ":Company",
"description": "If Income or Expense", "description": "If Income or Expense",
"fieldname": "cost_center", "fieldname": "cost_center",
@@ -107,14 +95,6 @@
"label": "Party", "label": "Party",
"options": "party_type" "options": "party_type"
}, },
{
"fieldname": "party_balance",
"fieldtype": "Currency",
"label": "Party Balance",
"options": "account_currency",
"print_hide": 1,
"read_only": 1
},
{ {
"fieldname": "currency_section", "fieldname": "currency_section",
"fieldtype": "Section Break", "fieldtype": "Section Break",
@@ -223,6 +203,7 @@
"no_copy": 1 "no_copy": 1
}, },
{ {
"allow_on_submit": 1,
"fieldname": "project", "fieldname": "project",
"fieldtype": "Link", "fieldtype": "Link",
"label": "Project", "label": "Project",
@@ -287,7 +268,7 @@
"idx": 1, "idx": 1,
"istable": 1, "istable": 1,
"links": [], "links": [],
"modified": "2023-11-23 11:44:25.841187", "modified": "2024-02-05 01:10:50.224840",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Accounts", "module": "Accounts",
"name": "Journal Entry Account", "name": "Journal Entry Account",

View File

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

View File

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

View File

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

View File

@@ -3,30 +3,37 @@
frappe.provide("erpnext.accounts.dimensions"); frappe.provide("erpnext.accounts.dimensions");
frappe.ui.form.on('Loyalty Program', { frappe.ui.form.on("Loyalty Program", {
setup: function(frm) { setup: function (frm) {
var help_content = var help_content = `<table class="table table-bordered" style="background-color: var(--scrollbar-track-color);">
`<table class="table table-bordered" style="background-color: var(--scrollbar-track-color);">
<tr><td> <tr><td>
<h4> <h4>
<i class="fa fa-hand-right"></i> <i class="fa fa-hand-right"></i>
${__('Notes')} ${__("Notes")}
</h4> </h4>
<ul> <ul>
<li> <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>
<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>
<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>
<li> <li>
${__("If unlimited expiry for the Loyalty Points, keep the Expiry Duration empty or 0.")} ${__("If unlimited expiry for the Loyalty Points, keep the Expiry Duration empty or 0.")}
</li> </li>
<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>
<li> <li>
${__("One customer can be part of only single Loyalty Program.")} ${__("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); set_field_options("loyalty_program_help", help_content);
}, },
onload: function(frm) { onload: function (frm) {
frm.set_query("expense_account", function(doc) { frm.set_query("expense_account", function (doc) {
return { return {
filters: { filters: {
"root_type": "Expense", root_type: "Expense",
'is_group': 0, is_group: 0,
'company': doc.company company: doc.company,
} },
}; };
}); });
@@ -52,13 +59,15 @@ frappe.ui.form.on('Loyalty Program', {
erpnext.accounts.dimensions.setup_dimension_filters(frm, frm.doctype); 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) { 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); erpnext.accounts.dimensions.update_dimension(frm, frm.doctype);
} },
}); });

View File

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

View File

@@ -1,16 +1,16 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors // Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt // License: GNU General Public License v3. See license.txt
frappe.ui.form.on('Monthly Distribution', { frappe.ui.form.on("Monthly Distribution", {
onload(frm) { onload(frm) {
if(frm.doc.__islocal) { if (frm.doc.__islocal) {
return frm.call('get_months').then(() => { return frm.call("get_months").then(() => {
frm.refresh_field('percentages'); frm.refresh_field("percentages");
}); });
} }
}, },
refresh(frm) { 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 // Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt // For license information, please see license.txt
frappe.ui.form.on('Opening Invoice Creation Tool', { frappe.ui.form.on("Opening Invoice Creation Tool", {
setup: function(frm) { setup: function (frm) {
frm.set_query('party_type', 'invoices', function(doc, cdt, cdn) { frm.set_query("party_type", "invoices", function (doc, cdt, cdn) {
return { return {
filters: { filters: {
'name': ['in', 'Customer, Supplier'] name: ["in", "Customer, Supplier"],
} },
}; };
}); });
if (frm.doc.company) { 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) { if (!frm.doc.import_in_progress) {
frm.dashboard.reset(); frm.dashboard.reset();
frm.doc.import_in_progress = true; frm.doc.import_in_progress = true;
} }
if (data.count == data.total) { if (data.count == data.total) {
setTimeout(() => { setTimeout(
() => {
frm.doc.import_in_progress = false; frm.doc.import_in_progress = false;
frm.clear_table("invoices"); frm.clear_table("invoices");
frm.refresh_fields(); frm.refresh_fields();
frm.page.clear_indicator(); frm.page.clear_indicator();
frm.dashboard.hide_progress(); frm.dashboard.hide_progress();
frappe.msgprint(__("Opening {0} Invoices created", [frm.doc.invoice_type])); frappe.msgprint(__("Opening {0} Invoices created", [frm.doc.invoice_type]));
}, 1500, data.title); },
1500,
data.title
);
return; return;
} }
frm.dashboard.show_progress(data.title, (data.count / data.total) * 100, data.message); 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); erpnext.accounts.dimensions.setup_dimension_filters(frm, frm.doctype);
}, },
refresh: function(frm) { refresh: function (frm) {
frm.disable_save(); frm.disable_save();
!frm.doc.import_in_progress && frm.trigger("make_dashboard"); !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); let btn_primary = frm.page.btn_primary.get(0);
return frm.call({ return frm.call({
doc: frm.doc, doc: frm.doc,
@@ -58,100 +62,98 @@ frappe.ui.form.on('Opening Invoice Creation Tool', {
} }
}, },
setup_company_filters: function(frm) { setup_company_filters: function (frm) {
frm.set_query('cost_center', 'invoices', function(doc, cdt, cdn) { frm.set_query("cost_center", "invoices", function (doc, cdt, cdn) {
return { return {
filters: { filters: {
'company': doc.company company: doc.company,
} },
}; };
}); });
frm.set_query('cost_center', function(doc) { frm.set_query("cost_center", function (doc) {
return { return {
filters: { 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 { return {
filters: { filters: {
'company': doc.company company: doc.company,
} },
} };
}); });
}, },
company: function(frm) { company: function (frm) {
if (frm.doc.company) { if (frm.doc.company) {
frm.trigger("setup_company_filters");
frm.trigger('setup_company_filters');
frappe.call({ 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: { args: {
company: frm.doc.company company: frm.doc.company,
}, },
callback: (r) => { callback: (r) => {
if (r.message) { if (r.message) {
frm.doc.__onload.temporary_opening_account = 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); erpnext.accounts.dimensions.update_dimension(frm, frm.doctype);
}, },
invoice_type: function(frm) { invoice_type: function (frm) {
$.each(frm.doc.invoices, (idx, row) => { $.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 = ""; row.party = "";
}); });
frm.refresh_fields(); frm.refresh_fields();
}, },
make_dashboard: function(frm) { make_dashboard: function (frm) {
let max_count = frm.doc.__onload.max_count; let max_count = frm.doc.__onload.max_count;
let opening_invoices_summary = frm.doc.__onload.opening_invoices_summary; 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( 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, data: opening_invoices_summary,
max_count: max_count max_count: max_count,
}), }),
__("Opening Invoices Summary") __("Opening Invoices Summary")
); );
section.on('click', '.invoice-link', function() { section.on("click", ".invoice-link", function () {
let doctype = $(this).attr('data-type'); let doctype = $(this).attr("data-type");
let company = $(this).attr('data-company'); let company = $(this).attr("data-company");
frappe.set_route('List', doctype, frappe.set_route("List", doctype, { is_opening: "Yes", company: company, docstatus: 1 });
{'is_opening': 'Yes', 'company': company, 'docstatus': 1});
}); });
frm.dashboard.show(); frm.dashboard.show();
} }
}, },
update_invoice_table: function(frm) { update_invoice_table: function (frm) {
$.each(frm.doc.invoices, (idx, row) => { $.each(frm.doc.invoices, (idx, row) => {
if (!row.temporary_opening_account) { if (!row.temporary_opening_account) {
row.temporary_opening_account = frm.doc.__onload.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.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) => { 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 // Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt // For license information, please see license.txt
frappe.ui.form.on('Party Link', { frappe.ui.form.on("Party Link", {
refresh: function(frm) { refresh: function (frm) {
frm.set_query('primary_role', () => { frm.set_query("primary_role", () => {
return { return {
filters: { filters: {
name: ['in', ['Customer', 'Supplier']] name: ["in", ["Customer", "Supplier"]],
} },
}; };
}); });
frm.set_query('secondary_role', () => { frm.set_query("secondary_role", () => {
let party_types = Object.keys(frappe.boot.party_account_types) let party_types = Object.keys(frappe.boot.party_account_types).filter(
.filter(p => p != frm.doc.primary_role); (p) => p != frm.doc.primary_role
);
return { return {
filters: { filters: {
name: ['in', party_types] name: ["in", party_types],
} },
}; };
}); });
}, },
primary_role(frm) { primary_role(frm) {
frm.set_value('primary_party', ''); frm.set_value("primary_party", "");
frm.set_value('secondary_role', ''); frm.set_value("secondary_role", "");
}, },
secondary_role(frm) { secondary_role(frm) {
frm.set_value('secondary_party', ''); frm.set_value("secondary_party", "");
} },
}); });

File diff suppressed because it is too large Load Diff

View File

@@ -1185,7 +1185,13 @@ class PaymentEntry(AccountsController):
references = [x for x in self.get("references") if x.name == entry.name] references = [x for x in self.get("references") if x.name == entry.name]
for ref in references: for ref in references:
if ref.reference_doctype in ("Sales Invoice", "Purchase Invoice", "Journal Entry"): if ref.reference_doctype in (
"Sales Invoice",
"Purchase Invoice",
"Journal Entry",
"Sales Order",
"Purchase Order",
):
self.add_advance_gl_for_reference(gl_entries, ref) self.add_advance_gl_for_reference(gl_entries, ref)
def add_advance_gl_for_reference(self, gl_entries, invoice): def add_advance_gl_for_reference(self, gl_entries, invoice):
@@ -1199,14 +1205,15 @@ class PaymentEntry(AccountsController):
"voucher_detail_no": invoice.name, "voucher_detail_no": invoice.name,
} }
posting_date = frappe.db.get_value( date_field = "posting_date"
invoice.reference_doctype, invoice.reference_name, "posting_date" if invoice.reference_doctype in ["Sales Order", "Purchase Order"]:
) date_field = "transaction_date"
posting_date = frappe.db.get_value(invoice.reference_doctype, invoice.reference_name, date_field)
if getdate(posting_date) < getdate(self.posting_date): if getdate(posting_date) < getdate(self.posting_date):
posting_date = self.posting_date posting_date = self.posting_date
dr_or_cr = "credit" if invoice.reference_doctype == "Sales Invoice" else "debit" dr_or_cr = "credit" if invoice.reference_doctype in ["Sales Invoice", "Sales Order"] else "debit"
args_dict["account"] = invoice.account args_dict["account"] = invoice.account
args_dict[dr_or_cr] = invoice.allocated_amount args_dict[dr_or_cr] = invoice.allocated_amount
args_dict[dr_or_cr + "_in_account_currency"] = invoice.allocated_amount args_dict[dr_or_cr + "_in_account_currency"] = invoice.allocated_amount
@@ -2108,6 +2115,11 @@ def get_reference_details(reference_doctype, reference_name, party_account_curre
else: else:
outstanding_amount = flt(total_amount) - flt(ref_doc.get("advance_paid")) outstanding_amount = flt(total_amount) - flt(ref_doc.get("advance_paid"))
if reference_doctype in ["Sales Order", "Purchase Order"]:
party_type = "Customer" if reference_doctype == "Sales Order" else "Supplier"
party_field = "customer" if reference_doctype == "Sales Order" else "supplier"
party = ref_doc.get(party_field)
account = get_party_account(party_type, party, ref_doc.company)
else: else:
# Get the exchange rate based on the posting date of the ref doc. # Get the exchange rate based on the posting date of the ref doc.
exchange_rate = get_exchange_rate(party_account_currency, company_currency, ref_doc.posting_date) exchange_rate = get_exchange_rate(party_account_currency, company_currency, ref_doc.posting_date)

View File

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

View File

@@ -1070,6 +1070,8 @@ class TestPaymentEntry(FrappeTestCase):
self.assertRaises(frappe.ValidationError, pe_draft.submit) self.assertRaises(frappe.ValidationError, pe_draft.submit)
def test_details_update_on_reference_table(self): def test_details_update_on_reference_table(self):
from erpnext.accounts.party import get_party_account
so = make_sales_order( so = make_sales_order(
customer="_Test Customer USD", currency="USD", qty=1, rate=100, do_not_submit=True customer="_Test Customer USD", currency="USD", qty=1, rate=100, do_not_submit=True
) )
@@ -1084,6 +1086,7 @@ class TestPaymentEntry(FrappeTestCase):
ref_details = get_reference_details(so.doctype, so.name, pe.paid_from_account_currency) ref_details = get_reference_details(so.doctype, so.name, pe.paid_from_account_currency)
expected_response = { expected_response = {
"account": get_party_account("Customer", so.customer, so.company),
"total_amount": 5000.0, "total_amount": 5000.0,
"outstanding_amount": 5000.0, "outstanding_amount": 5000.0,
"exchange_rate": 1.0, "exchange_rate": 1.0,

View File

@@ -1,11 +1,11 @@
// Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors // Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt // 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) { refresh(frm) {
erpnext.utils.check_payments_app(); erpnext.utils.check_payments_app();
if(!frm.doc.__islocal) { if (!frm.doc.__islocal) {
frm.set_df_property('payment_gateway', 'read_only', 1); frm.set_df_property("payment_gateway", "read_only", 1);
}
} }
},
}); });

View File

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

View File

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

View File

@@ -2,97 +2,94 @@
// For license information, please see license.txt // For license information, please see license.txt
frappe.provide("erpnext.accounts"); 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() { onload() {
const default_company = frappe.defaults.get_default('company'); const default_company = frappe.defaults.get_default("company");
this.frm.set_value('company', default_company); this.frm.set_value("company", default_company);
this.frm.set_value('party_type', ''); this.frm.set_value("party_type", "");
this.frm.set_value('party', ''); this.frm.set_value("party", "");
this.frm.set_value('receivable_payable_account', ''); this.frm.set_value("receivable_payable_account", "");
this.frm.set_query("party_type", () => { 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 { return {
filters: { filters: {
"company": this.frm.doc.company, name: ["in", Object.keys(frappe.boot.party_account_types)],
"is_group": 0, },
"account_type": frappe.boot.party_account_types[this.frm.doc.party_type],
"root_type": this.frm.doc.party_type == 'Customer' ? "Asset" : "Liability"
}
}; };
}); });
this.frm.set_query('default_advance_account', () => { this.frm.set_query("receivable_payable_account", () => {
return { return {
filters: { filters: {
"company": this.frm.doc.company, company: this.frm.doc.company,
"is_group": 0, is_group: 0,
"account_type": this.frm.doc.party_type == 'Customer' ? "Receivable": "Payable", account_type: frappe.boot.party_account_types[this.frm.doc.party_type],
"root_type": this.frm.doc.party_type == 'Customer' ? "Liability": "Asset" root_type: this.frm.doc.party_type == "Customer" ? "Asset" : "Liability",
} },
}; };
}); });
this.frm.set_query('bank_cash_account', () => { this.frm.set_query("default_advance_account", () => {
return { return {
filters:[ filters: {
['Account', 'company', '=', this.frm.doc.company], company: this.frm.doc.company,
['Account', 'is_group', '=', 0], is_group: 0,
['Account', 'account_type', 'in', ['Bank', 'Cash']] account_type: this.frm.doc.party_type == "Customer" ? "Receivable" : "Payable",
] root_type: this.frm.doc.party_type == "Customer" ? "Liability" : "Asset",
},
};
});
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", () => { this.frm.set_query("cost_center", () => {
return { return {
"filters": { filters: {
"company": this.frm.doc.company, company: this.frm.doc.company,
"is_group": 0 is_group: 0,
} },
} };
}); });
} }
refresh() { refresh() {
this.frm.disable_save(); this.frm.disable_save();
this.frm.set_df_property('invoices', 'cannot_delete_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("payments", "cannot_delete_rows", true);
this.frm.set_df_property('allocation', '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_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) { 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.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) { if (this.frm.doc.invoices.length && this.frm.doc.payments.length) {
this.frm.add_custom_button(__('Allocate'), () => this.frm.add_custom_button(__("Allocate"), () => this.frm.trigger("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.change_custom_button_type(__('Allocate'), null, 'primary');
this.frm.change_custom_button_type(__('Get Unreconciled Entries'), null, 'default');
} }
if (this.frm.doc.allocation.length) { if (this.frm.doc.allocation.length) {
this.frm.add_custom_button(__('Reconcile'), () => this.frm.add_custom_button(__("Reconcile"), () => this.frm.trigger("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(__('Reconcile'), null, 'primary'); this.frm.change_custom_button_type(__("Allocate"), null, "default");
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"); this.frm.trigger("set_query_for_dimension_filters");
@@ -101,31 +98,39 @@ erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationCo
if (this.frm.doc.receivable_payable_account) { if (this.frm.doc.receivable_payable_account) {
this.frm.call({ this.frm.call({
doc: this.frm.doc, doc: this.frm.doc,
method: 'is_auto_process_enabled', method: "is_auto_process_enabled",
callback: (r) => { callback: (r) => {
if (r.message) { if (r.message) {
this.frm.call({ this.frm
'method': "erpnext.accounts.doctype.process_payment_reconciliation.process_payment_reconciliation.is_any_doc_running", .call({
"args": { method: "erpnext.accounts.doctype.process_payment_reconciliation.process_payment_reconciliation.is_any_doc_running",
args: {
for_filter: { for_filter: {
company: this.frm.doc.company, company: this.frm.doc.company,
party_type: this.frm.doc.party_type, party_type: this.frm.doc.party_type,
party: this.frm.doc.party, party: this.frm.doc.party,
receivable_payable_account: this.frm.doc.receivable_payable_account receivable_payable_account: this.frm.doc.receivable_payable_account,
} },
} },
}).then(r => { })
.then((r) => {
if (r.message) { if (r.message) {
let doc_link = frappe.utils.get_form_link("Process Payment Reconciliation", r.message, true); let doc_link = frappe.utils.get_form_link(
let msg = __("Payment Reconciliation Job: {0} is running for this party. Can't reconcile now.", [doc_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"); this.frm.dashboard.add_comment(msg, "yellow");
} }
}); });
} }
} },
}); });
} }
} }
set_query_for_dimension_filters() { set_query_for_dimension_filters() {
frappe.call({ frappe.call({
@@ -135,29 +140,29 @@ erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationCo
}, },
callback: (r) => { callback: (r) => {
if (!r.exc && r.message) { if (!r.exc && r.message) {
r.message.forEach(x => { r.message.forEach((x) => {
this.frm.set_query(x.fieldname, () => { this.frm.set_query(x.fieldname, () => {
return { return {
'filters': x.filters filters: x.filters,
}; };
}); });
}); });
} }
} },
}); });
} }
company() { company() {
this.frm.set_value('party', ''); this.frm.set_value("party", "");
this.frm.set_value('receivable_payable_account', ''); this.frm.set_value("receivable_payable_account", "");
} }
party_type() { party_type() {
this.frm.set_value('party', ''); this.frm.set_value("party", "");
} }
party() { party() {
this.frm.set_value('receivable_payable_account', ''); this.frm.set_value("receivable_payable_account", "");
this.frm.trigger("clear_child_tables"); this.frm.trigger("clear_child_tables");
if (!this.frm.doc.receivable_payable_account && this.frm.doc.party_type && this.frm.doc.party) { if (!this.frm.doc.receivable_payable_account && this.frm.doc.party_type && this.frm.doc.party) {
@@ -167,7 +172,7 @@ erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationCo
company: this.frm.doc.company, company: this.frm.doc.company,
party_type: this.frm.doc.party_type, party_type: this.frm.doc.party_type,
party: this.frm.doc.party, party: this.frm.doc.party,
include_advance: 1 include_advance: 1,
}, },
callback: (r) => { callback: (r) => {
if (!r.exc && r.message) { if (!r.exc && r.message) {
@@ -175,7 +180,7 @@ erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationCo
this.frm.set_value("default_advance_account", r.message[1]); this.frm.set_value("default_advance_account", r.message[1]);
} }
this.frm.refresh(); this.frm.refresh();
} },
}); });
} }
} }
@@ -193,7 +198,6 @@ erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationCo
this.frm.trigger("get_unreconciled_entries"); this.frm.trigger("get_unreconciled_entries");
} }
clear_child_tables() { clear_child_tables() {
this.frm.clear_table("invoices"); this.frm.clear_table("invoices");
this.frm.clear_table("payments"); this.frm.clear_table("payments");
@@ -205,48 +209,48 @@ erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationCo
this.frm.clear_table("allocation"); this.frm.clear_table("allocation");
return this.frm.call({ return this.frm.call({
doc: this.frm.doc, doc: this.frm.doc,
method: 'get_unreconciled_entries', method: "get_unreconciled_entries",
callback: () => { callback: () => {
if (!(this.frm.doc.payments.length || this.frm.doc.invoices.length)) { 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")}); frappe.throw({
} else if (!(this.frm.doc.invoices.length)) { message: __("No Unreconciled Invoices and Payments found for this party and account"),
frappe.throw({message: __("No Outstanding Invoices found for this party")}); });
} else if (!(this.frm.doc.payments.length)) { } else if (!this.frm.doc.invoices.length) {
frappe.throw({message: __("No Unreconciled Payments found for this party")}); 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(); this.frm.refresh();
} },
}); });
} }
allocate() { allocate() {
let payments = this.frm.fields_dict.payments.grid.get_selected_children(); let payments = this.frm.fields_dict.payments.grid.get_selected_children();
if (!(payments.length)) { if (!payments.length) {
payments = this.frm.doc.payments; payments = this.frm.doc.payments;
} }
let invoices = this.frm.fields_dict.invoices.grid.get_selected_children(); let invoices = this.frm.fields_dict.invoices.grid.get_selected_children();
if (!(invoices.length)) { if (!invoices.length) {
invoices = this.frm.doc.invoices; invoices = this.frm.doc.invoices;
} }
return this.frm.call({ return this.frm.call({
doc: this.frm.doc, doc: this.frm.doc,
method: 'allocate_entries', method: "allocate_entries",
args: { args: {
payments: payments, payments: payments,
invoices: invoices invoices: invoices,
}, },
callback: () => { callback: () => {
this.frm.refresh(); this.frm.refresh();
} },
}); });
} }
reconcile() { 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) { if (show_dialog && show_dialog.length) {
this.data = []; this.data = [];
const dialog = new frappe.ui.Dialog({ const dialog = new frappe.ui.Dialog({
title: __("Select Difference Account"), title: __("Select Difference Account"),
@@ -261,66 +265,75 @@ erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationCo
get_data: () => { get_data: () => {
return this.data; return this.data;
}, },
fields: [{ fields: [
fieldtype:'Data', {
fieldname:"docname", fieldtype: "Data",
fieldname: "docname",
in_list_view: 1, in_list_view: 1,
hidden: 1 hidden: 1,
}, { },
fieldtype:'Data', {
fieldname:"reference_name", fieldtype: "Data",
fieldname: "reference_name",
label: __("Voucher No"), label: __("Voucher No"),
in_list_view: 1, in_list_view: 1,
read_only: 1 read_only: 1,
}, { },
fieldtype:'Link', {
options: 'Account', fieldtype: "Link",
options: "Account",
in_list_view: 1, in_list_view: 1,
label: __("Difference Account"), label: __("Difference Account"),
fieldname: 'difference_account', fieldname: "difference_account",
reqd: 1, reqd: 1,
get_query: () => { get_query: () => {
return { return {
filters: { filters: {
company: this.frm.doc.company, company: this.frm.doc.company,
is_group: 0 is_group: 0,
} },
} };
} },
}, {
fieldtype:'Currency',
in_list_view: 1,
label: __("Difference Amount"),
fieldname: 'difference_amount',
read_only: 1
}]
}, },
{ {
fieldtype: 'HTML', fieldtype: "Currency",
options: "<b> New Journal Entry will be posted for the difference amount </b>" 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>",
},
], ],
primary_action: () => { primary_action: () => {
const args = dialog.get_values()["allocation"]; const args = dialog.get_values()["allocation"];
args.forEach(d => { args.forEach((d) => {
frappe.model.set_value("Payment Reconciliation Allocation", d.docname, frappe.model.set_value(
"difference_account", d.difference_account); "Payment Reconciliation Allocation",
d.docname,
"difference_account",
d.difference_account
);
}); });
this.reconcile_payment_entries(); this.reconcile_payment_entries();
dialog.hide(); 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) { if (d.difference_amount) {
dialog.fields_dict.allocation.df.data.push({ dialog.fields_dict.allocation.df.data.push({
'docname': d.name, docname: d.name,
'reference_name': d.reference_name, reference_name: d.reference_name,
'difference_amount': d.difference_amount, difference_amount: d.difference_amount,
'difference_account': d.difference_account, difference_account: d.difference_account,
}); });
} }
}); });
@@ -336,41 +349,39 @@ erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationCo
reconcile_payment_entries() { reconcile_payment_entries() {
return this.frm.call({ return this.frm.call({
doc: this.frm.doc, doc: this.frm.doc,
method: 'reconcile', method: "reconcile",
callback: () => { callback: () => {
this.frm.clear_table("allocation"); this.frm.clear_table("allocation");
this.frm.refresh(); this.frm.refresh();
} },
}); });
} }
}; };
frappe.ui.form.on('Payment Reconciliation Allocation', { frappe.ui.form.on("Payment Reconciliation Allocation", {
allocated_amount: function(frm, cdt, cdn) { allocated_amount: function (frm, cdt, cdn) {
let row = locals[cdt][cdn]; let row = locals[cdt][cdn];
// filter invoice // 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 // 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({ frm.call({
doc: frm.doc, doc: frm.doc,
method: 'calculate_difference_on_allocation_change', method: "calculate_difference_on_allocation_change",
args: { args: {
payment_entry: payment, payment_entry: payment,
invoice: invoice, invoice: invoice,
allocated_amount: row.allocated_amount allocated_amount: row.allocated_amount,
}, },
callback: (r) => { callback: (r) => {
if (r.message) { if (r.message) {
row.difference_amount = r.message; row.difference_amount = r.message;
frm.refresh(); 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

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

View File

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

View File

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

View File

@@ -1,12 +1,18 @@
// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors // Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt // For license information, please see license.txt
frappe.ui.form.on('Payment Terms Template', { frappe.ui.form.on("Payment Terms Template", {
refresh: function(frm) { refresh: function (frm) {
frm.fields_dict.terms.grid.toggle_reqd("payment_term", frm.doc.allocate_payment_based_on_payment_terms); 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) { 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); 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 // Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt // License: GNU General Public License v3. See license.txt
frappe.ui.form.on('Period Closing Voucher', { frappe.ui.form.on("Period Closing Voucher", {
onload: function(frm) { onload: function (frm) {
if (!frm.doc.transaction_date) frm.doc.transaction_date = frappe.datetime.obj_to_str(new Date()); if (!frm.doc.transaction_date) frm.doc.transaction_date = frappe.datetime.obj_to_str(new Date());
}, },
setup: function(frm) { setup: function (frm) {
frm.set_query("closing_account_head", function() { frm.set_query("closing_account_head", function () {
return { return {
filters: [ filters: [
['Account', 'company', '=', frm.doc.company], ["Account", "company", "=", frm.doc.company],
['Account', 'is_group', '=', '0'], ["Account", "is_group", "=", "0"],
['Account', 'freeze_account', '=', 'No'], ["Account", "freeze_account", "=", "No"],
['Account', 'root_type', 'in', 'Liability, Equity'] ["Account", "root_type", "in", "Liability, Equity"],
] ],
} };
}); });
}, },
refresh: function(frm) { refresh: function (frm) {
if(frm.doc.docstatus > 0) { if (frm.doc.docstatus > 0) {
frm.add_custom_button(__('Ledger'), function() { frm.add_custom_button(
__("Ledger"),
function () {
frappe.route_options = { frappe.route_options = {
"voucher_no": frm.doc.name, voucher_no: frm.doc.name,
"from_date": frm.doc.posting_date, from_date: frm.doc.posting_date,
"to_date": moment(frm.doc.modified).format('YYYY-MM-DD'), to_date: moment(frm.doc.modified).format("YYYY-MM-DD"),
"company": frm.doc.company, company: frm.doc.company,
"group_by": "", group_by: "",
"show_cancelled_entries": frm.doc.docstatus === 2 show_cancelled_entries: frm.doc.docstatus === 2,
}; };
frappe.set_route("query-report", "General Ledger"); frappe.set_route("query-report", "General Ledger");
}, "fa fa-table"); },
"fa fa-table"
);
} }
} },
});
})

View File

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

@@ -21,19 +21,23 @@ erpnext.selling.POSInvoiceController = class POSInvoiceController extends erpnex
onload(doc) { onload(doc) {
super.onload(); super.onload();
this.frm.ignore_doctypes_on_cancel_all = ['POS Invoice Merge Log', 'POS Closing Entry', 'Serial and Batch Bundle']; this.frm.ignore_doctypes_on_cancel_all = [
"POS Invoice Merge Log",
"POS Closing Entry",
"Serial and Batch Bundle",
];
if(doc.__islocal && doc.is_pos && frappe.get_route_str() !== 'point-of-sale') { if (doc.__islocal && doc.is_pos && frappe.get_route_str() !== "point-of-sale") {
this.frm.script_manager.trigger("is_pos"); this.frm.script_manager.trigger("is_pos");
this.frm.refresh_fields(); this.frm.refresh_fields();
} }
this.frm.set_query("set_warehouse", function(doc) { this.frm.set_query("set_warehouse", function (doc) {
return { return {
filters: { filters: {
company: doc.company ? doc.company : '', company: doc.company ? doc.company : "",
} },
} };
}); });
erpnext.accounts.dimensions.setup_dimension_filters(this.frm, this.frm.doctype); erpnext.accounts.dimensions.setup_dimension_filters(this.frm, this.frm.doctype);
@@ -47,16 +51,18 @@ erpnext.selling.POSInvoiceController = class POSInvoiceController extends erpnex
super.refresh(); super.refresh();
if (doc.docstatus == 1 && !doc.is_return) { if (doc.docstatus == 1 && !doc.is_return) {
this.frm.add_custom_button(__('Return'), this.make_sales_return, __('Create')); this.frm.add_custom_button(__("Return"), this.make_sales_return, __("Create"));
this.frm.page.set_inner_btn_group_as_primary(__('Create')); this.frm.page.set_inner_btn_group_as_primary(__("Create"));
} }
if (doc.is_return && doc.__islocal) { if (doc.is_return && doc.__islocal) {
this.frm.return_print_format = "Sales Invoice Return"; this.frm.return_print_format = "Sales Invoice Return";
this.frm.set_value('consolidated_invoice', ''); this.frm.set_value("consolidated_invoice", "");
} }
this.frm.set_query("customer", (function () { this.frm.set_query(
"customer",
function () {
const customer_groups = this.settings?.customer_groups; const customer_groups = this.settings?.customer_groups;
if (!customer_groups?.length) return {}; if (!customer_groups?.length) return {};
@@ -64,9 +70,10 @@ erpnext.selling.POSInvoiceController = class POSInvoiceController extends erpnex
return { return {
filters: { filters: {
customer_group: ["in", customer_groups], customer_group: ["in", customer_groups],
} },
} };
}).bind(this)); }.bind(this)
);
} }
is_pos() { is_pos() {
@@ -74,19 +81,19 @@ erpnext.selling.POSInvoiceController = class POSInvoiceController extends erpnex
} }
async set_pos_data() { async set_pos_data() {
if(this.frm.doc.is_pos) { if (this.frm.doc.is_pos) {
this.frm.set_value("allocate_advances_automatically", 0); this.frm.set_value("allocate_advances_automatically", 0);
if(!this.frm.doc.company) { if (!this.frm.doc.company) {
this.frm.set_value("is_pos", 0); this.frm.set_value("is_pos", 0);
frappe.msgprint(__("Please specify Company to proceed")); frappe.msgprint(__("Please specify Company to proceed"));
} else { } else {
const r = await this.frm.call({ const r = await this.frm.call({
doc: this.frm.doc, doc: this.frm.doc,
method: "set_missing_values", method: "set_missing_values",
freeze: true freeze: true,
}); });
if(!r.exc) { if (!r.exc) {
if(r.message) { if (r.message) {
this.frm.pos_print_format = r.message.print_format || ""; this.frm.pos_print_format = r.message.print_format || "";
this.frm.meta.default_print_format = r.message.print_format || ""; this.frm.meta.default_print_format = r.message.print_format || "";
this.frm.doc.campaign = r.message.campaign; this.frm.doc.campaign = r.message.campaign;
@@ -103,32 +110,36 @@ erpnext.selling.POSInvoiceController = class POSInvoiceController extends erpnex
} }
customer() { customer() {
if (!this.frm.doc.customer) return if (!this.frm.doc.customer) return;
const pos_profile = this.frm.doc.pos_profile; const pos_profile = this.frm.doc.pos_profile;
if(this.frm.updating_party_details) return; if (this.frm.updating_party_details) return;
erpnext.utils.get_party_details(this.frm, erpnext.utils.get_party_details(
"erpnext.accounts.party.get_party_details", { this.frm,
"erpnext.accounts.party.get_party_details",
{
posting_date: this.frm.doc.posting_date, posting_date: this.frm.doc.posting_date,
party: this.frm.doc.customer, party: this.frm.doc.customer,
party_type: "Customer", party_type: "Customer",
account: this.frm.doc.debit_to, account: this.frm.doc.debit_to,
price_list: this.frm.doc.selling_price_list, price_list: this.frm.doc.selling_price_list,
pos_profile: pos_profile, pos_profile: pos_profile,
company_address: this.frm.doc.company_address company_address: this.frm.doc.company_address,
}, () => { },
() => {
this.apply_pricing_rule(); this.apply_pricing_rule();
}); }
);
} }
pos_profile(frm) { pos_profile(frm) {
if (!frm.pos_profile || frm.pos_profile == '') { if (!frm.pos_profile || frm.pos_profile == "") {
this.update_customer_groups_settings([]); this.update_customer_groups_settings([]);
return; return;
} }
frappe.call({ frappe.call({
method: "erpnext.selling.page.point_of_sale.point_of_sale.get_pos_profile_data", method: "erpnext.selling.page.point_of_sale.point_of_sale.get_pos_profile_data",
args: { "pos_profile": frm.pos_profile }, args: { pos_profile: frm.pos_profile },
callback: ({ message: profile }) => { callback: ({ message: profile }) => {
this.update_customer_groups_settings(profile?.customer_groups); this.update_customer_groups_settings(profile?.customer_groups);
this.frm.set_value("company", profile?.company); this.frm.set_value("company", profile?.company);
@@ -137,17 +148,17 @@ erpnext.selling.POSInvoiceController = class POSInvoiceController extends erpnex
} }
update_customer_groups_settings(customer_groups) { update_customer_groups_settings(customer_groups) {
this.settings.customer_groups = customer_groups?.map((group) => group.name) this.settings.customer_groups = customer_groups?.map((group) => group.name);
} }
amount(){ amount() {
this.write_off_outstanding_amount_automatically() this.write_off_outstanding_amount_automatically();
} }
change_amount(){ change_amount() {
if(this.frm.doc.paid_amount > this.frm.doc.grand_total){ if (this.frm.doc.paid_amount > this.frm.doc.grand_total) {
this.calculate_write_off_amount(); this.calculate_write_off_amount();
}else { } else {
this.frm.set_value("change_amount", 0.0); this.frm.set_value("change_amount", 0.0);
this.frm.set_value("base_change_amount", 0.0); this.frm.set_value("base_change_amount", 0.0);
} }
@@ -155,7 +166,7 @@ erpnext.selling.POSInvoiceController = class POSInvoiceController extends erpnex
this.frm.refresh_fields(); this.frm.refresh_fields();
} }
loyalty_amount(){ loyalty_amount() {
this.calculate_outstanding_amount(); this.calculate_outstanding_amount();
this.frm.refresh_field("outstanding_amount"); this.frm.refresh_field("outstanding_amount");
this.frm.refresh_field("paid_amount"); this.frm.refresh_field("paid_amount");
@@ -166,8 +177,12 @@ erpnext.selling.POSInvoiceController = class POSInvoiceController extends erpnex
if (cint(this.frm.doc.write_off_outstanding_amount_automatically)) { if (cint(this.frm.doc.write_off_outstanding_amount_automatically)) {
frappe.model.round_floats_in(this.frm.doc, ["grand_total", "paid_amount"]); frappe.model.round_floats_in(this.frm.doc, ["grand_total", "paid_amount"]);
// this will make outstanding amount 0 // this will make outstanding amount 0
this.frm.set_value("write_off_amount", this.frm.set_value(
flt(this.frm.doc.grand_total - this.frm.doc.paid_amount - this.frm.doc.total_advance, precision("write_off_amount")) "write_off_amount",
flt(
this.frm.doc.grand_total - this.frm.doc.paid_amount - this.frm.doc.total_advance,
precision("write_off_amount")
)
); );
} }
@@ -178,65 +193,69 @@ erpnext.selling.POSInvoiceController = class POSInvoiceController extends erpnex
make_sales_return() { make_sales_return() {
frappe.model.open_mapped_doc({ frappe.model.open_mapped_doc({
method: "erpnext.accounts.doctype.pos_invoice.pos_invoice.make_sales_return", method: "erpnext.accounts.doctype.pos_invoice.pos_invoice.make_sales_return",
frm: cur_frm frm: cur_frm,
}) });
} }
} };
extend_cscript(cur_frm.cscript, new erpnext.selling.POSInvoiceController({ frm: cur_frm })) extend_cscript(cur_frm.cscript, new erpnext.selling.POSInvoiceController({ frm: cur_frm }));
frappe.ui.form.on('POS Invoice', { frappe.ui.form.on("POS Invoice", {
redeem_loyalty_points: function(frm) { redeem_loyalty_points: function (frm) {
frm.events.get_loyalty_details(frm); frm.events.get_loyalty_details(frm);
}, },
loyalty_points: function(frm) { loyalty_points: function (frm) {
if (frm.redemption_conversion_factor) { if (frm.redemption_conversion_factor) {
frm.events.set_loyalty_points(frm); frm.events.set_loyalty_points(frm);
} else { } else {
frappe.call({ frappe.call({
method: "erpnext.accounts.doctype.loyalty_program.loyalty_program.get_redeemption_factor", method: "erpnext.accounts.doctype.loyalty_program.loyalty_program.get_redeemption_factor",
args: { args: {
"loyalty_program": frm.doc.loyalty_program loyalty_program: frm.doc.loyalty_program,
}, },
callback: function(r) { callback: function (r) {
if (r) { if (r) {
frm.redemption_conversion_factor = r.message; frm.redemption_conversion_factor = r.message;
frm.events.set_loyalty_points(frm); frm.events.set_loyalty_points(frm);
} }
} },
}); });
} }
}, },
get_loyalty_details: function(frm) { get_loyalty_details: function (frm) {
if (frm.doc.customer && frm.doc.redeem_loyalty_points) { if (frm.doc.customer && frm.doc.redeem_loyalty_points) {
frappe.call({ frappe.call({
method: "erpnext.accounts.doctype.loyalty_program.loyalty_program.get_loyalty_program_details", method: "erpnext.accounts.doctype.loyalty_program.loyalty_program.get_loyalty_program_details",
args: { args: {
"customer": frm.doc.customer, customer: frm.doc.customer,
"loyalty_program": frm.doc.loyalty_program, loyalty_program: frm.doc.loyalty_program,
"expiry_date": frm.doc.posting_date, expiry_date: frm.doc.posting_date,
"company": frm.doc.company company: frm.doc.company,
}, },
callback: function(r) { callback: function (r) {
if (r) { if (r) {
frm.set_value("loyalty_redemption_account", r.message.expense_account); frm.set_value("loyalty_redemption_account", r.message.expense_account);
frm.set_value("loyalty_redemption_cost_center", r.message.cost_center); frm.set_value("loyalty_redemption_cost_center", r.message.cost_center);
frm.redemption_conversion_factor = r.message.conversion_factor; frm.redemption_conversion_factor = r.message.conversion_factor;
} }
} },
}); });
} }
}, },
set_loyalty_points: function(frm) { set_loyalty_points: function (frm) {
if (frm.redemption_conversion_factor) { if (frm.redemption_conversion_factor) {
let loyalty_amount = flt(frm.redemption_conversion_factor*flt(frm.doc.loyalty_points), precision("loyalty_amount")); let loyalty_amount = flt(
var remaining_amount = flt(frm.doc.grand_total) - flt(frm.doc.total_advance) - flt(frm.doc.write_off_amount); frm.redemption_conversion_factor * flt(frm.doc.loyalty_points),
if (frm.doc.grand_total && (remaining_amount < loyalty_amount)) { precision("loyalty_amount")
let redeemable_points = parseInt(remaining_amount/frm.redemption_conversion_factor); );
frappe.throw(__("You can only redeem max {0} points in this order.",[redeemable_points])); var remaining_amount =
flt(frm.doc.grand_total) - flt(frm.doc.total_advance) - flt(frm.doc.write_off_amount);
if (frm.doc.grand_total && remaining_amount < loyalty_amount) {
let redeemable_points = parseInt(remaining_amount / frm.redemption_conversion_factor);
frappe.throw(__("You can only redeem max {0} points in this order.", [redeemable_points]));
} }
frm.set_value("loyalty_amount", loyalty_amount); frm.set_value("loyalty_amount", loyalty_amount);
} }
@@ -244,29 +263,33 @@ frappe.ui.form.on('POS Invoice', {
request_for_payment: function (frm) { request_for_payment: function (frm) {
if (!frm.doc.contact_mobile) { if (!frm.doc.contact_mobile) {
frappe.throw(__('Please enter mobile number first.')); frappe.throw(__("Please enter mobile number first."));
} }
frm.dirty(); frm.dirty();
frm.save().then(() => { frm.save().then(() => {
frappe.dom.freeze(__('Waiting for payment...')); frappe.dom.freeze(__("Waiting for payment..."));
frappe frappe
.call({ .call({
method: 'create_payment_request', method: "create_payment_request",
doc: frm.doc doc: frm.doc,
}) })
.fail(() => { .fail(() => {
frappe.dom.unfreeze(); frappe.dom.unfreeze();
frappe.msgprint(__('Payment request failed')); frappe.msgprint(__("Payment request failed"));
}) })
.then(({ message }) => { .then(({ message }) => {
const payment_request_name = message.name; const payment_request_name = message.name;
setTimeout(() => { setTimeout(() => {
frappe.db.get_value('Payment Request', payment_request_name, ['status', 'grand_total']).then(({ message }) => { frappe.db
if (message.status != 'Paid') { .get_value("Payment Request", payment_request_name, ["status", "grand_total"])
.then(({ message }) => {
if (message.status != "Paid") {
frappe.dom.unfreeze(); frappe.dom.unfreeze();
frappe.msgprint({ frappe.msgprint({
message: __('Payment Request took too long to respond. Please try requesting for payment again.'), message: __(
title: __('Request Timeout') "Payment Request took too long to respond. Please try requesting for payment again."
),
title: __("Request Timeout"),
}); });
} else if (frappe.dom.freeze_count != 0) { } else if (frappe.dom.freeze_count != 0) {
frappe.dom.unfreeze(); frappe.dom.unfreeze();
@@ -274,13 +297,15 @@ frappe.ui.form.on('POS Invoice', {
cur_pos.payment.events.submit_invoice(); cur_pos.payment.events.submit_invoice();
frappe.show_alert({ frappe.show_alert({
message: __("Payment of {0} received successfully.", [format_currency(message.grand_total, frm.doc.currency, 0)]), message: __("Payment of {0} received successfully.", [
indicator: 'green' format_currency(message.grand_total, frm.doc.currency, 0),
]),
indicator: "green",
}); });
} }
}); });
}, 60000); }, 60000);
}); });
}); });
} },
}); });

View File

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

View File

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

View File

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

View File

@@ -2,15 +2,14 @@
// License: GNU General Public License v3. See license.txt // License: GNU General Public License v3. See license.txt
// render // render
frappe.listview_settings['POS Opening Entry'] = { frappe.listview_settings["POS Opening Entry"] = {
get_indicator: function(doc) { get_indicator: function (doc) {
var status_color = { var status_color = {
"Draft": "red", Draft: "red",
"Open": "orange", Open: "orange",
"Closed": "green", Closed: "green",
"Cancelled": "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

@@ -1,149 +1,143 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors // Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt // License: GNU General Public License v3. See license.txt
frappe.ui.form.on('POS Profile', { frappe.ui.form.on("POS Profile", {
setup: function(frm) { setup: function (frm) {
frm.set_query("selling_price_list", function() { frm.set_query("selling_price_list", function () {
return { filters: { selling: 1 } }; return { filters: { selling: 1 } };
}); });
frm.set_query("tc_name", function() { frm.set_query("tc_name", function () {
return { filters: { selling: 1 } }; return { filters: { selling: 1 } };
}); });
erpnext.queries.setup_queries(frm, "Warehouse", function() { erpnext.queries.setup_queries(frm, "Warehouse", function () {
return erpnext.queries.warehouse(frm.doc); return erpnext.queries.warehouse(frm.doc);
}); });
frm.set_query("print_format", function() { frm.set_query("print_format", function () {
return { return {
filters: [ filters: [["Print Format", "doc_type", "=", "POS Invoice"]],
['Print Format', 'doc_type', '=', 'POS Invoice']
]
}; };
}); });
frm.set_query("account_for_change_amount", function(doc) { frm.set_query("account_for_change_amount", function (doc) {
if (!doc.company) { if (!doc.company) {
frappe.throw(__('Please set Company')); frappe.throw(__("Please set Company"));
} }
return { return {
filters: { filters: {
account_type: ['in', ["Cash", "Bank"]], account_type: ["in", ["Cash", "Bank"]],
is_group: 0, is_group: 0,
company: doc.company company: doc.company,
} },
}; };
}); });
frm.set_query("taxes_and_charges", function() { frm.set_query("taxes_and_charges", function () {
return { return {
filters: [ filters: [
['Sales Taxes and Charges Template', 'company', '=', frm.doc.company], ["Sales Taxes and Charges Template", "company", "=", frm.doc.company],
['Sales Taxes and Charges Template', 'docstatus', '!=', 2] ["Sales Taxes and Charges Template", "docstatus", "!=", 2],
] ],
}; };
}); });
frm.set_query('company_address', function(doc) { frm.set_query("company_address", function (doc) {
if (!doc.company) { if (!doc.company) {
frappe.throw(__('Please set Company')); frappe.throw(__("Please set Company"));
} }
return { return {
query: 'frappe.contacts.doctype.address.address.address_query', query: "frappe.contacts.doctype.address.address.address_query",
filters: { filters: {
link_doctype: 'Company', link_doctype: "Company",
link_name: doc.company link_name: doc.company,
} },
}; };
}); });
frm.set_query('income_account', function(doc) { frm.set_query("income_account", function (doc) {
if (!doc.company) { if (!doc.company) {
frappe.throw(__('Please set Company')); frappe.throw(__("Please set Company"));
} }
return { return {
filters: { filters: {
'is_group': 0, is_group: 0,
'company': doc.company, company: doc.company,
'account_type': "Income Account" account_type: "Income Account",
} },
}; };
}); });
frm.set_query('cost_center', function(doc) { frm.set_query("cost_center", function (doc) {
if (!doc.company) { if (!doc.company) {
frappe.throw(__('Please set Company')); frappe.throw(__("Please set Company"));
} }
return { return {
filters: { filters: {
'company': doc.company, company: doc.company,
'is_group': 0 is_group: 0,
} },
}; };
}); });
frm.set_query('expense_account', function(doc) { frm.set_query("expense_account", function (doc) {
if (!doc.company) { if (!doc.company) {
frappe.throw(__('Please set Company')); frappe.throw(__("Please set Company"));
} }
return { return {
filters: { filters: {
"report_type": "Profit and Loss", report_type: "Profit and Loss",
"company": doc.company, company: doc.company,
"is_group": 0 is_group: 0,
} },
}; };
}); });
frm.set_query("select_print_heading", function() { frm.set_query("select_print_heading", function () {
return { return {
filters: [ filters: [["Print Heading", "docstatus", "!=", 2]],
['Print Heading', 'docstatus', '!=', 2]
]
}; };
}); });
frm.set_query("write_off_account", function(doc) { frm.set_query("write_off_account", function (doc) {
return { return {
filters: { filters: {
'report_type': 'Profit and Loss', report_type: "Profit and Loss",
'is_group': 0, is_group: 0,
'company': doc.company company: doc.company,
} },
}; };
}); });
frm.set_query("write_off_cost_center", function(doc) { frm.set_query("write_off_cost_center", function (doc) {
return { return {
filters: { filters: {
'is_group': 0, is_group: 0,
'company': doc.company company: doc.company,
} },
}; };
}); });
erpnext.accounts.dimensions.setup_dimension_filters(frm, frm.doctype); erpnext.accounts.dimensions.setup_dimension_filters(frm, frm.doctype);
}, },
refresh: function(frm) { refresh: function (frm) {
if (frm.doc.company) { if (frm.doc.company) {
frm.trigger("toggle_display_account_head"); frm.trigger("toggle_display_account_head");
} }
}, },
company: function(frm) { company: function (frm) {
frm.trigger("toggle_display_account_head"); frm.trigger("toggle_display_account_head");
erpnext.accounts.dimensions.update_dimension(frm, frm.doctype); erpnext.accounts.dimensions.update_dimension(frm, frm.doctype);
}, },
toggle_display_account_head: function(frm) { toggle_display_account_head: function (frm) {
frm.toggle_display('expense_account', frm.toggle_display("expense_account", erpnext.is_perpetual_inventory_enabled(frm.doc.company));
erpnext.is_perpetual_inventory_enabled(frm.doc.company)); },
}
}); });

View File

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

View File

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

View File

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

View File

@@ -2,129 +2,128 @@
// For license information, please see license.txt // For license information, please see license.txt
frappe.ui.form.on("Process Payment Reconciliation", { frappe.ui.form.on("Process Payment Reconciliation", {
onload: function(frm) { onload: function (frm) {
// set queries // set queries
frm.set_query("party_type", function() { 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) {
return { return {
filters: { filters: {
"company": doc.company, name: ["in", Object.keys(frappe.boot.party_account_types)],
"is_group": 0,
"account_type": frappe.boot.party_account_types[doc.party_type]
}
};
});
frm.set_query('cost_center', function(doc) {
return {
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") frm.set_query("receivable_payable_account", function (doc) {
return {
filters: {
company: doc.company,
is_group: 0,
account_type: frappe.boot.party_account_types[doc.party_type],
},
};
});
frm.set_query("cost_center", function (doc) {
return {
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");
frm.add_custom_button(execute_btn, () => { frm.add_custom_button(execute_btn, () => {
frm.call({ 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: { args: {
docname: frm.doc.name docname: frm.doc.name,
} },
}).then(r => { }).then((r) => {
if(!r.exc) { if (!r.exc) {
frappe.show_alert(__("Job Started")); frappe.show_alert(__("Job Started"));
frm.reload_doc(); 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({ 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: { args: {
"docname": frm.docname, docname: frm.docname,
} },
}).then(r => { }).then((r) => {
if (r.message) { if (r.message) {
let progress = 0; let progress = 0;
let description = ""; let description = "";
if (r.message.processed) { if (r.message.processed) {
progress = (r.message.processed/r.message.total) * 100; progress = (r.message.processed / r.message.total) * 100;
description = r.message.processed + "/" + r.message.total + " processed"; description = r.message.processed + "/" + r.message.total + " processed";
} else if (r.message.total == 0 && frm.doc.status == "Completed") { } else if (r.message.total == 0 && frm.doc.status == "Completed") {
progress = 100; 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') { if (frm.doc.docstatus == 1 && frm.doc.status == "Running") {
let execute_btn = __("Pause") let execute_btn = __("Pause");
frm.add_custom_button(execute_btn, () => { frm.add_custom_button(execute_btn, () => {
frm.call({ 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: { args: {
"docname": frm.docname, docname: frm.docname,
} },
}).then(r => { }).then((r) => {
if (!r.exc) { if (!r.exc) {
frappe.show_alert(__("Job Paused")); frappe.show_alert(__("Job Paused"));
frm.reload_doc() frm.reload_doc();
} }
}); });
}); });
} }
}, },
company(frm) { company(frm) {
frm.set_value('party', ''); frm.set_value("party", "");
frm.set_value('receivable_payable_account', ''); frm.set_value("receivable_payable_account", "");
}, },
party_type(frm) { party_type(frm) {
frm.set_value('party', ''); frm.set_value("party", "");
}, },
party(frm) { 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) { if (!frm.doc.receivable_payable_account && frm.doc.party_type && frm.doc.party) {
return frappe.call({ return frappe.call({
method: "erpnext.accounts.party.get_party_account", method: "erpnext.accounts.party.get_party_account",
args: { args: {
company: frm.doc.company, company: frm.doc.company,
party_type: frm.doc.party_type, party_type: frm.doc.party_type,
party: frm.doc.party party: frm.doc.party,
}, },
callback: (r) => { callback: (r) => {
if (!r.exc && r.message) { if (!r.exc && r.message) {
frm.set_value("receivable_payable_account", r.message); frm.set_value("receivable_payable_account", r.message);
} }
frm.refresh(); frm.refresh();
},
}
}); });
} }
} },
}); });

View File

@@ -1,15 +1,15 @@
frappe.listview_settings['Process Payment Reconciliation'] = { frappe.listview_settings["Process Payment Reconciliation"] = {
add_fields: ["status"], add_fields: ["status"],
get_indicator: function(doc) { get_indicator: function (doc) {
let colors = { let colors = {
'Queued': 'orange', Queued: "orange",
'Paused': 'orange', Paused: "orange",
'Completed': 'green', Completed: "green",
'Partially Reconciled': 'orange', "Partially Reconciled": "orange",
'Running': 'blue', Running: "blue",
'Failed': 'red', Failed: "red",
}; };
let status = doc.status; 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", { frappe.ui.form.on("Process Payment Reconciliation Log", {
refresh(frm) { 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; let progress = 0;
if (frm.doc.reconciled_entries != 0) { if (frm.doc.reconciled_entries != 0) {
progress = frm.doc.reconciled_entries / frm.doc.total_allocations * 100; progress = (frm.doc.reconciled_entries / frm.doc.total_allocations) * 100;
} else if(frm.doc.total_allocations == 0 && frm.doc.status == "Completed"){ } else if (frm.doc.total_allocations == 0 && frm.doc.status == "Completed") {
progress = 100; 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"], add_fields: ["status"],
get_indicator: function(doc) { get_indicator: function (doc) {
var colors = { var colors = {
'Partially Reconciled': 'orange', "Partially Reconciled": "orange",
'Paused': 'orange', Paused: "orange",
'Reconciled': 'green', Reconciled: "green",
'Failed': 'red', Failed: "red",
'Cancelled': 'red', Cancelled: "red",
'Running': 'blue', Running: "blue",
}; };
let status = doc.status; let status = doc.status;
return [__(status), colors[status], "status,=,"+status]; return [__(status), colors[status], "status,=," + status];
}, },
}; };

View File

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

View File

@@ -455,11 +455,16 @@ def send_emails(document_name, from_scheduler=False, posting_date=None):
subject = frappe.render_template(doc.subject, context) subject = frappe.render_template(doc.subject, context)
message = frappe.render_template(doc.body, 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( frappe.enqueue(
queue="short", queue="short",
method=frappe.sendmail, method=frappe.sendmail,
recipients=recipients, recipients=recipients,
sender=doc.sender or frappe.session.user, sender=sender_email,
cc=cc, cc=cc,
subject=subject, subject=subject,
message=message, message=message,

View File

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

View File

@@ -60,6 +60,8 @@ product_discount_fields = [
"free_item_rate", "free_item_rate",
"same_item", "same_item",
"is_recursive", "is_recursive",
"recurse_for",
"apply_recursion_over",
"apply_multiple_pricing_rules", "apply_multiple_pricing_rules",
] ]

View File

@@ -107,6 +107,28 @@ class TestPromotionalScheme(unittest.TestCase):
price_rules = frappe.get_all("Pricing Rule", filters={"promotional_scheme": ps.name}) price_rules = frappe.get_all("Pricing Rule", filters={"promotional_scheme": ps.name})
self.assertEqual(price_rules, []) self.assertEqual(price_rules, [])
def test_pricing_rule_for_product_discount_slabs(self):
ps = make_promotional_scheme()
ps.set("price_discount_slabs", [])
ps.set(
"product_discount_slabs",
[
{
"rule_description": "12+1",
"min_qty": 12,
"free_item": "_Test Item 2",
"free_qty": 1,
"is_recursive": 1,
"recurse_for": 12,
}
],
)
ps.save()
pr = frappe.get_doc("Pricing Rule", {"promotional_scheme_id": ps.product_discount_slabs[0].name})
self.assertSequenceEqual(
[pr.min_qty, pr.free_item, pr.free_qty, pr.recurse_for], [12, "_Test Item 2", 1, 12]
)
def make_promotional_scheme(**args): def make_promotional_scheme(**args):
args = frappe._dict(args) args = frappe._dict(args)

View File

@@ -27,7 +27,9 @@
"threshold_percentage", "threshold_percentage",
"column_break_15", "column_break_15",
"priority", "priority",
"is_recursive" "is_recursive",
"recurse_for",
"apply_recursion_over"
], ],
"fields": [ "fields": [
{ {
@@ -161,17 +163,36 @@
"fieldname": "is_recursive", "fieldname": "is_recursive",
"fieldtype": "Check", "fieldtype": "Check",
"label": "Is Recursive" "label": "Is Recursive"
},
{
"default": "0",
"depends_on": "is_recursive",
"description": "Give free item for every N quantity",
"fieldname": "recurse_for",
"fieldtype": "Float",
"label": "Recurse Every (As Per Transaction UOM)",
"mandatory_depends_on": "is_recursive"
},
{
"default": "0",
"depends_on": "is_recursive",
"description": "Qty for which recursion isn't applicable.",
"fieldname": "apply_recursion_over",
"fieldtype": "Float",
"label": "Apply Recursion Over (As Per Transaction UOM)",
"mandatory_depends_on": "is_recursive"
} }
], ],
"index_web_pages_for_search": 1, "index_web_pages_for_search": 1,
"istable": 1, "istable": 1,
"links": [], "links": [],
"modified": "2021-03-06 21:58:18.162346", "modified": "2024-03-12 12:53:58.199108",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Accounts", "module": "Accounts",
"name": "Promotional Scheme Product Discount", "name": "Promotional Scheme Product Discount",
"owner": "Administrator", "owner": "Administrator",
"permissions": [], "permissions": [],
"sort_field": "modified", "sort_field": "modified",
"sort_order": "DESC" "sort_order": "DESC",
"states": []
} }

View File

@@ -15,6 +15,7 @@ class PromotionalSchemeProductDiscount(Document):
from frappe.types import DF from frappe.types import DF
apply_multiple_pricing_rules: DF.Check apply_multiple_pricing_rules: DF.Check
apply_recursion_over: DF.Float
disable: DF.Check disable: DF.Check
free_item: DF.Link | None free_item: DF.Link | None
free_item_rate: DF.Currency free_item_rate: DF.Currency
@@ -51,6 +52,7 @@ class PromotionalSchemeProductDiscount(Document):
"19", "19",
"20", "20",
] ]
recurse_for: DF.Float
rule_description: DF.SmallText rule_description: DF.SmallText
same_item: DF.Check same_item: DF.Check
threshold_percentage: DF.Percent threshold_percentage: DF.Percent

View File

@@ -14,19 +14,19 @@ erpnext.accounts.PurchaseInvoice = class PurchaseInvoice extends erpnext.buying.
super.setup(doc); super.setup(doc);
// formatter for purchase invoice item // formatter for purchase invoice item
if(this.frm.doc.update_stock) { if (this.frm.doc.update_stock) {
this.frm.set_indicator_formatter('item_code', function(doc) { this.frm.set_indicator_formatter("item_code", function (doc) {
return (doc.qty<=doc.received_qty) ? "green" : "orange"; return doc.qty <= doc.received_qty ? "green" : "orange";
}); });
} }
this.frm.set_query("unrealized_profit_loss_account", function() { this.frm.set_query("unrealized_profit_loss_account", function () {
return { return {
filters: { filters: {
company: doc.company, company: doc.company,
is_group: 0, is_group: 0,
root_type: "Liability", root_type: "Liability",
} },
}; };
}); });
} }
@@ -47,9 +47,9 @@ erpnext.accounts.PurchaseInvoice = class PurchaseInvoice extends erpnext.buying.
"Bank Transaction", "Bank Transaction",
]; ];
if(!this.frm.doc.__islocal) { if (!this.frm.doc.__islocal) {
// show credit_to in print format // show credit_to in print format
if(!this.frm.doc.supplier && this.frm.doc.credit_to) { if (!this.frm.doc.supplier && this.frm.doc.credit_to) {
this.frm.set_df_property("credit_to", "print_hide", 0); this.frm.set_df_property("credit_to", "print_hide", 0);
} }
} }
@@ -57,7 +57,7 @@ erpnext.accounts.PurchaseInvoice = class PurchaseInvoice extends erpnext.buying.
// Trigger supplier event on load if supplier is available // Trigger supplier event on load if supplier is available
// The reason for this is PI can be created from PR or PO and supplier is pre populated // The reason for this is PI can be created from PR or PO and supplier is pre populated
if (this.frm.doc.supplier && this.frm.doc.__islocal) { if (this.frm.doc.supplier && this.frm.doc.__islocal) {
this.frm.trigger('supplier'); this.frm.trigger("supplier");
} }
} }
@@ -70,116 +70,137 @@ erpnext.accounts.PurchaseInvoice = class PurchaseInvoice extends erpnext.buying.
this.show_general_ledger(); this.show_general_ledger();
erpnext.accounts.ledger_preview.show_accounting_ledger_preview(this.frm); erpnext.accounts.ledger_preview.show_accounting_ledger_preview(this.frm);
if(doc.update_stock==1) { if (doc.update_stock == 1) {
this.show_stock_ledger(); this.show_stock_ledger();
erpnext.accounts.ledger_preview.show_stock_ledger_preview(this.frm); erpnext.accounts.ledger_preview.show_stock_ledger_preview(this.frm);
} }
if (this.frm.doc.repost_required && this.frm.doc.docstatus===1) { if (this.frm.doc.repost_required && this.frm.doc.docstatus === 1) {
this.frm.set_intro(__("Accounting entries for this invoice need to be reposted. Please click on 'Repost' button to update.")); this.frm.set_intro(
this.frm.add_custom_button(__('Repost Accounting Entries'), __(
() => { "Accounting entries for this invoice need to be reposted. Please click on 'Repost' button to update."
)
);
this.frm
.add_custom_button(__("Repost Accounting Entries"), () => {
this.frm.call({ this.frm.call({
doc: this.frm.doc, doc: this.frm.doc,
method: 'repost_accounting_entries', method: "repost_accounting_entries",
freeze: true, freeze: true,
freeze_message: __('Reposting...'), freeze_message: __("Reposting..."),
callback: (r) => { callback: (r) => {
if (!r.exc) { if (!r.exc) {
frappe.msgprint(__('Accounting Entries are reposted.')); frappe.msgprint(__("Accounting Entries are reposted."));
me.frm.refresh(); me.frm.refresh();
} }
} },
}); });
}).removeClass('btn-default').addClass('btn-warning'); })
.removeClass("btn-default")
.addClass("btn-warning");
} }
if(!doc.is_return && doc.docstatus == 1 && doc.outstanding_amount != 0){ if (!doc.is_return && doc.docstatus == 1 && doc.outstanding_amount != 0) {
if(doc.on_hold) { if (doc.on_hold) {
this.frm.add_custom_button( this.frm.add_custom_button(
__('Change Release Date'), __("Change Release Date"),
function() {me.change_release_date()}, function () {
__('Hold Invoice') me.change_release_date();
},
__("Hold Invoice")
); );
this.frm.add_custom_button( this.frm.add_custom_button(
__('Unblock Invoice'), __("Unblock Invoice"),
function() {me.unblock_invoice()}, function () {
__('Create') me.unblock_invoice();
},
__("Create")
); );
} else if (!doc.on_hold) { } else if (!doc.on_hold) {
this.frm.add_custom_button( this.frm.add_custom_button(
__('Block Invoice'), __("Block Invoice"),
function() {me.block_invoice()}, function () {
__('Create') me.block_invoice();
},
__("Create")
); );
} }
} }
if(doc.docstatus == 1 && doc.outstanding_amount != 0 && !doc.on_hold) { if (doc.docstatus == 1 && doc.outstanding_amount != 0 && !doc.on_hold) {
this.frm.add_custom_button( this.frm.add_custom_button(__("Payment"), () => this.make_payment_entry(), __("Create"));
__('Payment'), cur_frm.page.set_inner_btn_group_as_primary(__("Create"));
() => this.make_payment_entry(),
__('Create')
);
cur_frm.page.set_inner_btn_group_as_primary(__('Create'));
} }
if(!doc.is_return && doc.docstatus==1) { if (!doc.is_return && doc.docstatus == 1) {
if(doc.outstanding_amount >= 0 || Math.abs(flt(doc.outstanding_amount)) < flt(doc.grand_total)) { if (doc.outstanding_amount >= 0 || Math.abs(flt(doc.outstanding_amount)) < flt(doc.grand_total)) {
cur_frm.add_custom_button(__('Return / Debit Note'), cur_frm.add_custom_button(__("Return / Debit Note"), this.make_debit_note, __("Create"));
this.make_debit_note, __('Create'));
} }
} }
if (doc.outstanding_amount > 0 && !cint(doc.is_return) && !doc.on_hold) { if (doc.outstanding_amount > 0 && !cint(doc.is_return) && !doc.on_hold) {
cur_frm.add_custom_button(__('Payment Request'), function() { cur_frm.add_custom_button(
me.make_payment_request() __("Payment Request"),
}, __('Create')); function () {
me.make_payment_request();
},
__("Create")
);
} }
if(doc.docstatus===0) { if (doc.docstatus === 0) {
this.frm.add_custom_button(__('Purchase Order'), function() { this.frm.add_custom_button(
__("Purchase Order"),
function () {
erpnext.utils.map_current_doc({ erpnext.utils.map_current_doc({
method: "erpnext.buying.doctype.purchase_order.purchase_order.make_purchase_invoice", method: "erpnext.buying.doctype.purchase_order.purchase_order.make_purchase_invoice",
source_doctype: "Purchase Order", source_doctype: "Purchase Order",
target: me.frm, target: me.frm,
setters: { setters: {
supplier: me.frm.doc.supplier || undefined, supplier: me.frm.doc.supplier || undefined,
schedule_date: undefined schedule_date: undefined,
}, },
get_query_filters: { get_query_filters: {
docstatus: 1, docstatus: 1,
status: ["not in", ["Closed", "On Hold"]], status: ["not in", ["Closed", "On Hold"]],
per_billed: ["<", 99.99], per_billed: ["<", 99.99],
company: me.frm.doc.company company: me.frm.doc.company,
} },
}) });
}, __("Get Items From")); },
__("Get Items From")
);
this.frm.add_custom_button(__('Purchase Receipt'), function() { this.frm.add_custom_button(
__("Purchase Receipt"),
function () {
erpnext.utils.map_current_doc({ erpnext.utils.map_current_doc({
method: "erpnext.stock.doctype.purchase_receipt.purchase_receipt.make_purchase_invoice", method: "erpnext.stock.doctype.purchase_receipt.purchase_receipt.make_purchase_invoice",
source_doctype: "Purchase Receipt", source_doctype: "Purchase Receipt",
target: me.frm, target: me.frm,
setters: { setters: {
supplier: me.frm.doc.supplier || undefined, supplier: me.frm.doc.supplier || undefined,
posting_date: undefined posting_date: undefined,
}, },
get_query_filters: { get_query_filters: {
docstatus: 1, docstatus: 1,
status: ["not in", ["Closed", "Completed", "Return Issued"]], status: ["not in", ["Closed", "Completed", "Return Issued"]],
company: me.frm.doc.company, company: me.frm.doc.company,
is_return: 0 is_return: 0,
} },
}) });
}, __("Get Items From")); },
__("Get Items From")
);
if (!this.frm.doc.is_return) { if (!this.frm.doc.is_return) {
frappe.db.get_single_value("Buying Settings", "maintain_same_rate").then((value) => { frappe.db.get_single_value("Buying Settings", "maintain_same_rate").then((value) => {
if (value) { if (value) {
this.frm.doc.items.forEach((item) => { this.frm.doc.items.forEach((item) => {
this.frm.fields_dict.items.grid.update_docfield_property( this.frm.fields_dict.items.grid.update_docfield_property(
"rate", "read_only", (item.purchase_receipt && item.pr_detail) "rate",
"read_only",
item.purchase_receipt && item.pr_detail
); );
}); });
} }
@@ -189,14 +210,18 @@ erpnext.accounts.PurchaseInvoice = class PurchaseInvoice extends erpnext.buying.
this.frm.toggle_reqd("supplier_warehouse", this.frm.doc.is_subcontracted); this.frm.toggle_reqd("supplier_warehouse", this.frm.doc.is_subcontracted);
if (doc.docstatus == 1 && !doc.inter_company_invoice_reference) { if (doc.docstatus == 1 && !doc.inter_company_invoice_reference) {
frappe.model.with_doc("Supplier", me.frm.doc.supplier, function() { frappe.model.with_doc("Supplier", me.frm.doc.supplier, function () {
var supplier = frappe.model.get_doc("Supplier", me.frm.doc.supplier); var supplier = frappe.model.get_doc("Supplier", me.frm.doc.supplier);
var internal = supplier.is_internal_supplier; var internal = supplier.is_internal_supplier;
var disabled = supplier.disabled; var disabled = supplier.disabled;
if (internal == 1 && disabled == 0) { if (internal == 1 && disabled == 0) {
me.frm.add_custom_button("Inter Company Invoice", function() { me.frm.add_custom_button(
"Inter Company Invoice",
function () {
me.make_inter_company_invoice(me.frm); me.make_inter_company_invoice(me.frm);
}, __('Create')); },
__("Create")
);
} }
}); });
} }
@@ -208,9 +233,9 @@ erpnext.accounts.PurchaseInvoice = class PurchaseInvoice extends erpnext.buying.
unblock_invoice() { unblock_invoice() {
const me = this; const me = this;
frappe.call({ frappe.call({
'method': 'erpnext.accounts.doctype.purchase_invoice.purchase_invoice.unblock_invoice', method: "erpnext.accounts.doctype.purchase_invoice.purchase_invoice.unblock_invoice",
'args': {'name': me.frm.doc.name}, args: { name: me.frm.doc.name },
'callback': (r) => me.frm.reload_doc() callback: (r) => me.frm.reload_doc(),
}); });
} }
@@ -225,50 +250,50 @@ erpnext.accounts.PurchaseInvoice = class PurchaseInvoice extends erpnext.buying.
can_change_release_date(date) { can_change_release_date(date) {
const diff = frappe.datetime.get_diff(date, frappe.datetime.nowdate()); const diff = frappe.datetime.get_diff(date, frappe.datetime.nowdate());
if (diff < 0) { if (diff < 0) {
frappe.throw(__('New release date should be in the future')); frappe.throw(__("New release date should be in the future"));
return false; return false;
} else { } else {
return true; return true;
} }
} }
make_comment_dialog_and_block_invoice(){ make_comment_dialog_and_block_invoice() {
const me = this; const me = this;
const title = __('Block Invoice'); const title = __("Block Invoice");
const fields = [ const fields = [
{ {
fieldname: 'release_date', fieldname: "release_date",
read_only: 0, read_only: 0,
fieldtype:'Date', fieldtype: "Date",
label: __('Release Date'), label: __("Release Date"),
default: me.frm.doc.release_date, default: me.frm.doc.release_date,
reqd: 1 reqd: 1,
}, },
{ {
fieldname: 'hold_comment', fieldname: "hold_comment",
read_only: 0, read_only: 0,
fieldtype:'Small Text', fieldtype: "Small Text",
label: __('Reason For Putting On Hold'), label: __("Reason For Putting On Hold"),
default: "" default: "",
}, },
]; ];
this.dialog = new frappe.ui.Dialog({ this.dialog = new frappe.ui.Dialog({
title: title, title: title,
fields: fields fields: fields,
}); });
this.dialog.set_primary_action(__('Save'), function() { this.dialog.set_primary_action(__("Save"), function () {
const dialog_data = me.dialog.get_values(); const dialog_data = me.dialog.get_values();
frappe.call({ frappe.call({
'method': 'erpnext.accounts.doctype.purchase_invoice.purchase_invoice.block_invoice', method: "erpnext.accounts.doctype.purchase_invoice.purchase_invoice.block_invoice",
'args': { args: {
'name': me.frm.doc.name, name: me.frm.doc.name,
'hold_comment': dialog_data.hold_comment, hold_comment: dialog_data.hold_comment,
'release_date': dialog_data.release_date release_date: dialog_data.release_date,
}, },
'callback': (r) => me.frm.reload_doc() callback: (r) => me.frm.reload_doc(),
}); });
me.dialog.hide(); me.dialog.hide();
}); });
@@ -279,25 +304,25 @@ erpnext.accounts.PurchaseInvoice = class PurchaseInvoice extends erpnext.buying.
make_dialog_and_set_release_date() { make_dialog_and_set_release_date() {
const me = this; const me = this;
const title = __('Set New Release Date'); const title = __("Set New Release Date");
const fields = [ const fields = [
{ {
fieldname: 'release_date', fieldname: "release_date",
read_only: 0, read_only: 0,
fieldtype:'Date', fieldtype: "Date",
label: __('Release Date'), label: __("Release Date"),
default: me.frm.doc.release_date default: me.frm.doc.release_date,
}, },
]; ];
this.dialog = new frappe.ui.Dialog({ this.dialog = new frappe.ui.Dialog({
title: title, title: title,
fields: fields fields: fields,
}); });
this.dialog.set_primary_action(__('Save'), function() { this.dialog.set_primary_action(__("Save"), function () {
me.dialog_data = me.dialog.get_values(); me.dialog_data = me.dialog.get_values();
if(me.can_change_release_date(me.dialog_data.release_date)) { if (me.can_change_release_date(me.dialog_data.release_date)) {
me.dialog_data.name = me.frm.doc.name; me.dialog_data.name = me.frm.doc.name;
me.set_release_date(me.dialog_data); me.set_release_date(me.dialog_data);
me.dialog.hide(); me.dialog.hide();
@@ -309,9 +334,9 @@ erpnext.accounts.PurchaseInvoice = class PurchaseInvoice extends erpnext.buying.
set_release_date(data) { set_release_date(data) {
return frappe.call({ return frappe.call({
'method': 'erpnext.accounts.doctype.purchase_invoice.purchase_invoice.change_release_date', method: "erpnext.accounts.doctype.purchase_invoice.purchase_invoice.change_release_date",
'args': data, args: data,
'callback': (r) => this.frm.reload_doc() callback: (r) => this.frm.reload_doc(),
}); });
} }
@@ -319,12 +344,13 @@ erpnext.accounts.PurchaseInvoice = class PurchaseInvoice extends erpnext.buying.
var me = this; var me = this;
// Do not update if inter company reference is there as the details will already be updated // Do not update if inter company reference is there as the details will already be updated
if(this.frm.updating_party_details || this.frm.doc.inter_company_invoice_reference) if (this.frm.updating_party_details || this.frm.doc.inter_company_invoice_reference) return;
return;
if (this.frm.doc.__onload && this.frm.doc.__onload.load_after_mapping) return; if (this.frm.doc.__onload && this.frm.doc.__onload.load_after_mapping) return;
erpnext.utils.get_party_details(this.frm, "erpnext.accounts.party.get_party_details", erpnext.utils.get_party_details(
this.frm,
"erpnext.accounts.party.get_party_details",
{ {
posting_date: this.frm.doc.posting_date, posting_date: this.frm.doc.posting_date,
bill_date: this.frm.doc.bill_date, bill_date: this.frm.doc.bill_date,
@@ -332,21 +358,23 @@ erpnext.accounts.PurchaseInvoice = class PurchaseInvoice extends erpnext.buying.
party_type: "Supplier", party_type: "Supplier",
account: this.frm.doc.credit_to, account: this.frm.doc.credit_to,
price_list: this.frm.doc.buying_price_list, price_list: this.frm.doc.buying_price_list,
fetch_payment_terms_template: cint(!this.frm.doc.ignore_default_payment_terms_template) fetch_payment_terms_template: cint(!this.frm.doc.ignore_default_payment_terms_template),
}, function() { },
function () {
me.apply_pricing_rule(); me.apply_pricing_rule();
me.frm.doc.apply_tds = me.frm.supplier_tds ? 1 : 0; me.frm.doc.apply_tds = me.frm.supplier_tds ? 1 : 0;
me.frm.doc.tax_withholding_category = me.frm.supplier_tds; me.frm.doc.tax_withholding_category = me.frm.supplier_tds;
me.frm.set_df_property("apply_tds", "read_only", me.frm.supplier_tds ? 0 : 1); me.frm.set_df_property("apply_tds", "read_only", me.frm.supplier_tds ? 0 : 1);
me.frm.set_df_property("tax_withholding_category", "hidden", me.frm.supplier_tds ? 0 : 1); me.frm.set_df_property("tax_withholding_category", "hidden", me.frm.supplier_tds ? 0 : 1);
}) }
);
} }
apply_tds(frm) { apply_tds(frm) {
var me = this; var me = this;
me.frm.set_value("tax_withheld_vouchers", []); me.frm.set_value("tax_withheld_vouchers", []);
if (!me.frm.doc.apply_tds) { if (!me.frm.doc.apply_tds) {
me.frm.set_value("tax_withholding_category", ''); me.frm.set_value("tax_withholding_category", "");
me.frm.set_df_property("tax_withholding_category", "hidden", 1); me.frm.set_df_property("tax_withholding_category", "hidden", 1);
} else { } else {
me.frm.set_value("tax_withholding_category", me.frm.supplier_tds); me.frm.set_value("tax_withholding_category", me.frm.supplier_tds);
@@ -356,7 +384,7 @@ erpnext.accounts.PurchaseInvoice = class PurchaseInvoice extends erpnext.buying.
credit_to() { credit_to() {
var me = this; var me = this;
if(this.frm.doc.credit_to) { if (this.frm.doc.credit_to) {
me.frm.call({ me.frm.call({
method: "frappe.client.get_value", method: "frappe.client.get_value",
args: { args: {
@@ -364,12 +392,12 @@ erpnext.accounts.PurchaseInvoice = class PurchaseInvoice extends erpnext.buying.
fieldname: "account_currency", fieldname: "account_currency",
filters: { name: me.frm.doc.credit_to }, filters: { name: me.frm.doc.credit_to },
}, },
callback: function(r, rt) { callback: function (r, rt) {
if(r.message) { if (r.message) {
me.frm.set_value("party_account_currency", r.message.account_currency); me.frm.set_value("party_account_currency", r.message.account_currency);
me.set_dynamic_labels(); me.set_dynamic_labels();
} }
} },
}); });
} }
} }
@@ -377,16 +405,16 @@ erpnext.accounts.PurchaseInvoice = class PurchaseInvoice extends erpnext.buying.
make_inter_company_invoice(frm) { make_inter_company_invoice(frm) {
frappe.model.open_mapped_doc({ frappe.model.open_mapped_doc({
method: "erpnext.accounts.doctype.purchase_invoice.purchase_invoice.make_inter_company_sales_invoice", method: "erpnext.accounts.doctype.purchase_invoice.purchase_invoice.make_inter_company_sales_invoice",
frm: frm frm: frm,
}); });
} }
is_paid() { is_paid() {
hide_fields(this.frm.doc); hide_fields(this.frm.doc);
if(cint(this.frm.doc.is_paid)) { if (cint(this.frm.doc.is_paid)) {
this.frm.set_value("allocate_advances_automatically", 0); this.frm.set_value("allocate_advances_automatically", 0);
if(!this.frm.doc.company) { if (!this.frm.doc.company) {
this.frm.set_value("is_paid", 0) this.frm.set_value("is_paid", 0);
frappe.msgprint(__("Please specify Company to proceed")); frappe.msgprint(__("Please specify Company to proceed"));
} }
} }
@@ -413,23 +441,27 @@ erpnext.accounts.PurchaseInvoice = class PurchaseInvoice extends erpnext.buying.
items_add(doc, cdt, cdn) { items_add(doc, cdt, cdn) {
var row = frappe.get_doc(cdt, cdn); var row = frappe.get_doc(cdt, cdn);
this.frm.script_manager.copy_from_first_row("items", row, this.frm.script_manager.copy_from_first_row("items", row, [
["expense_account", "discount_account", "cost_center", "project"]); "expense_account",
"discount_account",
"cost_center",
"project",
]);
} }
on_submit() { on_submit() {
super.on_submit(); super.on_submit();
$.each(this.frm.doc["items"] || [], function(i, row) { $.each(this.frm.doc["items"] || [], function (i, row) {
if(row.purchase_receipt) frappe.model.clear_doc("Purchase Receipt", row.purchase_receipt) if (row.purchase_receipt) frappe.model.clear_doc("Purchase Receipt", row.purchase_receipt);
}) });
} }
make_debit_note() { make_debit_note() {
frappe.model.open_mapped_doc({ frappe.model.open_mapped_doc({
method: "erpnext.accounts.doctype.purchase_invoice.purchase_invoice.make_debit_note", method: "erpnext.accounts.doctype.purchase_invoice.purchase_invoice.make_debit_note",
frm: cur_frm frm: cur_frm,
}) });
} }
}; };
@@ -438,172 +470,170 @@ cur_frm.script_manager.make(erpnext.accounts.PurchaseInvoice);
// Hide Fields // Hide Fields
// ------------ // ------------
function hide_fields(doc) { function hide_fields(doc) {
var parent_fields = ['due_date', 'is_opening', 'advances_section', 'from_date', 'to_date']; var parent_fields = ["due_date", "is_opening", "advances_section", "from_date", "to_date"];
if(cint(doc.is_paid) == 1) { if (cint(doc.is_paid) == 1) {
hide_field(parent_fields); hide_field(parent_fields);
} else { } else {
for (var i in parent_fields) { for (var i in parent_fields) {
var docfield = frappe.meta.docfield_map[doc.doctype][parent_fields[i]]; var docfield = frappe.meta.docfield_map[doc.doctype][parent_fields[i]];
if(!docfield.hidden) unhide_field(parent_fields[i]); if (!docfield.hidden) unhide_field(parent_fields[i]);
}
} }
} var item_fields_stock = ["warehouse_section", "received_qty", "rejected_qty"];
var item_fields_stock = ['warehouse_section', 'received_qty', 'rejected_qty']; cur_frm.fields_dict["items"].grid.set_column_disp(
item_fields_stock,
cur_frm.fields_dict['items'].grid.set_column_disp(item_fields_stock, cint(doc.update_stock) == 1 || cint(doc.is_return) == 1 ? true : false
(cint(doc.update_stock)==1 || cint(doc.is_return)==1 ? true : false)); );
cur_frm.refresh_fields(); cur_frm.refresh_fields();
} }
cur_frm.fields_dict.cash_bank_account.get_query = function(doc) { cur_frm.fields_dict.cash_bank_account.get_query = function (doc) {
return { return {
filters: [ filters: [
["Account", "account_type", "in", ["Cash", "Bank"]], ["Account", "account_type", "in", ["Cash", "Bank"]],
["Account", "is_group", "=",0], ["Account", "is_group", "=", 0],
["Account", "company", "=", doc.company], ["Account", "company", "=", doc.company],
["Account", "report_type", "=", "Balance Sheet"] ["Account", "report_type", "=", "Balance Sheet"],
] ],
} };
} };
cur_frm.fields_dict['items'].grid.get_field("item_code").get_query = function(doc, cdt, cdn) { cur_frm.fields_dict["items"].grid.get_field("item_code").get_query = function (doc, cdt, cdn) {
return { return {
query: "erpnext.controllers.queries.item_query", query: "erpnext.controllers.queries.item_query",
filters: {'is_purchase_item': 1} filters: { is_purchase_item: 1 },
} };
} };
cur_frm.fields_dict['credit_to'].get_query = function(doc) { cur_frm.fields_dict["credit_to"].get_query = function (doc) {
// filter on Account // filter on Account
return { return {
filters: { filters: {
'account_type': 'Payable', account_type: "Payable",
'is_group': 0, is_group: 0,
'company': doc.company company: doc.company,
} },
} };
} };
// Get Print Heading // Get Print Heading
cur_frm.fields_dict['select_print_heading'].get_query = function(doc, cdt, cdn) { cur_frm.fields_dict["select_print_heading"].get_query = function (doc, cdt, cdn) {
return { return {
filters:[ filters: [["Print Heading", "docstatus", "!=", 2]],
['Print Heading', 'docstatus', '!=', 2] };
] };
}
}
cur_frm.set_query("expense_account", "items", function(doc) { cur_frm.set_query("expense_account", "items", function (doc) {
return { return {
query: "erpnext.controllers.queries.get_expense_account", query: "erpnext.controllers.queries.get_expense_account",
filters: {'company': doc.company } filters: { company: doc.company },
} };
}); });
cur_frm.set_query("wip_composite_asset", "items", function() { cur_frm.set_query("wip_composite_asset", "items", function () {
return { return {
filters: {'is_composite_asset': 1, 'docstatus': 0 } filters: { is_composite_asset: 1, docstatus: 0 },
} };
}); });
cur_frm.cscript.expense_account = function(doc, cdt, cdn){ cur_frm.cscript.expense_account = function (doc, cdt, cdn) {
var d = locals[cdt][cdn]; var d = locals[cdt][cdn];
if(d.idx == 1 && d.expense_account){ if (d.idx == 1 && d.expense_account) {
var cl = doc.items || []; var cl = doc.items || [];
for(var i = 0; i < cl.length; i++){ for (var i = 0; i < cl.length; i++) {
if(!cl[i].expense_account) cl[i].expense_account = d.expense_account; if (!cl[i].expense_account) cl[i].expense_account = d.expense_account;
} }
} }
refresh_field('items'); refresh_field("items");
} };
cur_frm.fields_dict["items"].grid.get_field("cost_center").get_query = function(doc) { cur_frm.fields_dict["items"].grid.get_field("cost_center").get_query = function (doc) {
return { return {
filters: { filters: {
'company': doc.company, company: doc.company,
'is_group': 0 is_group: 0,
} },
};
};
} cur_frm.cscript.cost_center = function (doc, cdt, cdn) {
}
cur_frm.cscript.cost_center = function(doc, cdt, cdn){
var d = locals[cdt][cdn]; var d = locals[cdt][cdn];
if(d.cost_center){ if (d.cost_center) {
var cl = doc.items || []; var cl = doc.items || [];
for(var i = 0; i < cl.length; i++){ for (var i = 0; i < cl.length; i++) {
if(!cl[i].cost_center) cl[i].cost_center = d.cost_center; if (!cl[i].cost_center) cl[i].cost_center = d.cost_center;
} }
} }
refresh_field('items'); refresh_field("items");
} };
cur_frm.fields_dict['items'].grid.get_field('project').get_query = function(doc, cdt, cdn) { cur_frm.fields_dict["items"].grid.get_field("project").get_query = function (doc, cdt, cdn) {
return{ return {
filters:[ filters: [["Project", "status", "not in", "Completed, Cancelled"]],
['Project', 'status', 'not in', 'Completed, Cancelled'] };
] };
}
}
frappe.ui.form.on("Purchase Invoice", { frappe.ui.form.on("Purchase Invoice", {
setup: function(frm) { setup: function (frm) {
frm.custom_make_buttons = { frm.custom_make_buttons = {
'Purchase Invoice': 'Return / Debit Note', "Purchase Invoice": "Return / Debit Note",
'Payment Entry': 'Payment', "Payment Entry": "Payment",
'Landed Cost Voucher': function () { frm.trigger('create_landed_cost_voucher') }, "Landed Cost Voucher": function () {
} frm.trigger("create_landed_cost_voucher");
},
};
frm.set_query("additional_discount_account", function() { frm.set_query("additional_discount_account", function () {
return { return {
filters: { filters: {
company: frm.doc.company, company: frm.doc.company,
is_group: 0, is_group: 0,
report_type: "Profit and Loss", report_type: "Profit and Loss",
} },
}; };
}); });
frm.fields_dict['items'].grid.get_field('deferred_expense_account').get_query = function(doc) { frm.fields_dict["items"].grid.get_field("deferred_expense_account").get_query = function (doc) {
return { return {
filters: { filters: {
'root_type': 'Asset', root_type: "Asset",
'company': doc.company, company: doc.company,
"is_group": 0 is_group: 0,
} },
} };
} };
frm.fields_dict['items'].grid.get_field('discount_account').get_query = function(doc) { frm.fields_dict["items"].grid.get_field("discount_account").get_query = function (doc) {
return { return {
filters: { filters: {
'report_type': 'Profit and Loss', report_type: "Profit and Loss",
'company': doc.company, company: doc.company,
"is_group": 0 is_group: 0,
} },
} };
} };
}, },
refresh: function(frm) { refresh: function (frm) {
frm.events.add_custom_buttons(frm); frm.events.add_custom_buttons(frm);
}, },
mode_of_payment: function(frm) { mode_of_payment: function (frm) {
erpnext.accounts.pos.get_payment_mode_account(frm, frm.doc.mode_of_payment, function(account) { erpnext.accounts.pos.get_payment_mode_account(frm, frm.doc.mode_of_payment, function (account) {
frm.set_value("cash_bank_account", account); frm.set_value("cash_bank_account", account);
}) });
}, },
create_landed_cost_voucher: function (frm) { create_landed_cost_voucher: function (frm) {
let lcv = frappe.model.get_new_doc('Landed Cost Voucher'); let lcv = frappe.model.get_new_doc("Landed Cost Voucher");
lcv.company = frm.doc.company; lcv.company = frm.doc.company;
let lcv_receipt = frappe.model.get_new_doc('Landed Cost Purchase Invoice'); let lcv_receipt = frappe.model.get_new_doc("Landed Cost Purchase Invoice");
lcv_receipt.receipt_document_type = 'Purchase Invoice'; lcv_receipt.receipt_document_type = "Purchase Invoice";
lcv_receipt.receipt_document = frm.doc.name; lcv_receipt.receipt_document = frm.doc.name;
lcv_receipt.supplier = frm.doc.supplier; lcv_receipt.supplier = frm.doc.supplier;
lcv_receipt.grand_total = frm.doc.grand_total; lcv_receipt.grand_total = frm.doc.grand_total;
@@ -612,35 +642,43 @@ frappe.ui.form.on("Purchase Invoice", {
frappe.set_route("Form", lcv.doctype, lcv.name); frappe.set_route("Form", lcv.doctype, lcv.name);
}, },
add_custom_buttons: function(frm) { add_custom_buttons: function (frm) {
if (frm.doc.docstatus == 1 && frm.doc.per_received < 100) { if (frm.doc.docstatus == 1 && frm.doc.per_received < 100) {
frm.add_custom_button(__('Purchase Receipt'), () => { frm.add_custom_button(
__("Purchase Receipt"),
() => {
frm.events.make_purchase_receipt(frm); frm.events.make_purchase_receipt(frm);
}, __('Create')); },
__("Create")
);
} }
if (frm.doc.docstatus == 1 && frm.doc.per_received > 0) { if (frm.doc.docstatus == 1 && frm.doc.per_received > 0) {
frm.add_custom_button(__('Purchase Receipt'), () => { frm.add_custom_button(
__("Purchase Receipt"),
() => {
frappe.route_options = { frappe.route_options = {
'purchase_invoice': frm.doc.name purchase_invoice: frm.doc.name,
} };
frappe.set_route("List", "Purchase Receipt", "List") frappe.set_route("List", "Purchase Receipt", "List");
}, __('View')); },
__("View")
);
} }
}, },
onload: function(frm) { onload: function (frm) {
if(frm.doc.__onload && frm.is_new()) { if (frm.doc.__onload && frm.is_new()) {
if(frm.doc.supplier) { if (frm.doc.supplier) {
frm.doc.apply_tds = frm.doc.__onload.supplier_tds ? 1 : 0; frm.doc.apply_tds = frm.doc.__onload.supplier_tds ? 1 : 0;
} }
if(!frm.doc.__onload.supplier_tds) { if (!frm.doc.__onload.supplier_tds) {
frm.set_df_property("apply_tds", "read_only", 1); frm.set_df_property("apply_tds", "read_only", 1);
} }
} }
erpnext.queries.setup_queries(frm, "Warehouse", function() { erpnext.queries.setup_queries(frm, "Warehouse", function () {
return erpnext.queries.warehouse(frm.doc); return erpnext.queries.warehouse(frm.doc);
}); });
@@ -649,7 +687,7 @@ frappe.ui.form.on("Purchase Invoice", {
} }
}, },
is_subcontracted: function(frm) { is_subcontracted: function (frm) {
if (frm.doc.is_old_subcontracting_flow) { if (frm.doc.is_old_subcontracting_flow) {
erpnext.buying.get_default_bom(frm); erpnext.buying.get_default_bom(frm);
} }
@@ -657,30 +695,29 @@ frappe.ui.form.on("Purchase Invoice", {
frm.toggle_reqd("supplier_warehouse", frm.doc.is_subcontracted); frm.toggle_reqd("supplier_warehouse", frm.doc.is_subcontracted);
}, },
update_stock: function(frm) { update_stock: function (frm) {
hide_fields(frm.doc); hide_fields(frm.doc);
frm.fields_dict.items.grid.toggle_reqd("item_code", frm.doc.update_stock? true: false); frm.fields_dict.items.grid.toggle_reqd("item_code", frm.doc.update_stock ? true : false);
}, },
make_purchase_receipt: function(frm) { make_purchase_receipt: function (frm) {
frappe.model.open_mapped_doc({ frappe.model.open_mapped_doc({
method: "erpnext.accounts.doctype.purchase_invoice.purchase_invoice.make_purchase_receipt", method: "erpnext.accounts.doctype.purchase_invoice.purchase_invoice.make_purchase_receipt",
frm: frm, frm: frm,
freeze_message: __("Creating Purchase Receipt ...") freeze_message: __("Creating Purchase Receipt ..."),
}) });
}, },
company: function(frm) { company: function (frm) {
erpnext.accounts.dimensions.update_dimension(frm, frm.doctype); erpnext.accounts.dimensions.update_dimension(frm, frm.doctype);
if (frm.doc.company) { if (frm.doc.company) {
frappe.call({ frappe.call({
method: method: "erpnext.accounts.party.get_party_account",
"erpnext.accounts.party.get_party_account",
args: { args: {
party_type: 'Supplier', party_type: "Supplier",
party: frm.doc.supplier, party: frm.doc.supplier,
company: frm.doc.company company: frm.doc.company,
}, },
callback: (response) => { callback: (response) => {
if (response) frm.set_value("credit_to", response.message); if (response) frm.set_value("credit_to", response.message);
@@ -688,4 +725,4 @@ frappe.ui.form.on("Purchase Invoice", {
}); });
} }
}, },
}) });

View File

@@ -731,6 +731,7 @@ class PurchaseInvoice(BuyingController):
"cash_bank_account", "cash_bank_account",
"write_off_account", "write_off_account",
"unrealized_profit_loss_account", "unrealized_profit_loss_account",
"is_opening",
] ]
child_tables = {"items": ("expense_account",), "taxes": ("account_head",)} child_tables = {"items": ("expense_account",), "taxes": ("account_head",)}
self.needs_repost = self.check_if_fields_updated(fields_to_check, child_tables) self.needs_repost = self.check_if_fields_updated(fields_to_check, child_tables)
@@ -1023,9 +1024,14 @@ class PurchaseInvoice(BuyingController):
if provisional_accounting_for_non_stock_items: if provisional_accounting_for_non_stock_items:
if item.purchase_receipt: if item.purchase_receipt:
provisional_account = frappe.db.get_value( provisional_account, pr_qty, pr_base_rate = frappe.get_cached_value(
"Purchase Receipt Item", item.pr_detail, "provisional_expense_account" "Purchase Receipt Item",
) or self.get_company_default("default_provisional_account") item.pr_detail,
["provisional_expense_account", "qty", "base_rate"],
)
provisional_account = provisional_account or self.get_company_default(
"default_provisional_account"
)
purchase_receipt_doc = purchase_receipt_doc_map.get(item.purchase_receipt) purchase_receipt_doc = purchase_receipt_doc_map.get(item.purchase_receipt)
if not purchase_receipt_doc: if not purchase_receipt_doc:
@@ -1042,13 +1048,18 @@ class PurchaseInvoice(BuyingController):
"voucher_detail_no": item.pr_detail, "voucher_detail_no": item.pr_detail,
"account": provisional_account, "account": provisional_account,
}, },
["name"], "name",
) )
if expense_booked_in_pr: if expense_booked_in_pr:
# Intentionally passing purchase invoice item to handle partial billing # Intentionally passing purchase invoice item to handle partial billing
purchase_receipt_doc.add_provisional_gl_entry( purchase_receipt_doc.add_provisional_gl_entry(
item, gl_entries, self.posting_date, provisional_account, reverse=1 item,
gl_entries,
self.posting_date,
provisional_account,
reverse=1,
item_amount=(min(item.qty, pr_qty) * pr_base_rate),
) )
if not self.is_internal_transfer(): if not self.is_internal_transfer():

View File

@@ -22,48 +22,35 @@ frappe.listview_settings["Purchase Invoice"] = {
return [__(doc.status), "gray", "status,=," + doc.status]; return [__(doc.status), "gray", "status,=," + doc.status];
} }
if ( if (flt(doc.outstanding_amount) > 0 && doc.docstatus == 1 && cint(doc.on_hold)) {
flt(doc.outstanding_amount) > 0 &&
doc.docstatus == 1 &&
cint(doc.on_hold)
) {
if (!doc.release_date) { if (!doc.release_date) {
return [__("On Hold"), "darkgrey"]; return [__("On Hold"), "darkgrey"];
} else if ( } else if (frappe.datetime.get_diff(doc.release_date, frappe.datetime.nowdate()) > 0) {
frappe.datetime.get_diff(
doc.release_date,
frappe.datetime.nowdate()
) > 0
) {
return [__("Temporarily on Hold"), "darkgrey"]; return [__("Temporarily on Hold"), "darkgrey"];
} }
} }
const status_colors = { const status_colors = {
"Unpaid": "orange", Unpaid: "orange",
"Paid": "green", Paid: "green",
"Return": "gray", Return: "gray",
"Overdue": "red", Overdue: "red",
"Partly Paid": "yellow", "Partly Paid": "yellow",
"Internal Transfer": "darkgrey", "Internal Transfer": "darkgrey",
}; };
if (status_colors[doc.status]) { if (status_colors[doc.status]) {
return [ return [__(doc.status), status_colors[doc.status], "status,=," + doc.status];
__(doc.status),
status_colors[doc.status],
"status,=," + doc.status,
];
} }
}, },
onload: function(listview) { onload: function (listview) {
listview.page.add_action_item(__("Purchase Receipt"), ()=>{ listview.page.add_action_item(__("Purchase Receipt"), () => {
erpnext.bulk_transaction_processing.create(listview, "Purchase Invoice", "Purchase Receipt"); erpnext.bulk_transaction_processing.create(listview, "Purchase Invoice", "Purchase Receipt");
}); });
listview.page.add_action_item(__("Payment"), ()=>{ listview.page.add_action_item(__("Payment"), () => {
erpnext.bulk_transaction_processing.create(listview, "Purchase Invoice", "Payment Entry"); erpnext.bulk_transaction_processing.create(listview, "Purchase Invoice", "Payment Entry");
}); });
} },
}; };

View File

@@ -1529,18 +1529,7 @@ class TestPurchaseInvoice(FrappeTestCase, StockTestMixin):
self.assertEqual(payment_entry.taxes[0].allocated_amount, 0) self.assertEqual(payment_entry.taxes[0].allocated_amount, 0)
def test_provisional_accounting_entry(self): def test_provisional_accounting_entry(self):
create_item("_Test Non Stock Item", is_stock_item=0) setup_provisional_accounting()
provisional_account = create_account(
account_name="Provision Account",
parent_account="Current Liabilities - _TC",
company="_Test Company",
)
company = frappe.get_doc("Company", "_Test Company")
company.enable_provisional_accounting_for_non_stock_items = 1
company.default_provisional_account = provisional_account
company.save()
pr = make_purchase_receipt( pr = make_purchase_receipt(
item_code="_Test Non Stock Item", posting_date=add_days(nowdate(), -2) item_code="_Test Non Stock Item", posting_date=add_days(nowdate(), -2)
@@ -1584,8 +1573,97 @@ class TestPurchaseInvoice(FrappeTestCase, StockTestMixin):
self, pr.name, expected_gle_for_purchase_receipt_post_pi_cancel, pr.posting_date self, pr.name, expected_gle_for_purchase_receipt_post_pi_cancel, pr.posting_date
) )
company.enable_provisional_accounting_for_non_stock_items = 0 toggle_provisional_accounting_setting()
company.save()
def test_provisional_accounting_entry_for_over_billing(self):
setup_provisional_accounting()
# Configure Buying Settings to allow rate change
frappe.db.set_single_value("Buying Settings", "maintain_same_rate", 0)
# Create PR: rate = 1000, qty = 5
pr = make_purchase_receipt(
item_code="_Test Non Stock Item", rate=1000, posting_date=add_days(nowdate(), -2)
)
# Overbill PR: rate = 2000, qty = 10
pi = create_purchase_invoice_from_receipt(pr.name)
pi.set_posting_time = 1
pi.posting_date = add_days(pr.posting_date, -1)
pi.items[0].qty = 10
pi.items[0].rate = 2000
pi.items[0].expense_account = "Cost of Goods Sold - _TC"
pi.save()
pi.submit()
expected_gle = [
["Cost of Goods Sold - _TC", 20000, 0, add_days(pr.posting_date, -1)],
["Creditors - _TC", 0, 20000, add_days(pr.posting_date, -1)],
]
check_gl_entries(self, pi.name, expected_gle, pi.posting_date)
expected_gle_for_purchase_receipt = [
["Provision Account - _TC", 5000, 0, pr.posting_date],
["_Test Account Cost for Goods Sold - _TC", 0, 5000, pr.posting_date],
["Provision Account - _TC", 0, 5000, pi.posting_date],
["_Test Account Cost for Goods Sold - _TC", 5000, 0, pi.posting_date],
]
check_gl_entries(self, pr.name, expected_gle_for_purchase_receipt, pr.posting_date)
# Cancel purchase invoice to check reverse provisional entry cancellation
pi.cancel()
expected_gle_for_purchase_receipt_post_pi_cancel = [
["Provision Account - _TC", 0, 5000, pi.posting_date],
["_Test Account Cost for Goods Sold - _TC", 5000, 0, pi.posting_date],
]
check_gl_entries(
self, pr.name, expected_gle_for_purchase_receipt_post_pi_cancel, pr.posting_date
)
toggle_provisional_accounting_setting()
def test_provisional_accounting_entry_for_partial_billing(self):
setup_provisional_accounting()
# Configure Buying Settings to allow rate change
frappe.db.set_single_value("Buying Settings", "maintain_same_rate", 0)
# Create PR: rate = 1000, qty = 5
pr = make_purchase_receipt(
item_code="_Test Non Stock Item", rate=1000, posting_date=add_days(nowdate(), -2)
)
# Partially bill PR: rate = 500, qty = 2
pi = create_purchase_invoice_from_receipt(pr.name)
pi.set_posting_time = 1
pi.posting_date = add_days(pr.posting_date, -1)
pi.items[0].qty = 2
pi.items[0].rate = 500
pi.items[0].expense_account = "Cost of Goods Sold - _TC"
pi.save()
pi.submit()
expected_gle = [
["Cost of Goods Sold - _TC", 1000, 0, add_days(pr.posting_date, -1)],
["Creditors - _TC", 0, 1000, add_days(pr.posting_date, -1)],
]
check_gl_entries(self, pi.name, expected_gle, pi.posting_date)
expected_gle_for_purchase_receipt = [
["Provision Account - _TC", 5000, 0, pr.posting_date],
["_Test Account Cost for Goods Sold - _TC", 0, 5000, pr.posting_date],
["Provision Account - _TC", 0, 1000, pi.posting_date],
["_Test Account Cost for Goods Sold - _TC", 1000, 0, pi.posting_date],
]
check_gl_entries(self, pr.name, expected_gle_for_purchase_receipt, pr.posting_date)
toggle_provisional_accounting_setting()
def test_adjust_incoming_rate(self): def test_adjust_incoming_rate(self):
frappe.db.set_single_value("Buying Settings", "maintain_same_rate", 0) frappe.db.set_single_value("Buying Settings", "maintain_same_rate", 0)
@@ -2020,6 +2098,92 @@ class TestPurchaseInvoice(FrappeTestCase, StockTestMixin):
return_pi.submit() return_pi.submit()
self.assertEqual(return_pi.docstatus, 1) self.assertEqual(return_pi.docstatus, 1)
def test_purchase_invoice_with_use_serial_batch_field_for_rejected_qty(self):
from erpnext.stock.doctype.item.test_item import make_item
from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse
batch_item = make_item(
"_Test Purchase Invoice Batch Item For Rejected Qty",
properties={"has_batch_no": 1, "create_new_batch": 1, "is_stock_item": 1},
).name
serial_item = make_item(
"_Test Purchase Invoice Serial Item for Rejected Qty",
properties={"has_serial_no": 1, "is_stock_item": 1},
).name
rej_warehouse = create_warehouse("_Test Purchase INV Warehouse For Rejected Qty")
batch_no = "BATCH-PI-BNU-TPRBI-0001"
serial_nos = ["SNU-PI-TPRSI-0001", "SNU-PI-TPRSI-0002", "SNU-PI-TPRSI-0003"]
if not frappe.db.exists("Batch", batch_no):
frappe.get_doc(
{
"doctype": "Batch",
"batch_id": batch_no,
"item": batch_item,
}
).insert()
for serial_no in serial_nos:
if not frappe.db.exists("Serial No", serial_no):
frappe.get_doc(
{
"doctype": "Serial No",
"item_code": serial_item,
"serial_no": serial_no,
}
).insert()
pi = make_purchase_invoice(
item_code=batch_item,
received_qty=10,
qty=8,
rejected_qty=2,
update_stock=1,
rejected_warehouse=rej_warehouse,
use_serial_batch_fields=1,
batch_no=batch_no,
rate=100,
do_not_submit=1,
)
pi.append(
"items",
{
"item_code": serial_item,
"qty": 2,
"rate": 100,
"base_rate": 100,
"item_name": serial_item,
"uom": "Nos",
"stock_uom": "Nos",
"conversion_factor": 1,
"rejected_qty": 1,
"warehouse": pi.items[0].warehouse,
"rejected_warehouse": rej_warehouse,
"use_serial_batch_fields": 1,
"serial_no": "\n".join(serial_nos[:2]),
"rejected_serial_no": serial_nos[2],
},
)
pi.save()
pi.submit()
pi.reload()
for row in pi.items:
self.assertTrue(row.serial_and_batch_bundle)
self.assertTrue(row.rejected_serial_and_batch_bundle)
if row.item_code == batch_item:
self.assertEqual(row.batch_no, batch_no)
else:
self.assertEqual(row.serial_no, "\n".join(serial_nos[:2]))
self.assertEqual(row.rejected_serial_no, serial_nos[2])
def set_advance_flag(company, flag, default_account): def set_advance_flag(company, flag, default_account):
frappe.db.set_value( frappe.db.set_value(
@@ -2127,7 +2291,7 @@ def make_purchase_invoice(**args):
pi.cost_center = args.parent_cost_center pi.cost_center = args.parent_cost_center
bundle_id = None bundle_id = None
if args.get("batch_no") or args.get("serial_no"): if not args.use_serial_batch_fields and ((args.get("batch_no") or args.get("serial_no"))):
batches = {} batches = {}
qty = args.qty or 5 qty = args.qty or 5
item_code = args.item or args.item_code or "_Test Item" item_code = args.item or args.item_code or "_Test Item"
@@ -2174,6 +2338,9 @@ def make_purchase_invoice(**args):
"rejected_warehouse": args.rejected_warehouse or "", "rejected_warehouse": args.rejected_warehouse or "",
"asset_location": args.location or "", "asset_location": args.location or "",
"allow_zero_valuation_rate": args.get("allow_zero_valuation_rate") or 0, "allow_zero_valuation_rate": args.get("allow_zero_valuation_rate") or 0,
"use_serial_batch_fields": args.get("use_serial_batch_fields") or 0,
"batch_no": args.get("batch_no") if args.get("use_serial_batch_fields") else "",
"serial_no": args.get("serial_no") if args.get("use_serial_batch_fields") else "",
}, },
) )
@@ -2264,4 +2431,26 @@ def make_purchase_invoice_against_cost_center(**args):
return pi return pi
def setup_provisional_accounting(**args):
args = frappe._dict(args)
create_item("_Test Non Stock Item", is_stock_item=0)
company = args.company or "_Test Company"
provisional_account = create_account(
account_name=args.account_name or "Provision Account",
parent_account=args.parent_account or "Current Liabilities - _TC",
company=company,
)
toggle_provisional_accounting_setting(
enable=1, company=company, provisional_account=provisional_account
)
def toggle_provisional_accounting_setting(**args):
args = frappe._dict(args)
company = frappe.get_doc("Company", args.company or "_Test Company")
company.enable_provisional_accounting_for_non_stock_items = args.enable or 0
company.default_provisional_account = args.provisional_account
company.save()
test_records = frappe.get_test_records("Purchase Invoice") test_records = frappe.get_test_records("Purchase Invoice")

View File

@@ -8,24 +8,23 @@ frappe.ui.form.on("Purchase Taxes and Charges", {
add_deduct_tax(doc, cdt, cdn) { add_deduct_tax(doc, cdt, cdn) {
let d = locals[cdt][cdn]; let d = locals[cdt][cdn];
if(!d.category && d.add_deduct_tax) { if (!d.category && d.add_deduct_tax) {
frappe.msgprint(__("Please select Category first")); frappe.msgprint(__("Please select Category first"));
d.add_deduct_tax = ''; d.add_deduct_tax = "";
} } else if (d.category != "Total" && d.add_deduct_tax == "Deduct") {
else if(d.category != 'Total' && d.add_deduct_tax == 'Deduct') {
frappe.msgprint(__("Cannot deduct when category is for 'Valuation' or 'Valuation and Total'")); frappe.msgprint(__("Cannot deduct when category is for 'Valuation' or 'Valuation and Total'"));
d.add_deduct_tax = ''; d.add_deduct_tax = "";
} }
refresh_field('add_deduct_tax', d.name, 'taxes'); refresh_field("add_deduct_tax", d.name, "taxes");
}, },
category(doc, cdt, cdn) { category(doc, cdt, cdn) {
let d = locals[cdt][cdn]; let d = locals[cdt][cdn];
if(d.category != 'Total' && d.add_deduct_tax == 'Deduct') { if (d.category != "Total" && d.add_deduct_tax == "Deduct") {
frappe.msgprint(__("Cannot deduct when category is for 'Valuation' or 'Valuation and Total'")); frappe.msgprint(__("Cannot deduct when category is for 'Valuation' or 'Valuation and Total'"));
d.add_deduct_tax = ''; d.add_deduct_tax = "";
}
refresh_field('add_deduct_tax', d.name, 'taxes');
} }
refresh_field("add_deduct_tax", d.name, "taxes");
},
}); });

View File

@@ -2,47 +2,47 @@
// For license information, please see license.txt // For license information, please see license.txt
frappe.ui.form.on("Repost Accounting Ledger", { frappe.ui.form.on("Repost Accounting Ledger", {
setup: function(frm) { setup: function (frm) {
frm.fields_dict['vouchers'].grid.get_field('voucher_type').get_query = function(doc) { frm.fields_dict["vouchers"].grid.get_field("voucher_type").get_query = function (doc) {
return { return {
query: "erpnext.accounts.doctype.repost_accounting_ledger.repost_accounting_ledger.get_repost_allowed_types" query: "erpnext.accounts.doctype.repost_accounting_ledger.repost_accounting_ledger.get_repost_allowed_types",
} };
} };
frm.fields_dict['vouchers'].grid.get_field('voucher_no').get_query = function(doc) { frm.fields_dict["vouchers"].grid.get_field("voucher_no").get_query = function (doc) {
if (doc.company) { if (doc.company) {
return { return {
filters: { filters: {
company: doc.company, company: doc.company,
docstatus: 1 docstatus: 1,
} },
} };
}
} }
};
}, },
refresh: function(frm) { refresh: function (frm) {
frm.add_custom_button(__('Show Preview'), () => { frm.add_custom_button(__("Show Preview"), () => {
frm.call({ frm.call({
method: 'generate_preview', method: "generate_preview",
doc: frm.doc, doc: frm.doc,
freeze: true, freeze: true,
freeze_message: __('Generating Preview'), freeze_message: __("Generating Preview"),
callback: function(r) { callback: function (r) {
if (r && r.message) { if (r && r.message) {
let content = r.message; let content = r.message;
let opts = { let opts = {
title: "Preview", title: "Preview",
subtitle: "preview", subtitle: "preview",
content: content, content: content,
print_settings: {orientation: "landscape"}, print_settings: { orientation: "landscape" },
columns: [], columns: [],
data: [], data: [],
} };
frappe.render_grid(opts); frappe.render_grid(opts);
} }
} },
}); });
}); });
} },
}); });

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