Compare commits

...

264 Commits

Author SHA1 Message Date
Frappe PR Bot
70ce49e32c chore(release): Bumped to Version 15.18.0
# [15.18.0](https://github.com/frappe/erpnext/compare/v15.17.6...v15.18.0) (2024-03-27)

### Bug Fixes

* Add default finance book check in P&L statement ([f087159](f08715972a))
* Batch No is mandatory while making manufacture entry ([a638c9c](a638c9c8af))
* Book depreciation until the asset disposal date and removed unwanted commits ([2d7ff5d](2d7ff5d4cf))
* Cannot read properties of undefined (reading 'rate') ([d287ed5](d287ed5e47))
* existing batch from different warehouse not showing in the dropdown ([79d0478](79d047802a))
* incorrect total qty in job card ([68d57c3](68d57c3947))
* item not coming in quick entry ([008894d](008894d32b))
* permissions during bulk transaction logs ([6e6ca42](6e6ca42261))
* pick list not picked qty less than 1 ([5310ec3](5310ec38ca))
* rate not fetching from the item price ([fd02060](fd02060cd2))
* rate reset to zero ([4636ef0](4636ef0a29))
* remove faulty translation ([#40667](https://github.com/frappe/erpnext/issues/40667)) ([afa930f](afa930ff48))
* style for tax breakup ([501b09a](501b09a170))
* translatability of bom configurator labels ([cf49cec](cf49cec203))
* Turkish translations ([#40650](https://github.com/frappe/erpnext/issues/40650)) ([17a0876](17a087663b))
* use serial/batch fields for subcontracting receipt and in transit stock entry ([9ec24bc](9ec24bcc6c))
* use Text Editor for rendering tax breakup table ([a95bb27](a95bb27c65))
* validate gl for previous fiscal year ([4b973b2](4b973b2f86))
* validation error for the subcontracting receipt ([23ae82d](23ae82d282))
* wrong buying amount if delivered and billed qty varies ([c224240](c2242406f4))

### Features

* bisect doctype ([884a18f](884a18f8f1))
* nodes doctype ([bfccfa4](bfccfa4af1))

### Performance Improvements

* add in some indexes (backport [#40590](https://github.com/frappe/erpnext/issues/40590)) ([#40605](https://github.com/frappe/erpnext/issues/40605)) ([f66cf7d](f66cf7d838))
2024-03-27 03:27:37 +00:00
Deepesh Garg
d09821e1e1 Merge pull request #40678 from frappe/version-15-hotfix
chore: release v15
2024-03-27 08:56:26 +05:30
rohitwaghchaure
b6ac3e7d08 Merge pull request #40689 from frappe/mergify/bp/version-15-hotfix/pr-40685
fix: validation error for the subcontracting receipt (backport #40685)
2024-03-27 08:04:58 +05:30
Raffael Meyer
afa930ff48 fix: remove faulty translation (#40667) 2024-03-27 00:21:16 +01:00
Rohit Waghchaure
23ae82d282 fix: validation error for the subcontracting receipt
(cherry picked from commit 016585c248)
2024-03-26 14:27:36 +00:00
rohitwaghchaure
ad8961030e Merge pull request #40688 from frappe/mergify/bp/version-15-hotfix/pr-40684
fix: incorrect total qty in job card (backport #40684)
2024-03-26 19:54:46 +05:30
Rohit Waghchaure
68d57c3947 fix: incorrect total qty in job card
(cherry picked from commit c3546cf8e2)
2024-03-26 14:04:03 +00:00
rohitwaghchaure
9b9892da03 Merge pull request #40680 from frappe/mergify/bp/version-15-hotfix/pr-40674
fix: existing batch from different warehouse not showing in the dropdown (backport #40674)
2024-03-26 16:33:14 +05:30
Rohit Waghchaure
79d047802a fix: existing batch from different warehouse not showing in the dropdown
(cherry picked from commit 662cf21afb)
2024-03-26 10:35:51 +00:00
rohitwaghchaure
108e80419e Merge pull request #40673 from frappe/mergify/bp/version-15-hotfix/pr-40672
fix: item not coming in quick entry (backport #40672)
2024-03-26 14:33:46 +05:30
Rohit Waghchaure
008894d32b fix: item not coming in quick entry
(cherry picked from commit dcbb54c41f)
2024-03-26 06:13:17 +00:00
Deepesh Garg
634054c07b Merge pull request #40430 from frappe/mergify/bp/version-15-hotfix/pr-40385
fix: Book depreciation until the asset disposal date and remove unwanted commits (#40385)
2024-03-26 09:05:20 +05:30
SelenSoft
17a087663b fix: Turkish translations (#40650)
Co-authored-by: barredterra <14891507+barredterra@users.noreply.github.com>
2024-03-25 23:27:51 +01:00
Deepesh Garg
b04cef9f3f Merge pull request #40653 from frappe/mergify/bp/version-15-hotfix/pr-40640
fix: Add default finance book check in P&L statement (backport #40640)
2024-03-25 17:08:40 +05:30
Deepesh Garg
f08715972a fix: Add default finance book check in P&L statement
(cherry picked from commit 5be3417fdf)
2024-03-25 09:14:45 +00:00
Frappe PR Bot
22f3935024 chore(release): Bumped to Version 15.17.6
## [15.17.6](https://github.com/frappe/erpnext/compare/v15.17.5...v15.17.6) (2024-03-25)

### Bug Fixes

* reset update outstanding flag for old records ([1753a13](1753a138e9))
2024-03-25 02:55:11 +00:00
ruthra kumar
0b0b3f0d9d Merge pull request #40645 from frappe/mergify/bp/version-15/pr-40622
fix: reset update_outstanding_for_self flag for old records (backport #40622)
2024-03-25 08:24:03 +05:30
ruthra kumar
0658285a3b refactor: hide on print formats
(cherry picked from commit fdcdc8a56e)
2024-03-25 07:44:37 +05:30
ruthra kumar
1753a138e9 fix: reset update outstanding flag for old records
(cherry picked from commit a88bf8419e)
2024-03-25 07:44:16 +05:30
rohitwaghchaure
4e4e6c669d Merge pull request #40639 from frappe/mergify/bp/version-15-hotfix/pr-40638
fix: Batch No is mandatory while making manufacture entry (backport #40638)
2024-03-24 21:19:51 +05:30
Rohit Waghchaure
a638c9c8af fix: Batch No is mandatory while making manufacture entry
(cherry picked from commit 43fd60a877)
2024-03-24 13:02:10 +00:00
rohitwaghchaure
a95295b9f9 Merge pull request #40637 from frappe/mergify/bp/version-15-hotfix/pr-40594
fix: use serial/batch fields for subcontracting receipt and in transit in stock entry (backport #40594)
2024-03-24 17:45:50 +05:30
ruthra kumar
e33c383345 Merge pull request #40624 from frappe/mergify/bp/version-15-hotfix/pr-40622
refactor: reset update_outstanding_for_self flag for old records (backport #40622)
2024-03-24 16:39:03 +05:30
ruthra kumar
996f7d30b9 chore: resolve conflict 2024-03-24 16:24:10 +05:30
Rohit Waghchaure
9ec24bcc6c fix: use serial/batch fields for subcontracting receipt and in transit stock entry
(cherry picked from commit 3423334e4f)
2024-03-24 10:34:52 +00:00
Deepesh Garg
bfa316ad09 Merge pull request #40591 from frappe/mergify/bp/version-15-hotfix/pr-40587
refactor(Item Price): validate dates (#40587)
2024-03-23 08:58:47 +05:30
ruthra kumar
d238cdbdd5 refactor: hide on print formats
(cherry picked from commit fdcdc8a56e)
2024-03-22 14:54:02 +00:00
ruthra kumar
f25b5bdfab refactor: reset flag for old records
(cherry picked from commit a88bf8419e)

# Conflicts:
#	erpnext/patches.txt
2024-03-22 14:54:02 +00:00
Frappe PR Bot
c39d02fa14 chore(release): Bumped to Version 15.17.5
## [15.17.5](https://github.com/frappe/erpnext/compare/v15.17.4...v15.17.5) (2024-03-22)

### Bug Fixes

* rate reset to zero ([1ed9133](1ed9133bb6))
2024-03-22 10:30:44 +00:00
rohitwaghchaure
4a1c56113e Merge pull request #40619 from frappe/mergify/bp/version-15/pr-40617
fix: rate reset to zero (backport #40616) (backport #40617)
2024-03-22 15:59:36 +05:30
Rohit Waghchaure
1ed9133bb6 fix: rate reset to zero
(cherry picked from commit 6821baa850)
(cherry picked from commit 4636ef0a29)
2024-03-22 10:08:05 +00:00
rohitwaghchaure
9f13b6ed2b Merge pull request #40617 from frappe/mergify/bp/version-15-hotfix/pr-40616
fix: rate reset to zero (backport #40616)
2024-03-22 15:36:51 +05:30
Rohit Waghchaure
4636ef0a29 fix: rate reset to zero
(cherry picked from commit 6821baa850)
2024-03-22 09:50:50 +00:00
ruthra kumar
fcbe2556d3 Merge pull request #40613 from frappe/mergify/bp/version-15-hotfix/pr-38496
feat: utility to debug financial reports - Bisect Accounting Statements (backport #38496)
2024-03-22 14:19:42 +05:30
ruthra kumar
345d5a657a chore: resolve JS linter issue 2024-03-22 14:03:43 +05:30
ruthra kumar
e7b3ef0c90 chore: resolve linter issues
(cherry picked from commit 0890b414b1)
2024-03-22 07:53:45 +00:00
ruthra kumar
b371369699 refactor: cache results
(cherry picked from commit 14c8c8c33d)
2024-03-22 07:53:45 +00:00
ruthra kumar
067f101c99 refactor: flag to differentiate generated and default values
(cherry picked from commit 0925706d5e)
2024-03-22 07:53:44 +00:00
ruthra kumar
0305aafff8 refactor: save results in node
(cherry picked from commit ca14ae8f1b)
2024-03-22 07:53:44 +00:00
ruthra kumar
a59dc8b40c chore: restrict only to administrator and type info
(cherry picked from commit 90c6d4dc85)
2024-03-22 07:53:44 +00:00
ruthra kumar
6b1b2e863a chore: change data type for summary fields
(cherry picked from commit 228aa1a244)
2024-03-22 07:53:44 +00:00
ruthra kumar
415be361b4 refactor: adding labels to important section
(cherry picked from commit 993e2bfbf9)
2024-03-22 07:53:44 +00:00
ruthra kumar
509d6e3ca9 chore: UI cleanup
(cherry picked from commit ea3071db66)
2024-03-22 07:53:44 +00:00
ruthra kumar
6ff311c4e9 chore: add screen freeze on wait
(cherry picked from commit 395299803f)
2024-03-22 07:53:43 +00:00
ruthra kumar
348359ad5a chore: code cleanup
(cherry picked from commit 5e2d21c033)
2024-03-22 07:53:43 +00:00
ruthra kumar
1a08482655 chore: hide internal variables section
(cherry picked from commit c4c3090f46)
2024-03-22 07:53:43 +00:00
ruthra kumar
b686e1f972 chore: rename btree and remove debugging statements
(cherry picked from commit 6492019383)
2024-03-22 07:53:42 +00:00
ruthra kumar
5674ea450d chore: hide internal fields and better painting logic for heatmap
(cherry picked from commit f6831fba13)
2024-03-22 07:53:42 +00:00
ruthra kumar
f376659785 refactor: working heatmap
(cherry picked from commit 16db6c2f47)
2024-03-22 07:53:42 +00:00
ruthra kumar
c678134de6 chore: hide some internal fields
(cherry picked from commit bd3dc6482e)
2024-03-22 07:53:41 +00:00
ruthra kumar
a25f6493de refactor: calculate summary on tree navigation
(cherry picked from commit f7b7b2b438)
2024-03-22 07:53:41 +00:00
ruthra kumar
59ce9ccc8e refactor: use DB to store tree and state
(cherry picked from commit 99fbd8ad18)
2024-03-22 07:53:41 +00:00
ruthra kumar
a14eceb41a chore: use doctype as btree
(cherry picked from commit 9d20256366)
2024-03-22 07:53:41 +00:00
ruthra kumar
bfccfa4af1 feat: nodes doctype
(cherry picked from commit 85f2a6dd54)
2024-03-22 07:53:41 +00:00
ruthra kumar
0bce5d6057 chore: remove unwanted code
(cherry picked from commit de2eba0d98)
2024-03-22 07:53:40 +00:00
ruthra kumar
fd566f134d refactor: add basic navigation
1. remove unnecessary columns
2. added basic tree navigation

(cherry picked from commit 705ef4f5a3)
2024-03-22 07:53:40 +00:00
ruthra kumar
40176a6b41 refactor: ability to build and load tree from DB
(cherry picked from commit b2dde55f2c)
2024-03-22 07:53:40 +00:00
ruthra kumar
9f859c2bd3 refactor: introduce node class
(cherry picked from commit d53b34c0ce)
2024-03-22 07:53:40 +00:00
ruthra kumar
62987372ba refactor: more buttons
(cherry picked from commit a427029151)
2024-03-22 07:53:40 +00:00
ruthra kumar
80b77ffc87 refactor: date validation
(cherry picked from commit 2de3e6ce6d)
2024-03-22 07:53:39 +00:00
ruthra kumar
ed64d691fc refactor: support for BFS and DFS
(cherry picked from commit 03a38ed025)
2024-03-22 07:53:39 +00:00
ruthra kumar
1f235a7ba3 refactor: simplify DFS
(cherry picked from commit 26503a205f)
2024-03-22 07:53:39 +00:00
ruthra kumar
ce039f279b refactor: Depth First Search(DFS)
(cherry picked from commit 5a25c80f2e)
2024-03-22 07:53:39 +00:00
ruthra kumar
b6c2dbe581 refactor: some logic
(cherry picked from commit 4c8a8c3bcd)
2024-03-22 07:53:39 +00:00
ruthra kumar
884a18f8f1 feat: bisect doctype
(cherry picked from commit decdbd2782)
2024-03-22 07:53:39 +00:00
ruthra kumar
0393855243 refactor: primitive summary for p&l and balance sheet
(cherry picked from commit eb4c476490)
2024-03-22 07:53:38 +00:00
ruthra kumar
0e0b8e5ab4 Merge pull request #40608 from frappe/mergify/bp/version-15-hotfix/pr-40520
fix: permissions during bulk transaction logs (backport #40520)
2024-03-22 10:33:28 +05:30
David
6e6ca42261 fix: permissions during bulk transaction logs
(cherry picked from commit 49dd4c1ef3)
2024-03-22 04:38:45 +00:00
ruthra kumar
7344296a39 Merge pull request #40597 from frappe/mergify/bp/version-15-hotfix/pr-40386
fix: wrong buying amount if delivered and billed qty varies (backport #40386)
2024-03-22 09:04:37 +05:30
mergify[bot]
f66cf7d838 perf: add in some indexes (backport #40590) (#40605)
perf: add in some indexes (#40590)

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

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

Co-authored-by: Akhil Narang <me@akhilnarang.dev>
2024-03-22 08:51:57 +05:30
Frappe PR Bot
2b80cb99be chore(release): Bumped to Version 15.17.4
## [15.17.4](https://github.com/frappe/erpnext/compare/v15.17.3...v15.17.4) (2024-03-21)

### Bug Fixes

* rate not fetching from the item price ([0d95ace](0d95acefa2))
2024-03-21 17:30:02 +00:00
rohitwaghchaure
57e0b4ea5f Merge pull request #40602 from frappe/mergify/bp/version-15/pr-40600
fix: rate not fetching from the item price (backport #40595) (backport #40600)
2024-03-21 22:58:48 +05:30
Rohit Waghchaure
0d95acefa2 fix: rate not fetching from the item price
(cherry picked from commit d893a465d7)
(cherry picked from commit fd02060cd2)
2024-03-21 17:13:04 +00:00
rohitwaghchaure
5b155e37aa Merge pull request #40600 from frappe/mergify/bp/version-15-hotfix/pr-40595
fix: rate not fetching from the item price (backport #40595)
2024-03-21 22:40:47 +05:30
Rohit Waghchaure
fd02060cd2 fix: rate not fetching from the item price
(cherry picked from commit d893a465d7)
2024-03-21 16:50:13 +00:00
ruthra kumar
f5008a1467 test: buying amt calculation if DN and SI differ in qty
(cherry picked from commit ccb51ded95)
2024-03-21 15:46:01 +00:00
Dany Robert
c2242406f4 fix: wrong buying amount if delivered and billed qty varies
(cherry picked from commit b8da0d9334)
2024-03-21 15:46:01 +00:00
barredterra
df6226f07f chore: resolve conflicts 2024-03-21 14:16:27 +01:00
barredterra
357a1c9752 refactor(Item Price): validate dates
(cherry picked from commit cbcc47b5c4)

# Conflicts:
#	erpnext/stock/doctype/item_price/item_price.py
2024-03-21 13:13:27 +00:00
ruthra kumar
9e5e244e7a Merge pull request #40582 from frappe/mergify/bp/version-15-hotfix/pr-40580
refactor: config changes in Transaction Deletion Record (backport #40580)
2024-03-21 11:02:39 +05:30
Gursheen Kaur Anand
3dcd7380ac Merge pull request #40576 from frappe/mergify/bp/version-15-hotfix/pr-40572
fix: PCV validation for previous fiscal year (backport #40572)
2024-03-21 10:57:26 +05:30
ruthra kumar
b7dc28fff9 refactor: config changes in Transaction Deletion Record
(cherry picked from commit 4ba67fb3ec)
2024-03-21 05:17:25 +00:00
rohitwaghchaure
fa95bd331a Merge pull request #40564 from frappe/mergify/bp/version-15-hotfix/pr-40545
fix: translatability of bom configurator labels (backport #40545)
2024-03-21 01:58:16 +05:30
Gursheen Anand
4b973b2f86 fix: validate gl for previous fiscal year
(cherry picked from commit a1d108c062)
2024-03-20 15:30:03 +00:00
ruthra kumar
5194b87dc4 Merge pull request #40575 from frappe/mergify/bp/version-15-hotfix/pr-39717
refactor: Transaction Deletion record for large volumes (backport #39717)
2024-03-20 20:40:27 +05:30
Frappe PR Bot
85aeb1f3b1 chore(release): Bumped to Version 15.17.3
## [15.17.3](https://github.com/frappe/erpnext/compare/v15.17.2...v15.17.3) (2024-03-20)

### Bug Fixes

* style for tax breakup ([07bb836](07bb8360d5))
* use Text Editor for rendering tax breakup table ([64672e6](64672e655a))
2024-03-20 14:58:46 +00:00
Gursheen Kaur Anand
03a40f491b Merge pull request #40568 from frappe/mergify/bp/version-15/pr-40563
fix: use `Text Editor` for rendering tax breakup table (backport #40563)
2024-03-20 20:27:31 +05:30
Gursheen Kaur Anand
36c6820096 Merge pull request #40570 from frappe/mergify/bp/version-15-hotfix/pr-40563
fix: use `Text Editor` for rendering tax breakup table (backport #40563)
2024-03-20 20:27:03 +05:30
Gursheen Kaur Anand
9c204b7106 chore: resolve conflicts 2024-03-20 20:04:44 +05:30
Gursheen Kaur Anand
8e5d481cba chore: resolve conflicts 2024-03-20 20:03:03 +05:30
Gursheen Kaur Anand
37eae8eb4e chore: resolve conflicts 2024-03-20 19:58:01 +05:30
Gursheen Kaur Anand
4ede3a9ba5 chore: resolve conflicts 2024-03-20 19:57:24 +05:30
ruthra kumar
e7d2451f60 chore: fix linting issue in JS
(cherry picked from commit 02c522b7cd)
2024-03-20 14:13:21 +00:00
ruthra kumar
5bbccf1fbd refactor(test): test cases modified to handle new approach
(cherry picked from commit 81309576b0)
2024-03-20 14:13:21 +00:00
ruthra kumar
40574f0d72 refactor: ability to process in single transaction
(cherry picked from commit a158b825d7)
2024-03-20 14:13:20 +00:00
ruthra kumar
1104deb58e refactor: link running doc validation to company master
(cherry picked from commit 5a3afea8c7)
2024-03-20 14:13:20 +00:00
ruthra kumar
29804f6a41 chore: rename entry point
(cherry picked from commit 5fe0b20be1)
2024-03-20 14:13:20 +00:00
ruthra kumar
ae6260f717 chore: move status and error log to their own section
(cherry picked from commit 3cec62d4f8)
2024-03-20 14:13:19 +00:00
ruthra kumar
aceee829d2 refactor: minor UI tweaks
(cherry picked from commit 0455d0c46c)
2024-03-20 14:13:19 +00:00
ruthra kumar
02c3303fee refactor: exception propogation
(cherry picked from commit 4a55240e63)
2024-03-20 14:13:18 +00:00
ruthra kumar
3f45f63ff8 chore: code cleanup
(cherry picked from commit eea260b9f9)
2024-03-20 14:13:17 +00:00
ruthra kumar
3de53999ce refactor: better method naming
(cherry picked from commit 30463657bf)
2024-03-20 14:13:17 +00:00
ruthra kumar
b31e43e3db refactor: barebones hook on all doctypes with 'company' field
(cherry picked from commit ec194ef076)
2024-03-20 14:13:16 +00:00
ruthra kumar
d4c2e6c77d refactor: make sure only one task is running for doc
(cherry picked from commit 78c9cc63b1)
2024-03-20 14:13:16 +00:00
ruthra kumar
049c54bb32 chore: hide docfield in list view
(cherry picked from commit 98afb4d468)
2024-03-20 14:13:15 +00:00
ruthra kumar
d35bef12b6 refactor: validations to prevent duplicate jobs
(cherry picked from commit 31a2da552b)
2024-03-20 14:13:15 +00:00
ruthra kumar
90ad3d3176 refactor: no copy on summary table and more validations
(cherry picked from commit 55e93b3fe1)
2024-03-20 14:13:15 +00:00
ruthra kumar
db9cc5350d refactor: reset all flags and remove unwanted code
(cherry picked from commit 2dbe68a09d)
2024-03-20 14:13:15 +00:00
ruthra kumar
f67c447402 chore: show correct status in list view
(cherry picked from commit 1014940953)
2024-03-20 14:13:14 +00:00
ruthra kumar
cbaee05740 refactor: validate status before running events
(cherry picked from commit 86b5e2e277)
2024-03-20 14:13:14 +00:00
ruthra kumar
c827be4345 refactor: make Excluded doctype table read only
(cherry picked from commit 7c4cff2649)
2024-03-20 14:13:14 +00:00
ruthra kumar
efebec3f95 chore: remove unwanted UI code
(cherry picked from commit b98a5e4edc)
2024-03-20 14:13:14 +00:00
ruthra kumar
c3dd68ecc3 refactor: use separate child table for summary
(cherry picked from commit 49d3bcbc8d)
2024-03-20 14:13:13 +00:00
ruthra kumar
2bb1bfc4a0 refactor: chained callback
(cherry picked from commit b12ca65fcc)
2024-03-20 14:13:13 +00:00
ruthra kumar
195bffdf44 refactor: reorder flags in Tasks section
(cherry picked from commit cccb2d5141)
2024-03-20 14:13:13 +00:00
ruthra kumar
17ed1bb12c refactor: use flags to decide on current stage
(cherry picked from commit 6a77d86a53)
2024-03-20 14:13:13 +00:00
ruthra kumar
f9321767a6 refactor: UI trigger
(cherry picked from commit 8944ab8b6a)
2024-03-20 14:13:13 +00:00
ruthra kumar
9c5108e492 refactor: tasks section and UI niceties
(cherry picked from commit d0dc2c6e77)
2024-03-20 14:13:12 +00:00
ruthra kumar
529abd619a refactor: set status and trigger job on submit
(cherry picked from commit 6fbb67b1d2)
2024-03-20 14:13:12 +00:00
ruthra kumar
03fc3cec70 refactor: more options for 'status' and move it to top
(cherry picked from commit 0d65d878de)
2024-03-20 14:13:11 +00:00
Ankush Menat
501b09a170 fix: style for tax breakup
(cherry picked from commit 967540da18)
2024-03-20 13:06:45 +00:00
Gursheen Anand
a95bb27c65 fix: use Text Editor for rendering tax breakup table
(cherry picked from commit 1c63983873)

# Conflicts:
#	erpnext/buying/doctype/purchase_order/purchase_order.json
#	erpnext/buying/doctype/supplier_quotation/supplier_quotation.json
2024-03-20 13:06:45 +00:00
Ankush Menat
07bb8360d5 fix: style for tax breakup
(cherry picked from commit 967540da18)
2024-03-20 13:06:38 +00:00
Gursheen Anand
64672e655a fix: use Text Editor for rendering tax breakup table
(cherry picked from commit 1c63983873)

# Conflicts:
#	erpnext/buying/doctype/purchase_order/purchase_order.json
#	erpnext/buying/doctype/supplier_quotation/supplier_quotation.json
2024-03-20 13:06:38 +00:00
barredterra
cf49cec203 fix: translatability of bom configurator labels
(cherry picked from commit 4cfe99d74f)
2024-03-20 10:50:39 +00:00
rohitwaghchaure
bc5654b900 Merge pull request #40562 from frappe/mergify/bp/version-15-hotfix/pr-40561
fix: Cannot read properties of undefined (reading 'rate') (backport #40561)
2024-03-20 16:17:08 +05:30
Rohit Waghchaure
d287ed5e47 fix: Cannot read properties of undefined (reading 'rate')
(cherry picked from commit ac92a22914)
2024-03-20 09:31:42 +00:00
rohitwaghchaure
f881d23c05 Merge pull request #40560 from frappe/mergify/bp/version-15-hotfix/pr-40559
fix: pick list not picked materials having required qty less than 1 (backport #40559)
2024-03-20 14:16:44 +05:30
Rohit Waghchaure
5310ec38ca fix: pick list not picked qty less than 1
(cherry picked from commit 1a9ae33110)
2024-03-20 08:23:08 +00:00
Frappe PR Bot
1937059870 chore(release): Bumped to Version 15.17.2
## [15.17.2](https://github.com/frappe/erpnext/compare/v15.17.1...v15.17.2) (2024-03-20)

### Bug Fixes

* achieved targets for sales partners ([1ac8887](1ac888715c))
* advance journal fetching logic in Advances section ([bfa78aa](bfa78aaf74))
* attribute error on Bank Statement Import retry ([a0bf22c](a0bf22c9a5))
* auto-update due date for invoices via data import ([9cdde50](9cdde50f7c))
* balance qty in the stock ledger report (backport [#40506](https://github.com/frappe/erpnext/issues/40506)) ([#40507](https://github.com/frappe/erpnext/issues/40507)) ([69f442d](69f442dd79))
* currency symbol for Landed Cost Voucher Amount (backport [#40550](https://github.com/frappe/erpnext/issues/40550)) ([#40554](https://github.com/frappe/erpnext/issues/40554)) ([1c90797](1c90797879))
* Data too long for column 'stock_queue' (backport [#40436](https://github.com/frappe/erpnext/issues/40436)) ([#40451](https://github.com/frappe/erpnext/issues/40451)) ([ba6b856](ba6b8561c9))
* don't validate for currency, if account is unavailable ([5729ee5](5729ee563c))
* flaky Accounts Receivable test case ([0bb4a7d](0bb4a7d13a))
* incorrect gross profit on the quotation (backport [#40438](https://github.com/frappe/erpnext/issues/40438)) ([#40442](https://github.com/frappe/erpnext/issues/40442)) ([ce2626e](ce2626e911))
* index error on Exchange Rate Revaluation creation ([ebd967d](ebd967d7d3))
* invalid exchange loss booking on invoice againts base accounts ([72c9cd5](72c9cd5582))
* missing range for ageing summary ([dacc69c](dacc69c56f))
* not able to delete cancelled delivery note (backport [#40508](https://github.com/frappe/erpnext/issues/40508)) ([#40510](https://github.com/frappe/erpnext/issues/40510)) ([917a21b](917a21b989))
* rate changing while making PR (negative discount) (backport [#40539](https://github.com/frappe/erpnext/issues/40539)) ([#40540](https://github.com/frappe/erpnext/issues/40540)) ([0bdda12](0bdda1226f))
* Remove custom queries for customer ([3133505](313350534f))
* serial and batch for internal transfer (backport [#40467](https://github.com/frappe/erpnext/issues/40467)) ([#40477](https://github.com/frappe/erpnext/issues/40477)) ([61d59b3](61d59b392a))
* show correct variance for durations with no vouchers ([bc78bc3](bc78bc33f1))
* stock reco negative batch (backport [#40533](https://github.com/frappe/erpnext/issues/40533)) ([#40535](https://github.com/frappe/erpnext/issues/40535)) ([7f1f780](7f1f7809c8))
* stopped mr showing in the popup (backport [#40478](https://github.com/frappe/erpnext/issues/40478)) ([#40480](https://github.com/frappe/erpnext/issues/40480)) ([74b30a6](74b30a6a1d))
* **Supplier Quotation Comparison:** group by options ([1e16d2c](1e16d2ca25))
* Taxes not getting updated on change ([75b610d](75b610d7fc))
* **test:** manually filter rows and assert ([df13517](df1351783e))
* Update Existing Price List Rate not working (backport [#40333](https://github.com/frappe/erpnext/issues/40333)) ([#40527](https://github.com/frappe/erpnext/issues/40527)) ([44bbf4b](44bbf4b983))
* use in_import flag for checking imported records ([8242a9c](8242a9cd46))
2024-03-20 05:23:16 +00:00
rohitwaghchaure
717c78dcda Merge pull request #40538 from frappe/version-15-hotfix
chore: release v15
2024-03-20 10:52:04 +05:30
mergify[bot]
1c90797879 fix: currency symbol for Landed Cost Voucher Amount (backport #40550) (#40554)
fix: currency symbol for Landed Cost Voucher Amount (#40550)

(cherry picked from commit 0725707cb1)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-03-19 20:42:57 +05:30
Raffael Meyer
ba9f9bff19 Merge pull request #40548 from frappe/mergify/bp/version-15-hotfix/pr-40546
fix(Supplier Quotation Comparison): group by options (backport #40546)
2024-03-19 13:07:25 +01:00
barredterra
1e16d2ca25 fix(Supplier Quotation Comparison): group by options
(cherry picked from commit 87e36d290e)
2024-03-19 11:51:36 +00:00
Raffael Meyer
745e653339 Merge pull request #40544 from frappe/mergify/bp/version-15-hotfix/pr-40542 2024-03-19 12:49:32 +01:00
barredterra
f0e00daa1c refactor: usage of in_list
(cherry picked from commit d238751e6b)
2024-03-19 11:13:02 +00:00
mergify[bot]
0bdda1226f fix: rate changing while making PR (negative discount) (backport #40539) (#40540)
fix: rate changing while making PR (negative discount) (#40539)

(cherry picked from commit 8136954484)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-03-19 15:37:37 +05:30
rohitwaghchaure
05436dfcac Merge branch 'version-15' into version-15-hotfix 2024-03-19 15:28:47 +05:30
mergify[bot]
7f1f7809c8 fix: stock reco negative batch (backport #40533) (#40535)
fix: stock reco negative batch (#40533)

(cherry picked from commit a64c2ecf39)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-03-19 15:18:50 +05:30
mergify[bot]
44bbf4b983 fix: Update Existing Price List Rate not working (backport #40333) (#40527)
fix: Update Existing Price List Rate not working (#40333)

(cherry picked from commit 09ea7edb86)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-03-19 14:26:41 +05:30
Gursheen Kaur Anand
0ddb310dd4 Merge pull request #40531 from frappe/mergify/bp/version-15-hotfix/pr-40528
fix(minor): missing range for ageing summary in PSOA (backport #40528)
2024-03-19 12:44:04 +05:30
Gursheen Anand
dacc69c56f fix: missing range for ageing summary
(cherry picked from commit 643cc022fd)
2024-03-19 07:11:18 +00:00
ruthra kumar
7b4ede9c04 Merge pull request #40523 from frappe/mergify/bp/version-15-hotfix/pr-40502
refactor: toggle between 'http' and 'https' on exchange rate API (backport #40502)
2024-03-19 10:21:28 +05:30
ruthra kumar
1a0a70b5cd refactor: toggle between 'http' and 'https' on exchange rate API
(cherry picked from commit 8b81274769)
2024-03-19 04:30:16 +00:00
ruthra kumar
093b95604f Merge pull request #40516 from frappe/mergify/bp/version-15-hotfix/pr-40511
fix: invalid exchange loss booking on invoice against base accounts (backport #40511)
2024-03-18 21:00:38 +05:30
ruthra kumar
dd30a46f29 refactor(test): ensure Exchange gain/loss journals aren't created
(cherry picked from commit e1c2d006ca)
2024-03-18 15:14:44 +00:00
ruthra kumar
72c9cd5582 fix: invalid exchange loss booking on invoice againts base accounts
(cherry picked from commit 3d5dba6976)
2024-03-18 15:14:43 +00:00
mergify[bot]
917a21b989 fix: not able to delete cancelled delivery note (backport #40508) (#40510)
fix: not able to delete cancelled delivery note (#40508)

(cherry picked from commit 7695759f3c)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-03-18 15:26:32 +05:30
mergify[bot]
69f442dd79 fix: balance qty in the stock ledger report (backport #40506) (#40507)
fix: balance qty in the stock ledger report (#40506)

(cherry picked from commit 00de529a1e)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-03-18 13:03:27 +05:30
Gursheen Kaur Anand
a82df6ac7b Merge pull request #40503 from GursheenK/achieved-targets-for-territory-v15
fix: achieved targets for territory / partners bpv15
2024-03-18 11:21:59 +05:30
Gursheen Anand
bc78bc33f1 fix: show correct variance for durations with no vouchers 2024-03-18 10:18:16 +05:30
Gursheen Anand
1a3ea0c108 test: sales partner targets with invoices 2024-03-18 10:18:16 +05:30
Gursheen Anand
1ac888715c fix: achieved targets for sales partners 2024-03-18 10:18:16 +05:30
Deepesh Garg
6ecd545f17 Merge pull request #40492 from frappe/mergify/bp/version-15-hotfix/pr-40428
chore: Remove custom party queries (#40428)
2024-03-17 19:47:39 +05:30
ruthra kumar
be730fe66a Merge pull request #40499 from frappe/mergify/bp/version-15-hotfix/pr-40494
fix: AttributeError in Bank Statement Import (backport #40494)
2024-03-17 08:10:18 +05:30
ruthra kumar
09c1da9570 Merge pull request #40497 from frappe/mergify/bp/version-15-hotfix/pr-40495
fix: index error on Exchange Rate Revaluation creation (backport #40495)
2024-03-17 08:06:17 +05:30
ruthra kumar
a0bf22c9a5 fix: attribute error on Bank Statement Import retry
(cherry picked from commit aec630c74f)
2024-03-17 02:23:46 +00:00
ruthra kumar
5729ee563c fix: don't validate for currency, if account is unavailable
(cherry picked from commit 3cde81be65)
2024-03-17 02:23:46 +00:00
ruthra kumar
ebd967d7d3 fix: index error on Exchange Rate Revaluation creation
(cherry picked from commit bb279e368c)
2024-03-17 02:21:37 +00:00
Deepesh Garg
313350534f fix: Remove custom queries for customer
(cherry picked from commit 60ba25caf2)
2024-03-16 14:34:36 +00:00
Deepesh Garg
e3336c603c chore: Add supplier query back
(cherry picked from commit effc9d1492)
2024-03-16 14:34:36 +00:00
Deepesh Garg
2e38f4d599 chore: remove invalid comment
(cherry picked from commit e87b44f758)
2024-03-16 14:34:36 +00:00
Deepesh Garg
2512d4c7f2 chore: Remove custom party queries
(cherry picked from commit c9623b6fd6)
2024-03-16 14:34:36 +00:00
Deepesh Garg
823e377ef1 Merge pull request #40454 from frappe/mergify/bp/version-15-hotfix/pr-40433
fix: Taxes not getting updated on change (#40433)
2024-03-16 19:23:22 +05:30
ruthra kumar
db5cd4eace Merge pull request #40490 from frappe/mergify/bp/version-15-hotfix/pr-40485
refactor: validate SO and SI references in Delivery Notes (backport #40485)
2024-03-16 15:27:37 +05:30
ruthra kumar
409a65ec64 test: SO reference validation
(cherry picked from commit 4f396d3049)
2024-03-16 09:29:15 +00:00
ruthra kumar
28d3525b42 refactor: validate SO and SI references
(cherry picked from commit 4d090bd3b8)
2024-03-16 09:29:14 +00:00
ruthra kumar
f7ef0d69b7 Merge pull request #40474 from frappe/mergify/bp/version-15-hotfix/pr-40473
refactor: enable no-copy for update_outstanding_for_self (backport #40473)
2024-03-16 10:07:51 +05:30
ruthra kumar
0ca5f98ba3 Merge pull request #40471 from frappe/mergify/bp/version-15-hotfix/pr-40260
refactor: support payment against reverse payment reconciliation (backport #40260)
2024-03-16 10:06:25 +05:30
ruthra kumar
78eb6bd9ea Merge pull request #40466 from frappe/mergify/bp/version-15-hotfix/pr-40461
refactor: disallow '0' qty return invoices with stock effect (backport #40461)
2024-03-16 10:05:22 +05:30
mergify[bot]
74b30a6a1d fix: stopped mr showing in the popup (backport #40478) (#40480)
fix: stopped mr showing in the popup (#40478)

(cherry picked from commit 1ff8a6f24f)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-03-16 09:35:56 +05:30
ruthra kumar
ed4c8461d3 chore: resolve conflict 2024-03-15 20:16:38 +05:30
mergify[bot]
61d59b392a fix: serial and batch for internal transfer (backport #40467) (#40477)
fix: serial and batch for internal transfer (#40467)

* fix: serial and batch for internal transfer

* chore: fix test cases

(cherry picked from commit 59222813af)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-03-15 18:19:56 +05:30
ruthra kumar
fba13c6dbc refactor: enable no-copy for update_outstanding_for_self
(cherry picked from commit a1e8caa5c1)
2024-03-15 11:33:09 +00:00
Gursheen Kaur Anand
3397b80ddf Merge pull request #40470 from frappe/mergify/bp/version-15-hotfix/pr-40198
fix: auto-update due date for invoices via data import (backport #40198)
2024-03-15 13:16:56 +05:30
ruthra kumar
d82b1fc600 refactor(test): generate and use unique party
(cherry picked from commit a3d4aff29c)
2024-03-15 07:22:42 +00:00
ruthra kumar
7ea1edc4ff test: advance payment reconciliation against payment
'advance' payments booked in separate party account

(cherry picked from commit 2a08072443)
2024-03-15 07:22:42 +00:00
ruthra kumar
1762f9919a test: reverse payment reconciliation
(cherry picked from commit 6d9074d585)

# Conflicts:
#	erpnext/accounts/doctype/payment_entry/test_payment_entry.py
2024-03-15 07:22:41 +00:00
ruthra kumar
17fb287cd9 refactor: support payment against reverse payment reconciliation
(cherry picked from commit 5f15297f28)
2024-03-15 07:22:41 +00:00
Gursheen Anand
8242a9cd46 fix: use in_import flag for checking imported records
(cherry picked from commit f504f2caf3)
2024-03-15 07:16:26 +00:00
Gursheen Anand
9cdde50f7c fix: auto-update due date for invoices via data import
(cherry picked from commit c096133897)
2024-03-15 07:16:25 +00:00
ruthra kumar
5957ef9b9d test: validation to prevent '0' qty return with stock effect
(cherry picked from commit 647bba0f00)
2024-03-15 05:37:36 +00:00
ruthra kumar
144aec8d6a refactor: disallow '0' qty return invoices with stock effect
(cherry picked from commit 898affbee9)
2024-03-15 05:37:36 +00:00
ruthra kumar
3fe45404ea Merge pull request #40460 from frappe/mergify/bp/version-15-hotfix/pr-40420
fix: advance journal fetching logic in Advances section (backport #40420)
2024-03-14 15:51:15 +05:30
ruthra kumar
bfa78aaf74 fix: advance journal fetching logic in Advances section
(cherry picked from commit e786a93c2e)
2024-03-14 10:06:05 +00:00
Frappe PR Bot
436e030961 chore(release): Bumped to Version 15.17.1
## [15.17.1](https://github.com/frappe/erpnext/compare/v15.17.0...v15.17.1) (2024-03-14)

### Bug Fixes

* **test:** manually filter row and assert ([057e433](057e43330f))
2024-03-14 09:17:23 +00:00
ruthra kumar
217cef6f4e Merge pull request #40440 from frappe/mergify/bp/version-15/pr-40372
refactor: checkbox to toggle standalone Credit/Debit note behaviour (backport #40372)
2024-03-14 14:46:16 +05:30
mergify[bot]
54b5064f76 chore: fix test case (backport #40457) (#40458)
chore: fix test case

(cherry picked from commit ec83d54826)

Co-authored-by: Rohit Waghchaure <rohitw1991@gmail.com>
2024-03-14 14:43:05 +05:30
ruthra kumar
057e43330f fix(test): manually filter row and assert 2024-03-14 13:19:45 +05:30
Deepesh Garg
75b610d7fc fix: Taxes not getting updated on change
(cherry picked from commit 65ae9616ba)
2024-03-14 06:44:05 +00:00
mergify[bot]
ba6b8561c9 fix: Data too long for column 'stock_queue' (backport #40436) (#40451)
fix: Data too long for column 'stock_queue' (#40436)

(cherry picked from commit cd79dcccb6)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-03-14 11:49:10 +05:30
ruthra kumar
54a8473a91 Merge pull request #40447 from frappe/mergify/copy/version-15-hotfix/pr-40445
fix: flaky Accounts Receivable test case (copy #40445)
2024-03-14 10:29:27 +05:30
ruthra kumar
df1351783e fix(test): manually filter rows and assert 2024-03-14 10:14:35 +05:30
ruthra kumar
0bb4a7d13a fix: flaky Accounts Receivable test case
(cherry picked from commit 40bce240bde508801d07b9c38ededea5b4f297c8)
2024-03-13 16:53:44 +00:00
mergify[bot]
ce2626e911 fix: incorrect gross profit on the quotation (backport #40438) (#40442)
fix: incorrect gross profit on the quotation (#40438)

(cherry picked from commit f4a945aee4)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-03-13 21:56:20 +05:30
ruthra kumar
9ffb4c5ca9 chore: resolve conflicts 2024-03-13 17:55:22 +05:30
ruthra kumar
e07f9e6754 chore: better popup message
(cherry picked from commit 445d2acf50)

# Conflicts:
#	erpnext/controllers/accounts_controller.py
2024-03-13 12:08:39 +00:00
ruthra kumar
ed7a115511 test: cr note flag to update self
(cherry picked from commit ce3b1f09f5)
2024-03-13 12:08:38 +00:00
ruthra kumar
19763ce545 refactor: make AR/AP report aware of always standalone cr/dr notes
(cherry picked from commit 4d0c2d8e82)
2024-03-13 12:08:37 +00:00
ruthra kumar
95093ba7cd chore: patch for updating flag in Cr/Dr notes
(cherry picked from commit 849f478894)

# Conflicts:
#	erpnext/patches.txt
2024-03-13 12:08:37 +00:00
ruthra kumar
b56fe0e800 refactor: post ledger entries based on toggle
(cherry picked from commit 77aac6f571)
2024-03-13 12:08:36 +00:00
ruthra kumar
006971ecc6 refactor: checkbox in purchase invoice
(cherry picked from commit 767f2157e6)
2024-03-13 12:08:35 +00:00
ruthra kumar
9ccc22ca61 chore: update popup message
(cherry picked from commit adf13a19c4)

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

# Conflicts:
#	erpnext/accounts/doctype/sales_invoice/sales_invoice.json
2024-03-13 12:08:34 +00:00
ruthra kumar
bc53b67065 Merge pull request #40427 from frappe/mergify/bp/version-15-hotfix/pr-40372
refactor: checkbox to toggle standalone Credit/Debit note behaviour (backport #40372)
2024-03-13 16:28:50 +05:30
Nabin Hait
2d7ff5d4cf fix: Book depreciation until the asset disposal date and removed unwanted commits
(cherry picked from commit dedae4fecf)
2024-03-13 07:48:27 +00:00
ruthra kumar
70375dfbde refactor: pass 'name' to get_link_to_form 2024-03-13 13:15:07 +05:30
ruthra kumar
1093e0d46f chore: resolve conflicts 2024-03-13 12:17:46 +05:30
ruthra kumar
d87b98d945 chore: better popup message
(cherry picked from commit 445d2acf50)

# Conflicts:
#	erpnext/controllers/accounts_controller.py
2024-03-13 06:13:11 +00:00
ruthra kumar
752b01d83b test: cr note flag to update self
(cherry picked from commit ce3b1f09f5)
2024-03-13 06:13:11 +00:00
ruthra kumar
a0f78584e9 refactor: make AR/AP report aware of always standalone cr/dr notes
(cherry picked from commit 4d0c2d8e82)
2024-03-13 06:13:11 +00:00
ruthra kumar
4b44ae435a chore: patch for updating flag in Cr/Dr notes
(cherry picked from commit 849f478894)

# Conflicts:
#	erpnext/patches.txt
2024-03-13 06:13:10 +00:00
ruthra kumar
1c68946fb9 refactor: post ledger entries based on toggle
(cherry picked from commit 77aac6f571)
2024-03-13 06:13:10 +00:00
ruthra kumar
824d6b4102 refactor: checkbox in purchase invoice
(cherry picked from commit 767f2157e6)
2024-03-13 06:13:10 +00:00
ruthra kumar
b5f22c39ec chore: update popup message
(cherry picked from commit adf13a19c4)

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

# Conflicts:
#	erpnext/accounts/doctype/sales_invoice/sales_invoice.json
2024-03-13 06:13:09 +00:00
Frappe PR Bot
33185e0a3b chore(release): Bumped to Version 15.17.0
# [15.17.0](https://github.com/frappe/erpnext/compare/v15.16.2...v15.17.0) (2024-03-13)

### Bug Fixes

* **accounts:** Allow setting Number of new Cost Center (backport [#40212](https://github.com/frappe/erpnext/issues/40212)) ([#40314](https://github.com/frappe/erpnext/issues/40314)) ([7001e0a](7001e0a820))
* advance paid amount and ledger entries against SO/PO ([6a5a941](6a5a941a5a))
* barcode field on line item not working (backport [#40381](https://github.com/frappe/erpnext/issues/40381)) ([#40384](https://github.com/frappe/erpnext/issues/40384)) ([9ce68de](9ce68deff5))
* batch no not copied while making Material Consumption entry (backport [#40290](https://github.com/frappe/erpnext/issues/40290)) ([#40300](https://github.com/frappe/erpnext/issues/40300)) ([6d1c144](6d1c144a66))
* Blanket order rate getting changed on converting to order ([d8c6eb0](d8c6eb0bf2))
* conditionally apply `is_group` filter in accounting dimension query (backport [#40414](https://github.com/frappe/erpnext/issues/40414)) ([#40416](https://github.com/frappe/erpnext/issues/40416)) ([40752c1](40752c1f5c))
* decimal issue while making the stock entry (backport [#40394](https://github.com/frappe/erpnext/issues/40394)) ([#40397](https://github.com/frappe/erpnext/issues/40397)) ([91af7c0](91af7c033a))
* error message wording ([#40403](https://github.com/frappe/erpnext/issues/40403)) ([2a40808](2a40808b05))
* Filter for projects in Sales Cycle ([173b3b8](173b3b85f6))
* get_user_default_as_list args order ([44ff607](44ff607dcd))
* if input manualy material request on WO the material_request_item is not set so validate WO give error (backport [#40180](https://github.com/frappe/erpnext/issues/40180)) ([#40421](https://github.com/frappe/erpnext/issues/40421)) ([a5e6763](a5e6763be5))
* incorrect advance paid in Sales/Purchase Order ([6832908](6832908e92))
* incorrect work order status (backport [#40407](https://github.com/frappe/erpnext/issues/40407)) ([#40411](https://github.com/frappe/erpnext/issues/40411)) ([605132a](605132a31c))
* load ignored doctype and include Mode of Payment Account ([#40334](https://github.com/frappe/erpnext/issues/40334)) ([5fac500](5fac50036a))
* MR Default Supplier search query (backport [#40273](https://github.com/frappe/erpnext/issues/40273)) ([#40351](https://github.com/frappe/erpnext/issues/40351)) ([a195dd3](a195dd3c1f))
* negative stock error for the batch (backport [#40389](https://github.com/frappe/erpnext/issues/40389)) ([#40391](https://github.com/frappe/erpnext/issues/40391)) ([478b988](478b988290))
* not able to cancel purchase receipt for old subcontracting flow (backport [#40298](https://github.com/frappe/erpnext/issues/40298)) ([#40302](https://github.com/frappe/erpnext/issues/40302)) ([e0e80f7](e0e80f7eed))
* qc created for raw materials during manufacture entry (backport [#40408](https://github.com/frappe/erpnext/issues/40408)) ([#40413](https://github.com/frappe/erpnext/issues/40413)) ([f932265](f932265218))
* recursion issue while submitting work order (backport [#40400](https://github.com/frappe/erpnext/issues/40400)) ([#40402](https://github.com/frappe/erpnext/issues/40402)) ([d6e87f3](d6e87f3f17))
* Sender email in process statements of accounts ([953f640](953f64091a))
* **Shipment Parcel:** make length, width and height non-mandatory ([1476196](1476196966))
* stock ledger balance qty for the batch (backport [#40274](https://github.com/frappe/erpnext/issues/40274)) ([#40301](https://github.com/frappe/erpnext/issues/40301)) ([62aefce](62aefcef04))
* use serial batch fields for subcontracting receipt (backport [#40311](https://github.com/frappe/erpnext/issues/40311)) ([#40315](https://github.com/frappe/erpnext/issues/40315)) ([4b15c00](4b15c00b11))
* use serial/batch field for rejected items (backport [#40327](https://github.com/frappe/erpnext/issues/40327)) ([#40329](https://github.com/frappe/erpnext/issues/40329)) ([7ca7242](7ca72423b9))
* Use serial/batch fields for delivery note return (backport [#40374](https://github.com/frappe/erpnext/issues/40374)) ([#40376](https://github.com/frappe/erpnext/issues/40376)) ([32660ab](32660abdc8))

### Features

* add recursion qty field in promotional scheme ([5f4b23d](5f4b23d4af))
2024-03-13 04:29:12 +00:00
Deepesh Garg
0e4e0b3084 Merge pull request #40395 from frappe/version-15-hotfix
chore: release v15
2024-03-13 09:57:54 +05:30
mergify[bot]
a5e6763be5 fix: if input manualy material request on WO the material_request_item is not set so validate WO give error (backport #40180) (#40421)
fix: if input manualy material request on WO the material_request_item is not set so validate WO give error (#40180)

(cherry picked from commit f24f51b7de)

Co-authored-by: HENRY Florian <florian.henry@open-concept.pro>
2024-03-12 21:56:14 +05:30
mergify[bot]
26a1d84935 chore: Add translation to buttons in Update stock_summary_template.html (backport #40099) (#40419)
chore: Add translation to buttons in Update stock_summary_template.html (#40099)

chore: Add translation to buttons in Update stock_summary_template.html
(cherry picked from commit f3b4237ab6)

Co-authored-by: Ernesto Ruiz <eruiz@wbapps.com>
2024-03-12 21:31:30 +05:30
mergify[bot]
40752c1f5c fix: conditionally apply is_group filter in accounting dimension query (backport #40414) (#40416)
fix: conditionally apply `is_group` filter in accounting dimension query (#40414)

(cherry picked from commit daf4ae2a6b)

Co-authored-by: Rucha Mahabal <ruchamahabal2@gmail.com>
2024-03-12 20:45:31 +05:30
Raffael Meyer
0ad203ab89 Merge pull request #40406 from frappe/mergify/bp/version-15-hotfix/pr-40403
fix: error message wording (backport #40403)
2024-03-12 14:29:49 +01:00
mergify[bot]
605132a31c fix: incorrect work order status (backport #40407) (#40411)
fix: incorrect work order status (#40407)

(cherry picked from commit 948297692e)

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

(cherry picked from commit f8a1a7f515)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-03-12 18:29:11 +05:30
Raffael Meyer
2a40808b05 fix: error message wording (#40403)
(cherry picked from commit 79a0473705)
2024-03-12 11:26:56 +00:00
mergify[bot]
d6e87f3f17 fix: recursion issue while submitting work order (backport #40400) (#40402)
* fix: recursion issue while submitting work order (#40400)

(cherry picked from commit 72614bb8ff)

* chore: fix linter issue

---------

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-03-12 16:50:00 +05:30
mergify[bot]
91af7c033a fix: decimal issue while making the stock entry (backport #40394) (#40397)
fix: decimal issue while making the stock entry (#40394)

(cherry picked from commit 4a02d1497c)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2024-03-12 15:35:55 +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
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
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
698 changed files with 29204 additions and 22807 deletions

View File

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

View File

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

View File

@@ -20,6 +20,23 @@ repos:
- id: check-yaml
- id: debug-statements
- repo: https://github.com/pre-commit/mirrors-prettier
rev: v2.7.1
hooks:
- id: prettier
types_or: [javascript, vue, scss]
# Ignore any files that might contain jinja / bundles
exclude: |
(?x)^(
erpnext/public/dist/.*|
cypress/.*|
.*node_modules.*|
.*boilerplate.*|
erpnext/public/js/controllers/.*|
erpnext/templates/pages/order.js|
erpnext/templates/includes/.*
)$
- repo: https://github.com/pre-commit/mirrors-eslint
rev: v8.44.0
hooks:

View File

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

View File

@@ -3,7 +3,7 @@ import inspect
import frappe
__version__ = "15.16.2"
__version__ = "15.18.0"
def get_default_company(user=None):
@@ -13,7 +13,7 @@ def get_default_company(user=None):
if not user:
user = frappe.session.user
companies = get_user_default_as_list(user, "company")
companies = get_user_default_as_list("company", user)
if companies:
default_company = companies[0]
else:

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -9,7 +9,6 @@ from frappe import _
from frappe.model.document import Document
from frappe.query_builder.custom import ConstantColumn
from frappe.utils import cint, flt
from pypika.terms import Parameter
from erpnext import get_default_cost_center
from erpnext.accounts.doctype.bank_transaction.bank_transaction import get_total_allocated_amount
@@ -509,6 +508,18 @@ def check_matching(
to_reference_date,
):
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(
bank_account,
company,
@@ -520,20 +531,12 @@ def check_matching(
from_reference_date,
to_reference_date,
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 = []
for query in queries:
matching_vouchers.extend(frappe.db.sql(query, filters, as_dict=True))
matching_vouchers.extend(query.run(as_dict=True))
return (
sorted(matching_vouchers, key=lambda x: x["rank"], reverse=True) if matching_vouchers else []
@@ -551,6 +554,7 @@ def get_queries(
from_reference_date,
to_reference_date,
exact_match,
common_filters,
):
# get queries to get matching vouchers
account_from_to = "paid_to" if transaction.deposit > 0.0 else "paid_from"
@@ -571,6 +575,7 @@ def get_queries(
filter_by_reference_date,
from_reference_date,
to_reference_date,
common_filters,
)
or []
)
@@ -590,6 +595,7 @@ def get_matching_queries(
filter_by_reference_date,
from_reference_date,
to_reference_date,
common_filters,
):
queries = []
currency = get_account_currency(bank_account)
@@ -604,6 +610,7 @@ def get_matching_queries(
filter_by_reference_date,
from_reference_date,
to_reference_date,
common_filters,
)
queries.append(query)
@@ -616,16 +623,17 @@ def get_matching_queries(
filter_by_reference_date,
from_reference_date,
to_reference_date,
common_filters,
)
queries.append(query)
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)
if transaction.withdrawal > 0.0:
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)
if "bank_transaction" in document_types:
@@ -680,7 +688,7 @@ def get_bt_matching_query(exact_match, transaction):
.where(amount_condition)
.where(bt.docstatus == 1)
)
return str(query)
return query
def get_pe_matching_query(
@@ -692,6 +700,7 @@ def get_pe_matching_query(
filter_by_reference_date,
from_reference_date,
to_reference_date,
common_filters,
):
# get matching payment entries query
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.payment_type.isin([payment_type, "Internal Transfer"]))
.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(filter_by_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:
query = query.where(ref_condition)
return str(query)
return query
def get_je_matching_query(
@@ -754,6 +763,7 @@ def get_je_matching_query(
filter_by_reference_date,
from_reference_date,
to_reference_date,
common_filters,
):
# get matching journal entry query
# We have mapping at the bank level
@@ -793,7 +803,7 @@ def get_je_matching_query(
.where(je.docstatus == 1)
.where(je.voucher_type != "Opening Entry")
.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(je.docstatus == 1)
.where(filter_by_date)
@@ -803,19 +813,19 @@ def get_je_matching_query(
if frappe.flags.auto_reconcile_vouchers == True:
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
si = frappe.qb.DocType("Sales Invoice")
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_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)
query = (
@@ -836,23 +846,23 @@ def get_si_matching_query(exact_match, currency):
)
.where(si.docstatus == 1)
.where(sip.clearance_date.isnull())
.where(sip.account == Parameter("%(bank_account)s"))
.where(sip.account == common_filters.bank_account)
.where(amount_condition)
.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)
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_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)
query = (
@@ -872,9 +882,9 @@ def get_pi_matching_query(exact_match, currency):
.where(purchase_invoice.docstatus == 1)
.where(purchase_invoice.is_paid == 1)
.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(purchase_invoice.currency == currency)
)
return str(query)
return query

View File

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

View File

@@ -148,6 +148,9 @@ def start_import(
import_file = ImportFile("Bank Transaction", file=file, import_type="Insert New Records")
data = parse_data_from_template(import_file.raw_data)
# Importer expects 'Data Import' class, which has 'payload_count' attribute
if not data_import.get("payload_count"):
data_import.payload_count = len(data) - 1
if import_file_path:
add_bank_account(data, bank_account)

View File

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

View File

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

View File

@@ -56,17 +56,17 @@ class BankTransaction(Document):
Bank Transaction should be on the same currency as the Bank Account.
"""
if self.currency and self.bank_account:
account = frappe.get_cached_value("Bank Account", self.bank_account, "account")
account_currency = frappe.get_cached_value("Account", account, "account_currency")
if account := frappe.get_cached_value("Bank Account", self.bank_account, "account"):
account_currency = frappe.get_cached_value("Account", account, "account_currency")
if self.currency != account_currency:
frappe.throw(
_(
"Transaction currency: {0} cannot be different from Bank Account({1}) currency: {2}"
).format(
frappe.bold(self.currency), frappe.bold(self.bank_account), frappe.bold(account_currency)
if self.currency != account_currency:
frappe.throw(
_(
"Transaction currency: {0} cannot be different from Bank Account({1}) currency: {2}"
).format(
frappe.bold(self.currency), frappe.bold(self.bank_account), frappe.bold(account_currency)
)
)
)
def set_status(self):
if self.docstatus == 2:

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -41,7 +41,7 @@
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Cost Center Number",
"read_only": 1
"read_only_depends_on": "eval:!doc.__islocal"
},
{
"fieldname": "parent_cost_center",
@@ -170,4 +170,4 @@
"sort_field": "modified",
"sort_order": "ASC",
"states": []
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -31,6 +31,7 @@ class CurrencyExchangeSettings(Document):
result_key: DF.Table[CurrencyExchangeSettingsResult]
service_provider: DF.Literal["frankfurter.app", "exchangerate.host", "Custom"]
url: DF.Data | None
use_http: DF.Check
# end: auto-generated types
def validate(self):
@@ -53,7 +54,7 @@ class CurrencyExchangeSettings(Document):
self.set("result_key", [])
self.set("req_params", [])
self.api_endpoint = "https://api.exchangerate.host/convert"
self.api_endpoint = get_api_endpoint(self.service_provider, self.use_http)
self.append("result_key", {"key": "result"})
self.append("req_params", {"key": "access_key", "value": self.access_key})
self.append("req_params", {"key": "amount", "value": "1"})
@@ -64,7 +65,7 @@ class CurrencyExchangeSettings(Document):
self.set("result_key", [])
self.set("req_params", [])
self.api_endpoint = "https://frankfurter.app/{transaction_date}"
self.api_endpoint = get_api_endpoint(self.service_provider, self.use_http)
self.append("result_key", {"key": "rates"})
self.append("result_key", {"key": "{to_currency}"})
self.append("req_params", {"key": "base", "value": "{from_currency}"})
@@ -103,3 +104,19 @@ class CurrencyExchangeSettings(Document):
frappe.throw(_("Returned exchange rate is neither integer not float."))
self.url = response.url
@frappe.whitelist()
def get_api_endpoint(service_provider: str = None, use_http: bool = False):
if service_provider and service_provider in ["exchangerate.host", "frankfurter.app"]:
if service_provider == "exchangerate.host":
api = "api.exchangerate.host/convert"
elif service_provider == "frankfurter.app":
api = "frankfurter.app/{transaction_date}"
protocol = "https://"
if use_http:
protocol = "http://"
return protocol + api
return None

View File

@@ -10,7 +10,7 @@ frappe.ui.form.on("Dunning", {
company: frm.doc.company,
customer: frm.doc.customer,
outstanding_amount: [">", 0],
status: "Overdue"
status: "Overdue",
},
};
});
@@ -19,16 +19,16 @@ frappe.ui.form.on("Dunning", {
filters: {
company: frm.doc.company,
root_type: "Income",
is_group: 0
}
is_group: 0,
},
};
});
frm.set_query("cost_center", () => {
return {
filters: {
company: frm.doc.company,
is_group: 0
}
is_group: 0,
},
};
});
@@ -51,7 +51,8 @@ frappe.ui.form.on("Dunning", {
__("Payment"),
function () {
frm.events.make_payment_entry(frm);
}, __("Create")
},
__("Create")
);
frm.page.set_inner_btn_group_as_primary(__("Create"));
}
@@ -69,7 +70,7 @@ frappe.ui.form.on("Dunning", {
get_query_filters: {
docstatus: 1,
status: "Overdue",
company: frm.doc.company
company: frm.doc.company,
},
allow_child_item_selection: true,
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
company: function (frm) {
@@ -90,8 +94,8 @@ frappe.ui.form.on("Dunning", {
args: { name: frm.doc.company, existing_address: frm.doc.company_address || "" },
debounce: 2000,
callback: function (r) {
frm.set_value("company_address", r && r.message || "");
}
frm.set_value("company_address", (r && r.message) || "");
},
});
if (frm.fields_dict.currency) {
@@ -125,16 +129,16 @@ frappe.ui.form.on("Dunning", {
transaction_date: frm.doc.posting_date,
from_currency: frm.doc.currency,
to_currency: company_currency,
args: "for_selling"
args: "for_selling",
},
freeze: true,
freeze_message: __("Fetching exchange rates ..."),
callback: function(r) {
callback: function (r) {
const exchange_rate = flt(r.message);
if (exchange_rate != frm.doc.conversion_rate) {
frm.set_value("conversion_rate", exchange_rate);
}
}
},
});
} else {
frm.trigger("conversion_rate");
@@ -166,8 +170,7 @@ frappe.ui.form.on("Dunning", {
get_dunning_letter_text: function (frm) {
if (frm.doc.dunning_type) {
frappe.call({
method:
"erpnext.accounts.doctype.dunning.dunning.get_dunning_letter_text",
method: "erpnext.accounts.doctype.dunning.dunning.get_dunning_letter_text",
args: {
dunning_type: frm.doc.dunning_type,
language: frm.doc.language,
@@ -204,10 +207,7 @@ frappe.ui.form.on("Dunning", {
calculate_overdue_days: function (frm) {
frm.doc.overdue_payments.forEach((row) => {
if (frm.doc.posting_date && row.due_date) {
const overdue_days = moment(frm.doc.posting_date).diff(
row.due_date,
"days"
);
const overdue_days = moment(frm.doc.posting_date).diff(row.due_date, "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) {
frm.doc.overdue_payments.forEach((row) => {
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);
});
},
calculate_totals: function (frm) {
const total_interest = frm.doc.overdue_payments
.reduce((prev, cur) => prev + cur.interest, 0);
const total_outstanding = frm.doc.overdue_payments
.reduce((prev, cur) => prev + cur.outstanding, 0);
const total_interest = frm.doc.overdue_payments.reduce((prev, cur) => prev + cur.interest, 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 base_dunning_amount = dunning_amount * frm.doc.conversion_rate;
const grand_total = total_outstanding + dunning_amount;
@@ -240,8 +241,7 @@ frappe.ui.form.on("Dunning", {
},
make_payment_entry: function (frm) {
return frappe.call({
method:
"erpnext.accounts.doctype.payment_entry.payment_entry.get_payment_entry",
method: "erpnext.accounts.doctype.payment_entry.payment_entry.get_payment_entry",
args: {
dt: frm.doc.doctype,
dn: frm.doc.name,
@@ -257,5 +257,5 @@ frappe.ui.form.on("Dunning", {
frappe.ui.form.on("Overdue Payment", {
interest: function (frm) {
frm.trigger("calculate_totals");
}
});
},
});

View File

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

View File

@@ -628,21 +628,21 @@ def get_account_details(
if account_balance and (
account_balance[0].balance or account_balance[0].balance_in_account_currency
):
account_with_new_balance = ExchangeRateRevaluation.calculate_new_account_balance(
if account_with_new_balance := ExchangeRateRevaluation.calculate_new_account_balance(
company, posting_date, account_balance
)
row = account_with_new_balance[0]
account_details.update(
{
"balance_in_base_currency": row["balance_in_base_currency"],
"balance_in_account_currency": row["balance_in_account_currency"],
"current_exchange_rate": row["current_exchange_rate"],
"new_exchange_rate": row["new_exchange_rate"],
"new_balance_in_base_currency": row["new_balance_in_base_currency"],
"new_balance_in_account_currency": row["new_balance_in_account_currency"],
"zero_balance": row["zero_balance"],
"gain_loss": row["gain_loss"],
}
)
):
row = account_with_new_balance[0]
account_details.update(
{
"balance_in_base_currency": row["balance_in_base_currency"],
"balance_in_account_currency": row["balance_in_account_currency"],
"current_exchange_rate": row["current_exchange_rate"],
"new_exchange_rate": row["new_exchange_rate"],
"new_balance_in_base_currency": row["new_balance_in_base_currency"],
"new_balance_in_account_currency": row["new_balance_in_account_currency"],
"zero_balance": row["zero_balance"],
"gain_loss": row["gain_loss"],
}
)
return account_details

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -4,58 +4,82 @@
frappe.provide("erpnext.accounts");
frappe.provide("erpnext.journal_entry");
frappe.ui.form.on("Journal Entry", {
setup: function(frm) {
setup: function (frm) {
frm.add_fetch("bank_account", "account", "account");
frm.ignore_doctypes_on_cancel_all = ['Sales Invoice', 'Purchase Invoice', 'Journal Entry', "Repost Payment Ledger", 'Asset', 'Asset Movement', '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();
if (frm.doc.repost_required && frm.doc.docstatus===1) {
frm.set_intro(__("Accounting entries for this Journal Entry need to be reposted. Please click on 'Repost' button to update."));
frm.add_custom_button(__('Repost Accounting Entries'),
() => {
frm.call({
doc: frm.doc,
method: 'repost_accounting_entries',
freeze: true,
freeze_message: __('Reposting...'),
callback: (r) => {
if (!r.exc) {
frappe.msgprint(__('Accounting Entries are reposted.'));
frm.refresh();
}
if (frm.doc.repost_required && frm.doc.docstatus === 1) {
frm.set_intro(
__(
"Accounting entries for this Journal Entry need to be reposted. Please click on 'Repost' button to update."
)
);
frm.add_custom_button(__("Repost Accounting Entries"), () => {
frm.call({
doc: frm.doc,
method: "repost_accounting_entries",
freeze: true,
freeze_message: __("Reposting..."),
callback: (r) => {
if (!r.exc) {
frappe.msgprint(__("Accounting Entries are reposted."));
frm.refresh();
}
});
}).removeClass('btn-default').addClass('btn-warning');
},
});
})
.removeClass("btn-default")
.addClass("btn-warning");
}
if(frm.doc.docstatus > 0) {
frm.add_custom_button(__('Ledger'), function() {
frappe.route_options = {
"voucher_no": frm.doc.name,
"from_date": frm.doc.posting_date,
"to_date": moment(frm.doc.modified).format('YYYY-MM-DD'),
"company": frm.doc.company,
"finance_book": frm.doc.finance_book,
"group_by": '',
"show_cancelled_entries": frm.doc.docstatus === 2
};
frappe.set_route("query-report", "General Ledger");
}, __('View'));
if (frm.doc.docstatus > 0) {
frm.add_custom_button(
__("Ledger"),
function () {
frappe.route_options = {
voucher_no: frm.doc.name,
from_date: frm.doc.posting_date,
to_date: moment(frm.doc.modified).format("YYYY-MM-DD"),
company: frm.doc.company,
finance_book: frm.doc.finance_book,
group_by: "",
show_cancelled_entries: frm.doc.docstatus === 2,
};
frappe.set_route("query-report", "General Ledger");
},
__("View")
);
}
if(frm.doc.docstatus==1) {
frm.add_custom_button(__('Reverse Journal Entry'), function() {
return erpnext.journal_entry.reverse_journal_entry(frm);
}, __('Actions'));
if (frm.doc.docstatus == 1) {
frm.add_custom_button(
__("Reverse Journal Entry"),
function () {
return erpnext.journal_entry.reverse_journal_entry(frm);
},
__("Actions")
);
}
if (frm.doc.__islocal) {
frm.add_custom_button(__('Quick Entry'), function() {
frm.add_custom_button(__("Quick Entry"), function () {
return erpnext.journal_entry.quick_entry(frm);
});
}
@@ -63,52 +87,63 @@ frappe.ui.form.on("Journal Entry", {
// hide /unhide fields based on currency
erpnext.journal_entry.toggle_fields_based_on_currency(frm);
if ((frm.doc.voucher_type == "Inter Company Journal Entry") && (frm.doc.docstatus == 1) && (!frm.doc.inter_company_journal_entry_reference)) {
frm.add_custom_button(__("Create Inter Company Journal Entry"),
function() {
if (
frm.doc.voucher_type == "Inter Company Journal Entry" &&
frm.doc.docstatus == 1 &&
!frm.doc.inter_company_journal_entry_reference
) {
frm.add_custom_button(
__("Create Inter Company Journal Entry"),
function () {
frm.trigger("make_inter_company_journal_entry");
}, __('Make'));
},
__("Make")
);
}
erpnext.accounts.unreconcile_payment.add_unreconcile_btn(frm);
},
before_save: function(frm) {
if ((frm.doc.docstatus == 0) && (!frm.doc.is_system_generated)) {
let payment_entry_references = frm.doc.accounts.filter(elem => (elem.reference_type == "Payment Entry"));
before_save: function (frm) {
if (frm.doc.docstatus == 0 && !frm.doc.is_system_generated) {
let payment_entry_references = frm.doc.accounts.filter(
(elem) => elem.reference_type == "Payment Entry"
);
if (payment_entry_references.length > 0) {
let rows = payment_entry_references.map(x => "#"+x.idx);
frappe.throw(__("Rows: {0} have 'Payment Entry' as reference_type. This should not be set manually.", [frappe.utils.comma_and(rows)]));
let rows = payment_entry_references.map((x) => "#" + x.idx);
frappe.throw(
__("Rows: {0} have 'Payment Entry' as reference_type. This should not be set manually.", [
frappe.utils.comma_and(rows),
])
);
}
}
},
make_inter_company_journal_entry: function(frm) {
make_inter_company_journal_entry: function (frm) {
var d = new frappe.ui.Dialog({
title: __("Select Company"),
fields: [
{
'fieldname': 'company',
'fieldtype': 'Link',
'label': __('Company'),
'options': 'Company',
"get_query": function () {
fieldname: "company",
fieldtype: "Link",
label: __("Company"),
options: "Company",
get_query: function () {
return {
filters: [
["Company", "name", "!=", frm.doc.company]
]
filters: [["Company", "name", "!=", frm.doc.company]],
};
},
'reqd': 1
}
reqd: 1,
},
],
});
d.set_primary_action(__('Create'), function() {
d.set_primary_action(__("Create"), function () {
d.hide();
var args = d.get_values();
frappe.call({
args: {
"name": frm.doc.name,
"voucher_type": frm.doc.voucher_type,
"company": args.company
name: frm.doc.name,
voucher_type: frm.doc.voucher_type,
company: args.company,
},
method: "erpnext.accounts.doctype.journal_entry.journal_entry.make_inter_company_journal_entry",
callback: function (r) {
@@ -116,96 +151,101 @@ frappe.ui.form.on("Journal Entry", {
var doc = frappe.model.sync(r.message)[0];
frappe.set_route("Form", doc.doctype, doc.name);
}
}
},
});
});
d.show();
},
multi_currency: function(frm) {
multi_currency: function (frm) {
erpnext.journal_entry.toggle_fields_based_on_currency(frm);
},
posting_date: function(frm) {
if(!frm.doc.multi_currency || !frm.doc.posting_date) return;
posting_date: function (frm) {
if (!frm.doc.multi_currency || !frm.doc.posting_date) return;
$.each(frm.doc.accounts || [], function(i, row) {
$.each(frm.doc.accounts || [], function (i, row) {
erpnext.journal_entry.set_exchange_rate(frm, row.doctype, row.name);
})
});
},
company: function(frm) {
company: function (frm) {
frappe.call({
method: "frappe.client.get_value",
args: {
doctype: "Company",
filters: {"name": frm.doc.company},
fieldname: "cost_center"
filters: { name: frm.doc.company },
fieldname: "cost_center",
},
callback: function(r){
if(r.message){
$.each(frm.doc.accounts || [], function(i, jvd) {
callback: function (r) {
if (r.message) {
$.each(frm.doc.accounts || [], function (i, jvd) {
frappe.model.set_value(jvd.doctype, jvd.name, "cost_center", r.message.cost_center);
});
}
}
},
});
erpnext.accounts.dimensions.update_dimension(frm, frm.doctype);
},
voucher_type: function(frm){
voucher_type: function (frm) {
if (!frm.doc.company) return null;
if(!frm.doc.company) return null;
if((!(frm.doc.accounts || []).length) || ((frm.doc.accounts || []).length === 1 && !frm.doc.accounts[0].account)) {
if(in_list(["Bank Entry", "Cash Entry"], frm.doc.voucher_type)) {
if (
!(frm.doc.accounts || []).length ||
((frm.doc.accounts || []).length === 1 && !frm.doc.accounts[0].account)
) {
if (["Bank Entry", "Cash Entry"].includes(frm.doc.voucher_type)) {
return frappe.call({
type: "GET",
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_default_bank_cash_account",
args: {
"account_type": (frm.doc.voucher_type=="Bank Entry" ?
"Bank" : (frm.doc.voucher_type=="Cash Entry" ? "Cash" : null)),
"company": frm.doc.company
account_type:
frm.doc.voucher_type == "Bank Entry"
? "Bank"
: frm.doc.voucher_type == "Cash Entry"
? "Cash"
: null,
company: frm.doc.company,
},
callback: function(r) {
if(r.message) {
callback: function (r) {
if (r.message) {
// If default company bank account not set
if(!$.isEmptyObject(r.message)){
if (!$.isEmptyObject(r.message)) {
update_jv_details(frm.doc, [r.message]);
}
}
}
},
});
}
}
},
from_template: function(frm){
if (frm.doc.from_template){
frappe.db.get_doc("Journal Entry Template", frm.doc.from_template)
.then((doc) => {
frappe.model.clear_table(frm.doc, "accounts");
frm.set_value({
"company": doc.company,
"voucher_type": doc.voucher_type,
"naming_series": doc.naming_series,
"is_opening": doc.is_opening,
"multi_currency": doc.multi_currency
})
update_jv_details(frm.doc, doc.accounts);
from_template: function (frm) {
if (frm.doc.from_template) {
frappe.db.get_doc("Journal Entry Template", frm.doc.from_template).then((doc) => {
frappe.model.clear_table(frm.doc, "accounts");
frm.set_value({
company: doc.company,
voucher_type: doc.voucher_type,
naming_series: doc.naming_series,
is_opening: doc.is_opening,
multi_currency: doc.multi_currency,
});
update_jv_details(frm.doc, doc.accounts);
});
}
}
},
});
var update_jv_details = function(doc, r) {
$.each(r, function(i, d) {
var update_jv_details = function (doc, r) {
$.each(r, function (i, d) {
var row = frappe.model.add_child(doc, "Journal Entry Account", "accounts");
frappe.model.set_value(row.doctype, row.name, "account", d.account)
frappe.model.set_value(row.doctype, row.name, "account", d.account);
});
refresh_field("accounts");
}
};
erpnext.accounts.JournalEntry = class JournalEntry extends frappe.ui.form.Controller {
onload() {
@@ -220,69 +260,67 @@ erpnext.accounts.JournalEntry = class JournalEntry extends frappe.ui.form.Contro
load_defaults() {
//this.frm.show_print_first = true;
if(this.frm.doc.__islocal && this.frm.doc.company) {
if (this.frm.doc.__islocal && this.frm.doc.company) {
frappe.model.set_default_values(this.frm.doc);
$.each(this.frm.doc.accounts || [], function(i, jvd) {
$.each(this.frm.doc.accounts || [], function (i, jvd) {
frappe.model.set_default_values(jvd);
});
var posting_date = this.frm.doc.posting_date;
if(!this.frm.doc.amended_from) this.frm.set_value('posting_date', posting_date || frappe.datetime.get_today());
if (!this.frm.doc.amended_from)
this.frm.set_value("posting_date", posting_date || frappe.datetime.get_today());
}
}
setup_queries() {
var me = this;
me.frm.set_query("account", "accounts", function(doc, cdt, cdn) {
me.frm.set_query("account", "accounts", function (doc, cdt, cdn) {
return erpnext.journal_entry.account_query(me.frm);
});
me.frm.set_query("party_type", "accounts", function(doc, cdt, cdn) {
me.frm.set_query("party_type", "accounts", function (doc, cdt, cdn) {
const row = locals[cdt][cdn];
return {
query: "erpnext.setup.doctype.party_type.party_type.get_party_type",
filters: {
'account': row.account
}
}
account: row.account,
},
};
});
me.frm.set_query("reference_name", "accounts", function(doc, cdt, cdn) {
me.frm.set_query("reference_name", "accounts", function (doc, cdt, cdn) {
var jvd = frappe.get_doc(cdt, cdn);
// journal entry
if(jvd.reference_type==="Journal Entry") {
if (jvd.reference_type === "Journal Entry") {
frappe.model.validate_missing(jvd, "account");
return {
query: "erpnext.accounts.doctype.journal_entry.journal_entry.get_against_jv",
filters: {
account: jvd.account,
party: jvd.party
}
party: jvd.party,
},
};
}
var out = {
filters: [
[jvd.reference_type, "docstatus", "=", 1]
]
filters: [[jvd.reference_type, "docstatus", "=", 1]],
};
if(in_list(["Sales Invoice", "Purchase Invoice"], jvd.reference_type)) {
if (["Sales Invoice", "Purchase Invoice"].includes(jvd.reference_type)) {
out.filters.push([jvd.reference_type, "outstanding_amount", "!=", 0]);
// Filter by cost center
if(jvd.cost_center) {
if (jvd.cost_center) {
out.filters.push([jvd.reference_type, "cost_center", "in", ["", jvd.cost_center]]);
}
// account filter
frappe.model.validate_missing(jvd, "account");
var party_account_field = jvd.reference_type==="Sales Invoice" ? "debit_to": "credit_to";
var party_account_field = jvd.reference_type === "Sales Invoice" ? "debit_to" : "credit_to";
out.filters.push([jvd.reference_type, party_account_field, "=", jvd.account]);
}
if(in_list(["Sales Order", "Purchase Order"], jvd.reference_type)) {
if (["Sales Order", "Purchase Order"].includes(jvd.reference_type)) {
// party_type and party mandatory
frappe.model.validate_missing(jvd, "party_type");
frappe.model.validate_missing(jvd, "party");
@@ -290,11 +328,11 @@ erpnext.accounts.JournalEntry = class JournalEntry extends frappe.ui.form.Contro
out.filters.push([jvd.reference_type, "per_billed", "<", 100]);
}
if(jvd.party_type && jvd.party) {
if (jvd.party_type && jvd.party) {
let party_field = "";
if(jvd.reference_type.indexOf("Sales")===0) {
if (jvd.reference_type.indexOf("Sales") === 0) {
party_field = "customer";
} else if (jvd.reference_type.indexOf("Purchase")===0) {
} else if (jvd.reference_type.indexOf("Purchase") === 0) {
party_field = "supplier";
}
@@ -305,51 +343,49 @@ erpnext.accounts.JournalEntry = class JournalEntry extends frappe.ui.form.Contro
return out;
});
}
reference_name(doc, cdt, cdn) {
var d = frappe.get_doc(cdt, cdn);
if(d.reference_name) {
if (d.reference_type==="Purchase Invoice" && !flt(d.debit)) {
this.get_outstanding('Purchase Invoice', d.reference_name, doc.company, d);
} else if (d.reference_type==="Sales Invoice" && !flt(d.credit)) {
this.get_outstanding('Sales Invoice', d.reference_name, doc.company, d);
} else if (d.reference_type==="Journal Entry" && !flt(d.credit) && !flt(d.debit)) {
this.get_outstanding('Journal Entry', d.reference_name, doc.company, d);
if (d.reference_name) {
if (d.reference_type === "Purchase Invoice" && !flt(d.debit)) {
this.get_outstanding("Purchase Invoice", d.reference_name, doc.company, d);
} else if (d.reference_type === "Sales Invoice" && !flt(d.credit)) {
this.get_outstanding("Sales Invoice", d.reference_name, doc.company, d);
} else if (d.reference_type === "Journal Entry" && !flt(d.credit) && !flt(d.debit)) {
this.get_outstanding("Journal Entry", d.reference_name, doc.company, d);
}
}
}
get_outstanding(doctype, docname, company, child) {
var args = {
"doctype": doctype,
"docname": docname,
"party": child.party,
"account": child.account,
"account_currency": child.account_currency,
"company": company
}
doctype: doctype,
docname: docname,
party: child.party,
account: child.account,
account_currency: child.account_currency,
company: company,
};
return frappe.call({
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_outstanding",
args: { args: args},
callback: function(r) {
if(r.message) {
$.each(r.message, function(field, value) {
args: { args: args },
callback: function (r) {
if (r.message) {
$.each(r.message, function (field, value) {
frappe.model.set_value(child.doctype, child.name, field, value);
})
});
}
}
},
});
}
accounts_add(doc, cdt, cdn) {
var row = frappe.get_doc(cdt, cdn);
$.each(doc.accounts, function(i, d) {
if(d.account && d.party && d.party_type) {
$.each(doc.accounts, function (i, d) {
if (d.account && d.party && d.party_type) {
row.account = d.account;
row.party = d.party;
row.party_type = d.party_type;
@@ -357,8 +393,8 @@ erpnext.accounts.JournalEntry = class JournalEntry extends frappe.ui.form.Contro
});
// set difference
if(doc.difference) {
if(doc.difference > 0) {
if (doc.difference) {
if (doc.difference > 0) {
row.credit_in_account_currency = doc.difference;
row.credit = doc.difference;
} else {
@@ -368,41 +404,43 @@ erpnext.accounts.JournalEntry = class JournalEntry extends frappe.ui.form.Contro
}
cur_frm.cscript.update_totals(doc);
erpnext.accounts.dimensions.copy_dimension_from_first_row(this.frm, cdt, cdn, 'accounts');
erpnext.accounts.dimensions.copy_dimension_from_first_row(this.frm, cdt, cdn, "accounts");
}
};
cur_frm.script_manager.make(erpnext.accounts.JournalEntry);
cur_frm.cscript.update_totals = function(doc) {
var td=0.0; var tc =0.0;
cur_frm.cscript.update_totals = function (doc) {
var td = 0.0;
var tc = 0.0;
var accounts = doc.accounts || [];
for(var i in accounts) {
for (var i in accounts) {
td += flt(accounts[i].debit, precision("debit", accounts[i]));
tc += flt(accounts[i].credit, precision("credit", accounts[i]));
}
doc = locals[doc.doctype][doc.name];
doc.total_debit = td;
doc.total_credit = tc;
doc.difference = flt((td - tc), precision("difference"));
refresh_many(['total_debit','total_credit','difference']);
}
doc.difference = flt(td - tc, precision("difference"));
refresh_many(["total_debit", "total_credit", "difference"]);
};
cur_frm.cscript.get_balance = function(doc,dt,dn) {
cur_frm.cscript.get_balance = function (doc, dt, dn) {
cur_frm.cscript.update_totals(doc);
cur_frm.call('get_balance', null, () => { cur_frm.refresh(); });
}
cur_frm.call("get_balance", null, () => {
cur_frm.refresh();
});
};
cur_frm.cscript.validate = function(doc,cdt,cdn) {
cur_frm.cscript.validate = function (doc, cdt, cdn) {
cur_frm.cscript.update_totals(doc);
}
};
frappe.ui.form.on("Journal Entry Account", {
party: function(frm, cdt, cdn) {
party: function (frm, cdt, cdn) {
var d = frappe.get_doc(cdt, cdn);
if(!d.account && d.party_type && d.party) {
if(!frm.doc.company) frappe.throw(__("Please select Company"));
if (!d.account && d.party_type && d.party) {
if (!frm.doc.company) frappe.throw(__("Please select Company"));
return frm.call({
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_party_account_and_currency",
child: d,
@@ -410,89 +448,97 @@ frappe.ui.form.on("Journal Entry Account", {
company: frm.doc.company,
party_type: d.party_type,
party: d.party,
}
},
});
}
},
cost_center: function(frm, dt, dn) {
cost_center: function (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_details(frm, dt, dn);
},
debit_in_account_currency: function(frm, cdt, cdn) {
debit_in_account_currency: function (frm, cdt, cdn) {
erpnext.journal_entry.set_exchange_rate(frm, cdt, cdn);
},
credit_in_account_currency: function(frm, cdt, cdn) {
credit_in_account_currency: function (frm, cdt, cdn) {
erpnext.journal_entry.set_exchange_rate(frm, cdt, cdn);
},
debit: function(frm, dt, dn) {
debit: function (frm, dt, dn) {
cur_frm.cscript.update_totals(frm.doc);
},
credit: function(frm, dt, dn) {
credit: function (frm, dt, dn) {
cur_frm.cscript.update_totals(frm.doc);
},
exchange_rate: function(frm, cdt, cdn) {
exchange_rate: function (frm, cdt, cdn) {
var company_currency = frappe.get_doc(":Company", frm.doc.company).default_currency;
var row = locals[cdt][cdn];
if(row.account_currency == company_currency || !frm.doc.multi_currency) {
if (row.account_currency == company_currency || !frm.doc.multi_currency) {
frappe.model.set_value(cdt, cdn, "exchange_rate", 1);
}
erpnext.journal_entry.set_debit_credit_in_company_currency(frm, cdt, cdn);
}
})
},
});
frappe.ui.form.on("Journal Entry Account", "accounts_remove", function(frm) {
frappe.ui.form.on("Journal Entry Account", "accounts_remove", function (frm) {
cur_frm.cscript.update_totals(frm.doc);
});
$.extend(erpnext.journal_entry, {
toggle_fields_based_on_currency: function(frm) {
toggle_fields_based_on_currency: function (frm) {
var fields = ["currency_section", "account_currency", "exchange_rate", "debit", "credit"];
var grid = frm.get_field("accounts").grid;
if(grid) grid.set_column_disp(fields, frm.doc.multi_currency);
if (grid) grid.set_column_disp(fields, frm.doc.multi_currency);
// dynamic label
var field_label_map = {
"debit_in_account_currency": "Debit",
"credit_in_account_currency": "Credit"
debit_in_account_currency: "Debit",
credit_in_account_currency: "Credit",
};
$.each(field_label_map, function (fieldname, label) {
frm.fields_dict.accounts.grid.update_docfield_property(
fieldname,
'label',
frm.doc.multi_currency ? (label + " in Account Currency") : label
"label",
frm.doc.multi_currency ? label + " in Account Currency" : label
);
})
});
},
set_debit_credit_in_company_currency: function(frm, cdt, cdn) {
set_debit_credit_in_company_currency: function (frm, cdt, cdn) {
var row = locals[cdt][cdn];
frappe.model.set_value(cdt, cdn, "debit",
flt(flt(row.debit_in_account_currency)*row.exchange_rate, precision("debit", row)));
frappe.model.set_value(
cdt,
cdn,
"debit",
flt(flt(row.debit_in_account_currency) * row.exchange_rate, precision("debit", row))
);
frappe.model.set_value(cdt, cdn, "credit",
flt(flt(row.credit_in_account_currency)*row.exchange_rate, precision("credit", row)));
frappe.model.set_value(
cdt,
cdn,
"credit",
flt(flt(row.credit_in_account_currency) * row.exchange_rate, precision("credit", row))
);
cur_frm.cscript.update_totals(frm.doc);
},
set_exchange_rate: function(frm, cdt, cdn) {
set_exchange_rate: function (frm, cdt, cdn) {
var company_currency = frappe.get_doc(":Company", frm.doc.company).default_currency;
var row = locals[cdt][cdn];
if(row.account_currency == company_currency || !frm.doc.multi_currency) {
if (row.account_currency == company_currency || !frm.doc.multi_currency) {
row.exchange_rate = 1;
erpnext.journal_entry.set_debit_credit_in_company_currency(frm, cdt, cdn);
} else if (!row.exchange_rate || row.exchange_rate == 1 || row.account_type == "Bank") {
@@ -507,50 +553,70 @@ $.extend(erpnext.journal_entry, {
reference_name: cstr(row.reference_name),
debit: flt(row.debit_in_account_currency),
credit: flt(row.credit_in_account_currency),
exchange_rate: row.exchange_rate
exchange_rate: row.exchange_rate,
},
callback: function(r) {
if(r.message) {
callback: function (r) {
if (r.message) {
row.exchange_rate = r.message;
erpnext.journal_entry.set_debit_credit_in_company_currency(frm, cdt, cdn);
}
}
})
},
});
} else {
erpnext.journal_entry.set_debit_credit_in_company_currency(frm, cdt, cdn);
}
refresh_field("exchange_rate", cdn, "accounts");
},
quick_entry: function(frm) {
quick_entry: function (frm) {
var naming_series_options = frm.fields_dict.naming_series.df.options;
var naming_series_default = frm.fields_dict.naming_series.df.default || naming_series_options.split("\n")[0];
var naming_series_default =
frm.fields_dict.naming_series.df.default || naming_series_options.split("\n")[0];
var dialog = new frappe.ui.Dialog({
title: __("Quick Journal Entry"),
fields: [
{fieldtype: "Currency", fieldname: "debit", label: __("Amount"), reqd: 1},
{fieldtype: "Link", fieldname: "debit_account", label: __("Debit Account"), reqd: 1,
{ fieldtype: "Currency", fieldname: "debit", label: __("Amount"), reqd: 1 },
{
fieldtype: "Link",
fieldname: "debit_account",
label: __("Debit Account"),
reqd: 1,
options: "Account",
get_query: function() {
get_query: function () {
return erpnext.journal_entry.account_query(frm);
}
},
},
{fieldtype: "Link", fieldname: "credit_account", label: __("Credit Account"), reqd: 1,
{
fieldtype: "Link",
fieldname: "credit_account",
label: __("Credit Account"),
reqd: 1,
options: "Account",
get_query: function() {
get_query: function () {
return erpnext.journal_entry.account_query(frm);
}
},
},
{fieldtype: "Date", fieldname: "posting_date", label: __("Date"), reqd: 1,
default: frm.doc.posting_date},
{fieldtype: "Small Text", fieldname: "user_remark", label: __("User Remark")},
{fieldtype: "Select", fieldname: "naming_series", label: __("Series"), reqd: 1,
options: naming_series_options, default: naming_series_default},
]
{
fieldtype: "Date",
fieldname: "posting_date",
label: __("Date"),
reqd: 1,
default: frm.doc.posting_date,
},
{ fieldtype: "Small Text", fieldname: "user_remark", label: __("User Remark") },
{
fieldtype: "Select",
fieldname: "naming_series",
label: __("Series"),
reqd: 1,
options: naming_series_options,
default: naming_series_default,
},
],
});
dialog.set_primary_action(__("Save"), function() {
dialog.set_primary_action(__("Save"), function () {
var btn = this;
var values = dialog.get_values();
@@ -567,11 +633,21 @@ $.extend(erpnext.journal_entry, {
var debit_row = frm.fields_dict.accounts.grid.add_new_row();
frappe.model.set_value(debit_row.doctype, debit_row.name, "account", values.debit_account);
frappe.model.set_value(debit_row.doctype, debit_row.name, "debit_in_account_currency", values.debit);
frappe.model.set_value(
debit_row.doctype,
debit_row.name,
"debit_in_account_currency",
values.debit
);
var credit_row = frm.fields_dict.accounts.grid.add_new_row();
frappe.model.set_value(credit_row.doctype, credit_row.name, "account", values.credit_account);
frappe.model.set_value(credit_row.doctype, credit_row.name, "credit_in_account_currency", values.debit);
frappe.model.set_value(
credit_row.doctype,
credit_row.name,
"credit_in_account_currency",
values.debit
);
frm.save();
@@ -581,33 +657,36 @@ $.extend(erpnext.journal_entry, {
dialog.show();
},
account_query: function(frm) {
account_query: function (frm) {
var filters = {
company: frm.doc.company,
is_group: 0
is_group: 0,
};
if(!frm.doc.multi_currency) {
if (!frm.doc.multi_currency) {
$.extend(filters, {
account_currency: ['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 };
},
reverse_journal_entry: function() {
reverse_journal_entry: function () {
frappe.model.open_mapped_doc({
method: "erpnext.accounts.doctype.journal_entry.journal_entry.make_reverse_journal_entry",
frm: cur_frm
})
frm: cur_frm,
});
},
});
$.extend(erpnext.journal_entry, {
set_account_details: function(frm, dt, dn) {
set_account_details: function (frm, dt, dn) {
var d = locals[dt][dn];
if(d.account) {
if(!frm.doc.company) frappe.throw(__("Please select Company first"));
if(!frm.doc.posting_date) frappe.throw(__("Please select Posting Date first"));
if (d.account) {
if (!frm.doc.company) frappe.throw(__("Please select Company first"));
if (!frm.doc.posting_date) frappe.throw(__("Please select Posting Date first"));
return frappe.call({
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_account_details_and_party_type",
@@ -619,13 +698,13 @@ $.extend(erpnext.journal_entry, {
credit: flt(d.credit_in_account_currency),
exchange_rate: d.exchange_rate,
},
callback: function(r) {
if(r.message) {
callback: function (r) {
if (r.message) {
$.extend(d, r.message);
erpnext.journal_entry.set_debit_credit_in_company_currency(frm, dt, dn);
refresh_field('accounts');
refresh_field("accounts");
}
}
},
});
}
},

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -404,7 +404,9 @@ class PaymentEntry(AccountsController):
ref_details = get_reference_details(
d.reference_doctype, d.reference_name, self.party_account_currency
)
if ref_exchange_rate:
# Only update exchange rate when the reference is Journal Entry
if ref_exchange_rate and d.reference_doctype == "Journal Entry":
ref_details.update({"exchange_rate": ref_exchange_rate})
for field, value in ref_details.items():
@@ -526,9 +528,9 @@ class PaymentEntry(AccountsController):
def get_valid_reference_doctypes(self):
if self.party_type == "Customer":
return ("Sales Order", "Sales Invoice", "Journal Entry", "Dunning")
return ("Sales Order", "Sales Invoice", "Journal Entry", "Dunning", "Payment Entry")
elif self.party_type == "Supplier":
return ("Purchase Order", "Purchase Invoice", "Journal Entry")
return ("Purchase Order", "Purchase Invoice", "Journal Entry", "Payment Entry")
elif self.party_type == "Shareholder":
return ("Journal Entry",)
elif self.party_type == "Employee":
@@ -1185,7 +1187,14 @@ class PaymentEntry(AccountsController):
references = [x for x in self.get("references") if x.name == entry.name]
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",
"Payment Entry",
):
self.add_advance_gl_for_reference(gl_entries, ref)
def add_advance_gl_for_reference(self, gl_entries, invoice):
@@ -1199,14 +1208,17 @@ class PaymentEntry(AccountsController):
"voucher_detail_no": invoice.name,
}
posting_date = frappe.db.get_value(
invoice.reference_doctype, invoice.reference_name, "posting_date"
)
date_field = "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):
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", "Payment Entry"] else "debit"
)
args_dict["account"] = invoice.account
args_dict[dr_or_cr] = invoice.allocated_amount
args_dict[dr_or_cr + "_in_account_currency"] = invoice.allocated_amount
@@ -1653,7 +1665,7 @@ def get_outstanding_reference_documents(args, validate=False):
outstanding_invoices = get_outstanding_invoices(
args.get("party_type"),
args.get("party"),
party_account,
[party_account],
common_filter=common_filter,
posting_date=posting_and_due_date,
min_outstanding=args.get("outstanding_amt_greater_than"),
@@ -2108,6 +2120,11 @@ def get_reference_details(reference_doctype, reference_name, party_account_curre
else:
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:
# 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)

View File

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

View File

@@ -1070,6 +1070,8 @@ class TestPaymentEntry(FrappeTestCase):
self.assertRaises(frappe.ValidationError, pe_draft.submit)
def test_details_update_on_reference_table(self):
from erpnext.accounts.party import get_party_account
so = make_sales_order(
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)
expected_response = {
"account": get_party_account("Customer", so.customer, so.company),
"total_amount": 5000.0,
"outstanding_amount": 5000.0,
"exchange_rate": 1.0,
@@ -1511,6 +1514,168 @@ class TestPaymentEntry(FrappeTestCase):
self.assertEqual(references[1].payment_term, "Basic Amount Receivable")
self.assertEqual(references[2].payment_term, "Tax Receivable")
def test_reverse_payment_reconciliation(self):
customer = create_customer(frappe.generate_hash(length=10), "INR")
pe = create_payment_entry(
party_type="Customer",
party=customer,
payment_type="Receive",
paid_from="Debtors - _TC",
paid_to="_Test Cash - _TC",
)
pe.submit()
reverse_pe = create_payment_entry(
party_type="Customer",
party=customer,
payment_type="Pay",
paid_from="_Test Cash - _TC",
paid_to="Debtors - _TC",
)
reverse_pe.submit()
pr = frappe.get_doc("Payment Reconciliation")
pr.company = "_Test Company"
pr.party_type = "Customer"
pr.party = customer
pr.receivable_payable_account = "Debtors - _TC"
pr.get_unreconciled_entries()
self.assertEqual(len(pr.invoices), 1)
self.assertEqual(len(pr.payments), 1)
self.assertEqual(reverse_pe.name, pr.invoices[0].invoice_number)
self.assertEqual(pe.name, pr.payments[0].reference_name)
invoices = [x.as_dict() for x in pr.invoices]
payments = [pr.payments[0].as_dict()]
pr.allocate_entries(frappe._dict({"invoices": invoices, "payments": payments}))
pr.reconcile()
self.assertEqual(len(pr.invoices), 0)
self.assertEqual(len(pr.payments), 0)
def test_advance_reverse_payment_reconciliation(self):
from erpnext.accounts.doctype.account.test_account import create_account
company = "_Test Company"
customer = create_customer(frappe.generate_hash(length=10), "INR")
advance_account = create_account(
parent_account="Current Assets - _TC",
account_name="Advances Received",
company=company,
account_type="Receivable",
)
frappe.db.set_value(
"Company",
company,
{
"book_advance_payments_in_separate_party_account": 1,
"default_advance_received_account": advance_account,
},
)
# Reverse Payment(essentially an Invoice)
reverse_pe = create_payment_entry(
party_type="Customer",
party=customer,
payment_type="Pay",
paid_from="_Test Cash - _TC",
paid_to=advance_account,
)
reverse_pe.save() # use save() to trigger set_liability_account()
reverse_pe.submit()
# Advance Payment
pe = create_payment_entry(
party_type="Customer",
party=customer,
payment_type="Receive",
paid_from=advance_account,
paid_to="_Test Cash - _TC",
)
pe.save() # use save() to trigger set_liability_account()
pe.submit()
# Partially reconcile advance against invoice
pr = frappe.get_doc("Payment Reconciliation")
pr.company = company
pr.party_type = "Customer"
pr.party = customer
pr.receivable_payable_account = "Debtors - _TC"
pr.default_advance_account = advance_account
pr.get_unreconciled_entries()
self.assertEqual(len(pr.invoices), 1)
self.assertEqual(len(pr.payments), 1)
invoices = [x.as_dict() for x in pr.get("invoices")]
payments = [x.as_dict() for x in pr.get("payments")]
pr.allocate_entries(frappe._dict({"invoices": invoices, "payments": payments}))
pr.allocation[0].allocated_amount = 400
pr.reconcile()
# assert General and Payment Ledger entries post partial reconciliation
self.expected_gle = [
{"account": "Debtors - _TC", "debit": 0.0, "credit": 400.0},
{"account": advance_account, "debit": 400.0, "credit": 0.0},
{"account": advance_account, "debit": 0.0, "credit": 1000.0},
{"account": "_Test Cash - _TC", "debit": 1000.0, "credit": 0.0},
]
self.expected_ple = [
{
"account": advance_account,
"voucher_no": pe.name,
"against_voucher_no": pe.name,
"amount": -1000.0,
},
{
"account": "Debtors - _TC",
"voucher_no": pe.name,
"against_voucher_no": reverse_pe.name,
"amount": -400.0,
},
{
"account": advance_account,
"voucher_no": pe.name,
"against_voucher_no": pe.name,
"amount": 400.0,
},
]
self.voucher_no = pe.name
self.check_gl_entries()
self.check_pl_entries()
# Unreconcile
unrecon = (
frappe.get_doc(
{
"doctype": "Unreconcile Payment",
"company": company,
"voucher_type": pe.doctype,
"voucher_no": pe.name,
"allocations": [{"reference_doctype": reverse_pe.doctype, "reference_name": reverse_pe.name}],
}
)
.save()
.submit()
)
# assert General and Payment Ledger entries post unreconciliation
self.expected_gle = [
{"account": advance_account, "debit": 0.0, "credit": 1000.0},
{"account": "_Test Cash - _TC", "debit": 1000.0, "credit": 0.0},
]
self.expected_ple = [
{
"account": advance_account,
"voucher_no": pe.name,
"against_voucher_no": pe.name,
"amount": -1000.0,
},
]
self.voucher_no = pe.name
self.check_gl_entries()
self.check_pl_entries()
def create_payment_entry(**args):
payment_entry = frappe.new_doc("Payment Entry")

View File

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

View File

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

View File

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

View File

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

View File

@@ -340,10 +340,15 @@ class PaymentReconciliation(Document):
self.build_qb_filter_conditions(get_invoices=True)
accounts = [self.receivable_payable_account]
if self.default_advance_account:
accounts.append(self.default_advance_account)
non_reconciled_invoices = get_outstanding_invoices(
self.party_type,
self.party,
self.receivable_payable_account,
accounts,
common_filter=self.common_filter_conditions,
posting_date=self.ple_posting_date_filter,
min_outstanding=self.minimum_invoice_amount if self.minimum_invoice_amount else None,

View File

@@ -1130,6 +1130,17 @@ class TestPaymentReconciliation(FrappeTestCase):
self.assertEqual(pr.allocation[0].allocated_amount, 85)
self.assertEqual(pr.allocation[0].difference_amount, 0)
pr.reconcile()
si.reload()
self.assertEqual(si.outstanding_amount, 0)
# No Exchange Gain/Loss journal should be generated
exc_gain_loss_journals = frappe.db.get_all(
"Journal Entry Account",
filters={"reference_type": si.doctype, "reference_name": si.name, "docstatus": 1},
fields=["parent"],
)
self.assertEqual(exc_gain_loss_journals, [])
def test_reconciliation_purchase_invoice_against_return(self):
self.supplier = "_Test Supplier USD"
pi = self.create_purchase_invoice(qty=5, rate=50, do_not_submit=True)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -141,7 +141,8 @@ class PeriodClosingVoucher(AccountsController):
previous_fiscal_year = get_fiscal_year(last_year_closing, company=self.company, boolean=True)
if previous_fiscal_year and not frappe.db.exists(
"GL Entry", {"posting_date": ("<=", last_year_closing), "company": self.company}
"GL Entry",
{"posting_date": ("<=", last_year_closing), "company": self.company, "is_cancelled": 0},
):
return

View File

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

View File

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

View File

@@ -21,19 +21,23 @@ erpnext.selling.POSInvoiceController = class POSInvoiceController extends erpnex
onload(doc) {
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.refresh_fields();
}
this.frm.set_query("set_warehouse", function(doc) {
this.frm.set_query("set_warehouse", function (doc) {
return {
filters: {
company: doc.company ? doc.company : '',
}
}
company: doc.company ? doc.company : "",
},
};
});
erpnext.accounts.dimensions.setup_dimension_filters(this.frm, this.frm.doctype);
@@ -47,26 +51,29 @@ erpnext.selling.POSInvoiceController = class POSInvoiceController extends erpnex
super.refresh();
if (doc.docstatus == 1 && !doc.is_return) {
this.frm.add_custom_button(__('Return'), this.make_sales_return, __('Create'));
this.frm.page.set_inner_btn_group_as_primary(__('Create'));
this.frm.add_custom_button(__("Return"), this.make_sales_return, __("Create"));
this.frm.page.set_inner_btn_group_as_primary(__("Create"));
}
if (doc.is_return && doc.__islocal) {
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 () {
const customer_groups = this.settings?.customer_groups;
this.frm.set_query(
"customer",
function () {
const customer_groups = this.settings?.customer_groups;
if (!customer_groups?.length) return {};
if (!customer_groups?.length) return {};
return {
filters: {
customer_group: ["in", customer_groups],
}
}
}).bind(this));
return {
filters: {
customer_group: ["in", customer_groups],
},
};
}.bind(this)
);
}
is_pos() {
@@ -74,19 +81,19 @@ erpnext.selling.POSInvoiceController = class POSInvoiceController extends erpnex
}
async set_pos_data() {
if(this.frm.doc.is_pos) {
if (this.frm.doc.is_pos) {
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);
frappe.msgprint(__("Please specify Company to proceed"));
} else {
const r = await this.frm.call({
doc: this.frm.doc,
method: "set_missing_values",
freeze: true
freeze: true,
});
if(!r.exc) {
if(r.message) {
if (!r.exc) {
if (r.message) {
this.frm.pos_print_format = r.message.print_format || "";
this.frm.meta.default_print_format = r.message.print_format || "";
this.frm.doc.campaign = r.message.campaign;
@@ -103,32 +110,36 @@ erpnext.selling.POSInvoiceController = class POSInvoiceController extends erpnex
}
customer() {
if (!this.frm.doc.customer) return
if (!this.frm.doc.customer) return;
const pos_profile = this.frm.doc.pos_profile;
if(this.frm.updating_party_details) return;
erpnext.utils.get_party_details(this.frm,
"erpnext.accounts.party.get_party_details", {
if (this.frm.updating_party_details) return;
erpnext.utils.get_party_details(
this.frm,
"erpnext.accounts.party.get_party_details",
{
posting_date: this.frm.doc.posting_date,
party: this.frm.doc.customer,
party_type: "Customer",
account: this.frm.doc.debit_to,
price_list: this.frm.doc.selling_price_list,
pos_profile: pos_profile,
company_address: this.frm.doc.company_address
}, () => {
company_address: this.frm.doc.company_address,
},
() => {
this.apply_pricing_rule();
});
}
);
}
pos_profile(frm) {
if (!frm.pos_profile || frm.pos_profile == '') {
if (!frm.pos_profile || frm.pos_profile == "") {
this.update_customer_groups_settings([]);
return;
}
frappe.call({
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 }) => {
this.update_customer_groups_settings(profile?.customer_groups);
this.frm.set_value("company", profile?.company);
@@ -137,17 +148,17 @@ erpnext.selling.POSInvoiceController = class POSInvoiceController extends erpnex
}
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(){
this.write_off_outstanding_amount_automatically()
amount() {
this.write_off_outstanding_amount_automatically();
}
change_amount(){
if(this.frm.doc.paid_amount > this.frm.doc.grand_total){
change_amount() {
if (this.frm.doc.paid_amount > this.frm.doc.grand_total) {
this.calculate_write_off_amount();
}else {
} else {
this.frm.set_value("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();
}
loyalty_amount(){
loyalty_amount() {
this.calculate_outstanding_amount();
this.frm.refresh_field("outstanding_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)) {
frappe.model.round_floats_in(this.frm.doc, ["grand_total", "paid_amount"]);
// this will make outstanding amount 0
this.frm.set_value("write_off_amount",
flt(this.frm.doc.grand_total - this.frm.doc.paid_amount - this.frm.doc.total_advance, precision("write_off_amount"))
this.frm.set_value(
"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() {
frappe.model.open_mapped_doc({
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', {
redeem_loyalty_points: function(frm) {
frappe.ui.form.on("POS Invoice", {
redeem_loyalty_points: function (frm) {
frm.events.get_loyalty_details(frm);
},
loyalty_points: function(frm) {
loyalty_points: function (frm) {
if (frm.redemption_conversion_factor) {
frm.events.set_loyalty_points(frm);
} else {
frappe.call({
method: "erpnext.accounts.doctype.loyalty_program.loyalty_program.get_redeemption_factor",
args: {
"loyalty_program": frm.doc.loyalty_program
loyalty_program: frm.doc.loyalty_program,
},
callback: function(r) {
callback: function (r) {
if (r) {
frm.redemption_conversion_factor = r.message;
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) {
frappe.call({
method: "erpnext.accounts.doctype.loyalty_program.loyalty_program.get_loyalty_program_details",
args: {
"customer": frm.doc.customer,
"loyalty_program": frm.doc.loyalty_program,
"expiry_date": frm.doc.posting_date,
"company": frm.doc.company
customer: frm.doc.customer,
loyalty_program: frm.doc.loyalty_program,
expiry_date: frm.doc.posting_date,
company: frm.doc.company,
},
callback: function(r) {
callback: function (r) {
if (r) {
frm.set_value("loyalty_redemption_account", r.message.expense_account);
frm.set_value("loyalty_redemption_cost_center", r.message.cost_center);
frm.redemption_conversion_factor = r.message.conversion_factor;
}
}
},
});
}
},
set_loyalty_points: function(frm) {
set_loyalty_points: function (frm) {
if (frm.redemption_conversion_factor) {
let loyalty_amount = flt(frm.redemption_conversion_factor*flt(frm.doc.loyalty_points), precision("loyalty_amount"));
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]));
let loyalty_amount = flt(
frm.redemption_conversion_factor * flt(frm.doc.loyalty_points),
precision("loyalty_amount")
);
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);
}
@@ -244,43 +263,49 @@ frappe.ui.form.on('POS Invoice', {
request_for_payment: function (frm) {
if (!frm.doc.contact_mobile) {
frappe.throw(__('Please enter mobile number first.'));
frappe.throw(__("Please enter mobile number first."));
}
frm.dirty();
frm.save().then(() => {
frappe.dom.freeze(__('Waiting for payment...'));
frappe.dom.freeze(__("Waiting for payment..."));
frappe
.call({
method: 'create_payment_request',
doc: frm.doc
method: "create_payment_request",
doc: frm.doc,
})
.fail(() => {
frappe.dom.unfreeze();
frappe.msgprint(__('Payment request failed'));
frappe.msgprint(__("Payment request failed"));
})
.then(({ message }) => {
const payment_request_name = message.name;
setTimeout(() => {
frappe.db.get_value('Payment Request', payment_request_name, ['status', 'grand_total']).then(({ message }) => {
if (message.status != 'Paid') {
frappe.dom.unfreeze();
frappe.msgprint({
message: __('Payment Request took too long to respond. Please try requesting for payment again.'),
title: __('Request Timeout')
});
} else if (frappe.dom.freeze_count != 0) {
frappe.dom.unfreeze();
cur_frm.reload_doc();
cur_pos.payment.events.submit_invoice();
frappe.db
.get_value("Payment Request", payment_request_name, ["status", "grand_total"])
.then(({ message }) => {
if (message.status != "Paid") {
frappe.dom.unfreeze();
frappe.msgprint({
message: __(
"Payment Request took too long to respond. Please try requesting for payment again."
),
title: __("Request Timeout"),
});
} else if (frappe.dom.freeze_count != 0) {
frappe.dom.unfreeze();
cur_frm.reload_doc();
cur_pos.payment.events.submit_invoice();
frappe.show_alert({
message: __("Payment of {0} received successfully.", [format_currency(message.grand_total, frm.doc.currency, 0)]),
indicator: 'green'
});
}
});
frappe.show_alert({
message: __("Payment of {0} received successfully.", [
format_currency(message.grand_total, frm.doc.currency, 0),
]),
indicator: "green",
});
}
});
}, 60000);
});
});
}
},
});

View File

@@ -775,7 +775,7 @@
},
{
"fieldname": "other_charges_calculation",
"fieldtype": "Long Text",
"fieldtype": "Text Editor",
"label": "Taxes and Charges Calculation",
"no_copy": 1,
"oldfieldtype": "HTML",
@@ -1563,7 +1563,7 @@
"icon": "fa fa-file-text",
"is_submittable": 1,
"links": [],
"modified": "2023-11-20 12:27:12.848149",
"modified": "2024-03-20 16:00:34.268756",
"modified_by": "Administrator",
"module": "Accounts",
"name": "POS Invoice",

View File

@@ -109,7 +109,7 @@ class POSInvoice(SalesInvoice):
loyalty_redemption_cost_center: DF.Link | None
naming_series: DF.Literal["ACC-PSINV-.YYYY.-"]
net_total: DF.Currency
other_charges_calculation: DF.LongText | None
other_charges_calculation: DF.TextEditor | None
outstanding_amount: DF.Currency
packed_items: DF.Table[PackedItem]
paid_amount: DF.Currency

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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