Compare commits

...

257 Commits

Author SHA1 Message Date
gavin
49b0afccbd Merge pull request #21213 from gavindsouza/freeze-v10
chore(v10): pin python dependencies
2020-06-15 10:27:53 +05:30
Gavin D'souza
1183d3e1bc chore(travis): update and install setuptools and pip 2020-04-09 20:22:20 +05:30
Gavin D'souza
f876f4c2b2 chore: allow sudo in travis runs 2020-04-09 17:50:33 +05:30
Gavin D'souza
ac4a3057cf fix: travis add pip3 addon 2020-04-09 17:40:25 +05:30
Gavin D'souza
999216e727 fix: update easy install script usage 2020-04-09 15:17:41 +05:30
Gavin D'souza
a5fa29f256 chore: pin python dependencies 2020-04-09 10:44:34 +05:30
Deepesh Garg
1fddde0c0e fix: Account type in Handling Difference in Inventory account (#19678)
* fix: Account type in Handling Difference in Inventory account

* fix: Add Stock Adjustment account

* fix: Rename account to stock adjustment
2019-11-28 18:29:46 +05:30
Mangesh-Khairnar
e269aa9781 fix(bin): update requested qty in bin (#18314) 2019-07-15 14:07:50 +05:30
Aditya Hase
30be1181ea fix(error-report): Do not send error reports to support@erpnext.com (#17864) 2019-06-06 11:16:01 +05:30
Shivam Mishra
5a1b778cd2 Merge pull request #17793 from adityahase/remove-manifest-v10
perf: Remove MANIFEST.in
2019-05-29 15:31:19 +05:30
Aditya Hase
6dcc3a7596 perf: Remove MANIFEST.in
Faster pip install -e erpnext

https://stackoverflow.com/questions/24727709/do-python-projects-need-a-manifest-in-and-what-should-be-in-it

https://github.com/frappe/frappe/pull/7360
2019-05-29 15:15:51 +05:30
Shivam Mishra
3657b2b0a4 fix: Task status fix (#17498) 2019-05-06 14:52:30 +05:30
Nabin Hait
cd701e3e6f Merge pull request #17149 from hrwX/gst_patch
fix(India): run patch for GST custom fields
2019-05-03 09:26:04 +05:30
Nabin Hait
55e54ef6a1 skip the patch for outside India 2019-05-02 21:56:44 +05:30
Nabin Hait
fb12805435 Merge pull request #17345 from deepeshgarg007/delivery_note_v10
fix: Make button not appearing in delivery note
2019-04-23 18:41:33 +05:30
deepeshgarg007
d21f1c0ce2 fix: Make button not appearing in delivery note 2019-04-23 17:56:05 +05:30
Saurabh
60b6f79349 Merge pull request #17303 from sahil28297/new_v10_site_sync
fix(site_sync): return more data in level
2019-04-22 12:01:35 +05:30
Sahil Khan
9366449cb4 fix: import iteritems 2019-04-22 11:07:18 +05:30
Sahil Khan
d12ede8510 fix: syntax error 2019-04-22 10:11:35 +05:30
Deepesh Garg
63f1eded95 fix: Datatype fix for balance in account currency (#17314) 2019-04-20 20:41:17 +05:30
Sahil Khan
a34f459065 fix: refactor level 2019-04-20 14:29:11 +05:30
Sahil Khan
ff1bd34e4c fix(site_sync): return more data in level 2019-04-19 16:36:40 +05:30
sahil28297
6e63de447a Merge pull request #17247 from frappe/revert-17227-v10_site_sync
Revert "feat(site_sync): return erpnext data"
2019-04-16 13:23:48 +05:30
sahil28297
d7ae52cd49 Revert "feat(site_sync): return erpnext data" 2019-04-16 13:23:16 +05:30
Nabin Hait
57646ec7de Merge pull request #17240 from hrwX/delivery_note_fix
fix(Delivery Note): Show get items even if note has been amended
2019-04-16 13:21:30 +05:30
Himanshu
d492db4ccb fix: let user delete the elements of items 2019-04-16 13:16:19 +05:30
Nabin Hait
16651241e8 Merge pull request #17227 from sahil28297/v10_site_sync
feat(site_sync): return erpnext data
2019-04-16 12:43:15 +05:30
Himanshu Warekar
e87e6d07ba fix: show get items even if note has been amended 2019-04-16 11:43:25 +05:30
Sahil Khan
a75973e9e5 feat(site_sync): return erpnext data 2019-04-14 18:45:31 +05:30
Himanshu Warekar
4802fc018b fix: run patch for gst 2019-04-05 17:01:19 +05:30
Nabin Hait
e012e2207a Merge pull request #17103 from hrwX/hsn_v10
fix(India): HSN Code
2019-04-05 15:52:01 +05:30
Himanshu Warekar
b7e0ae68ca fix: run gst patch 2019-04-04 11:17:15 +05:30
Himanshu Warekar
0e971f5088 Merge branch 'v10.x.x' of https://github.com/frappe/erpnext into hsn_v10 2019-04-04 11:16:44 +05:30
Nabin Hait
79936fa949 map supplier warehouse from PR to PI 2019-04-01 21:50:20 +05:30
Himanshu Warekar
203a712071 fix(India): HSN Code 2019-04-01 20:03:13 +05:30
Himanshu
c4bdefe666 fix(Leave Balance Report): return correct total number of leaves (#17009)
* fix: return correct total nuber of leaves

* Use ORM for query
2019-03-26 17:00:20 +05:30
Sagar Vora
898977bda8 Merge branch 'hotfix' 2019-01-29 17:10:19 +05:30
Sagar Vora
b32d9458b5 bumped to version 10.1.81 2019-01-29 17:30:19 +05:50
Nabin Hait
25cb13c0f8 Merge pull request #16508 from navdeepghai1/salary-slip-net-pay-fixes
fix(human resources): gross pay calculation issue
2019-01-29 12:08:11 +05:30
Nabin Hait
1c5d681f65 Merge pull request #16500 from scmmishra/v10-remove-docs
feat: [v10] Deprecate In App Help
2019-01-29 11:05:25 +05:30
Nabin Hait
8fae0b3017 Merge pull request #16242 from rohitwaghchaure/is_fixed_asset_checkbox_not_copied
[Fix] Is fixed asset checkbox not checked if user duplicate the existing invoice
2019-01-29 11:03:44 +05:30
Nabin Hait
57928a5382 Merge pull request #16468 from sagarvora/fix-scorecard
fix(buying): make supplier scorecard usable
2019-01-29 11:00:18 +05:30
Nabin Hait
b44b200e7c Merge branch 'hotfix' into fix-scorecard 2019-01-29 11:00:07 +05:30
Aditya Hase
9acb885e60 fix(sqli): Avoid SQL Injection with sender param (#16509) 2019-01-29 10:52:37 +05:30
Navdeep Ghai
ec570026e1 Merge branch 'hotfix' into salary-slip-net-pay-fixes 2019-01-29 09:12:37 +04:00
Nabin Hait
385e3bb284 Merge pull request #16446 from Zlash65/jv-fix
fix(accounts): wrong filters sent to fetch reference name in Journal Entry
2019-01-29 10:41:15 +05:30
navdeepghai1
92bb84aa70 Changed static precision(2) value to system setting currency_precision value 2019-01-28 16:54:58 +04:00
Sagar Vora
a1a946fcd6 Merge branch 'hotfix' into fix-scorecard 2019-01-28 12:20:55 +05:30
navdeepghai1
aac404a155 Fixed net_pay calculation issue 2019-01-28 10:42:16 +04:00
scmmishra
1b63fa1920 [fix] Formatting issues 2019-01-25 20:45:04 +05:30
scmmishra
e1f5d22a02 [fix] Code formatting, removed trailing spaces 2019-01-25 20:45:04 +05:30
scmmishra
000e216354 [feat] Added docsUrl variable to configure help_links 2019-01-25 20:44:45 +05:30
scmmishra
0be2aa33ac [fix] Links now redirect to erpnext.com 2019-01-25 20:41:54 +05:30
scmmishra
c6c1628c8a [feat] Modified help config 2019-01-25 20:41:54 +05:30
Nabin Hait
50e552321b Merge pull request #16363 from scmmishra/leave-application-naming
fix: Naming series not reflecting in leave application
2019-01-25 10:34:01 +05:30
Sagar Vora
e9778d9556 fix: do not use built-in "input", reload_doc 2019-01-23 17:13:31 +05:30
Sagar Vora
f51661b225 fix: allow operators, make weighting_function mandatory 2019-01-23 16:42:28 +05:30
Sagar Vora
9aeabce3d3 fix: trailing whitespace, duplication & more 2019-01-23 16:01:19 +05:30
Sagar Vora
57d7c837aa fix: supplier scorecard test 2019-01-23 14:26:35 +05:30
Sagar Vora
fb256d68ff Merge branch 'fix-supplier-scorecard' of /home/snv/Work/master_bench/apps/erpnext into fix-scorecard 2019-01-23 14:13:40 +05:30
Sagar Vora
037d0f8ba6 fix(buying): make supplier scorecard usable 2019-01-23 14:11:25 +05:30
Frappe Bot
d801437f5f Merge branch 'hotfix' 2019-01-23 08:08:53 +00:00
Frappe Bot
342854f6f2 bumped to version 10.1.80 2019-01-23 08:08:53 +00:00
Nabin Hait
06607fda4e fix: removed print statement 2019-01-23 12:15:48 +05:30
Nabin Hait
141c543f97 Update journal_entry.js 2019-01-23 12:14:55 +05:30
Aditya Hase
819a16d0f5 fix(dead-code): Remove .py files (#16462) 2019-01-23 07:57:08 +05:30
FinByz Tech Pvt. Ltd
237a871f17 fix: NoneType object has no attribute "gstin" (#16458)
* fix: NoneType object has no attribute "gstin"

* fix: handle NoneType values
2019-01-22 20:49:06 +05:30
Sagar Vora
33bc3f3309 Merge branch 'hotfix' 2019-01-22 18:15:44 +05:30
Sagar Vora
2a9a867f05 bumped to version 10.1.79 2019-01-22 18:35:44 +05:50
Sagar Vora
ecf6467799 fix(travis): Redis must be working for caching, so reverting (#16455) 2019-01-22 17:41:56 +05:30
Sagar Vora
8c8e4fd130 Merge branch 'hotfix' 2019-01-22 15:33:48 +05:30
Sagar Vora
1e61dd024b bumped to version 10.1.78 2019-01-22 15:53:48 +05:50
Zlash65
270c4c2a87 fix: push party filter only if applicable 2019-01-22 12:47:25 +05:30
Zlash65
c8d632ddff fix: add set query for payroll entry in JV 2019-01-22 12:46:13 +05:30
Faris Ansari
f523611e12 Merge branch 'hotfix' into leave-application-naming 2019-01-18 14:30:39 +05:30
Nabin Hait
7bea25a23a Merge pull request #16415 from ks093/ks093-shopping-cart-fixes
fix: Show stock validation message while placing order and Quotation series field fix in shopping cart settings.
2019-01-18 10:46:24 +05:30
ks093
61c781325d Fix to show low stock message.
In case of order being placed with stock quantity more than available, message showing stock available wasn't showing due to tuple unpacking not happening correctly.
2019-01-17 12:16:43 +05:30
ks093
1ed819bb10 Refresh quotation_series field to show series 2019-01-17 12:09:04 +05:30
Nabin Hait
c8ac825f0d Merge branch 'hotfix' into leave-application-naming 2019-01-16 17:54:35 +05:30
Nabin Hait
f0571ddf4b Merge pull request #16393 from diamorafaela/quotation-currency
fix: Quotation to Sales Order with different currency
2019-01-16 10:13:44 +05:30
Nabin Hait
d98315c41c Merge pull request #16402 from sagarvora/fix-patch-testing
fix(tests): change patch order, optimise Travis
2019-01-16 10:13:14 +05:30
Saurabh
529cc1ca51 bumped to version 10.1.77 2019-01-15 19:46:36 +06:00
Nabin Hait
d36bc5a9fd Merge pull request #16327 from nabinhait/group_warehouse_stock_reco
Fetch items based on group warehouse in Stock Reconciliation
2019-01-15 17:49:07 +05:30
Sagar Vora
876d868fa1 fix(tests): change patch order, optimise travis 2019-01-15 15:45:33 +05:30
NahuelOperto
9080221d46 fix: added test cases 2019-01-14 12:12:56 -03:00
Nabin Hait
d92024bb0f Merge branch 'hotfix' into leave-application-naming 2019-01-14 20:26:01 +05:30
Nabin Hait
acd7f73d57 Merge branch 'hotfix' into group_warehouse_stock_reco 2019-01-14 20:25:53 +05:30
Nabin Hait
55c672eefd Merge branch 'hotfix' into is_fixed_asset_checkbox_not_copied 2019-01-14 20:25:22 +05:30
Nabin Hait
910a744263 Merge pull request #16391 from nabinhait/cc_fix
fix: Travis fix for hotfix branch
2019-01-14 20:24:23 +05:30
Nabin Hait
4ed7cfc515 tests(cost-center-company): Validate cost center's company and revent tests 2019-01-14 17:14:39 +05:30
NahuelOperto
7facc34851 fix: removed filter from method validate 2019-01-11 10:46:38 -03:00
Nabin Hait
0d208851a4 Fix(stock-reco): Fixed codacy issues 2019-01-10 17:56:11 +05:30
Sagar Vora
f99e013ebc fix: gstin validation should work when there is no state (#16378) 2019-01-10 11:57:24 +05:30
Nabin Hait
6b466fe230 Merge pull request #16326 from hrwX/hotfix-gst-fix
fix: GSTIN validation
2019-01-10 11:23:42 +05:30
Sagar Vora
07cf4e8f5b fix: use division consistent with Python 3 & other changes 2019-01-10 11:14:58 +05:30
karthikeyan5
2825b929c1 fix(GSTIN Validation - india): added checksum validation for GSTIN 2019-01-09 19:15:10 +05:30
scmmishra
e2762df90b Fix: Naming series not reflecting in leave application 2019-01-08 17:38:28 +05:30
Sagar Vora
f5a00dc0c1 Merge branch 'hotfix' into is_fixed_asset_checkbox_not_copied 2019-01-07 15:45:33 +05:30
Sagar Vora
d40743a570 fix: 14th digit may not be zero 2019-01-07 13:38:43 +05:30
Himanshu
75ab042632 removed lowercase regex 2019-01-04 17:13:43 +05:30
Himanshu
547229fef1 PAN card validation in GST 2019-01-03 23:20:38 +05:30
Nabin Hait
47c9826b6f test(reco-warehouse): Get items for group warehouse 2019-01-03 15:24:59 +05:30
Himanshu
53c040f838 Gst number validation fix 2019-01-03 12:50:18 +05:30
Himanshu
a09a6e4020 Merge pull request #2 from frappe/hotfix
Hotfix
2019-01-03 12:47:03 +05:30
Nabin Hait
cacbdec565 Merge pull request #16283 from rohitwaghchaure/fix_not_able_to_delete_customer
[Fix] Not able to delete customer if contact is available
2018-12-31 11:55:24 +05:30
Nabin Hait
fcbe410c2f feat(stock-reco): Fetch items based on group warehouse 2018-12-28 16:31:05 +05:30
Frappe Bot
23ee3c6fbe Merge branch 'hotfix' 2018-12-26 11:09:34 +00:00
Frappe Bot
9a9c9c2ba3 bumped to version 10.1.76 2018-12-26 11:09:34 +00:00
Rohit Waghchaure
52a692ee08 [Fix] Not able to delete customer if contact is available 2018-12-26 02:34:13 +05:30
rohitwaghchaure
7ec5e80b70 [Fix] While making sales invoice from delivery note, system not remove the returned qty (#16141) 2018-12-24 14:55:31 +05:30
Navdeep Ghai
c4d38c0afc Fix the disappears of image bug after uploading and saving the employee (#16217)
* Fix image disappears of image after uploading and saving the employee

* Fix the codacy issue
2018-12-24 14:53:19 +05:30
Shreya Shah
91ddadeefa fix: add currency to options (#16199) 2018-12-24 14:25:12 +05:30
Shreya Shah
d2b9093ecc fix: Check if items exist (#16248) 2018-12-24 14:21:07 +05:30
Raffael Meyer
ed3561279d Update README.md (#16224) 2018-12-24 14:19:51 +05:30
Nabin Hait
e9a2d57357 Merge pull request #16249 from shreyashah115/error-fix-2
Purchase order validation sql error
2018-12-21 10:59:20 +05:30
shreyashah115@gmail.com
ba8c041206 fix: Check if items exist 2018-12-20 13:23:51 +05:30
Rohit Waghchaure
f6f503a1f6 [Fix] Is fixed asset checkbox not checked if user duplicate the existing invoice 2018-12-19 15:15:35 +05:30
Frappe Bot
402ffa8b29 Merge branch 'hotfix' 2018-12-10 12:14:33 +00:00
Frappe Bot
65a9991d84 bumped to version 10.1.75 2018-12-10 12:14:33 +00:00
Nabin Hait
3248e0bb3e Merge pull request #16163 from netchampfaris/hotfix-setupwizard-abbr
fix(setup-wizard): Validate abbr length before switching to next slide
2018-12-07 15:20:23 +05:30
Nabin Hait
1b529d997c Merge pull request #16146 from rohitwaghchaure/remove_tax_amt_from_the_billed_amt_in_project
[Fix] In project, tax amount is added in the total billed amount(sales) field
2018-12-07 15:17:35 +05:30
Nabin Hait
01ccb8b099 Merge pull request #16144 from deepeshgarg007/list_view
[Fix]List view currency bug fix
2018-12-07 15:09:09 +05:30
Deepesh Garg
6967b44ac8 Merge branch 'hotfix' into list_view 2018-12-07 08:30:20 +05:30
Frappe Bot
efb2712d14 Merge branch 'hotfix' 2018-12-06 09:14:35 +00:00
Frappe Bot
be0a349a52 bumped to version 10.1.74 2018-12-06 09:14:35 +00:00
Nabin Hait
32c95c3292 Merge pull request #16113 from nabinhait/travis-fix
fix(test): Fixed tests for discount with margin and period closing voucher
2018-12-06 11:58:56 +05:30
Faris Ansari
40c15348da fix(setup-wizard): Validate abbr length before switching to next slide 2018-12-06 07:37:32 +05:30
rohitwaghchaure
f85856d9f8 Merge pull request #16155 from rohitwaghchaure/changed_parent_for_item_attribute_value
[Fix] Permissions issue
2018-12-04 18:45:07 +05:30
Rohit Waghchaure
675567419b [Fix] Permissions issue 2018-12-04 18:43:52 +05:30
Rohit Waghchaure
636d186d08 [Fix] In project, tax amount is added in the total billed amount(sales) field 2018-12-03 16:04:08 +05:30
deepeshgarg007
114cc810a0 List view currency bug fix 2018-12-03 15:13:06 +05:30
Nabin Hait
6b93f2fe0a Merge pull request #16139 from Zlash65/fix-assess
[Minor] Assessment Result fix
2018-12-03 14:33:01 +05:30
Nabin Hait
0b4ea25f83 Merge pull request #16138 from rohitwaghchaure/user_permissions_issue_item
[Fix] Permissions issue while making item variants
2018-12-03 14:32:40 +05:30
Nabin Hait
dd7b020b01 fix(test): Fixed tests for period closing voucher 2018-12-03 14:24:41 +05:30
Nabin Hait
dce68422a7 Merge pull request #16133 from rohitwaghchaure/fixed_stock_value_diifference_calculation_for_stock_reco
[Fix] Stock value difference calculation for stock reconciliation
2018-12-03 14:20:40 +05:30
Zlash65
db43c3af68 display message if details to fetch grade isnt filled up 2018-12-03 12:15:10 +05:30
Rohit Waghchaure
a8003c1af7 [Fix] Permissions issue while making item variants 2018-12-03 11:49:52 +05:30
rohitwaghchaure
ce72d26e95 Merge pull request #16125 from frappe/revert-16112-accounts_receivable_summary_print_issue
Revert "[Fix] Accounts receivable summary print is not working"
2018-11-30 16:21:53 +05:30
Rohit Waghchaure
16b8ecbe05 [Fix] Stock value difference calculation for stock reconciliation 2018-11-30 16:20:52 +05:30
Nabin Hait
eda0a6eb33 fix(test): Fixed tests for period closing voucher 2018-11-30 15:15:17 +05:30
rohitwaghchaure
ca332bdcdb Revert "[Fix] Accounts receivable summary print is not working" 2018-11-29 18:15:29 +05:30
Ameya Shenoy
e3136c38e1 bumped to version 10.1.73 2018-11-28 07:57:27 +00:00
Nabin Hait
ce870316c5 Merge pull request #16112 from rohitwaghchaure/accounts_receivable_summary_print_issue
[Fix] Accounts receivable summary print is not working
2018-11-27 17:57:17 +05:30
Nabin Hait
f642f86982 Merge branch 'hotfix' into accounts_receivable_summary_print_issue 2018-11-27 17:56:49 +05:30
Nabin Hait
96598936ad fix(test): Fixed tests for discount with margin and period closing voucher 2018-11-27 17:48:13 +05:30
Rohit Waghchaure
10bcd5113c [Fix] Accounts receivable summary print is not working 2018-11-27 16:25:35 +05:30
Nabin Hait
b98d08a2cb Merge pull request #16049 from rohitwaghchaure/incorrect_stock_value_difference_calculation
[Fix] Incorrect stock value difference because of negative stock
2018-11-27 13:21:43 +05:30
Nabin Hait
ccb03fb255 Merge pull request #16073 from deepeshgarg007/receivable-summary
Accounts receivable summary print fix
2018-11-27 13:11:37 +05:30
Nabin Hait
3c31e4ad4b Merge pull request #16088 from rohitwaghchaure/fixed_pos_profile_packing_items
If is pos is enabled and no pos profile then use the item's default warehouse for packing materials
2018-11-27 13:10:14 +05:30
Nabin Hait
0ccc05bdf7 Merge pull request #15997 from rohitwaghchaure/address_not_set_from_api
[Fix] Address not set from the API
2018-11-26 20:17:03 +05:30
Nabin Hait
7f02659425 Merge branch 'hotfix' into address_not_set_from_api 2018-11-26 20:16:54 +05:30
Nabin Hait
2598c475ed Merge pull request #15999 from codingCoffee/css
css: build files in v10
2018-11-26 20:02:18 +05:30
Rohit Waghchaure
3893ba302c If is pos and no pos profile use the item's default warehouse for packing materials 2018-11-26 14:13:24 +05:30
deepeshgarg007
5dbb9f5312 Accounts receivable summary print fix 2018-11-23 19:54:08 +05:30
Rohit Waghchaure
6424f47f3b [Fix] Incorrect stock value difference because of negative stock 2018-11-21 23:18:41 +05:30
Ameya Shenoy
27a0c37963 css: build files in v10 2018-11-15 19:21:30 +00:00
Rohit Waghchaure
f4dc71661d [Fix] Address not set from the API 2018-11-15 17:04:02 +05:30
Frappe Bot
0b697c5298 Merge branch 'hotfix' 2018-11-15 09:04:14 +00:00
Frappe Bot
2426d00dd6 bumped to version 10.1.72 2018-11-15 09:04:14 +00:00
rohitwaghchaure
5395b164cd Merge pull request #15983 from rohitwaghchaure/fixed_claimed_amount_issue
Claimed amount is not reset on cancel of employee advance
2018-11-14 13:21:11 +05:30
Rohit Waghchaure
047a7123eb Claimed amount is not reset on cancel 2018-11-14 13:20:00 +05:30
Frappe Bot
cb1726d6ec Merge branch 'hotfix' 2018-11-13 10:55:31 +00:00
Frappe Bot
6b78e520d2 bumped to version 10.1.71 2018-11-13 10:55:31 +00:00
khushalti
fad08e1bcb [fix] - GL entry not creating on PR if rejected qty mentoned (#15815) 2018-11-13 12:09:32 +05:30
Ameya Shenoy
3d58576797 Merge pull request #15963 from codingCoffee/frankfurter
fix: changed currency exchange API to frankfurter
2018-11-12 17:55:48 +05:30
Ameya Shenoy
438490fd29 fix: changed currency exchange API to frankfurter
- Switched to Frankfurter's public API (frankfurter.app) from
self hosted API (frankfurter.erpnext.org)
2018-11-12 15:15:06 +05:30
Frappe Bot
f001a9eb4f Merge branch 'hotfix' 2018-11-09 10:09:04 +00:00
Frappe Bot
f8a5cfe8d8 bumped to version 10.1.70 2018-11-09 10:09:04 +00:00
rohitwaghchaure
a88eaa6e20 [Fix] User able to change discount if pricing rule has discount value as zero (#15921) 2018-11-08 13:05:08 +05:30
Nabin Hait
6ff2f395f5 fix(gle): Post gl entry for booking COGS from Sales Invoice even if grand_total is zero (#15825) 2018-11-08 12:30:44 +05:30
Frappe Bot
ccff3e2aec Merge branch 'hotfix' 2018-11-07 11:26:10 +00:00
Frappe Bot
7f37d26f05 bumped to version 10.1.69 2018-11-07 11:26:10 +00:00
Shreya Shah
c704630d5f fix: Return default if company not found (#15915) 2018-11-06 17:24:45 +05:30
Ameya Shenoy
1a41929c6b Merge branch 'hotfix' 2018-11-06 11:02:04 +00:00
Ameya Shenoy
a97a520aa8 bumped to version 10.1.68 2018-11-06 11:02:04 +00:00
Nabin Hait
3e6663d47e fix(serial no): Set supplier info based on pur invoice if serial no is created from Purchase Invoice (#15820) 2018-11-05 14:01:59 +05:30
Ameya Shenoy
eeb66dfc8e Merge branch 'hotfix' 2018-11-05 06:40:25 +00:00
Ameya Shenoy
59f16bc942 bumped to version 10.1.67 2018-11-05 06:40:25 +00:00
rohitwaghchaure
e77f38e7e2 Merge pull request #15894 from rohitwaghchaure/fix_update_claimed_amount
Column ‘claimed_amount’ cannot be null
2018-11-02 18:14:08 +05:30
Rohit Waghchaure
598d34445f [Fix] Column ‘claimed_amount’ cannot be null 2018-11-02 16:02:33 +05:30
Navdeep Ghai
768513f2f9 fixed divided by zero error (#15885) 2018-11-02 12:19:05 +05:30
rohitwaghchaure
dcb71a61ad [Fix] Payment entry not able to submit (#15859) 2018-11-02 12:12:42 +05:30
Ameya Shenoy
3f32218bc0 Merge branch 'hotfix' 2018-10-31 13:35:59 +00:00
Ameya Shenoy
b4bff7e298 bumped to version 10.1.66 2018-10-31 13:35:58 +00:00
Shreya Shah
41c5fda196 fix(sms-center): Fix db query (#15774) 2018-10-31 18:04:30 +05:30
Shreya Shah
305c82bd8d fix(medical-record): Remove z-index property (#15790) 2018-10-31 18:02:55 +05:30
rohitwaghchaure
cd11bdfdbb [Fix] Supplier wise sales analytics report not showing item details which is added in purchase invoice with update stock (#15869) 2018-10-31 18:02:00 +05:30
Shreya Shah
0c0e49a421 fix: Fix fieldnames in template (#15860) 2018-10-31 18:00:09 +05:30
rohitwaghchaure
3f398d24f3 [Fix] Precision issue, not able to submit the stock entry (#15863) 2018-10-31 17:58:26 +05:30
Ameya Shenoy
d9a82738d0 Merge branch 'hotfix' 2018-10-30 12:48:42 +00:00
Ameya Shenoy
1f7a5dcd07 bumped to version 10.1.65 2018-10-30 12:48:42 +00:00
Shreya Shah
452619c668 fix(report): Return if not list (#15849) 2018-10-30 11:26:01 +05:30
rohitwaghchaure
9d0dba5569 Merge pull request #15851 from frappe/pos-delete-fix
fix: Delete button in POS mobile
2018-10-29 15:19:11 +05:30
Faris Ansari
3df1327b94 fix: Delete button in POS mobile
Delete button was covered by page-actions container
2018-10-29 15:15:10 +05:30
Ameya Shenoy
38eaaade89 Merge branch 'hotfix' 2018-10-23 12:52:46 +00:00
Ameya Shenoy
2a98e59bd4 bumped to version 10.1.64 2018-10-23 12:52:46 +00:00
Ameya Shenoy
03348364e9 Merge pull request #15739 from kennethsequeira/hotfix
Fix for "Improve this page" incorrect link generated in v10 sites
2018-10-23 18:05:25 +05:30
Ameya Shenoy
83fd31973f Merge branch 'hotfix' 2018-10-23 07:58:12 +00:00
Ameya Shenoy
ac64b39562 bumped to version 10.1.63 2018-10-23 07:58:11 +00:00
Ameya Shenoy
c73c576536 Merge pull request #15759 from codingCoffee/salesperson
fix(): fetch correct warehouse for item in report
2018-10-23 13:25:42 +05:30
rohitwaghchaure
034429b34d Merge pull request #15756 from rohitwaghchaure/fixed_allow_edit_rate
[Fix] User able to edit the rate in offline POS even if it has no permissions
2018-10-23 09:43:57 +05:30
Ameya Shenoy
874866e9f9 Merge branch 'hotfix' 2018-10-22 10:34:35 +00:00
Ameya Shenoy
c365ce8f21 bumped to version 10.1.62 2018-10-22 10:34:35 +00:00
Ameya Shenoy
3a11f34355 fix(): fetch correct warehouse for item in report
Fix 'Sales Person-wise Transaction Summary' Report by fetching the
correct Warehouse for the Item fron the respective, Sales Order/Sales
Invoice/ Delivery Note
2018-10-22 10:15:07 +00:00
Nabin Hait
91eac5a7cf fix(report): Optimization for financial statements 2018-10-22 15:05:40 +05:30
Rohit Waghchaure
aef7a6ec44 [Fix] User able to edit the rate in offline POS even if it has no permissions 2018-10-22 13:51:32 +05:30
Ameya Shenoy
6192d24235 Merge branch 'hotfix' 2018-10-19 12:48:17 +00:00
Ameya Shenoy
24fe7286fc bumped to version 10.1.61 2018-10-19 12:48:16 +00:00
Kenneth Sequeira
991c121b57 added source link for ERPNext docs 2018-10-19 14:31:21 +05:30
Kenneth Sequeira
23ec18e3e4 added docs_app variable to point docs to foundation app 2018-10-19 03:28:12 +05:30
Nabin Hait
500ddc94c7 fix(gle): GL Entry for invoices before introduction of rounding_adjustment (#15732) 2018-10-18 16:48:28 +05:30
Ameya Shenoy
bbd8b04012 Merge branch 'hotfix' 2018-10-17 09:04:11 +00:00
Ameya Shenoy
bb1b6b42e2 bumped to version 10.1.60 2018-10-17 09:04:11 +00:00
Shreya Shah
8e71074e1c fix(report): Add column for Item Name (#15702) 2018-10-16 14:36:49 +05:30
Shreya Shah
ff0deedca9 fix(discount-amount): Print hide discount_amount if print without amount (#15704) 2018-10-16 14:34:30 +05:30
deepeshgarg007
4bb90add1d Currency symbol bug fix (#15698) 2018-10-15 19:07:49 +05:30
Nabin Hait
44ec05f79b fix(bom): deadlock issue via bom replace tool (#15694) 2018-10-15 18:56:16 +05:30
Bibin
7844b79274 [Bug-Fix] accounts_receivable.html (#15688)
* Update accounts_receivable.html

In the print format and PDF the total was showing as 0 (Zero) , when I made these changes it fixed the issue

* Update accounts_receivable.html
2018-10-15 18:25:26 +05:30
Nabin Hait
ea75295bb3 Merge branch 'hotfix' 2018-10-15 15:41:25 +05:30
Nabin Hait
d2c643eb0b bumped to version 10.1.59 2018-10-15 16:11:25 +06:00
rohitwaghchaure
94fcb0e9f9 [Enhance] Add user image in the employee from the user (#15680) 2018-10-15 14:57:46 +05:30
rohitwaghchaure
3362d6b948 [Fix] Precision issue in the expense claim (#15678) 2018-10-15 11:07:13 +05:30
Saurabh
75c1682e61 Merge branch 'hotfix' 2018-10-09 17:55:32 +05:30
Saurabh
2dc8972794 bumped to version 10.1.58 2018-10-09 18:25:32 +06:00
Saurabh
f786eccdf9 Merge pull request #15633 from Zlash65/setup-fix
[Minor] Setup Wizard failing fix
2018-10-09 17:49:54 +05:30
Zlash65
a1036ad50b setup wizard failing fix 2018-10-09 17:38:28 +05:30
Shreya Shah
5b34d00bc0 fix(accounts-receivable): Column values in Print and PDF (#15622) 2018-10-08 18:20:51 +05:30
Ameya Shenoy
ee3b788024 Merge branch 'hotfix' 2018-10-08 09:37:37 +00:00
Ameya Shenoy
b509b06edf bumped to version 10.1.57 2018-10-08 09:37:37 +00:00
Zarrar
5fcccda883 [Minor] Supplier Quotation (#15578)
* throw meaningful error if RFQ does not have selected supplier

* Update supplier_quotation.py

* codacy fix
2018-10-08 14:30:53 +05:30
Shreya Shah
4fb9230d16 Add missing method link_to_mrs to buying.js (#15613) 2018-10-08 14:18:03 +05:30
Shreya Shah
37d3686372 fix(setup_taxes): Pop if frappe.message_log (#15615) 2018-10-08 14:17:16 +05:30
Ameya Shenoy
5eafa5a487 Merge branch 'hotfix' 2018-10-05 08:54:46 +00:00
Ameya Shenoy
97dbb4d125 bumped to version 10.1.56 2018-10-05 08:54:46 +00:00
Shreya Shah
17ac38ff29 Enable save before saving to update form after save (#15579) 2018-10-05 11:51:13 +05:30
Ameya Shenoy
65652071ff Merge branch 'hotfix' 2018-10-04 09:11:50 +00:00
Ameya Shenoy
79dc8ac9cc bumped to version 10.1.55 2018-10-04 09:11:50 +00:00
rohitwaghchaure
15e7646edd Merge pull request #15569 from rohitwaghchaure/stock_adjustment_to_cost_of_goods_sold
Book cost of goods sold instead of stock adjustment
2018-10-03 17:36:29 +05:30
Rohit Waghchaure
d1b87ba41c Book cost of goods sold instead of stock adjustment 2018-10-03 16:29:43 +05:30
rohitwaghchaure
a5576f5b21 [Fix] Stock difference between gl entry and stock ledger entry booked in stock adjustment (#15374) 2018-10-03 10:39:50 +05:30
rohitwaghchaure
8976ad5ca1 Merge pull request #15523 from rohitwaghchaure/fix_attendance_tool_issue
[Fix] Attendance tool
2018-10-01 15:07:49 +05:30
Rohit Waghchaure
c7f8b82fff [Fix] Attendance tool 2018-10-01 12:30:58 +05:30
rohitwaghchaure
6b62b86bbf Merge pull request #15545 from rohitwaghchaure/salary_slip_not_creating_because_of_the_date_issue
[Fix] Salary slip
2018-10-01 12:03:26 +05:30
Rohit Waghchaure
8fbf856618 [Fix] Salary slip 2018-10-01 12:00:45 +05:30
Nabin Hait
7d6d678e8d purchase receipt return entry in dashboard 2018-09-26 19:04:11 +05:30
Nabin Hait
c22ba2ec26 fix(sales return): validation message fix 2018-09-26 18:56:45 +05:30
rohitwaghchaure
0cf0ebf08b [Refactored] Asset Depreciation Ledger report based on GL entries (#15415)
* [Refactored] Asset Depreciation Ledger report is based on GL entries

* Provision to make manual JV from the asset if Calculate Depreciation is disabled
2018-09-26 15:24:49 +05:30
Ameya Shenoy
0ff35a852a Merge branch 'hotfix' 2018-09-26 07:26:49 +00:00
Ameya Shenoy
e04431ea5c bumped to version 10.1.54 2018-09-26 07:26:49 +00:00
rohitwaghchaure
fafc277666 [Fix] BOM update tool, too many writes in one request. Please send smaller requests (#15432) 2018-09-25 18:59:20 +05:30
rohitwaghchaure
fe1e4a41e6 Validate negative stock serial number (#15492) 2018-09-25 18:36:32 +05:30
Faris Ansari
7a8c5b0c2c fix(setup wizard): Validate FY dates (#15473) 2018-09-25 18:34:33 +05:30
Saurabh
056ecdca6a Merge branch 'hotfix' 2018-09-20 13:22:36 +05:30
Saurabh
3b281a0a1b bumped to version 10.1.53 2018-09-20 13:52:36 +06:00
rohitwaghchaure
a60ab1af75 [Fix] Salary slip is not saving (#15449) 2018-09-20 13:18:49 +05:30
rohitwaghchaure
550fc695f1 [Fix] Precision issue in the accounts receivable report (#15440) 2018-09-19 19:03:40 +05:30
Zarrar
013493de7a lable for discount_amount should be configurable (#15408) 2018-09-17 11:06:49 +05:30
125 changed files with 2792 additions and 2107 deletions

View File

@@ -1,5 +1,12 @@
language: python
dist: trusty
dist: xenial
addons:
apt:
packages:
- "python3"
- "python3-pip"
python:
- "2.7"
@@ -9,14 +16,13 @@ services:
install:
- pip install flake8==3.3.0
- flake8 . --count --select=E901,E999,F821,F822,F823 --show-source --statistics
- sudo rm /etc/apt/sources.list.d/docker.list
- sudo -H python3 -m pip install --upgrade setuptools pip
- sudo apt-get install hhvm && rm -rf /home/travis/.kiex/
- sudo apt-get purge -y mysql-common mysql-server mysql-client
- nvm install v7.10.0
- wget https://raw.githubusercontent.com/frappe/bench/master/playbooks/install.py
- sudo python install.py --develop --user travis --without-bench-setup
- sudo pip install -e ~/bench
- sudo python3 install.py --develop --user travis --without-bench-setup
- sudo python3 -m pip install -e ~/bench
- rm $TRAVIS_BUILD_DIR/.git/shallow
- bash $TRAVIS_BUILD_DIR/travis/bench_init.sh
@@ -31,7 +37,6 @@ before_script:
- bench get-app erpnext $TRAVIS_BUILD_DIR
- bench use test_site
- bench reinstall --yes
- bench build
- bench scheduler disable
- sed -i 's/9000/9001/g' sites/common_site_config.json
- bench start &

View File

@@ -1,20 +0,0 @@
include MANIFEST.in
include requirements.txt
include *.json
include *.md
include *.py
include *.txt
include .travis.yml
recursive-include erpnext *.txt
recursive-include erpnext *.css
recursive-include erpnext *.csv
recursive-include erpnext *.html
recursive-include erpnext *.ico
recursive-include erpnext *.js
recursive-include erpnext *.json
recursive-include erpnext *.md
recursive-include erpnext *.png
recursive-include erpnext *.py
recursive-include erpnext *.svg
recursive-include erpnext/public *
recursive-exclude * *.pyc

View File

@@ -8,7 +8,7 @@ Includes: Accounting, Inventory, Manufacturing, CRM, Sales, Purchase, Project Ma
ERPNext is built on the [Frappé](https://github.com/frappe/frappe) Framework, a full-stack web app framework in Python & JavaScript.
- [User Guide](https://erpnext.org/docs/user)
- [User Guide](https://erpnext.com/docs/user)
- [Discussion Forum](https://discuss.erpnext.com/)
---

View File

@@ -5,7 +5,7 @@ import frappe
from erpnext.hooks import regional_overrides
from frappe.utils import getdate
__version__ = '10.1.52'
__version__ = '10.1.81'
def get_default_company(user=None):
'''Get default company for user'''

View File

@@ -1,465 +1,466 @@
{
"country_code": "ae",
"name": "U.A.E - Chart of Accounts",
"country_code": "ae",
"name": "U.A.E - Chart of Accounts",
"tree": {
"Assets": {
"Current Assets": {
"Accounts Receivable": {
"Corporate Credit Cards": {
"account_type": "Receivable"
},
},
"Other Receivable": {
"Accrued Rebates Due from Suppliers": {
"account_type": "Receivable"
},
"Accured Income from Suppliers": {
},
"Accrued Income from Suppliers": {
"account_type": "Receivable"
},
},
"Other Debtors": {
"account_type": "Receivable"
},
},
"account_type": "Receivable"
},
},
"Post Dated Cheques Received": {
"account_type": "Receivable"
},
},
"Staff Receivable": {
"account_type": "Receivable"
},
},
"Trade Receivable": {
"account_type": "Receivable"
},
},
"Trade in Opening Fees": {
"account_type": "Receivable"
},
},
"account_type": "Receivable"
},
},
"Cash in Hand & Banks": {
"Banks": {
"Bank Margin On LC & LG": {},
"Banks Blocked Deposits": {},
"Banks Call Deposit Accounts": {},
"Bank Margin On LC & LG": {},
"Banks Blocked Deposits": {},
"Banks Call Deposit Accounts": {},
"Banks Current Accounts": {
"account_type": "Bank"
},
},
"account_type": "Bank"
},
},
"Cash in Hand": {
"Cash in Safe": {
"Main Safe": {
"account_type": "Cash"
},
},
"Main Safe - Foreign Currency": {
"account_type": "Cash"
}
},
},
"Petty Cash": {
"Petty Cash - Admininistration": {
"account_type": "Cash"
},
},
"Petty Cash - Others": {
"account_type": "Cash"
}
},
},
"account_type": "Cash"
},
},
"Cash in Transit": {
"Credit Cards": {
"Gateway Credit Cards": {
"account_type": "Bank"
},
},
"Manual Visa & Master Cards": {
"account_type": "Bank"
},
},
"PayPal Account": {
"account_type": "Bank"
},
},
"Visa & Master Credit Cards": {
"account_type": "Bank"
}
}
}
},
},
"Inventory": {
"Consigned Stock": {
"Handling Difference in Inventory": {
"account_type": "Stock Adjustment"
},
"Items Delivered to Customs on temprary Base": {}
},
"Handling Difference in Inventory": {},
"Items Delivered to Customs on temporary Base": {}
},
"Stock in Hand": {
"account_type": "Stock"
}
},
"Perliminary and Preoperating Expenses": {
},
"Preliminary and Preoperating Expenses": {
"Preoperating Expenses": {}
},
},
"Prepayments & Deposits": {
"Deposits": {
"Deposit - Office Rent": {},
"Deposit Others": {},
"Deposit to Immigration (Visa)": {},
"Deposit - Office Rent": {},
"Deposit Others": {},
"Deposit to Immigration (Visa)": {},
"Deposits - Customs": {}
},
},
"Prepaid Taxes": {
"Sales Taxes Receivables": {},
"Sales Taxes Receivables": {},
"Withholding Tax Receivables": {}
},
},
"Prepayments": {
"Other Prepayments": {},
"PrePaid Advertisement Expenses": {},
"Prepaid Bank Guarantee": {},
"Prepaid Consultancy Fees": {},
"Prepaid Employees Housing": {},
"Prepaid Finance charge for Loans": {},
"Prepaid Legal Fees": {},
"Prepaid License Fees": {},
"Prepaid Life Insurance": {},
"Prepaid Maintenance": {},
"Prepaid Medical Insurance": {},
"Prepaid Office Rent": {},
"Prepaid Other Insurance": {},
"Prepaid Schooling Fees": {},
"Prepaid Site Hosting Fees": {},
"Other Prepayments": {},
"PrePaid Advertisement Expenses": {},
"Prepaid Bank Guarantee": {},
"Prepaid Consultancy Fees": {},
"Prepaid Employees Housing": {},
"Prepaid Finance charge for Loans": {},
"Prepaid Legal Fees": {},
"Prepaid License Fees": {},
"Prepaid Life Insurance": {},
"Prepaid Maintenance": {},
"Prepaid Medical Insurance": {},
"Prepaid Office Rent": {},
"Prepaid Other Insurance": {},
"Prepaid Schooling Fees": {},
"Prepaid Site Hosting Fees": {},
"Prepaid Sponsorship Fees": {}
}
}
},
},
"Long Term Assets": {
"Fixed Assets": {
"Accumulated Depreciation": {
"Acc. Depreciation of Motor Vehicles": {
"account_type": "Accumulated Depreciation"
},
},
"Acc. Deprn.Computer Hardware & Software": {
"account_type": "Accumulated Depreciation"
},
},
"Acc.Deprn.of Furniture & Office Equipment": {
"account_type": "Accumulated Depreciation"
},
},
"Amortisation on Leasehold Improvement": {
"account_type": "Accumulated Depreciation"
},
},
"account_type": "Accumulated Depreciation"
},
},
"Fixed Assets (Cost Price)": {
"Computer Hardware & Software": {
"account_type": "Fixed Asset"
},
},
"Furniture and Equipment": {
"account_type": "Fixed Asset"
},
"Leasehold Improvement": {},
"Motor Vehicules": {
},
"Leasehold Improvement": {},
"Motor Vehicles": {
"account_type": "Fixed Asset"
},
"Work In Progrees": {},
},
"Work In Progress": {},
"account_type": "Fixed Asset"
}
},
},
"Intangible Assets": {
"Computer Card Renewal": {},
"Dispoal of Outlets": {},
"Computer Card Renewal": {},
"Disposal of Outlets": {},
"Registration of Trademarks": {}
},
"Intercompany Accounts": {},
},
"Intercompany Accounts": {},
"Investments": {
"Investments in Subsidiaries": {}
}
},
},
"root_type": "Asset"
},
},
"Closing And Temporary Accounts": {
"Closing Accounts": {
"Closing Account": {}
},
},
"root_type": "Liability"
},
},
"Expenses": {
"Commercial Expenses": {
"Consultancy Fees": {},
"Consultancy Fees": {},
"Provision for Doubtful Debts": {}
},
},
"Cost of Sale": {
"Cost Of Goods Sold": {
"Cost Of Goods Sold I/C Sales": {},
"Cost Of Goods Sold I/C Sales": {},
"Cost of Goods Sold in Trading": {
"account_type": "Cost of Goods Sold"
},
},
"account_type": "Cost of Goods Sold"
},
},
"Expenses Included In Valuation": {
"account_type": "Expenses Included In Valuation"
},
"Stock Adjustment": {
"account_type": "Stock Adjustment"
}
},
},
"Depreciation": {
"Depreciation & Amortization": {
"Amortization on Leasehold Improvement": {},
"Amortization on Leasehold Improvement": {},
"Depreciation Of Computer Hard & Soft": {
"account_type": "Depreciation"
},
},
"Depreciation Of Furniture & Office Equipment\n\t\t\t": {
"account_type": "Depreciation"
},
},
"Depreciation Of Motor Vehicles": {
"account_type": "Depreciation"
}
}
},
},
"Direct Expenses": {
"Financial Charges": {
"Air Miles Card Charges": {},
"Amex Credit Cards Charges": {},
"Bank Finance & Loan Charges": {},
"Credit Card Charges": {},
"Credit Card Swipe Charges": {},
"Air Miles Card Charges": {},
"Amex Credit Cards Charges": {},
"Bank Finance & Loan Charges": {},
"Credit Card Charges": {},
"Credit Card Swipe Charges": {},
"PayPal Charges": {}
}
},
},
"MISC Charges": {
"Other Charges": {
"Captial Loss": {
"Disposal of Business Branch": {},
"Loss On Fixed Assets Disposal": {},
"Capital Loss": {
"Disposal of Business Branch": {},
"Loss On Fixed Assets Disposal": {},
"Loss on Difference on Exchange": {}
},
},
"Other Non Operating Exp": {
"Other Non Operating Expenses": {}
},
},
"Previous Year Adjustments": {
"Previous Year Adjustments Account": {}
},
},
"Royalty Fees": {
"Royalty to Parent Co.": {}
},
},
"Tax / Zakat Expenses": {
"Income Tax": {
"account_type": "Tax"
},
"Zakat": {},
},
"Zakat": {},
"account_type": "Tax"
}
}
},
},
"Share Resources": {
"Share Resource Expenses Account": {}
},
},
"Store Operating Expenses": {
"Selling, General & Admin Expenses": {
"Advertising Expenses": {
"Other - Advertising Expenses": {}
},
},
"Bank & Finance Charges": {
"Other Bank Charges": {}
},
},
"Communications": {
"Courrier": {},
"Others - Communication": {},
"Telephone": {},
"Courier": {},
"Others - Communication": {},
"Telephone": {},
"Web Site Hosting Fees": {}
},
},
"Office & Various Expenses": {
"Cleaning": {},
"Convoyance Expenses": {},
"Gifts & Donations": {},
"Insurance": {},
"Kitchen and Buffet Expenses": {},
"Maintenance": {},
"Others - Office Various Expenses": {},
"Security & Guard": {},
"Stationary From Suppliers": {},
"Stationary Out Of Stock": {},
"Subscriptions": {},
"Training": {},
"Cleaning": {},
"Conveyance Expenses": {},
"Gifts & Donations": {},
"Insurance": {},
"Kitchen and Buffet Expenses": {},
"Maintenance": {},
"Others - Office Various Expenses": {},
"Security & Guard": {},
"Stationary From Suppliers": {},
"Stationary Out Of Stock": {},
"Subscriptions": {},
"Training": {},
"Vehicle Expenses": {}
},
},
"Personnel Cost": {
"Basic Salary": {},
"End Of Service Indemnity": {},
"Housing Allowance": {},
"Leave Salary": {},
"Leave Ticket": {},
"Life Insurance": {},
"Medical Insurance": {},
"Personnel Cost Others": {},
"Sales Commission": {},
"Staff School Allowances": {},
"Transportation Allowance": {},
"Uniform": {},
"Basic Salary": {},
"End Of Service Indemnity": {},
"Housing Allowance": {},
"Leave Salary": {},
"Leave Ticket": {},
"Life Insurance": {},
"Medical Insurance": {},
"Personnel Cost Others": {},
"Sales Commission": {},
"Staff School Allowances": {},
"Transportation Allowance": {},
"Uniform": {},
"Visa Expenses": {}
},
},
"Professional & Legal Fees": {
"Audit Fees": {},
"Legal fees": {},
"Others - Professional Fees": {},
"Sponsorship Fees": {},
"Audit Fees": {},
"Legal fees": {},
"Others - Professional Fees": {},
"Sponsorship Fees": {},
"Trade License Fees": {}
},
},
"Provision & Write Off": {
"Amortisation of Preoperating Expenses": {},
"Cash Shortage": {},
"Others - Provision & Write off": {},
"Write Off Inventory": {},
"Amortisation of Preoperating Expenses": {},
"Cash Shortage": {},
"Others - Provision & Write off": {},
"Write Off Inventory": {},
"Write Off Receivables & Payables": {}
},
},
"Rent Expenses": {
"Office Rent": {},
"Office Rent": {},
"Warehouse Rent": {}
},
},
"Travel Expenses": {
"Air tickets": {},
"Hotel": {},
"Meals": {},
"Others": {},
"Air tickets": {},
"Hotel": {},
"Meals": {},
"Others": {},
"Per Diem": {}
},
},
"Utilities": {
"Other Utility Cahrges": {},
"Other Utility Cahrges": {},
"Water & Electricity": {}
}
}
},
},
"root_type": "Expense"
},
},
"Liabilities": {
"Current Liabilities": {
"Accounts Payable": {
"Payables": {
"Advance Paybale to Suppliers": {
"account_type": "Payable"
},
},
"Consigned Payable": {
"account_type": "Payable"
},
},
"Other Payable": {
"account_type": "Payable"
},
},
"Post Dated Cheques Paid": {
"account_type": "Payable"
},
"Staff Payable": {},
},
"Staff Payable": {},
"Suppliers Price Protection": {
"account_type": "Payable"
},
},
"Trade Payable": {
"account_type": "Payable"
},
},
"account_type": "Payable"
}
},
},
"Accruals & Provisions": {
"Accruals": {
"Accrued Personnel Cost": {
"Accrued - Commissions": {},
"Accrued - Leave Salary": {},
"Accrued - Leave Tickets": {},
"Accrued - Salaries": {},
"Accrued Other Personnel Cost": {},
"Accrued Salaries Increment": {},
"Accrued - Commissions": {},
"Accrued - Leave Salary": {},
"Accrued - Leave Tickets": {},
"Accrued - Salaries": {},
"Accrued Other Personnel Cost": {},
"Accrued Salaries Increment": {},
"Accrued-Staff Bonus": {}
}
},
},
"Accrued Expenses": {
"Accrued Other Expenses": {
"Accrued - Audit Fees": {},
"Accrued - Office Rent": {},
"Accrued - Sponsorship": {},
"Accrued - Telephone": {},
"Accrued - Utilities": {},
"Accrued - Audit Fees": {},
"Accrued - Office Rent": {},
"Accrued - Sponsorship": {},
"Accrued - Telephone": {},
"Accrued - Utilities": {},
"Accrued Others": {}
}
},
},
"Other Current Liabilities": {
"Accrued Dubai Customs": {},
"Deferred income": {},
"Accrued Dubai Customs": {},
"Deferred income": {},
"Shipping & Handling": {}
},
},
"Provisions": {
"Tax Payables": {
"Income Tax Payable": {},
"Sales Tax Payable": {},
"Income Tax Payable": {},
"Sales Tax Payable": {},
"Withholding Tax Payable": {}
}
},
},
"Short Term Loan": {}
},
},
"Duties and Taxes": {
"account_type": "Tax",
"account_type": "Tax",
"is_group": 1
},
},
"Reservations & Credit Notes": {
"Credit Notes": {
"Credit Notes to Customers": {},
"Credit Notes to Customers": {},
"Reservations": {}
}
},
},
"Stock Liabilities": {
"Stock Received But Not Billed": {
"account_type": "Stock Received But Not Billed"
}
},
},
"Unearned Income": {}
},
},
"Long Term Liabilities": {
"Long Term Loans & Provisions": {}
},
},
"root_type": "Liability"
},
},
"Revenue": {
"Direct Revenue": {
"Other Direct Revenue": {
"Other Revenue - Operating": {
"Advertising Income": {},
"Branding Income": {},
"Early Setmt Margin from Suppliers": {},
"Marketing Rebate from Suppliers": {},
"Rebate from Suppliers": {},
"Service Income": {},
"Advertising Income": {},
"Branding Income": {},
"Early Setmt Margin from Suppliers": {},
"Marketing Rebate from Suppliers": {},
"Rebate from Suppliers": {},
"Service Income": {},
"Space Rental Income": {}
}
}
},
},
"Indirect Revenue": {
"Other Indirect Revenue": {
"Capital Gain": {},
"Excess In Till": {},
"Gain On Difference Of Exchange": {},
"Management Consultancy Fees": {},
"Capital Gain": {},
"Excess In Till": {},
"Gain On Difference Of Exchange": {},
"Management Consultancy Fees": {},
"Other Income": {}
},
},
"Other Revenue - Non Operating": {
"Interest Revenue": {},
"Interest from FD": {},
"Products Listing Fees from Suppliers": {},
"Interest Revenue": {},
"Interest from FD": {},
"Products Listing Fees from Suppliers": {},
"Trade Opening Fees from suppliers": {}
}
},
},
"Sales": {
"Sales from Other Regions": {
"Sales from Other Region": {}
},
},
"Sales of same region": {
"Management Consultancy Fees 1": {},
"Sales Account": {},
"Management Consultancy Fees 1": {},
"Sales Account": {},
"Sales of I/C": {}
}
},
},
"root_type": "Income"
},
},
"Share Holder Equity": {
"Capital": {
"Contributed Capital": {},
"Share Capital": {},
"Shareholders Current A/c": {},
"Sub Ordinated Loan": {},
"Contributed Capital": {},
"Share Capital": {},
"Shareholders Current A/c": {},
"Sub Ordinated Loan": {},
"Treasury Stocks": {}
},
},
"Retained Earnings": {
"Current Year Results": {},
"Dividends Paid": {},
"Current Year Results": {},
"Dividends Paid": {},
"Previous Years Results": {}
},
"account_type": "Equity",
},
"account_type": "Equity",
"root_type": "Equity"
}
}

View File

@@ -18,15 +18,14 @@ class GLEntry(Document):
self.flags.ignore_submit_comment = True
self.check_mandatory()
self.validate_and_set_fiscal_year()
self.pl_must_have_cost_center()
self.validate_cost_center()
if not self.flags.from_repost:
self.pl_must_have_cost_center()
self.check_pl_account()
self.validate_cost_center()
self.validate_party()
self.validate_currency()
def on_update_with_args(self, adv_adj, update_outstanding = 'Yes', from_repost=False):
if not from_repost:
self.validate_account_details(adv_adj)

View File

@@ -145,6 +145,13 @@ erpnext.accounts.JournalEntry = frappe.ui.form.Controller.extend({
};
}
// payroll entry
if(jvd.reference_type==="Payroll Entry") {
return {
query: "erpnext.hr.doctype.payroll_entry.payroll_entry.get_payroll_entries_for_jv",
};
}
var out = {
filters: [
[jvd.reference_type, "docstatus", "=", 1]
@@ -167,10 +174,18 @@ erpnext.accounts.JournalEntry = frappe.ui.form.Controller.extend({
out.filters.push([jvd.reference_type, "per_billed", "<", 100]);
}
if(jvd.party_type && jvd.party) {
out.filters.push([jvd.reference_type,
(jvd.reference_type.indexOf("Sales")===0 ? "customer" : "supplier"), "=", jvd.party]);
var party_field = "";
if(jvd.reference_type.indexOf("Sales")===0) {
var party_field = "customer";
} else if (jvd.reference_type.indexOf("Purchase")===0) {
var party_field = "supplier";
}
if (party_field) {
out.filters.push([jvd.reference_type, party_field, "=", jvd.party]);
}
}
return out;

View File

@@ -791,15 +791,25 @@ frappe.ui.form.on('Payment Entry', {
var write_off_row = $.map(frm.doc["deductions"] || [], function(t) {
return t.account==r.message[account] ? t : null; });
if (!write_off_row.length) {
var row = frm.add_child("deductions");
var row = [];
var difference_amount = flt(frm.doc.difference_amount,
precision("difference_amount"));
if (!write_off_row.length && difference_amount) {
row = frm.add_child("deductions");
row.account = r.message[account];
row.cost_center = r.message["cost_center"];
} else {
var row = write_off_row[0];
row = write_off_row[0];
}
if (row) {
row.amount = flt(row.amount) + difference_amount;
} else {
frappe.msgprint(__("No gain or loss in the exchange rate"))
}
row.amount = flt(row.amount) + flt(frm.doc.difference_amount);
refresh_field("deductions");
frm.events.set_unallocated_amount(frm);

View File

@@ -70,12 +70,14 @@ class PeriodClosingVoucher(AccountsController):
net_pl_balance += flt(acc.balance_in_company_currency)
if net_pl_balance:
cost_center = frappe.db.get_value("Company", self.company, "cost_center")
gl_entries.append(self.get_gl_dict({
"account": self.closing_account_head,
"debit_in_account_currency": abs(net_pl_balance) if net_pl_balance > 0 else 0,
"debit": abs(net_pl_balance) if net_pl_balance > 0 else 0,
"credit_in_account_currency": abs(net_pl_balance) if net_pl_balance < 0 else 0,
"credit": abs(net_pl_balance) if net_pl_balance < 0 else 0
"credit": abs(net_pl_balance) if net_pl_balance < 0 else 0,
"cost_center": cost_center
}))
from erpnext.accounts.general_ledger import make_gl_entries

View File

@@ -72,6 +72,7 @@ class TestPeriodClosingVoucher(unittest.TestCase):
"company": "_Test Company",
"fiscal_year": get_fiscal_year(today(), company="_Test Company")[0],
"posting_date": today(),
"cost_center": "_Test Cost Center - _TC",
"remarks": "test"
})
pcv.insert()

View File

@@ -185,7 +185,8 @@ def get_pricing_rule_for_item(args):
"discount_percentage": 0.0
})
else:
item_details.discount_percentage = pricing_rule.discount_percentage or args.discount_percentage
item_details.discount_percentage = (pricing_rule.get('discount_percentage', 0)
if pricing_rule else args.discount_percentage)
elif args.get('pricing_rule'):
item_details = remove_pricing_rule_for_item(args.get("pricing_rule"), item_details)

View File

@@ -11,12 +11,16 @@ from erpnext.stock.get_item_details import get_item_details
from frappe import MandatoryError
class TestPricingRule(unittest.TestCase):
def setUp(self):
frappe.db.sql("delete from `tabPricing Rule`")
def tearDown(self):
frappe.db.sql("delete from `tabPricing Rule`")
def test_pricing_rule_for_discount(self):
from erpnext.stock.get_item_details import get_item_details
from frappe import MandatoryError
frappe.db.sql("delete from `tabPricing Rule`")
test_record = {
"doctype": "Pricing Rule",
"title": "_Test Pricing Rule",
@@ -88,14 +92,10 @@ class TestPricingRule(unittest.TestCase):
details = get_item_details(args)
self.assertEquals(details.get("discount_percentage"), 15)
frappe.db.sql("delete from `tabPricing Rule`")
def test_pricing_rule_for_margin(self):
from erpnext.stock.get_item_details import get_item_details
from frappe import MandatoryError
frappe.db.sql("delete from `tabPricing Rule`")
test_record = {
"doctype": "Pricing Rule",
"title": "_Test Pricing Rule",
@@ -109,14 +109,14 @@ class TestPricingRule(unittest.TestCase):
"company": "_Test Company"
}
frappe.get_doc(test_record.copy()).insert()
item_price = frappe.get_doc({
"doctype": "Item Price",
"price_list": "_Test Price List 2",
"item_code": "_Test FG Item 2",
"price_list_rate": 100
})
item_price.insert(ignore_permissions=True)
args = frappe._dict({
@@ -136,14 +136,10 @@ class TestPricingRule(unittest.TestCase):
self.assertEquals(details.get("margin_type"), "Percentage")
self.assertEquals(details.get("margin_rate_or_amount"), 10)
frappe.db.sql("delete from `tabPricing Rule`")
def test_pricing_rule_for_variants(self):
from erpnext.stock.get_item_details import get_item_details
from frappe import MandatoryError
frappe.db.sql("delete from `tabPricing Rule`")
if not frappe.db.exists("Item", "Test Variant PRT"):
frappe.get_doc({
"doctype": "Item",
@@ -209,8 +205,6 @@ class TestPricingRule(unittest.TestCase):
self.assertEquals(details.get("discount_percentage"), 17.5)
def test_pricing_rule_for_stock_qty(self):
frappe.db.sql("delete from `tabPricing Rule`")
test_record = {
"doctype": "Pricing Rule",
"title": "_Test Pricing Rule",
@@ -253,24 +247,18 @@ class TestPricingRule(unittest.TestCase):
def test_pricing_rule_with_margin_and_discount(self):
frappe.delete_doc_if_exists('Pricing Rule', '_Test Pricing Rule')
make_pricing_rule(selling=1, margin_type="Percentage", margin_rate_or_amount=10)
make_pricing_rule(selling=1, margin_type="Percentage", margin_rate_or_amount=10, discount_percentage=10)
si = create_sales_invoice(do_not_save=True)
si.items[0].price_list_rate = 1000
si.payment_schedule = []
si.insert(ignore_permissions=True)
item = si.items[0]
self.assertEquals(item.rate, 1100)
self.assertEquals(item.margin_rate_or_amount, 10)
# With discount
item.discount_percentage = 10
si.payment_schedule = []
si.save()
item = si.items[0]
self.assertEquals(item.rate_with_margin, 1100)
self.assertEqual(item.discount_percentage, 10)
self.assertEquals(item.discount_amount, 110)
self.assertEquals(item.rate, 990)
self.assertEquals(item.discount_percentage, 10)
frappe.db.sql("delete from `tabPricing Rule`")
def make_pricing_rule(**args):
args = frappe._dict(args)

View File

@@ -363,7 +363,10 @@ class PurchaseInvoice(BuyingController):
return gl_entries
def make_supplier_gl_entry(self, gl_entries):
grand_total = self.rounded_total or self.grand_total
# Checked both rounding_adjustment and rounded_total
# because rounded_total had value even before introcution of posting GLE based on rounded total
grand_total = self.rounded_total if (self.rounding_adjustment and self.rounded_total) else self.grand_total
if grand_total:
# Didnot use base_grand_total to book rounding loss gle
grand_total_in_company_currency = flt(grand_total * self.conversion_rate,
@@ -388,16 +391,20 @@ class PurchaseInvoice(BuyingController):
expenses_included_in_valuation = self.get_company_default("expenses_included_in_valuation")
warehouse_account = get_warehouse_account_map()
voucher_wise_stock_value = {}
if self.update_stock:
for d in frappe.get_all('Stock Ledger Entry',
fields = ["voucher_detail_no", "stock_value_difference"], filters={'voucher_no': self.name}):
voucher_wise_stock_value.setdefault(d.voucher_detail_no, d.stock_value_difference)
for item in self.get("items"):
if flt(item.base_net_amount):
account_currency = get_account_currency(item.expense_account)
if self.update_stock and self.auto_accounting_for_stock and item.item_code in stock_items:
val_rate_db_precision = 6 if cint(item.precision("valuation_rate")) <= 6 else 9
# warehouse account
warehouse_debit_amount = flt(flt(item.valuation_rate, val_rate_db_precision)
* flt(item.qty) * flt(item.conversion_factor), item.precision("base_net_amount"))
warehouse_debit_amount = self.make_stock_adjustment_entry(gl_entries,
item, voucher_wise_stock_value, account_currency)
gl_entries.append(
self.get_gl_dict({
@@ -469,6 +476,36 @@ class PurchaseInvoice(BuyingController):
self.negative_expense_to_be_booked += flt(item.item_tax_amount, \
item.precision("item_tax_amount"))
def make_stock_adjustment_entry(self, gl_entries, item, voucher_wise_stock_value, account_currency):
net_amt_precision = item.precision("base_net_amount")
val_rate_db_precision = 6 if cint(item.precision("valuation_rate")) <= 6 else 9
warehouse_debit_amount = flt(flt(item.valuation_rate, val_rate_db_precision)
* flt(item.qty) * flt(item.conversion_factor), net_amt_precision)
# Stock ledger value is not matching with the warehouse amount
if (self.update_stock and voucher_wise_stock_value.get(item.name) and
warehouse_debit_amount != flt(voucher_wise_stock_value.get(item.name), net_amt_precision)):
cost_of_goods_sold_account = self.get_company_default("default_expense_account")
stock_amount = flt(voucher_wise_stock_value.get(item.name), net_amt_precision)
stock_adjustment_amt = warehouse_debit_amount - stock_amount
gl_entries.append(
self.get_gl_dict({
"account": cost_of_goods_sold_account,
"against": item.expense_account,
"debit": stock_adjustment_amt,
"remarks": self.get("remarks") or _("Stock Adjustment"),
"cost_center": item.cost_center,
"project": item.project
}, account_currency)
)
warehouse_debit_amount = stock_amount
return warehouse_debit_amount
def make_tax_gl_entries(self, gl_entries):
# tax table gl entries
valuation_tax = {}

View File

@@ -506,7 +506,7 @@ def save_invoice(doc, name, name_list):
frappe.db.commit()
name_list.append(name)
except Exception:
frappe.log_error(frappe.get_traceback())
frappe.db.rollback()
frappe.log_error(frappe.get_traceback())
return name_list

View File

@@ -589,9 +589,6 @@ class SalesInvoice(SellingController):
def make_gl_entries(self, gl_entries=None, repost_future_gle=True, from_repost=False):
auto_accounting_for_stock = erpnext.is_perpetual_inventory_enabled(self.company)
if not self.grand_total:
return
if not gl_entries:
gl_entries = self.get_gl_entries()
@@ -641,7 +638,9 @@ class SalesInvoice(SellingController):
return gl_entries
def make_customer_gl_entry(self, gl_entries):
grand_total = self.rounded_total or self.grand_total
# Checked both rounding_adjustment and rounded_total
# because rounded_total had value even before introcution of posting GLE based on rounded total
grand_total = self.rounded_total if (self.rounding_adjustment and self.rounded_total) else self.grand_total
if grand_total:
# Didnot use base_grand_total to book rounding loss gle
grand_total_in_company_currency = flt(grand_total * self.conversion_rate,
@@ -669,9 +668,11 @@ class SalesInvoice(SellingController):
self.get_gl_dict({
"account": tax.account_head,
"against": self.customer,
"credit": flt(tax.base_tax_amount_after_discount_amount),
"credit_in_account_currency": flt(tax.base_tax_amount_after_discount_amount) \
if account_currency==self.company_currency else flt(tax.tax_amount_after_discount_amount),
"credit": flt(tax.base_tax_amount_after_discount_amount,
tax.precision("tax_amount_after_discount_amount")),
"credit_in_account_currency": (flt(tax.base_tax_amount_after_discount_amount,
tax.precision("base_tax_amount_after_discount_amount")) if account_currency==self.company_currency else
flt(tax.tax_amount_after_discount_amount, tax.precision("tax_amount_after_discount_amount"))),
"cost_center": tax.cost_center
}, account_currency)
)
@@ -679,7 +680,7 @@ class SalesInvoice(SellingController):
def make_item_gl_entries(self, gl_entries):
# income account gl entries
for item in self.get("items"):
if flt(item.base_net_amount):
if flt(item.base_net_amount, item.precision("base_net_amount")):
if item.is_fixed_asset:
asset = frappe.get_doc("Asset", item.asset)
@@ -696,9 +697,10 @@ class SalesInvoice(SellingController):
self.get_gl_dict({
"account": item.income_account,
"against": self.customer,
"credit": item.base_net_amount,
"credit_in_account_currency": item.base_net_amount \
if account_currency==self.company_currency else item.net_amount,
"credit": flt(item.base_net_amount, item.precision("base_net_amount")),
"credit_in_account_currency": (flt(item.base_net_amount, item.precision("base_net_amount"))
if account_currency==self.company_currency
else flt(item.net_amount, item.precision("net_amount"))),
"cost_center": item.cost_center
}, account_currency)
)
@@ -769,7 +771,7 @@ class SalesInvoice(SellingController):
def make_write_off_gl_entry(self, gl_entries):
# write off entries, applicable if only pos
if self.write_off_account and self.write_off_amount:
if self.write_off_account and flt(self.write_off_amount, self.precision("write_off_amount")):
write_off_account_currency = get_account_currency(self.write_off_account)
default_cost_center = frappe.db.get_value('Company', self.company, 'cost_center')
@@ -779,9 +781,10 @@ class SalesInvoice(SellingController):
"party_type": "Customer",
"party": self.customer,
"against": self.write_off_account,
"credit": self.base_write_off_amount,
"credit_in_account_currency": self.base_write_off_amount \
if self.party_account_currency==self.company_currency else self.write_off_amount,
"credit": flt(self.base_write_off_amount, self.precision("base_write_off_amount")),
"credit_in_account_currency": (flt(self.base_write_off_amount,
self.precision("base_write_off_amount")) if self.party_account_currency==self.company_currency
else flt(self.write_off_amount, self.precision("write_off_amount"))),
"against_voucher": self.return_against if cint(self.is_return) else self.name,
"against_voucher_type": self.doctype
}, self.party_account_currency)
@@ -790,15 +793,16 @@ class SalesInvoice(SellingController):
self.get_gl_dict({
"account": self.write_off_account,
"against": self.customer,
"debit": self.base_write_off_amount,
"debit_in_account_currency": self.base_write_off_amount \
if write_off_account_currency==self.company_currency else self.write_off_amount,
"debit": flt(self.base_write_off_amount, self.precision("base_write_off_amount")),
"debit_in_account_currency": (flt(self.base_write_off_amount,
self.precision("base_write_off_amount")) if write_off_account_currency==self.company_currency
else flt(self.write_off_amount, self.precision("write_off_amount"))),
"cost_center": self.write_off_cost_center or default_cost_center
}, write_off_account_currency)
)
def make_gle_for_rounding_adjustment(self, gl_entries):
if self.rounding_adjustment:
if flt(self.rounding_adjustment, self.precision("rounding_adjustment")):
round_off_account, round_off_cost_center = \
get_round_off_account_and_cost_center(self.company)
@@ -806,8 +810,10 @@ class SalesInvoice(SellingController):
self.get_gl_dict({
"account": round_off_account,
"against": self.customer,
"credit_in_account_currency": self.rounding_adjustment,
"credit": self.base_rounding_adjustment,
"credit_in_account_currency": flt(self.rounding_adjustment,
self.precision("rounding_adjustment")),
"credit": flt(self.base_rounding_adjustment,
self.precision("base_rounding_adjustment")),
"cost_center": round_off_cost_center,
}
))

View File

@@ -75,7 +75,7 @@
<td class="text-right">{%= format_currency(balance_row[range3]) %}</td>
<td class="text-right">{%= format_currency(balance_row[range4]) %}</td>
<td class="text-right">
{%= format_currency(flt(balance_row[__("Outstanding Amount")]), data[data.length-1]["currency"]) %}
{%= format_currency(flt(balance_row[("outstanding_amount")]), data[data.length-1]["currency"]) %}
</td>
</tr>
<td>{%= __("PDC/LC") %}</td>
@@ -84,7 +84,7 @@
<td></td>
<td></td>
<td class="text-right">
{%= format_currency(flt(balance_row[__("PDC/LC Amount")]), data[data.length-1]["currency"]) %}
{%= format_currency(flt(balance_row[("pdc/lc_amount")]), data[data.length-1]["currency"]) %}
</td>
<tr class="cvs-footer">
<th class="text-left">{%= __("Cheques Required") %}</th>
@@ -93,7 +93,7 @@
<th></th>
<th></th>
<th class="text-right">
{%= format_currency(flt(balance_row[__("Outstanding Amount")]-balance_row[__("PDC/LC Amount")]), data[data.length-1]["currency"]) %}</th>
{%= format_currency(flt(balance_row[("outstanding_amount")]-balance_row[("pdc/lc_amount")]), data[data.length-1]["currency"]) %}</th>
</tr>
</tbody>
@@ -161,26 +161,26 @@
</td>
{% } %}
<td style="text-align: right">
{%= format_currency(data[i]["Invoiced Amount"], data[i]["currency"]) %}</td>
{%= format_currency(data[i]["invoiced_amount"], data[i]["currency"]) %}</td>
{% if(!filters.show_pdc_in_print) { %}
<td style="text-align: right">
{%= format_currency(data[i]["Paid Amount"], data[i]["currency"]) %}</td>
{%= format_currency(data[i]["paid_amount"], data[i]["currency"]) %}</td>
<td style="text-align: right">
{%= report.report_name === "Accounts Receivable" ? format_currency(data[i]["Credit Note"], data[i]["currency"]) : format_currency(data[i]["Debit Note"], data[i]["currency"]) %}</td>
{%= report.report_name === "Accounts Receivable" ? format_currency(data[i]["credit_note"], data[i]["currency"]) : format_currency(data[i]["debit_note"], data[i]["currency"]) %}</td>
{% } %}
<td style="text-align: right">
{%= format_currency(data[i]["Outstanding Amount"], data[i]["currency"]) %}</td>
{%= format_currency(data[i]["outstanding_amount"], data[i]["currency"]) %}</td>
{% if(filters.show_pdc_in_print) { %}
{% if(report.report_name === "Accounts Receivable") { %}
<td style="text-align: right">
{%= data[i][__("Customer LPO")] %}</td>
{%= data[i]["po_no"] %}</td>
{% } %}
<td style="text-align: right">{%= frappe.datetime.str_to_user(data[i][__("PDC/LC Date")]) %}</td>
<td style="text-align: right">{%= data[i][__("PDC/LC Ref")] %}</td>
<td style="text-align: right">{%= format_currency(data[i][__("PDC/LC Amount")], data[i]["currency"]) %}</td>
<td style="text-align: right">{%= format_currency(data[i][__("Remaining Balance")], data[i]["currency"]) %}</td>
<td style="text-align: right">{%= frappe.datetime.str_to_user(data[i][("pdc/lc_date")]) %}</td>
<td style="text-align: right">{%= data[i][("pdc/lc_ref")] %}</td>
<td style="text-align: right">{%= format_currency(data[i][("pdc/lc_amount")], data[i]["currency"]) %}</td>
<td style="text-align: right">{%= format_currency(data[i][("remaining_balance")], data[i]["currency"]) %}</td>
{% } %}
{% } else { %}
<td></td>
@@ -189,15 +189,15 @@
{% } %}
<td><b>{%= __("Total") %}</b></td>
<td style="text-align: right">
{%= format_currency(data[i]["Invoiced Amount"], data[i]["currency"] ) %}</td>
{%= format_currency(data[i]["invoiced_amount"], data[i]["currency"] ) %}</td>
{% if(!filters.show_pdc_in_print) { %}
<td style="text-align: right">
{%= format_currency(data[i]["Paid Amount"], data[i]["currency"]) %}</td>
<td style="text-align: right">{%= report.report_name === "Accounts Receivable" ? format_currency(data[i]["Credit Note"], data[i]["currency"]) : format_currency(data[i]["Debit Note"], data[i]["currency"]) %} </td>
{%= format_currency(data[i]["paid_amount"], data[i]["currency"]) %}</td>
<td style="text-align: right">{%= report.report_name === "Accounts Receivable" ? format_currency(data[i]["credit_note"], data[i]["currency"]) : format_currency(data[i]["debit_note"], data[i]["currency"]) %} </td>
{% } %}
<td style="text-align: right">
{%= format_currency(data[i]["Outstanding Amount"], data[i]["currency"]) %}</td>
{%= format_currency(data[i]["outstanding_amount"], data[i]["currency"]) %}</td>
{% if(filters.show_pdc_in_print) { %}
{% if(report.report_name === "Accounts Receivable") { %}
@@ -205,9 +205,9 @@
{%= data[i][__("Customer LPO")] %}</td>
{% } %}
<td style="text-align: right">{%= frappe.datetime.str_to_user(data[i][__("PDC/LC Date")]) %}</td>
<td style="text-align: right">{%= data[i][__("PDC/LC Ref")] %}</td>
<td style="text-align: right">{%= format_currency(data[i][__("PDC/LC Amount")], data[i]["currency"]) %}</td>
<td style="text-align: right">{%= format_currency(data[i][__("Remaining Balance")], data[i]["currency"]) %}</td>
<td style="text-align: right">{%= data[i][("pdc/lc_ref")] %}</td>
<td style="text-align: right">{%= format_currency(data[i][("pdc/lc_amount")], data[i]["currency"]) %}</td>
<td style="text-align: right">{%= format_currency(data[i][("remaining_balance")], data[i]["currency"]) %}</td>
{% } %}
{% } %}
{% } else { %}
@@ -220,7 +220,7 @@
<br> {%= data[i][__("Customer Name")] %}
{% } else if(data[i][__("Supplier Name")] != data[i][__("Supplier")]) { %}
<br> {%= data[i][__("Supplier Name")] %}
{% } %}
{% } %}
{% } %}
<br>{%= __("Remarks") %}:
{%= data[i][__("Remarks")] %}
@@ -228,14 +228,14 @@
{% } else { %}
<td><b>{%= __("Total") %}</b></td>
{% } %}
<td style="text-align: right">{%= format_currency(data[i][__("Total Invoiced Amt")], data[i]["currency"]) %}</td>
<td style="text-align: right">{%= format_currency(data[i][__("Total Paid Amt")], data[i]["currency"]) %}</td>
<td style="text-align: right">{%= report.report_name === "Accounts Receivable Summary" ? format_currency(data[i][__("Credit Note Amt")], data[i]["currency"]) : format_currency(data[i][__("Debit Note Amt")], data[i]["currency"]) %}</td>
<td style="text-align: right">{%= format_currency(data[i][__("Total Outstanding Amt")], data[i]["currency"]) %}</td>
<td style="text-align: right">{%= format_currency(data[i][("total_invoiced_amt")], data[i]["currency"]) %}</td>
<td style="text-align: right">{%= format_currency(data[i][("total_paid_amt")], data[i]["currency"]) %}</td>
<td style="text-align: right">{%= report.report_name === "Accounts Receivable Summary" ? format_currency(data[i][__("credit_note_amt")], data[i]["currency"]) : format_currency(data[i][__("debit_note_amt")], data[i]["currency"]) %}</td>
<td style="text-align: right">{%= format_currency(data[i][("total_outstanding_amt")], data[i]["currency"]) %}</td>
{% } %}
{% } %}
</tr>
{% } %}
</tbody>
</table>
<p class="text-right text-muted">{{ __("Printed On ") }}{%= dateutil.str_to_user(dateutil.get_datetime_as_string()) %}</p>
<p class="text-right text-muted">{{ __("Printed On ") }}{%= dateutil.str_to_user(dateutil.get_datetime_as_string()) %}</p>

View File

@@ -60,6 +60,7 @@ class ReceivablePayableReport(object):
for label in ("Invoiced Amount", "Paid Amount", credit_or_debit_note, "Outstanding Amount"):
columns.append({
"label": label,
"fieldname": frappe.scrub(label),
"fieldtype": "Currency",
"options": "currency",
"width": 120
@@ -87,25 +88,49 @@ class ReceivablePayableReport(object):
"width": 120
})
columns.append({
columns += [
{
"fieldname": "currency",
"label": _("Currency"),
"fieldtype": "Link",
"options": "Currency",
"width": 100
})
columns += [
_("PDC/LC Date") + ":Date:110",
_("PDC/LC Ref") + ":Data:110",
_("PDC/LC Amount") + ":Currency/currency:130",
_("Remaining Balance") + ":Currency/currency:130"
]
},
{
"fieldname": "pdc/lc_date",
"label": _("PDC/LC Date"),
"fieldtype": "Date",
"width": 110
},
{
"fieldname": "pdc/lc_ref",
"label": _("PDC/LC Ref"),
"fieldtype": "Data",
"width": 110
},
{
"fieldname": "pdc/lc_amount",
"label": _("PDC/LC Amount"),
"fieldtype": "Currency",
"options": "Currency",
"width": 130
},
{
"fieldname": "remaining_balance",
"label": _("Remaining Balance"),
"fieldtype": "Currency",
"options": "Currency",
"width": 130
}]
if args.get('party_type') == 'Customer':
columns += [_("Customer LPO") + ":Data:100"]
columns.append({
"label": _("Customer LPO"),
"fieldtype": "Data",
"fieldname": "po_no",
"width": 100,
})
columns += [_("Delivery Note") + ":Data:100"]
if args.get("party_type") == "Customer":
columns += [
_("Territory") + ":Link/Territory:80",
@@ -134,7 +159,6 @@ class ReceivablePayableReport(object):
data = []
pdc_details = get_pdc_details(args.get("party_type"), self.filters.report_date)
gl_entries_data = self.get_entries_till(self.filters.report_date, args.get("party_type"))
if gl_entries_data:
@@ -253,14 +277,16 @@ class ReceivablePayableReport(object):
for e in self.get_gl_entries_for(gle.party, gle.party_type, gle.voucher_type, gle.voucher_no):
if getdate(e.posting_date) <= report_date and e.name!=gle.name:
amount = flt(e.get(reverse_dr_or_cr)) - flt(e.get(dr_or_cr))
amount = flt(e.get(reverse_dr_or_cr), currency_precision) - flt(e.get(dr_or_cr), currency_precision)
if e.voucher_no not in return_entries:
payment_amount += amount
else:
credit_note_amount += amount
outstanding_amount = flt((flt(gle.get(dr_or_cr)) - flt(gle.get(reverse_dr_or_cr)) \
- payment_amount - credit_note_amount), currency_precision)
outstanding_amount = (flt((flt(gle.get(dr_or_cr), currency_precision)
- flt(gle.get(reverse_dr_or_cr), currency_precision)
- payment_amount - credit_note_amount), currency_precision))
credit_note_amount = flt(credit_note_amount, currency_precision)
return outstanding_amount, credit_note_amount
@@ -422,7 +448,6 @@ def get_pdc_details(party_type, report_date):
and pent.party_type = %s
group by pent.party, pref.reference_name""", (report_date, party_type), as_dict=1):
pdc_details.setdefault((pdc.invoice_no, pdc.party), pdc)
if scrub(party_type):
amount_field = ("jea.debit_in_account_currency"
if party_type == 'Supplier' else "jea.credit_in_account_currency")

View File

@@ -3,7 +3,7 @@
from __future__ import unicode_literals
import frappe
from frappe import _
from frappe import _, scrub
from frappe.utils import flt
from erpnext.accounts.report.accounts_receivable.accounts_receivable import ReceivablePayableReport
@@ -18,25 +18,93 @@ class AccountsReceivableSummary(ReceivablePayableReport):
if party_naming_by == "Naming Series":
columns += [ args.get("party_type") + " Name::140"]
credit_debit_label = _("Credit Note Amt") if args.get('party_type') == 'Customer' else _("Debit Note Amt")
credit_debit_label = "Credit Note Amt" if args.get('party_type') == 'Customer' else "Debit Note Amt"
columns += [{
"label": _("Total Invoiced Amt"),
"fieldname": "total_invoiced_amt",
"fieldtype": "Currency",
"options": "currency",
"width": 100
},
{
"label": _("Total Paid Amt"),
"fieldname": "total_paid_amt",
"fieldtype": "Currency",
"options": "currency",
"width": 100
}]
columns += [
_("Total Invoiced Amt") + ":Currency/currency:140",
_("Total Paid Amt") + ":Currency/currency:140",
credit_debit_label + ":Currency/currency:140",
_("Total Outstanding Amt") + ":Currency/currency:160",
"0-" + str(self.filters.range1) + ":Currency/currency:100",
str(self.filters.range1) + "-" + str(self.filters.range2) + ":Currency/currency:100",
str(self.filters.range2) + "-" + str(self.filters.range3) + ":Currency/currency:100",
str(self.filters.range3) + _("-Above") + ":Currency/currency:100"]
{
"label": _(credit_debit_label),
"fieldname": scrub(credit_debit_label),
"fieldtype": "Currency",
"options": "currency",
"width": 140
},
{
"label": _("Total Outstanding Amt"),
"fieldname": "total_outstanding_amt",
"fieldtype": "Currency",
"options": "currency",
"width": 160
},
{
"label": _("0-" + str(self.filters.range1)),
"fieldname": scrub("0-" + str(self.filters.range1)),
"fieldtype": "Currency",
"options": "currency",
"width": 160
},
{
"label": _(str(self.filters.range1) + "-" + str(self.filters.range2)),
"fieldname": scrub(str(self.filters.range1) + "-" + str(self.filters.range2)),
"fieldtype": "Currency",
"options": "currency",
"width": 160
},
{
"label": _(str(self.filters.range2) + "-" + str(self.filters.range3)),
"fieldname": scrub(str(self.filters.range2) + "-" + str(self.filters.range3)),
"fieldtype": "Currency",
"options": "currency",
"width": 160
},
{
"label": _(str(self.filters.range3) + _("-Above")),
"fieldname": scrub(str(self.filters.range3) + _("-Above")),
"fieldtype": "Currency",
"options": "currency",
"width": 160
}
]
if args.get("party_type") == "Customer":
columns += [
_("Territory") + ":Link/Territory:80",
_("Customer Group") + ":Link/Customer Group:120"
]
columns += [{
"label": _("Territory"),
"fieldname": "territory",
"fieldtype": "Link",
"options": "Territory",
"width": 80
},
{
"label": _("Customer Group"),
"fieldname": "customer_group",
"fieldtype": "Link",
"options": "Customer Group",
"width": 80
}]
if args.get("party_type") == "Supplier":
columns += [_("Supplier Type") + ":Link/Supplier Type:80"]
columns += [{
"label": _("Supplier Group"),
"fieldname": "supplier_group",
"fieldtype": "Link",
"options": "Supplier Group",
"width": 80
}]
columns.append({
"fieldname": "currency",
"label": _("Currency"),
@@ -67,7 +135,7 @@ class AccountsReceivableSummary(ReceivablePayableReport):
row += [self.get_territory(party), self.get_customer_group(party)]
if args.get("party_type") == "Supplier":
row += [self.get_supplier_type(party)]
row.append(party_dict.currency)
data.append(row)
@@ -91,7 +159,7 @@ class AccountsReceivableSummary(ReceivablePayableReport):
for k in party_total[d.party].keys():
if k != "currency":
party_total[d.party][k] += flt(d.get(k, 0))
party_total[d.party].currency = d.currency
return party_total

View File

@@ -3,47 +3,75 @@
from __future__ import unicode_literals
import frappe
from frappe.utils import flt
from frappe import _
def execute(filters=None):
columns, data = get_columns(), get_data(filters)
return columns, data
def get_data(filters):
data = frappe.db.sql("""
select
a.name as asset, a.asset_category, a.status,
a.depreciation_method, a.purchase_date, a.gross_purchase_amount,
ds.schedule_date as depreciation_date, ds.depreciation_amount,
ds.accumulated_depreciation_amount,
(a.gross_purchase_amount - ds.accumulated_depreciation_amount) as amount_after_depreciation,
ds.journal_entry as depreciation_entry
from
`tabAsset` a, `tabDepreciation Schedule` ds
where
a.name = ds.parent
and a.docstatus=1
and ifnull(ds.journal_entry, '') != ''
and ds.schedule_date between %(from_date)s and %(to_date)s
and a.company = %(company)s
{conditions}
order by
a.name asc, ds.schedule_date asc
""".format(conditions=get_filter_conditions(filters)), filters, as_dict=1)
return data
def get_filter_conditions(filters):
conditions = ""
data = []
depreciation_accounts = frappe.db.sql_list(""" select name from tabAccount
where ifnull(account_type, '') = 'Depreciation' """)
filters_data = [["company", "=", filters.get('company')],
["posting_date", ">=", filters.get('from_date')],
["posting_date", "<=", filters.get('to_date')],
["against_voucher_type", "=", "Asset"],
["account", "in", depreciation_accounts]]
if filters.get("asset"):
conditions += " and a.name = %(asset)s"
filters_data.append(["against_voucher", "=", filters.get("asset")])
if filters.get("asset_category"):
conditions += " and a.asset_category = %(asset_category)s"
return conditions
assets = frappe.db.sql_list("""select name from tabAsset
where asset_category = %s and docstatus=1""", filters.get("asset_category"))
filters_data.append(["against_voucher", "in", assets])
gl_entries = frappe.get_all('GL Entry',
filters= filters_data,
fields = ["against_voucher", "debit_in_account_currency as debit", "voucher_no", "posting_date"],
order_by= "against_voucher, posting_date")
if not gl_entries:
return data
assets = [d.against_voucher for d in gl_entries]
assets_details = get_assets_details(assets)
for d in gl_entries:
asset_data = assets_details.get(d.against_voucher)
if not asset_data.get("accumulated_depreciation_amount"):
asset_data.accumulated_depreciation_amount = d.debit
else:
asset_data.accumulated_depreciation_amount += d.debit
row = frappe._dict(asset_data)
row.update({
"depreciation_amount": d.debit,
"depreciation_date": d.posting_date,
"amount_after_depreciation": (flt(row.gross_purchase_amount) -
flt(row.accumulated_depreciation_amount)),
"depreciation_entry": d.voucher_no
})
data.append(row)
return data
def get_assets_details(assets):
assets_details = {}
fields = ["name as asset", "gross_purchase_amount",
"asset_category", "status", "depreciation_method", "purchase_date"]
for d in frappe.get_all("Asset", fields = fields, filters = {'name': ('in', assets)}):
assets_details.setdefault(d.asset, d)
return assets_details
def get_columns():
return [
{

View File

@@ -306,19 +306,20 @@ def set_gl_entries_by_account(company, from_date, to_date, root_lft, root_rgt, f
additional_conditions = get_additional_conditions(from_date, ignore_closing_entries, filters)
accounts = frappe.db.sql_list("""select name from `tabAccount`
where lft >= %s and rgt <= %s""", (root_lft, root_rgt))
additional_conditions += " and account in ('{}')"\
.format("', '".join([frappe.db.escape(d) for d in accounts]))
gl_entries = frappe.db.sql("""select posting_date, account, debit, credit, is_opening, fiscal_year from `tabGL Entry`
where company=%(company)s
{additional_conditions}
and posting_date <= %(to_date)s
and account in (select name from `tabAccount`
where lft >= %(lft)s and rgt <= %(rgt)s)
order by account, posting_date""".format(additional_conditions=additional_conditions),
{
"company": company,
"from_date": from_date,
"to_date": to_date,
"lft": root_lft,
"rgt": root_rgt
},
as_dict=True)

View File

@@ -216,7 +216,7 @@ def get_accountwise_gle(filters, gl_entries, gle_map):
if gle.posting_date < from_date or cstr(gle.is_opening) == "Yes":
update_value_in_dict(gle_map[gle.account].totals, 'opening', gle)
update_value_in_dict(totals, 'opening', gle)
update_value_in_dict(gle_map[gle.account].totals, 'closing', gle)
update_value_in_dict(totals, 'closing', gle)
@@ -323,7 +323,7 @@ def get_columns(filters):
{
"label": _("Balance") + " (" + filters.account_currency + ")",
"fieldname": "balance_in_account_currency",
"fieldtype": "Data",
"fieldtype": "Float",
"width": 100
}
])

View File

@@ -16,7 +16,7 @@ def _execute(filters=None, additional_table_columns=None, additional_query_colum
if not filters: filters = {}
columns = get_columns(additional_table_columns)
company_currency = erpnext.get_company_currency(filters.company)
company_currency = erpnext.get_company_currency(filters.get('company'))
item_list = get_items(filters, additional_query_columns)
if item_list:
@@ -54,7 +54,7 @@ def _execute(filters=None, additional_table_columns=None, additional_query_colum
]
row += [(d.base_net_rate * d.qty)/d.stock_qty, d.base_net_amount] \
if d.stock_uom != d.uom else [d.base_net_rate, d.base_net_amount]
if d.stock_uom != d.uom and d.stock_qty != 0 else [d.base_net_rate, d.base_net_amount]
total_tax = 0
for tax in tax_columns:

View File

@@ -67,11 +67,33 @@ frappe.ui.form.on('Asset', {
frm.trigger("create_asset_maintenance");
}, __("Make"));
}
if (!frm.doc.calculate_depreciation) {
frm.add_custom_button(__("Depreciation Entry"), function() {
frm.trigger("make_journal_entry");
}, __("Make"));
}
frm.page.set_inner_btn_group_as_primary(__("Make"));
frm.trigger("setup_chart");
}
},
make_journal_entry: function(frm) {
frappe.call({
method: "erpnext.assets.doctype.asset.asset.make_journal_entry",
args: {
asset_name: frm.doc.name
},
callback: function(r) {
if (r.message) {
var doclist = frappe.model.sync(r.message);
frappe.set_route("Form", doclist[0].doctype, doclist[0].name);
}
}
})
},
setup_chart: function(frm) {
var x_intervals = [frm.doc.purchase_date];
var asset_values = [frm.doc.gross_purchase_amount];

View File

@@ -283,3 +283,34 @@ def get_item_details(item_code):
})
return ret
@frappe.whitelist()
def make_journal_entry(asset_name):
asset = frappe.get_doc("Asset", asset_name)
fixed_asset_account, accumulated_depreciation_account, depreciation_expense_account = \
get_depreciation_accounts(asset)
depreciation_cost_center, depreciation_series = frappe.db.get_value("Company", asset.company,
["depreciation_cost_center", "series_for_depreciation_entry"])
depreciation_cost_center = asset.cost_center or depreciation_cost_center
je = frappe.new_doc("Journal Entry")
je.voucher_type = "Depreciation Entry"
je.naming_series = depreciation_series
je.company = asset.company
je.remark = "Depreciation Entry against asset {0}".format(asset_name)
je.append("accounts", {
"account": depreciation_expense_account,
"reference_type": "Asset",
"reference_name": asset.name,
"cost_center": depreciation_cost_center
})
je.append("accounts", {
"account": accumulated_depreciation_account,
"reference_type": "Asset",
"reference_name": asset.name
})
return je

View File

@@ -5,13 +5,13 @@
from __future__ import unicode_literals
import frappe
from frappe import _
from frappe.utils import flt, today, getdate
from frappe.utils import flt, today, getdate, cint
def post_depreciation_entries(date=None):
# Return if automatic booking of asset depreciation is disabled
if not frappe.db.get_value("Accounts Settings", None, "book_asset_depreciation_entry_automatically"):
if not cint(frappe.db.get_value("Accounts Settings", None, "book_asset_depreciation_entry_automatically")):
return
if not date:
date = today()
for asset in get_depreciable_assets(date):

View File

@@ -49,7 +49,17 @@ class TestAsset(unittest.TestCase):
self.assertFalse(frappe.db.get_value("GL Entry",
{"voucher_type": "Purchase Invoice", "voucher_no": pi.name}))
def test_is_fixed_asset_set(self):
doc = frappe.new_doc('Purchase Invoice')
doc.supplier = '_Test Supplier'
doc.append('items', {
'item_code': 'Macbook Pro',
'qty': 1
})
doc.set_missing_values()
self.assertEquals(doc.items[0].is_fixed_asset, 1)
def test_schedule_for_straight_line_method(self):
asset = frappe.get_doc("Asset", "Macbook Pro 1")

View File

@@ -85,6 +85,7 @@ class PurchaseOrder(BuyingController):
frappe.msgprint(_("{0} currently has a {1} Supplier Scorecard standing, and Purchase Orders to this supplier should be issued with caution.").format(self.supplier, standing), title=_("Caution"), indicator='orange')
def validate_minimum_order_qty(self):
if not self.get("items"): return
items = list(set([d.item_code for d in self.get("items")]))
itemwise_min_order_qty = frappe._dict(frappe.db.sql("""select name, min_order_qty

View File

@@ -60,7 +60,12 @@ class SupplierQuotation(BuyingController):
for rfq in rfq_list:
doc = frappe.get_doc('Request for Quotation', rfq)
doc_sup = frappe.get_all('Request for Quotation Supplier', filters=
{'parent': doc.name, 'supplier': self.supplier}, fields=['name', 'quote_status'])[0]
{'parent': doc.name, 'supplier': self.supplier}, fields=['name', 'quote_status'])
doc_sup = doc_sup[0] if doc_sup else None
if not doc_sup:
frappe.throw(_("Supplier {0} not found in {1}").format(self.supplier,
"<a href='desk#Form/Request for Quotation/{0}'> Request for Quotation {0} </a>".format(doc.name)))
quote_status = _('Received')
for item in doc.items:
@@ -152,4 +157,4 @@ def make_quotation(source_name, target_doc=None):
}
}, target_doc)
return doclist
return doclist

View File

@@ -13,15 +13,23 @@ frappe.ui.form.on("Supplier Scorecard", {
},
onload: function(frm) {
if (frm.doc.__unsaved == 1) {
loadAllCriteria(frm);
loadAllStandings(frm);
}
},
refresh: function(frm) {
if (frm.dashboard.hasOwnProperty('heatmap')) {
frm.dashboard.heatmap.setLegend([0,20,40,60,80,101],["#991600","#169900"]);
}
load_criteria: function(frm) {
frappe.call({
method: "erpnext.buying.doctype.supplier_scorecard_criteria.supplier_scorecard_criteria.get_criteria_list",
callback: function(r) {
frm.set_value('criteria', []);
for (var i = 0; i < r.message.length; i++)
{
var row = frm.add_child("criteria");
row.criteria_name = r.message[i].name;
frm.script_manager.trigger("criteria_name", row.doctype, row.name);
}
refresh_field("criteria");
}
});
}
});
@@ -29,8 +37,8 @@ frappe.ui.form.on("Supplier Scorecard", {
frappe.ui.form.on("Supplier Scorecard Scoring Standing", {
standing_name: function(frm, cdt, cdn) {
if (frm.doc.standing_name != undefined) {
var d = frappe.get_doc(cdt, cdn);
var d = frappe.get_doc(cdt, cdn);
if (d.standing_name) {
return frm.call({
method: "erpnext.buying.doctype.supplier_scorecard_standing.supplier_scorecard_standing.get_scoring_standing",
child: d,
@@ -42,86 +50,29 @@ frappe.ui.form.on("Supplier Scorecard Scoring Standing", {
}
});
frappe.ui.form.on("Supplier Scorecard Scoring Variable", {
variable_label: function(frm, cdt, cdn) {
if (frm.doc.variable_label != undefined) {
var d = frappe.get_doc(cdt, cdn);
return frm.call({
method: "erpnext.buying.doctype.supplier_scorecard_variable.supplier_scorecard_variable.get_scoring_variable",
child: d,
args: {
variable_label: d.variable_label
}
});
}
}
});
frappe.ui.form.on("Supplier Scorecard Scoring Criteria", {
criteria_name: function(frm, cdt, cdn) {
if (frm.doc.criteria_name != undefined) {
var d = frappe.get_doc(cdt, cdn);
frm.call({
method: "erpnext.buying.doctype.supplier_scorecard_criteria.supplier_scorecard_criteria.get_variables",
var d = frappe.get_doc(cdt, cdn);
if (d.criteria_name) {
return frm.call({
method: "frappe.client.get",
args: {
criteria_name: d.criteria_name
fieldname: "weight",
doctype: "Supplier Scorecard Criteria",
filters: {name: d.criteria_name}
},
callback: function(r) {
for (var i = 0; i < r.message.length; i++)
{
var exists = false;
for (var j = 0; j < frm.doc.variables.length; j++)
{
if(!frm.doc.variables[j].hasOwnProperty("variable_label")) {
frm.get_field("variables").grid.grid_rows[j].remove();
}
else if(frm.doc.variables[j].variable_label === r.message[i]) {
exists = true;
}
}
if (!exists){
var new_row = frm.add_child("variables");
new_row.variable_label = r.message[i];
frm.script_manager.trigger("variable_label", new_row.doctype, new_row.name);
}
if(r.message){
d.weight = r.message.weight;
frm.refresh_field('criteria', 'weight');
}
refresh_field("variables");
}
});
return frm.call({
method: "erpnext.buying.doctype.supplier_scorecard_criteria.supplier_scorecard_criteria.get_scoring_criteria",
child: d,
args: {
criteria_name: d.criteria_name
}
});
}
}
});
var loadAllCriteria = function(frm) {
frappe.call({
method: "erpnext.buying.doctype.supplier_scorecard_criteria.supplier_scorecard_criteria.get_criteria_list",
callback: function(r) {
for (var j = 0; j < frm.doc.criteria.length; j++)
{
if(!frm.doc.criteria[j].hasOwnProperty("criteria_name")) {
frm.get_field("criteria").grid.grid_rows[j].remove();
}
}
for (var i = 0; i < r.message.length; i++)
{
var new_row = frm.add_child("criteria");
new_row.criteria_name = r.message[i].name;
frm.script_manager.trigger("criteria_name", new_row.doctype, new_row.name);
}
refresh_field("criteria");
}
});
};
var loadAllStandings = function(frm) {
frappe.call({
method: "erpnext.buying.doctype.supplier_scorecard_standing.supplier_scorecard_standing.get_standings_list",

View File

@@ -54,6 +54,7 @@ class SupplierScorecard(Document):
`tabSupplier Scorecard Period` scp
WHERE
scp.scorecard = %(sc)s
AND scp.docstatus = 1
ORDER BY
scp.end_date DESC""",
{"sc": self.name}, as_dict=1)
@@ -110,7 +111,8 @@ def get_timeline_data(doctype, name):
FROM
`tabSupplier Scorecard Period` sc
WHERE
sc.scorecard = %(scs)s""",
sc.scorecard = %(scs)s
AND sc.docstatus = 1""",
{"scs": scs.name}, as_dict=1)
for sc in scorecards:
@@ -162,6 +164,7 @@ def make_all_scorecards(docname):
`tabSupplier Scorecard Period` scp
WHERE
scp.scorecard = %(sc)s
AND scp.docstatus = 1
AND (
(scp.start_date > %(end_date)s
AND scp.end_date < %(start_date)s)
@@ -170,12 +173,12 @@ def make_all_scorecards(docname):
AND scp.end_date > %(start_date)s))
ORDER BY
scp.end_date DESC""",
{"sc": docname, "start_date": start_date, "end_date": end_date, "supplier": supplier}, as_dict=1)
{"sc": docname, "start_date": start_date, "end_date": end_date}, as_dict=1)
if len(scorecards) == 0:
period_card = make_supplier_scorecard(docname, None)
period_card.start_date = start_date
period_card.end_date = end_date
period_card.save()
period_card.submit()
scp_count = scp_count + 1
if start_date < first_start_date:
first_start_date = start_date

View File

@@ -21,12 +21,6 @@ class TestSupplierScorecard(unittest.TestCase):
d.weight = 0
self.assertRaises(frappe.ValidationError,my_doc.insert)
def test_missing_variable(self):
delete_test_scorecards()
my_doc = make_supplier_scorecard()
del my_doc.variables
self.assertRaises(frappe.ValidationError,my_doc.insert)
def make_supplier_scorecard():
my_doc = frappe.get_doc(valid_scorecard[0])
@@ -118,56 +112,6 @@ valid_scorecard = [
}
],
"prevent_pos":0,
"variables": [
{
"param_name":"cost_of_on_time_shipments",
"doctype":"Supplier Scorecard Scoring Variable",
"parenttype":"Supplier Scorecard",
"variable_label":"Cost of On Time Shipments",
"path":"get_cost_of_on_time_shipments",
"parentfield":"variables"
},
{
"param_name":"tot_cost_shipments",
"doctype":"Supplier Scorecard Scoring Variable",
"parenttype":"Supplier Scorecard",
"variable_label":"Total Cost of Shipments",
"path":"get_total_cost_of_shipments",
"parentfield":"variables"
},
{
"param_name":"tot_days_late",
"doctype":"Supplier Scorecard Scoring Variable",
"parenttype":"Supplier Scorecard",
"variable_label":"Total Days Late",
"path":"get_total_days_late",
"parentfield":"variables"
},
{
"param_name":"total_working_days",
"doctype":"Supplier Scorecard Scoring Variable",
"parenttype":"Supplier Scorecard",
"variable_label":"Total Working Days",
"path":"get_total_workdays",
"parentfield":"variables"
},
{
"param_name":"on_time_shipment_num",
"doctype":"Supplier Scorecard Scoring Variable",
"parenttype":"Supplier Scorecard",
"variable_label":"# of On Time Shipments",
"path":"get_on_time_shipments",
"parentfield":"variables"
},
{
"param_name":"total_shipments",
"doctype":"Supplier Scorecard Scoring Variable",
"parenttype":"Supplier Scorecard",
"variable_label":"Total Shipments",
"path":"get_total_shipments",
"parentfield":"variables"
}
],
"period":"Per Month",
"doctype":"Supplier Scorecard",
"warn_pos":0,
@@ -177,14 +121,12 @@ valid_scorecard = [
{
"weight":100.0,
"doctype":"Supplier Scorecard Scoring Criteria",
"formula":"(({cost_of_on_time_shipments} / {tot_cost_shipments}) if {tot_cost_shipments} > 0 else 1 )* 100 ",
"criteria_name":"Delivery",
"max_score":100.0,
"criteria_name":"Delivery"
}
],
"supplier":"_Test Supplier",
"name":"_Test Supplier",
"weighting_function":"{total_score} * max( 0, min ( 1 , (12 - {period_number}) / 12) )",
"weighting_function":"{total_score} * max( 0, min ( 1 , (12 - {period_number}) / 12) )"
}
]

View File

@@ -4,7 +4,7 @@
"allow_import": 0,
"allow_rename": 0,
"autoname": "field:criteria_name",
"beta": 1,
"beta": 0,
"creation": "2017-05-29 01:32:43.064891",
"custom": 0,
"docstatus": 0,
@@ -43,36 +43,6 @@
"set_only_once": 0,
"unique": 1
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "weight",
"fieldtype": "Percent",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Criteria Weight",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
@@ -87,7 +57,7 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Max Score",
"length": 0,
@@ -114,10 +84,10 @@
"fieldtype": "Small Text",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"ignore_xss_filter": 1,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Criteria Formula",
"length": 0,
@@ -133,6 +103,36 @@
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "weight",
"fieldtype": "Percent",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Criteria Weight",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
}
],
"has_web_view": 0,
@@ -145,7 +145,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2017-07-17 10:30:47.458285",
"modified": "2019-01-22 10:47:00.000822",
"modified_by": "Administrator",
"module": "Buying",
"name": "Supplier Scorecard Criteria",

View File

@@ -30,21 +30,11 @@ class SupplierScorecardCriteria(Document):
for dummy2 in range(0, len(match.groups())):
test_formula = test_formula.replace('{' + match.group(1) + '}', "0")
test_formula = test_formula.replace('&lt;','<').replace('&gt;','>')
try:
frappe.safe_eval(test_formula, None, {'max':max, 'min': min})
except Exception:
frappe.throw(_("Error evaluating the criteria formula"))
@frappe.whitelist()
def get_scoring_criteria(criteria_name):
criteria = frappe.get_doc("Supplier Scorecard Criteria", criteria_name)
return criteria
@frappe.whitelist()
def get_criteria_list():
criteria = frappe.db.sql("""
@@ -56,7 +46,6 @@ def get_criteria_list():
return criteria
@frappe.whitelist()
def get_variables(criteria_name):
criteria = frappe.get_doc("Supplier Scorecard Criteria", criteria_name)
return _get_variables(criteria)
@@ -69,21 +58,16 @@ def _get_variables(criteria):
for dummy1, match in enumerate(mylist):
for dummy2 in range(0, len(match.groups())):
try:
#var = frappe.get_doc("Supplier Scorecard Variable", {'param_name' : d})
var = frappe.db.sql("""
SELECT
scv.name
scv.variable_label, scv.description, scv.param_name, scv.path
FROM
`tabSupplier Scorecard Variable` scv
WHERE
param_name=%(param)s""",
{'param':match.group(1)},)[0][0]
{'param':match.group(1)}, as_dict=1)[0]
my_variables.append(var)
except Exception:
# Ignore the ones where the variable can't be found
frappe.throw(_('Unable to find variable: ') + str(match.group(1)), InvalidFormulaVariable)
#pass
#frappe.msgprint(str(my_variables))
return my_variables

View File

@@ -6,9 +6,11 @@
frappe.ui.form.on("Supplier Scorecard Period", {
onload: function(frm) {
frm.get_field("variables").grid.toggle_display("value", true);
frm.get_field("criteria").grid.toggle_display("score", true);
let criteria_grid = frm.get_field("criteria").grid;
criteria_grid.toggle_enable("criteria_name", false);
criteria_grid.toggle_enable("weight", false);
criteria_grid.toggle_display("max_score", true);
criteria_grid.toggle_display("formula", true);
criteria_grid.toggle_display("score", true);
}
});

View File

@@ -4,7 +4,7 @@
"allow_import": 0,
"allow_rename": 0,
"autoname": "naming_series:",
"beta": 1,
"beta": 0,
"creation": "2017-05-30 00:38:18.773013",
"custom": 0,
"docstatus": 0,
@@ -281,7 +281,7 @@
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
@@ -346,6 +346,36 @@
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "amended_from",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Amended From",
"length": 0,
"no_copy": 1,
"options": "Supplier Scorecard Period",
"permlevel": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
}
],
"has_web_view": 0,
@@ -354,11 +384,11 @@
"idx": 0,
"image_view": 0,
"in_create": 1,
"is_submittable": 0,
"is_submittable": 1,
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2017-07-12 07:33:26.130861",
"modified": "2019-01-23 13:58:26.137770",
"modified_by": "Administrator",
"module": "Buying",
"name": "Supplier Scorecard Period",
@@ -368,7 +398,7 @@
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"cancel": 1,
"create": 1,
"delete": 1,
"email": 1,
@@ -382,7 +412,7 @@
"role": "System Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"submit": 1,
"write": 1
}
],

View File

@@ -8,6 +8,7 @@ from frappe import throw, _
from frappe.model.document import Document
from frappe.model.mapper import get_mapped_doc
import erpnext.buying.doctype.supplier_scorecard_variable.supplier_scorecard_variable as variable_functions
from erpnext.buying.doctype.supplier_scorecard_criteria.supplier_scorecard_criteria import get_variables
class SupplierScorecardPeriod(Document):
@@ -28,7 +29,6 @@ class SupplierScorecardPeriod(Document):
def calculate_variables(self):
for var in self.variables:
if '.' in var.path:
method_to_call = import_string_path(var.path)
var.value = method_to_call(self)
@@ -39,29 +39,9 @@ class SupplierScorecardPeriod(Document):
def calculate_criteria(self):
#Get the criteria
for crit in self.criteria:
#me = ""
my_eval_statement = crit.formula.replace("\r", "").replace("\n", "")
#for let in my_eval_statement:
# me += let.encode('hex') + " "
#frappe.msgprint(me)
for var in self.variables:
if var.value:
if var.param_name in my_eval_statement:
my_eval_statement = my_eval_statement.replace('{' + var.param_name + '}', "{:.2f}".format(var.value))
else:
if var.param_name in my_eval_statement:
my_eval_statement = my_eval_statement.replace('{' + var.param_name + '}', '0.0')
#frappe.msgprint(my_eval_statement )
my_eval_statement = my_eval_statement.replace('&lt;','<').replace('&gt;','>')
try:
crit.score = min(crit.max_score, max( 0 ,frappe.safe_eval(my_eval_statement, None, {'max':max, 'min': min})))
crit.score = min(crit.max_score, max( 0 ,frappe.safe_eval(self.get_eval_statement(crit.formula), None, {'max':max, 'min': min})))
except Exception:
frappe.throw(_("Could not solve criteria score function for {0}. Make sure the formula is valid.".format(crit.criteria_name)),frappe.ValidationError)
crit.score = 0
@@ -73,26 +53,27 @@ class SupplierScorecardPeriod(Document):
self.total_score = myscore
def calculate_weighted_score(self, weighing_function):
my_eval_statement = weighing_function.replace("\r", "").replace("\n", "")
for var in self.variables:
if var.value:
if var.param_name in my_eval_statement:
my_eval_statement = my_eval_statement.replace('{' + var.param_name + '}', "{:.2f}".format(var.value))
else:
if var.param_name in my_eval_statement:
my_eval_statement = my_eval_statement.replace('{' + var.param_name + '}', '0.0')
my_eval_statement = my_eval_statement.replace('&lt;','<').replace('&gt;','>')
try:
weighed_score = frappe.safe_eval(my_eval_statement, None, {'max':max, 'min': min})
weighed_score = frappe.safe_eval(self.get_eval_statement(weighing_function), None, {'max':max, 'min': min})
except Exception:
frappe.throw(_("Could not solve weighted score function. Make sure the formula is valid."),frappe.ValidationError)
weighed_score = 0
return weighed_score
def get_eval_statement(self, formula):
my_eval_statement = formula.replace("\r", "").replace("\n", "")
for var in self.variables:
if var.value:
if var.param_name in my_eval_statement:
my_eval_statement = my_eval_statement.replace('{' + var.param_name + '}', "{:.2f}".format(var.value))
else:
if var.param_name in my_eval_statement:
my_eval_statement = my_eval_statement.replace('{' + var.param_name + '}', '0.0')
return my_eval_statement
def import_string_path(path):
components = path.split('.')
@@ -102,30 +83,28 @@ def import_string_path(path):
return mod
def post_process(source, target):
pass
@frappe.whitelist()
def make_supplier_scorecard(source_name, target_doc=None):
#def update_item(obj, target, source_parent):
# target.qty = flt(obj.qty) - flt(obj.received_qty)
# target.stock_qty = (flt(obj.qty) - flt(obj.received_qty)) * flt(obj.conversion_factor)
# target.amount = (flt(obj.qty) - flt(obj.received_qty)) * flt(obj.rate)
# target.base_amount = (flt(obj.qty) - flt(obj.received_qty)) * \
# flt(obj.rate) * flt(source_parent.conversion_rate)
def update_criteria_fields(obj, target, source_parent):
target.max_score, target.formula = frappe.db.get_value('Supplier Scorecard Criteria',
obj.criteria_name, ['max_score', 'formula'])
def post_process(source, target):
variables = []
for cr in target.criteria:
for var in get_variables(cr.criteria_name):
if var not in variables:
variables.append(var)
target.extend('variables', variables)
doc = get_mapped_doc("Supplier Scorecard", source_name, {
"Supplier Scorecard": {
"doctype": "Supplier Scorecard Period"
},
"Supplier Scorecard Scoring Variable": {
"doctype": "Supplier Scorecard Scoring Variable",
"add_if_empty": True
},
"Supplier Scorecard Scoring Constraint": {
"doctype": "Supplier Scorecard Scoring Constraint",
"add_if_empty": True
"Supplier Scorecard Scoring Criteria": {
"doctype": "Supplier Scorecard Scoring Criteria",
"postprocess": update_criteria_fields,
}
}, target_doc, post_process)

View File

@@ -1,280 +1,252 @@
{
"allow_copy": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 1,
"creation": "2017-05-29 01:32:17.988454",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "",
"editable_grid": 1,
"engine": "InnoDB",
"allow_copy": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
"creation": "2017-05-29 01:32:17.988454",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "",
"editable_grid": 1,
"engine": "InnoDB",
"fields": [
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 3,
"fieldname": "criteria_name",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Criteria Name",
"length": 0,
"no_copy": 0,
"options": "Supplier Scorecard Criteria",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 5,
"fieldname": "criteria_name",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Criteria Name",
"length": 0,
"no_copy": 0,
"options": "Supplier Scorecard Criteria",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "section_break_2",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 2,
"fieldname": "score",
"fieldtype": "Percent",
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Score",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 2,
"fieldname": "weight",
"fieldtype": "Percent",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Criteria Weight",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_4",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_4",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 2,
"fieldname": "weight",
"fieldtype": "Percent",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Criteria Weight",
"length": 0,
"no_copy": 0,
"options": "",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "100",
"fieldname": "max_score",
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Max Score",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "100",
"fieldname": "max_score",
"fieldtype": "Float",
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Max Score",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "section_break_6",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "section_break_6",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "formula",
"fieldtype": "Small Text",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Criteria Formula",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "score",
"fieldtype": "Percent",
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Score",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "formula",
"fieldtype": "Small Text",
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 1,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Criteria Formula",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2017-07-12 07:33:41.532361",
"modified_by": "Administrator",
"module": "Buying",
"name": "Supplier Scorecard Scoring Criteria",
"name_case": "",
"owner": "Administrator",
"permissions": [],
"quick_entry": 1,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1,
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2019-01-23 13:49:13.350095",
"modified_by": "Administrator",
"module": "Buying",
"name": "Supplier Scorecard Scoring Criteria",
"name_case": "",
"owner": "Administrator",
"permissions": [],
"quick_entry": 1,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1,
"track_seen": 0
}

View File

@@ -3,7 +3,7 @@
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 1,
"beta": 0,
"creation": "2017-05-29 01:36:22.697234",
"custom": 0,
"docstatus": 0,
@@ -473,7 +473,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2017-07-12 07:33:20.615684",
"modified": "2019-01-22 10:47:41.146704",
"modified_by": "Administrator",
"module": "Buying",
"name": "Supplier Scorecard Scoring Standing",

View File

@@ -3,7 +3,7 @@
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 1,
"beta": 0,
"creation": "2017-05-29 01:30:06.105240",
"custom": 0,
"docstatus": 0,
@@ -35,7 +35,7 @@
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
@@ -65,7 +65,37 @@
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 2,
"fieldname": "value",
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Value",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
@@ -73,36 +103,6 @@
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "is_custom",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Custom?",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
@@ -111,7 +111,7 @@
"columns": 0,
"fieldname": "param_name",
"fieldtype": "Data",
"hidden": 0,
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
@@ -128,7 +128,7 @@
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
@@ -141,7 +141,7 @@
"columns": 0,
"fieldname": "path",
"fieldtype": "Data",
"hidden": 0,
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
@@ -158,36 +158,6 @@
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 2,
"fieldname": "value",
"fieldtype": "Float",
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Value",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
@@ -204,7 +174,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2017-07-12 07:33:36.671502",
"modified": "2019-01-23 09:55:19.749828",
"modified_by": "Administrator",
"module": "Buying",
"name": "Supplier Scorecard Scoring Variable",

View File

@@ -4,7 +4,7 @@
"allow_import": 0,
"allow_rename": 0,
"autoname": "field:standing_name",
"beta": 1,
"beta": 0,
"creation": "2017-05-29 01:36:47.893639",
"custom": 0,
"docstatus": 0,
@@ -385,7 +385,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2017-07-12 07:33:16.560273",
"modified": "2019-01-22 10:47:49.195421",
"modified_by": "Administrator",
"module": "Buying",
"name": "Supplier Scorecard Standing",

View File

@@ -4,7 +4,7 @@
"allow_import": 0,
"allow_rename": 0,
"autoname": "field:variable_label",
"beta": 1,
"beta": 0,
"creation": "2017-05-29 01:30:34.688389",
"custom": 0,
"docstatus": 0,
@@ -101,7 +101,7 @@
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
"unique": 1
},
{
"allow_bulk_edit": 0,
@@ -203,7 +203,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2017-07-12 07:33:31.395262",
"modified": "2019-01-23 09:39:59.866398",
"modified_by": "Administrator",
"module": "Buying",
"name": "Supplier Scorecard Variable",

View File

@@ -27,13 +27,6 @@ class SupplierScorecardVariable(Document):
if not hasattr(sys.modules[__name__], self.path):
frappe.throw(_("Could not find path for " + self.path), VariablePathNotFound)
@frappe.whitelist()
def get_scoring_variable(variable_label):
variable = frappe.get_doc("Supplier Scorecard Variable", variable_label)
return variable
def get_total_workdays(scorecard):
""" Gets the number of days in this period"""
delta = getdate(scorecard.end_date) - getdate(scorecard.start_date)

View File

@@ -1 +1 @@
- [ERPNext Manual in German](http://erpnext.org/docs/user/manual/de/) contributed by [CWT Connector & Wire Technology GmbH](http://www.cwt-assembly.com/)
- [ERPNext Manual in German](http://erpnext.com/docs/user/manual/de/) contributed by [CWT Connector & Wire Technology GmbH](http://www.cwt-assembly.com/)

View File

@@ -1,3 +1,3 @@
from __future__ import unicode_literals
source_link = "https://github.com/frappe/erpnext"
source_link = "https://github.com/erpnext/foundation"

View File

@@ -218,6 +218,9 @@ class AccountsController(TransactionBase):
if stock_qty != len(get_serial_nos(item.get('serial_no'))):
item.set(fieldname, value)
if self.doctype in ["Purchase Invoice", "Sales Invoice"] and item.meta.get_field('is_fixed_asset'):
item.set('is_fixed_asset', ret.get('is_fixed_asset', 0))
if ret.get("pricing_rule"):
# if user changed the discount percentage then set user's discount percentage ?
item.set("discount_percentage", ret.get("discount_percentage"))

View File

@@ -10,6 +10,7 @@ from erpnext.accounts.party import get_party_details
from erpnext.stock.get_item_details import get_conversion_factor
from erpnext.buying.utils import validate_for_items, update_last_purchase_rate
from erpnext.stock.stock_ledger import get_valuation_rate
from frappe.contacts.doctype.address.address import get_address_display
from erpnext.controllers.stock_controller import StockController
@@ -39,6 +40,7 @@ class BuyingController(StockController):
self.set_qty_as_per_stock_uom()
self.validate_stock_or_nonstock_items()
self.validate_warehouse()
self.set_supplier_address()
if self.doctype=="Purchase Invoice":
self.validate_purchase_receipt_if_update_stock()
@@ -96,6 +98,16 @@ class BuyingController(StockController):
if not d.cost_center and lc_voucher_data and lc_voucher_data[0][1]:
d.db_set('cost_center', lc_voucher_data[0][1])
def set_supplier_address(self):
address_dict = {
'supplier_address': 'address_display',
'shipping_address': 'shipping_address_display'
}
for address_field, address_display_field in address_dict.items():
if self.get(address_field):
self.set(address_display_field, get_address_display(self.get(address_field)))
def set_total_in_words(self):
from frappe.utils import money_in_words
if self.meta.get_field("base_in_words"):
@@ -450,7 +462,7 @@ class BuyingController(StockController):
update_last_purchase_rate(self, is_submit = 0)
def validate_schedule_date(self):
if not self.schedule_date:
if not self.schedule_date and self.get("items"):
self.schedule_date = min([d.schedule_date for d in self.get("items")])
if self.schedule_date:

View File

@@ -139,7 +139,7 @@ def validate_quantity(doc, args, ref, valid_items, already_returned_items):
.format(args.item_code), StockOverReturnError)
elif abs(current_stock_qty) > max_returnable_qty:
frappe.throw(_("Row # {0}: Cannot return more than {1} for Item {2}")
.format(args.idx, reference_qty, args.item_code), StockOverReturnError)
.format(args.idx, max_returnable_qty, args.item_code), StockOverReturnError)
def get_ref_item_dict(valid_items, ref_item_row):
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos

View File

@@ -8,6 +8,7 @@ from frappe import _, throw
from erpnext.stock.get_item_details import get_bin_details
from erpnext.stock.utils import get_incoming_rate
from erpnext.stock.get_item_details import get_conversion_factor
from frappe.contacts.doctype.address.address import get_address_display
from erpnext.controllers.stock_controller import StockController
@@ -40,6 +41,7 @@ class SellingController(StockController):
self.validate_selling_price()
self.set_qty_as_per_stock_uom()
self.set_po_nos()
self.set_customer_address()
check_active_sales_items(self)
def set_missing_values(self, for_validate=False):
@@ -344,6 +346,17 @@ class SellingController(StockController):
po_nos = frappe.get_all('Sales Order', 'po_no', filters = {'name': ('in', sales_orders)})
self.po_no = ', '.join(list(set([d.po_no for d in po_nos if d.po_no])))
def set_customer_address(self):
address_dict = {
'customer_address': 'address_display',
'shipping_address_name': 'shipping_address',
'company_address': 'company_address_display'
}
for address_field, address_display_field in address_dict.items():
if self.get(address_field):
self.set(address_display_field, get_address_display(self.get(address_field)))
def validate_items(self):
# validate items to see if they have is_sales_item enabled
from erpnext.controllers.buying_controller import validate_item_type

View File

@@ -66,8 +66,11 @@ class calculate_taxes_and_totals(object):
if item.doctype in ['Quotation Item', 'Sales Order Item', 'Delivery Note Item', 'Sales Invoice Item']:
item.rate_with_margin, item.base_rate_with_margin = self.calculate_margin(item)
item.rate = flt(item.rate_with_margin * (1.0 - (item.discount_percentage / 100.0)), item.precision("rate"))\
if item.rate_with_margin > 0 else item.rate
if flt(item.rate_with_margin) > 0:
item.rate = flt(item.rate_with_margin * (1.0 - (item.discount_percentage / 100.0)), item.precision("rate"))
item.discount_amount = item.rate_with_margin - item.rate
elif flt(item.price_list_rate) > 0:
item.discount_amount = item.price_list_rate - item.rate
item.net_rate = item.rate
item.amount = flt(item.rate * item.qty, item.precision("amount"))

View File

@@ -1,9 +0,0 @@
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
from frappe.model.document import Document
class Lead(Document):
pass

View File

@@ -50,6 +50,12 @@ frappe.ui.form.on("Assessment Result", {
frappe.ui.form.on("Assessment Result Detail", {
score: function(frm, cdt, cdn) {
var d = locals[cdt][cdn];
if(!d.maximum_score || !frm.doc.grading_scale) {
d.score = "";
frappe.throw(__("Please fill in all the details to generate Assessment Result."));
}
if (d.score > d.maximum_score) {
frappe.throw(__("Score cannot be greater than Maximum Score"));
}

View File

@@ -73,6 +73,7 @@ def get_attendance_list(from_date, to_date, student_group, students_list):
return att_map
def get_students_with_leave_application(from_date, to_date, students_list):
if not students_list: return
leave_applications = frappe.db.sql("""
select student, from_date, to_date
from `tabStudent Leave Application`

View File

@@ -111,6 +111,7 @@ frappe.ui.form.on('Patient Appointment', {
frm.set_value('appointment_time', selected_slot);
frm.set_value('duration', data.time_per_appointment);
d.hide();
frm.enable_save();
frm.save();
}
});

View File

@@ -14,10 +14,6 @@
margin-bottom: -4px;
}
.medical_record-row > * {
z-index: -999;
}
.date-indicator {
background:none;
font-size:12px;

View File

@@ -13,8 +13,6 @@ source_link = "https://github.com/frappe/erpnext"
develop_version = '10.x.x-develop'
error_report_email = "support@erpnext.com"
app_include_js = "assets/js/erpnext.min.js"
app_include_css = "assets/css/erpnext.css"
web_include_js = "assets/js/erpnext-web.min.js"

View File

@@ -45,14 +45,21 @@ class Employee(NestedSet):
self.validate_prefered_email()
if self.user_id:
self.validate_for_enabled_user_id()
self.validate_duplicate_user_id()
self.validate_user_details()
else:
existing_user_id = frappe.db.get_value("Employee", self.name, "user_id")
if existing_user_id:
frappe.permissions.remove_user_permission(
"Employee", self.name, existing_user_id)
def validate_user_details(self):
data = frappe.db.get_value('User',
self.user_id, ['enabled', 'user_image'], as_dict=1)
if data.get("user_image"):
self.image = data.get("user_image")
self.validate_for_enabled_user_id(data.get("enabled", 0))
self.validate_duplicate_user_id()
def update_nsm_model(self):
frappe.utils.nestedset.update_nsm(self)
@@ -133,10 +140,10 @@ class Employee(NestedSet):
if self.status == 'Left' and not self.relieving_date:
throw(_("Please enter relieving date."))
def validate_for_enabled_user_id(self):
def validate_for_enabled_user_id(self, enabled):
if not self.status == 'Active':
return
enabled = frappe.db.get_value("User", self.user_id, "enabled")
if enabled is None:
frappe.throw(_("User {0} does not exist").format(self.user_id))
if enabled == 0:
@@ -329,4 +336,4 @@ def get_children(doctype, parent=None, company=None, is_root=False, is_tree=Fals
.format(company=company, condition=condition), as_dict=1)
# return employee
return employee
return employee

View File

@@ -58,7 +58,7 @@ class EmployeeAdvance(Document):
select sum(ifnull(allocated_amount, 0))
from `tabExpense Claim Advance`
where employee_advance = %s and docstatus=1 and allocated_amount > 0
""", self.name)[0][0]
""", self.name)[0][0] or 0
frappe.db.set_value("Employee Advance", self.name, "claimed_amount", claimed_amount)

View File

@@ -224,10 +224,11 @@ class ExpenseClaim(AccountsController):
self.total_advance_amount += flt(d.allocated_amount)
if self.total_advance_amount:
if flt(self.total_advance_amount) > flt(self.total_claimed_amount):
precision = self.precision("total_advance_amount")
if flt(self.total_advance_amount, precision) > flt(self.total_claimed_amount, precision):
frappe.throw(_("Total advance amount cannot be greater than total claimed amount"))
if self.total_sanctioned_amount \
and flt(self.total_advance_amount) > flt(self.total_sanctioned_amount):
and flt(self.total_advance_amount, precision) > flt(self.total_sanctioned_amount, precision):
frappe.throw(_("Total advance amount cannot be greater than total sanctioned amount"))
def validate_sanctioned_amount(self):

View File

@@ -3,7 +3,7 @@
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"autoname": "LAP/.#####",
"autoname": "naming_series:",
"beta": 0,
"creation": "2013-02-20 11:18:11",
"custom": 0,
@@ -796,7 +796,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 3,
"modified": "2017-06-13 14:28:52.426044",
"modified": "2019-01-08 17:35:10.795225",
"modified_by": "Administrator",
"module": "HR",
"name": "Leave Application",

View File

@@ -381,6 +381,19 @@ def get_leave_balance_on(employee, leave_type, date, allocation_records=None,
return flt(allocation.total_leaves_allocated) - flt(leaves_taken)
def get_total_allocated_leaves(employee, leave_type, date):
filters= {
'from_date': ['<=', date],
'to_date': ['>=', date],
'docstatus': 1,
'leave_type': leave_type,
'employee': employee
}
leave_allocation_records = frappe.db.get_all('Leave Allocation', filters=filters, fields=['total_leaves_allocated'])
return flt(leave_allocation_records[0]['total_leaves_allocated']) if leave_allocation_records else flt(0)
def get_approved_leaves_for_period(employee, leave_type, from_date, to_date):
leave_applications = frappe.db.sql("""
select employee, leave_type, from_date, to_date, total_leave_days

View File

@@ -525,3 +525,16 @@ def payroll_entry_has_bank_entries(name):
response['submitted'] = 1 if bank_entries else 0
return response
def get_payroll_entries_for_jv(doctype, txt, searchfield, start, page_len, filters):
return frappe.db.sql("""
select name from `tabPayroll Entry`
where `{key}` LIKE %(txt)s
and name not in
(select reference_name from `tabJournal Entry Account`
where reference_type="Payroll Entry")
order by name limit %(start)s, %(page_len)s"""
.format(key=searchfield), {
'txt': "%%%s%%" % frappe.db.escape(txt),
'start': start, 'page_len': page_len
})

View File

@@ -113,16 +113,14 @@ frappe.ui.form.on('Salary Slip Timesheet', {
// Get leave details
//---------------------------------------------------------------------
var get_emp_and_leave_details = function(doc, dt, dn) {
if(!doc.start_date){
return frappe.call({
method: 'get_emp_and_leave_details',
doc: locals[dt][dn],
callback: function(r, rt) {
cur_frm.refresh();
calculate_all(doc, dt, dn);
}
});
}
return frappe.call({
method: 'get_emp_and_leave_details',
doc: locals[dt][dn],
callback: function(r, rt) {
cur_frm.refresh();
calculate_all(doc, dt, dn);
}
});
}
cur_frm.cscript.employee = function(doc,dt,dn){

View File

@@ -181,7 +181,8 @@ class SalarySlip(TransactionBase):
if len(st_name) > 1:
frappe.msgprint(_("Multiple active Salary Structures found for employee {0} for the given dates")
.format(self.employee), title=_('Warning'))
return st_name and st_name[0][0] or ''
self.salary_structure = st_name and st_name[0][0] or ''
return self.salary_structure
else:
self.salary_structure = None
frappe.msgprint(_("No active or default Salary Structure found for employee {0} for the given dates")
@@ -329,7 +330,7 @@ class SalarySlip(TransactionBase):
if frappe.db.get_value('Timesheet', data.time_sheet, 'status') == 'Payrolled':
frappe.throw(_("Salary Slip of employee {0} already created for time sheet {1}").format(self.employee, data.time_sheet))
def sum_components(self, component_type, total_field):
def sum_components(self, component_type, total_field, precision):
joining_date, relieving_date = frappe.db.get_value("Employee", self.employee,
["date_of_joining", "relieving_date"])
@@ -349,7 +350,7 @@ class SalarySlip(TransactionBase):
)):
d.amount = rounded(
(flt(d.default_amount) * flt(self.payment_days)
(flt(d.default_amount, precision) * flt(self.payment_days)
/ cint(self.total_working_days)), self.precision("amount", component_type)
)
@@ -359,19 +360,19 @@ class SalarySlip(TransactionBase):
elif not d.amount:
d.amount = d.default_amount
if not d.do_not_include_in_total:
self.set(total_field, self.get(total_field) + flt(d.amount))
self.set(total_field, self.get(total_field) + flt(d.amount, precision))
def calculate_net_pay(self):
if self.salary_structure:
self.calculate_component_amounts()
disable_rounded_total = cint(frappe.db.get_value("Global Defaults", None, "disable_rounded_total"))
precision = frappe.defaults.get_global_default("currency_precision")
self.total_deduction = 0
self.gross_pay = 0
self.sum_components('earnings', 'gross_pay')
self.sum_components('deductions', 'total_deduction')
self.sum_components('earnings', 'gross_pay', precision)
self.sum_components('deductions', 'total_deduction', precision)
self.set_loan_repayment()
@@ -472,4 +473,4 @@ def unlink_ref_doc_from_salary_slip(ref_no):
if linked_ss:
for ss in linked_ss:
ss_doc = frappe.get_doc("Salary Slip", ss)
frappe.db.set_value("Salary Slip", ss_doc.name, "journal_entry", "")
frappe.db.set_value("Salary Slip", ss_doc.name, "journal_entry", "")

View File

@@ -5,7 +5,7 @@
from __future__ import unicode_literals
import frappe
from frappe.utils import cstr, add_days, date_diff
from frappe.utils import cstr, add_days, date_diff, getdate
from frappe import _
from frappe.utils.csvutils import UnicodeWriter
from frappe.model.document import Document
@@ -48,8 +48,9 @@ def add_data(w, args):
for employee in employees:
existing_attendance = {}
if existing_attendance_records \
and tuple([date, employee.name]) in existing_attendance_records:
existing_attendance = existing_attendance_records[tuple([date, employee.name])]
and tuple([getdate(date), employee.name]) in existing_attendance_records:
existing_attendance = existing_attendance_records[tuple([getdate(date), employee.name])]
row = [
existing_attendance and existing_attendance.name or "",
employee.name, employee.employee_name, date,
@@ -114,6 +115,7 @@ def upload():
if not row: continue
row_idx = i + 5
d = frappe._dict(zip(columns, row))
d["doctype"] = "Attendance"
if d.name:
d["docstatus"] = frappe.db.get_value("Attendance", d.name, "docstatus")
@@ -121,6 +123,8 @@ def upload():
try:
check_record(d)
ret.append(import_doc(d, "Attendance", 1, row_idx, submit=True))
except AttributeError:
pass
except Exception as e:
error = True
ret.append('Error for row (#%d) %s : %s' % (row_idx,

View File

@@ -5,21 +5,21 @@ from __future__ import unicode_literals
import frappe
from frappe import _
from erpnext.hr.doctype.leave_application.leave_application \
import get_leave_allocation_records, get_leave_balance_on, get_approved_leaves_for_period
import get_leave_allocation_records, get_leave_balance_on, get_approved_leaves_for_period, get_total_allocated_leaves
def execute(filters=None):
leave_types = frappe.db.sql_list("select name from `tabLeave Type` order by name asc")
columns = get_columns(leave_types)
data = get_data(filters, leave_types)
return columns, data
def get_columns(leave_types):
columns = [
_("Employee") + ":Link/Employee:150",
_("Employee Name") + "::200",
_("Employee") + ":Link/Employee:150",
_("Employee Name") + "::200",
_("Department") +"::150"
]
@@ -27,18 +27,18 @@ def get_columns(leave_types):
columns.append(_(leave_type) + " " + _("Opening") + ":Float:160")
columns.append(_(leave_type) + " " + _("Taken") + ":Float:160")
columns.append(_(leave_type) + " " + _("Balance") + ":Float:160")
return columns
def get_data(filters, leave_types):
user = frappe.session.user
allocation_records_based_on_to_date = get_leave_allocation_records(filters.to_date)
allocation_records_based_on_from_date = get_leave_allocation_records(filters.from_date)
active_employees = frappe.get_all("Employee",
filters = { "status": "Active", "company": filters.company},
active_employees = frappe.get_all("Employee",
filters = { "status": "Active", "company": filters.company},
fields = ["name", "employee_name", "department", "user_id"])
data = []
for employee in active_employees:
leave_approvers = [l.leave_approver for l in frappe.db.sql("""select leave_approver from `tabEmployee Leave Approver` where parent = %s""",
@@ -52,15 +52,14 @@ def get_data(filters, leave_types):
filters.from_date, filters.to_date)
# opening balance
opening = get_leave_balance_on(employee.name, leave_type, filters.from_date,
allocation_records_based_on_from_date.get(employee.name, frappe._dict()))
opening = get_total_allocated_leaves(employee.name, leave_type, filters.to_date)
# closing balance
closing = get_leave_balance_on(employee.name, leave_type, filters.to_date,
allocation_records_based_on_to_date.get(employee.name, frappe._dict()))
row += [opening, leaves_taken, closing]
data.append(row)
return data

View File

@@ -354,7 +354,8 @@ class BOM(WebsiteGenerator):
bom_list = self.traverse_tree(bom_list)
for bom in bom_list:
bom_obj = frappe.get_doc("BOM", bom)
bom_obj.on_update()
bom_obj.check_recursion()
bom_obj.update_exploded_items()
return bom_list

View File

@@ -16,16 +16,23 @@ class BOMUpdateTool(Document):
self.update_new_bom()
bom_list = self.get_parent_boms(self.new_bom)
updated_bom = []
for bom in bom_list:
bom_obj = frappe.get_doc("BOM", bom)
bom_obj.get_doc_before_save()
updated_bom = bom_obj.update_cost_and_exploded_items(updated_bom)
bom_obj.calculate_cost()
bom_obj.update_parent_cost()
bom_obj.db_update()
if (getattr(bom_obj.meta, 'track_changes', False)
and bom_obj._doc_before_save and not bom_obj.flags.ignore_version):
bom_obj.save_version()
try:
bom_obj = frappe.get_doc("BOM", bom)
bom_obj.get_doc_before_save()
updated_bom = bom_obj.update_cost_and_exploded_items(updated_bom)
bom_obj.calculate_cost()
bom_obj.update_parent_cost()
bom_obj.db_update()
if (getattr(bom_obj.meta, 'track_changes', False)
and bom_obj._doc_before_save and not bom_obj.flags.ignore_version):
bom_obj.save_version()
frappe.db.commit()
except Exception:
frappe.db.rollback()
frappe.log_error(frappe.get_traceback())
def validate_bom(self):
if cstr(self.current_bom) == cstr(self.new_bom):
@@ -55,7 +62,7 @@ class BOMUpdateTool(Document):
bom_list.append(d[0])
self.get_parent_boms(d[0], bom_list)
return bom_list
return list(set(bom_list))
@frappe.whitelist()
def enqueue_replace_bom(args):

View File

@@ -1,8 +0,0 @@
import frappe
def set_required_items(production_order):
pass
def reserve_for_production(production_order):
'''Reserve pending raw materials for production'''
pass

View File

@@ -1,5 +1,6 @@
execute:import unidecode # new requirement
erpnext.patches.v8_0.move_perpetual_inventory_setting
erpnext.patches.v8_9.set_print_zero_amount_taxes
erpnext.patches.v10_0.rename_schools_to_education
erpnext.patches.v4_0.validate_v3_patch
erpnext.patches.v4_0.fix_employee_user_id
@@ -410,7 +411,7 @@ erpnext.patches.v8_0.save_system_settings
erpnext.patches.v8_1.delete_deprecated_reports
erpnext.patches.v9_0.remove_subscription_module
erpnext.patches.v8_7.make_subscription_from_recurring_data
erpnext.patches.v8_1.setup_gst_india #2017-06-27
erpnext.patches.v8_1.setup_gst_india #2019-04-04
execute:frappe.reload_doc('regional', 'doctype', 'gst_hsn_code')
erpnext.patches.v8_1.removed_roles_from_gst_report_non_indian_account
erpnext.patches.v8_1.gst_fixes #2017-07-06
@@ -442,7 +443,6 @@ erpnext.patches.v8_9.add_setup_progress_actions #08-09-2017 #26-09-2017 #22-11-2
erpnext.patches.v8_9.rename_company_sales_target_field
erpnext.patches.v8_8.set_bom_rate_as_per_uom
erpnext.patches.v8_8.add_new_fields_in_accounts_settings
erpnext.patches.v8_9.set_print_zero_amount_taxes
erpnext.patches.v8_9.set_default_customer_group
erpnext.patches.v8_9.remove_employee_from_salary_structure_parent
erpnext.patches.v8_9.delete_gst_doctypes_for_outside_india_accounts
@@ -498,6 +498,7 @@ erpnext.patches.v10_0.update_hub_connector_domain
erpnext.patches.v10_0.set_student_party_type
erpnext.patches.v10_0.update_project_in_sle
erpnext.patches.v10_0.fix_reserved_qty_for_sub_contract
erpnext.patches.v10_0.repost_requested_qty_for_non_stock_uom_items
erpnext.patches.v10_0.taxes_issue_with_pos
erpnext.patches.v10_0.set_qty_in_transactions_based_on_serial_no_input
erpnext.patches.v10_0.show_leaves_of_all_department_members_in_calendar
@@ -505,4 +506,8 @@ erpnext.patches.v10_0.update_status_in_purchase_receipt
erpnext.patches.v10_0.update_address_template_for_india
erpnext.patches.v10_0.set_discount_amount
erpnext.patches.v10_0.recalculate_gross_margin_for_project
erpnext.patches.v10_0.delete_hub_documents
erpnext.patches.v10_0.delete_hub_documents
erpnext.patches.v10_0.update_user_image_in_employee
erpnext.patches.v10_0.repost_gle_for_purchase_receipts_with_rejected_items
erpnext.patches.v10_0.allow_operators_in_supplier_scorecard
erpnext.patches.v10_0.gst_hsn_fixes

View File

@@ -0,0 +1,23 @@
# Copyright (c) 2019, Frappe and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe
def execute():
frappe.reload_doc('buying', 'doctype', 'supplier_scorecard_criteria')
frappe.reload_doc('buying', 'doctype', 'supplier_scorecard_scoring_criteria')
frappe.reload_doc('buying', 'doctype', 'supplier_scorecard')
for criteria in frappe.get_all('Supplier Scorecard Criteria', fields=['name', 'formula'], limit_page_length=None):
frappe.db.set_value('Supplier Scorecard Criteria', criteria.name,
'formula', criteria.formula.replace('&lt;','<').replace('&gt;','>'))
for criteria in frappe.get_all('Supplier Scorecard Scoring Criteria', fields=['name', 'formula'], limit_page_length=None):
if criteria.formula: # not mandatory
frappe.db.set_value('Supplier Scorecard Scoring Criteria', criteria.name,
'formula', criteria.formula.replace('&lt;','<').replace('&gt;','>'))
for sc in frappe.get_all('Supplier Scorecard', fields=['name', 'weighting_function'], limit_page_length=None):
frappe.db.set_value('Supplier Scorecard', sc.name, 'weighting_function',
sc.weighting_function.replace('&lt;','<').replace('&gt;','>'))

View File

@@ -0,0 +1,18 @@
import frappe
from erpnext.regional.india.setup import setup
from frappe.custom.doctype.custom_field.custom_field import create_custom_fields
def execute():
company = frappe.get_all('Company', filters = {'country': 'India'})
if not company:
return
hsn_sac_field = dict(fieldname='gst_hsn_code', label='HSN/SAC',
fieldtype='Data', options='item_code.gst_hsn_code', insert_after='description',
allow_on_submit=1, print_hide=1)
custom_fields = {
'Material Request Item': [hsn_sac_field]
}
create_custom_fields(custom_fields)

View File

@@ -0,0 +1,32 @@
# Copyright (c) 2017, Frappe and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe, erpnext
def execute():
for company in frappe.get_all("Company"):
if not erpnext.is_perpetual_inventory_enabled(company.name):
continue
acc_frozen_upto = frappe.db.get_value("Accounts Settings", None, "acc_frozen_upto") or "1900-01-01"
pr_with_rejected_warehouse = frappe.db.sql("""
select pr.name
from `tabPurchase Receipt` pr, `tabPurchase Receipt Item` pr_item
where pr.name = pr_item.parent
and pr.posting_date > %s
and pr.docstatus=1
and pr.company = %s
and pr_item.rejected_qty > 0
""", (acc_frozen_upto, company.name), as_dict=1)
for d in pr_with_rejected_warehouse:
doc = frappe.get_doc("Purchase Receipt", d.name)
doc.docstatus = 2
doc.make_gl_entries_on_cancel(repost_future_gle=False)
# update gl entries for submit state of PR
doc.docstatus = 1
doc.make_gl_entries(repost_future_gle=False)

View File

@@ -0,0 +1,21 @@
# Copyright (c) 2019, Web Notes Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe
def execute():
from erpnext.stock.stock_balance import update_bin_qty, get_indented_qty
count=0
for item_code, warehouse in frappe.db.sql("""select distinct item_code, warehouse
from `tabMaterial Request Item` where docstatus = 1 and stock_uom<>uom"""):
try:
count += 1
update_bin_qty(item_code, warehouse, {
"indented_qty": get_indented_qty(item_code, warehouse),
})
if count % 200 == 0:
frappe.db.commit()
except:
frappe.db.rollback()

View File

@@ -0,0 +1,19 @@
# Copyright (c) 2017, Frappe and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe
def execute():
frappe.reload_doc('hr', 'doctype', 'employee')
frappe.db.sql("""
UPDATE
`tabEmployee`, `tabUser`
SET
`tabEmployee`.image = `tabUser`.user_image
WHERE
`tabEmployee`.user_id = `tabUser`.name and
`tabEmployee`.user_id is not null and
`tabEmployee`.user_id != '' and `tabEmployee`.image is null
""")

View File

@@ -254,13 +254,13 @@ class Project(Document):
self.total_purchase_cost = total_purchase_cost and total_purchase_cost[0][0] or 0
def update_sales_amount(self):
total_sales_amount = frappe.db.sql("""select sum(base_grand_total)
total_sales_amount = frappe.db.sql("""select sum(base_net_total)
from `tabSales Order` where project = %s and docstatus=1""", self.name)
self.total_sales_amount = total_sales_amount and total_sales_amount[0][0] or 0
def update_billed_amount(self):
total_billed_amount = frappe.db.sql("""select sum(base_grand_total)
total_billed_amount = frappe.db.sql("""select sum(base_net_total)
from `tabSales Invoice` where project = %s and docstatus=1""", self.name)
self.total_billed_amount = total_billed_amount and total_billed_amount[0][0] or 0

View File

@@ -143,6 +143,13 @@ class Task(NestedSet):
self.update_nsm_model()
def update_status(self):
if self.status not in ('Cancelled', 'Closed') and self.exp_end_date:
from datetime import datetime
if self.exp_end_date < datetime.now().date():
self.db_set('status', 'Overdue')
self.update_project()
@frappe.whitelist()
def check_if_child_exists(name):
return frappe.db.sql("""select name from `tabTask`
@@ -168,10 +175,9 @@ def set_multiple_status(names, status):
task.save()
def set_tasks_as_overdue():
frappe.db.sql("""update tabTask set `status`='Overdue'
where exp_end_date is not null
and exp_end_date < CURDATE()
and `status` not in ('Closed', 'Cancelled')""")
tasks = frappe.get_all("Task", filters={'status':['not in',['Cancelled', 'Closed']]})
for task in tasks:
frappe.get_doc("Task", task.name).update_status()
@frappe.whitelist()
def get_children(doctype, parent, task=None, project=None, is_root=False):

View File

@@ -346,6 +346,11 @@ body[data-route="pos"] .btn-more {
body[data-route="pos"] .collapse-btn {
cursor: pointer;
}
@media (max-width: 767px) {
body[data-route="pos"] .page-actions {
max-width: 110px;
}
}
.price-info {
position: absolute;
left: 0;

View File

@@ -14,7 +14,7 @@ $(document).bind('toolbar_setup', function() {
$('.navbar-home').html('<img class="erpnext-icon" src="'+
frappe.urllib.get_base_url()+'/assets/erpnext/images/erp-icon.svg" />');
$('[data-link="docs"]').attr("href", "https://frappe.github.io/erpnext/")
$('[data-link="docs"]').attr("href", "https://erpnext.com/docs")
$('[data-link="issues"]').attr("href", "https://github.com/frappe/erpnext/issues")
@@ -23,7 +23,8 @@ $(document).bind('toolbar_setup', function() {
// additional help links for erpnext
var $help_menu = $('.dropdown-help ul .documentation-links');
$('<li><a data-link-type="forum" href="https://erpnext.com/docs/user/manual" \
target="_blank">'+__('Documentation')+'</a></li>').insertBefore($help_menu);
$('<li><a data-link-type="forum" href="https://discuss.erpnext.com" \
target="_blank">'+__('User Forum')+'</a></li>').insertBefore($help_menu);
$('<li><a href="https://gitter.im/frappe/erpnext" \

View File

@@ -227,6 +227,69 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
tc_name: function() {
this.get_terms();
},
link_to_mrs: function() {
var my_items = [];
for (var i in cur_frm.doc.items) {
if(!cur_frm.doc.items[i].material_request){
my_items.push(cur_frm.doc.items[i].item_code);
}
}
frappe.call({
method: "erpnext.buying.utils.get_linked_material_requests",
args:{
items: my_items
},
callback: function(r) {
if(!r.message) {
frappe.throw(__("No pending Material Requests found to link for the given items."))
}
else {
var i = 0;
var item_length = cur_frm.doc.items.length;
while (i < item_length) {
var qty = cur_frm.doc.items[i].qty;
(r.message[0] || []).forEach(function(d) {
if (d.qty > 0 && qty > 0 && cur_frm.doc.items[i].item_code == d.item_code && !cur_frm.doc.items[i].material_request_item)
{
cur_frm.doc.items[i].material_request = d.mr_name;
cur_frm.doc.items[i].material_request_item = d.mr_item;
var my_qty = Math.min(qty, d.qty);
qty = qty - my_qty;
d.qty = d.qty - my_qty;
cur_frm.doc.items[i].stock_qty = my_qty*cur_frm.doc.items[i].conversion_factor;
cur_frm.doc.items[i].qty = my_qty;
frappe.msgprint("Assigning " + d.mr_name + " to " + d.item_code + " (row " + cur_frm.doc.items[i].idx + ")");
if (qty > 0)
{
frappe.msgprint("Splitting " + qty + " units of " + d.item_code);
var newrow = frappe.model.add_child(cur_frm.doc, cur_frm.doc.items[i].doctype, "items");
item_length++;
for (var key in cur_frm.doc.items[i])
{
newrow[key] = cur_frm.doc.items[i][key];
}
newrow.idx = item_length;
newrow["stock_qty"] = newrow.conversion_factor*qty;
newrow["qty"] = qty;
newrow["material_request"] = "";
newrow["material_request_item"] = "";
}
}
});
i++;
}
refresh_field("items");
//cur_frm.save();
}
}
});
}
});

View File

@@ -10,9 +10,8 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
+ flt(item.price_list_rate) * ( flt(item.margin_rate_or_amount) / 100);
} else {
item.rate_with_margin = flt(item.price_list_rate) + flt(item.margin_rate_or_amount);
item.base_rate_with_margin = flt(item.rate_with_margin) * flt(this.frm.doc.conversion_rate);
}
item.base_rate_with_margin = flt(item.rate_with_margin) * flt(this.frm.doc.conversion_rate);
item.rate = flt(item.rate_with_margin , precision("rate", item));
if(item.discount_percentage){

View File

@@ -33,7 +33,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
item.margin_rate_or_amount = 0;
item.rate_with_margin = 0;
}
item.base_rate_with_margin = item.rate_with_margin * flt(frm.doc.conversion_rate);
cur_frm.cscript.set_gross_profit(item);
cur_frm.cscript.calculate_taxes_and_totals();

View File

@@ -1,528 +1,526 @@
frappe.provide('frappe.help.help_links');
const docsUrl = 'https://erpnext.com/docs/';
frappe.help.help_links['Form/Rename Tool'] = [
{ label: 'Bulk Rename', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/data/bulk-rename' },
{ label: 'Bulk Rename', url: docsUrl + 'user/manual/en/setting-up/data/bulk-rename' },
]
//Setup
frappe.help.help_links['List/User'] = [
{ label: 'New User', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/users-and-permissions/adding-users' },
{ label: 'Rename User', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/articles/rename-user' },
{ label: 'New User', url: docsUrl + 'user/manual/en/setting-up/users-and-permissions/adding-users' },
{ label: 'Rename User', url: docsUrl + 'user/manual/en/setting-up/articles/rename-user' },
]
frappe.help.help_links['permission-manager'] = [
{ label: 'Role Permissions Manager', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/users-and-permissions/role-based-permissions' },
{ label: 'Managing Perm Level in Permissions Manager', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/articles/managing-perm-level' },
{ label: 'User Permissions', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/users-and-permissions/user-permissions' },
{ label: 'Sharing', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/users-and-permissions/sharing' },
{ label: 'Password', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/articles/change-password' },
{ label: 'Role Permissions Manager', url: docsUrl + 'user/manual/en/setting-up/users-and-permissions/role-based-permissions' },
{ label: 'Managing Perm Level in Permissions Manager', url: docsUrl + 'user/manual/en/setting-up/articles/managing-perm-level' },
{ label: 'User Permissions', url: docsUrl + 'user/manual/en/setting-up/users-and-permissions/user-permissions' },
{ label: 'Sharing', url: docsUrl + 'user/manual/en/setting-up/users-and-permissions/sharing' },
{ label: 'Password', url: docsUrl + 'user/manual/en/setting-up/articles/change-password' },
]
frappe.help.help_links['Form/System Settings'] = [
{ label: 'Naming Series', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/settings/system-settings' },
{ label: 'Naming Series', url: docsUrl + 'user/manual/en/setting-up/settings/system-settings' },
]
frappe.help.help_links['data-import-tool'] = [
{ label: 'Importing and Exporting Data', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/data/data-import-tool' },
{ label: 'Overwriting Data from Data Import Tool', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/articles/overwriting-data-from-data-import-tool' },
{ label: 'Importing and Exporting Data', url: docsUrl + 'user/manual/en/setting-up/data/data-import-tool' },
{ label: 'Overwriting Data from Data Import Tool', url: docsUrl + 'user/manual/en/setting-up/articles/overwriting-data-from-data-import-tool' },
]
frappe.help.help_links['module_setup'] = [
{ label: 'Role Permissions Manager', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/users-and-permissions/role-based-permissions' },
{ label: 'Role Permissions Manager', url: docsUrl + 'user/manual/en/setting-up/users-and-permissions/role-based-permissions' },
]
frappe.help.help_links['Form/Naming Series'] = [
{ label: 'Naming Series', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/settings/naming-series' },
{ label: 'Setting the Current Value for Naming Series', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/articles/naming-series-current-value' },
{ label: 'Naming Series', url: docsUrl + 'user/manual/en/setting-up/settings/naming-series' },
{ label: 'Setting the Current Value for Naming Series', url: docsUrl + 'user/manual/en/setting-up/articles/naming-series-current-value' },
]
frappe.help.help_links['Form/Global Defaults'] = [
{ label: 'Global Settings', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/settings/global-defaults' },
{ label: 'Global Settings', url: docsUrl + 'user/manual/en/setting-up/settings/global-defaults' },
]
frappe.help.help_links['Form/Email Digest'] = [
{ label: 'Email Digest', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/email/email-digest' },
{ label: 'Email Digest', url: docsUrl + 'user/manual/en/setting-up/email/email-digest' },
]
frappe.help.help_links['List/Print Heading'] = [
{ label: 'Print Heading', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/print/print-headings' },
{ label: 'Print Heading', url: docsUrl + 'user/manual/en/setting-up/print/print-headings' },
]
frappe.help.help_links['List/Letter Head'] = [
{ label: 'Letter Head', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/print/letter-head' },
{ label: 'Letter Head', url: docsUrl + 'user/manual/en/setting-up/print/letter-head' },
]
frappe.help.help_links['List/Address Template'] = [
{ label: 'Address Template', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/print/address-template' },
{ label: 'Address Template', url: docsUrl + 'user/manual/en/setting-up/print/address-template' },
]
frappe.help.help_links['List/Terms and Conditions'] = [
{ label: 'Terms and Conditions', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/print/terms-and-conditions' },
{ label: 'Terms and Conditions', url: docsUrl + 'user/manual/en/setting-up/print/terms-and-conditions' },
]
frappe.help.help_links['List/Cheque Print Template'] = [
{ label: 'Cheque Print Template', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/print/cheque-print-template' },
{ label: 'Cheque Print Template', url: docsUrl + 'user/manual/en/setting-up/print/cheque-print-template' },
]
frappe.help.help_links['List/Email Account'] = [
{ label: 'Email Account', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/email/email-account' },
{ label: 'Email Account', url: docsUrl + 'user/manual/en/setting-up/email/email-account' },
]
frappe.help.help_links['List/Email Alert'] = [
{ label: 'Email Alert', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/email/email-alerts' },
frappe.help.help_links['List/Notification'] = [
{ label: 'Notification', url: docsUrl + 'user/manual/en/setting-up/email/notifications' },
]
frappe.help.help_links['Form/Email Alert'] = [
{ label: 'Email Alert', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/email/email-alerts' },
frappe.help.help_links['Form/Notification'] = [
{ label: 'Notification', url: docsUrl + 'user/manual/en/setting-up/email/notifications' },
]
frappe.help.help_links['List/Email Digest'] = [
{ label: 'Email Digest', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/email/email-digest' },
{ label: 'Email Digest', url: docsUrl + 'user/manual/en/setting-up/email/email-digest' },
]
frappe.help.help_links['List/Auto Email Report'] = [
{ label: 'Auto Email Reports', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/email/email-reports' },
{ label: 'Auto Email Reports', url: docsUrl + 'user/manual/en/setting-up/email/email-reports' },
]
frappe.help.help_links['Form/Print Settings'] = [
{ label: 'Print Settings', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/print/print-settings' },
{ label: 'Print Settings', url: docsUrl + 'user/manual/en/setting-up/print/print-settings' },
]
frappe.help.help_links['print-format-builder'] = [
{ label: 'Print Format Builder', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/print/print-settings' },
{ label: 'Print Format Builder', url: docsUrl + 'user/manual/en/setting-up/print/print-settings' },
]
frappe.help.help_links['List/Print Heading'] = [
{ label: 'Print Heading', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/print/print-headings' },
{ label: 'Print Heading', url: docsUrl + 'user/manual/en/setting-up/print/print-headings' },
]
//setup-integrations
frappe.help.help_links['Form/PayPal Settings'] = [
{ label: 'PayPal Settings', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/integrations/paypal-integration' },
{ label: 'PayPal Settings', url: docsUrl + 'user/manual/en/setting-up/integrations/paypal-integration' },
]
frappe.help.help_links['Form/Razorpay Settings'] = [
{ label: 'Razorpay Settings', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/integrations/razorpay-integration' },
{ label: 'Razorpay Settings', url: docsUrl + 'user/manual/en/setting-up/integrations/razorpay-integration' },
]
frappe.help.help_links['Form/Dropbox Settings'] = [
{ label: 'Dropbox Settings', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/integrations/dropbox-backup' },
{ label: 'Dropbox Settings', url: docsUrl + 'user/manual/en/setting-up/integrations/dropbox-backup' },
]
frappe.help.help_links['Form/LDAP Settings'] = [
{ label: 'LDAP Settings', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/integrations/ldap-integration' },
{ label: 'LDAP Settings', url: docsUrl + 'user/manual/en/setting-up/integrations/ldap-integration' },
]
frappe.help.help_links['Form/Stripe Settings'] = [
{ label: 'Stripe Settings', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/integrations/stripe-integration' },
{ label: 'Stripe Settings', url: docsUrl + 'user/manual/en/setting-up/integrations/stripe-integration' },
]
//Sales
frappe.help.help_links['Form/Quotation'] = [
{ label: 'Quotation', url: 'https://frappe.github.io/erpnext/user/manual/en/selling/quotation' },
{ label: 'Applying Discount', url: 'https://frappe.github.io/erpnext/user/manual/en/selling/articles/applying-discount' },
{ label: 'Sales Person', url: 'https://frappe.github.io/erpnext/user/manual/en/selling/articles/sales-persons-in-the-sales-transactions' },
{ label: 'Applying Margin', url: 'https://frappe.github.io/erpnext/user/manual/en/selling/articles/adding-margin' },
{ label: 'Quotation', url: docsUrl + 'user/manual/en/selling/quotation' },
{ label: 'Applying Discount', url: docsUrl + 'user/manual/en/selling/articles/applying-discount' },
{ label: 'Sales Person', url: docsUrl + 'user/manual/en/selling/articles/sales-persons-in-the-sales-transactions' },
{ label: 'Applying Margin', url: docsUrl + 'user/manual/en/selling/articles/adding-margin' },
]
frappe.help.help_links['List/Customer'] = [
{ label: 'Customer', url: 'https://frappe.github.io/erpnext/user/manual/en/CRM/customer' },
{ label: 'Credit Limit', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/credit-limit' },
{ label: 'Customer', url: docsUrl + 'user/manual/en/CRM/customer' },
{ label: 'Credit Limit', url: docsUrl + 'user/manual/en/accounts/credit-limit' },
]
frappe.help.help_links['Form/Customer'] = [
{ label: 'Customer', url: 'https://frappe.github.io/erpnext/user/manual/en/CRM/customer' },
{ label: 'Credit Limit', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/credit-limit' },
{ label: 'Customer', url: docsUrl + 'user/manual/en/CRM/customer' },
{ label: 'Credit Limit', url: docsUrl + 'user/manual/en/accounts/credit-limit' },
]
frappe.help.help_links['List/Sales Taxes and Charges Template'] = [
{ label: 'Setting Up Taxes', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/setting-up-taxes' },
{ label: 'Setting Up Taxes', url: docsUrl + 'user/manual/en/setting-up/setting-up-taxes' },
]
frappe.help.help_links['Form/Sales Taxes and Charges Template'] = [
{ label: 'Setting Up Taxes', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/setting-up-taxes' },
{ label: 'Setting Up Taxes', url: docsUrl + 'user/manual/en/setting-up/setting-up-taxes' },
]
frappe.help.help_links['List/Sales Order'] = [
{ label: 'Sales Order', url: 'https://frappe.github.io/erpnext/user/manual/en/selling/sales-order' },
{ label: 'Recurring Sales Order', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/recurring-orders-and-invoices' },
{ label: 'Applying Discount', url: 'https://frappe.github.io/erpnext/user/manual/en/selling/articles/applying-discount' },
{ label: 'Sales Order', url: docsUrl + 'user/manual/en/selling/sales-order' },
{ label: 'Recurring Sales Order', url: docsUrl + 'user/manual/en/accounts/recurring-orders-and-invoices' },
{ label: 'Applying Discount', url: docsUrl + 'user/manual/en/selling/articles/applying-discount' },
]
frappe.help.help_links['Form/Sales Order'] = [
{ label: 'Sales Order', url: 'https://frappe.github.io/erpnext/user/manual/en/selling/sales-order' },
{ label: 'Recurring Sales Order', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/recurring-orders-and-invoices' },
{ label: 'Applying Discount', url: 'https://frappe.github.io/erpnext/user/manual/en/selling/articles/applying-discount' },
{ label: 'Drop Shipping', url: 'https://frappe.github.io/erpnext/user/manual/en/selling/articles/drop-shipping' },
{ label: 'Sales Person', url: 'https://frappe.github.io/erpnext/user/manual/en/selling/articles/sales-persons-in-the-sales-transactions' },
{ label: 'Close Sales Order', url: 'https://frappe.github.io/erpnext/user/manual/en/selling/articles/close-sales-order' },
{ label: 'Applying Margin', url: 'https://frappe.github.io/erpnext/user/manual/en/selling/articles/adding-margin' },
{ label: 'Sales Order', url: docsUrl + 'user/manual/en/selling/sales-order' },
{ label: 'Recurring Sales Order', url: docsUrl + 'user/manual/en/accounts/recurring-orders-and-invoices' },
{ label: 'Applying Discount', url: docsUrl + 'user/manual/en/selling/articles/applying-discount' },
{ label: 'Drop Shipping', url: docsUrl + 'user/manual/en/selling/articles/drop-shipping' },
{ label: 'Sales Person', url: docsUrl + 'user/manual/en/selling/articles/sales-persons-in-the-sales-transactions' },
{ label: 'Close Sales Order', url: docsUrl + 'user/manual/en/selling/articles/close-sales-order' },
{ label: 'Applying Margin', url: docsUrl + 'user/manual/en/selling/articles/adding-margin' },
]
frappe.help.help_links['Form/Product Bundle'] = [
{ label: 'Product Bundle', url: 'https://frappe.github.io/erpnext/user/manual/en/selling/setup/product-bundle' },
{ label: 'Product Bundle', url: docsUrl + 'user/manual/en/selling/setup/product-bundle' },
]
frappe.help.help_links['Form/Selling Settings'] = [
{ label: 'Selling Settings', url: 'https://frappe.github.io/erpnext/user/manual/en/selling/setup/selling-settings' },
{ label: 'Selling Settings', url: docsUrl + 'user/manual/en/selling/setup/selling-settings' },
]
//Buying
frappe.help.help_links['List/Supplier'] = [
{ label: 'Supplier', url: 'https://frappe.github.io/erpnext/user/manual/en/buying/supplier' },
{ label: 'Supplier', url: docsUrl + 'user/manual/en/buying/supplier' },
]
frappe.help.help_links['Form/Supplier'] = [
{ label: 'Supplier', url: 'https://frappe.github.io/erpnext/user/manual/en/buying/supplier' },
{ label: 'Supplier', url: docsUrl + 'user/manual/en/buying/supplier' },
]
frappe.help.help_links['Form/Request for Quotation'] = [
{ label: 'Request for Quotation', url: 'https://frappe.github.io/erpnext/user/manual/en/buying/request-for-quotation' },
{ label: 'RFQ Video', url: 'https://frappe.github.io/erpnext/user/videos/learn/request-for-quotation.html' },
{ label: 'Request for Quotation', url: docsUrl + 'user/manual/en/buying/request-for-quotation' },
{ label: 'RFQ Video', url: docsUrl + 'user/videos/learn/request-for-quotation.html' },
]
frappe.help.help_links['Form/Supplier Quotation'] = [
{ label: 'Supplier Quotation', url: 'https://frappe.github.io/erpnext/user/manual/en/buying/supplier-quotation' },
{ label: 'Supplier Quotation', url: docsUrl + 'user/manual/en/buying/supplier-quotation' },
]
frappe.help.help_links['Form/Buying Settings'] = [
{ label: 'Buying Settings', url: 'https://frappe.github.io/erpnext/user/manual/en/buying/setup/buying-settings' },
{ label: 'Buying Settings', url: docsUrl + 'user/manual/en/buying/setup/buying-settings' },
]
frappe.help.help_links['List/Purchase Order'] = [
{ label: 'Purchase Order', url: 'https://frappe.github.io/erpnext/user/manual/en/buying/purchase-order' },
{ label: 'Recurring Purchase Order', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/recurring-orders-and-invoices' },
{ label: 'Purchase Order', url: docsUrl + 'user/manual/en/buying/purchase-order' },
{ label: 'Recurring Purchase Order', url: docsUrl + 'user/manual/en/accounts/recurring-orders-and-invoices' },
]
frappe.help.help_links['Form/Purchase Order'] = [
{ label: 'Purchase Order', url: 'https://frappe.github.io/erpnext/user/manual/en/buying/purchase-order' },
{ label: 'Item UoM', url: 'https://frappe.github.io/erpnext/user/manual/en/buying/articles/purchasing-in-different-unit' },
{ label: 'Supplier Item Code', url: 'https://frappe.github.io/erpnext/user/manual/en/buying/articles/maintaining-suppliers-part-no-in-item' },
{ label: 'Recurring Purchase Order', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/recurring-orders-and-invoices' },
{ label: 'Subcontracting', url: 'https://frappe.github.io/erpnext/user/manual/en/manufacturing/subcontracting' },
{ label: 'Purchase Order', url: docsUrl + 'user/manual/en/buying/purchase-order' },
{ label: 'Item UoM', url: docsUrl + 'user/manual/en/buying/articles/purchasing-in-different-unit' },
{ label: 'Supplier Item Code', url: docsUrl + 'user/manual/en/buying/articles/maintaining-suppliers-part-no-in-item' },
{ label: 'Recurring Purchase Order', url: docsUrl + 'user/manual/en/accounts/recurring-orders-and-invoices' },
{ label: 'Subcontracting', url: docsUrl + 'user/manual/en/manufacturing/subcontracting' },
]
frappe.help.help_links['List/Purchase Taxes and Charges Template'] = [
{ label: 'Setting Up Taxes', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/setting-up-taxes' },
{ label: 'Setting Up Taxes', url: docsUrl + 'user/manual/en/setting-up/setting-up-taxes' },
]
frappe.help.help_links['List/POS Profile'] = [
{ label: 'POS Profile', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/pos-setting' },
{ label: 'POS Profile', url: docsUrl + 'user/manual/en/setting-up/pos-setting' },
]
frappe.help.help_links['List/Price List'] = [
{ label: 'Price List', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/price-lists' },
{ label: 'Price List', url: docsUrl + 'user/manual/en/setting-up/price-lists' },
]
frappe.help.help_links['List/Authorization Rule'] = [
{ label: 'Authorization Rule', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/authorization-rule' },
{ label: 'Authorization Rule', url: docsUrl + 'user/manual/en/setting-up/authorization-rule' },
]
frappe.help.help_links['Form/SMS Settings'] = [
{ label: 'SMS Settings', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/sms-setting' },
{ label: 'SMS Settings', url: docsUrl + 'user/manual/en/setting-up/sms-setting' },
]
frappe.help.help_links['List/Stock Reconciliation'] = [
{ label: 'Stock Reconciliation', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/stock-reconciliation-for-non-serialized-item' },
{ label: 'Stock Reconciliation', url: docsUrl + 'user/manual/en/setting-up/stock-reconciliation-for-non-serialized-item' },
]
frappe.help.help_links['Tree/Territory'] = [
{ label: 'Territory', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/territory' },
{ label: 'Territory', url: docsUrl + 'user/manual/en/setting-up/territory' },
]
frappe.help.help_links['Form/Dropbox Backup'] = [
{ label: 'Dropbox Backup', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/third-party-backups' },
{ label: 'Setting Up Dropbox Backup', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/articles/setting-up-dropbox-backups' },
{ label: 'Dropbox Backup', url: docsUrl + 'user/manual/en/setting-up/third-party-backups' },
{ label: 'Setting Up Dropbox Backup', url: docsUrl + 'user/manual/en/setting-up/articles/setting-up-dropbox-backups' },
]
frappe.help.help_links['List/Workflow'] = [
{ label: 'Workflow', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/workflows' },
{ label: 'Workflow', url: docsUrl + 'user/manual/en/setting-up/workflows' },
]
frappe.help.help_links['List/Company'] = [
{ label: 'Company', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/company-setup' },
{ label: 'Managing Multiple Companies', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/articles/managing-multiple-companies' },
{ label: 'Delete All Related Transactions for a Company', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/articles/delete-a-company-and-all-related-transactions' },
{ label: 'Company', url: docsUrl + 'user/manual/en/setting-up/company-setup' },
{ label: 'Managing Multiple Companies', url: docsUrl + 'user/manual/en/setting-up/articles/managing-multiple-companies' },
{ label: 'Delete All Related Transactions for a Company', url: docsUrl + 'user/manual/en/setting-up/articles/delete-a-company-and-all-related-transactions' },
]
//Accounts
frappe.help.help_links['modules/Accounts'] = [
{ label: 'Introduction to Accounts', url: 'http://frappe.github.io/erpnext/user/manual/en/accounts/' },
{ label: 'Chart of Accounts', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/chart-of-accounts.html' },
{ label: 'Multi Currency Accounting', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/multi-currency-accounting' },
{ label: 'Introduction to Accounts', url: 'http://erpnext.com/docs/user/manual/en/accounts/' },
{ label: 'Chart of Accounts', url: docsUrl + 'user/manual/en/accounts/chart-of-accounts.html' },
{ label: 'Multi Currency Accounting', url: docsUrl + 'user/manual/en/accounts/multi-currency-accounting' },
]
frappe.help.help_links['Tree/Account'] = [
{ label: 'Chart of Accounts', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/chart-of-accounts' },
{ label: 'Managing Tree Mastes', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/articles/managing-tree-structure-masters' },
{ label: 'Chart of Accounts', url: docsUrl + 'user/manual/en/accounts/chart-of-accounts' },
{ label: 'Managing Tree Mastes', url: docsUrl + 'user/manual/en/setting-up/articles/managing-tree-structure-masters' },
]
frappe.help.help_links['Form/Sales Invoice'] = [
{ label: 'Sales Invoice', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/sales-invoice' },
{ label: 'Accounts Opening Balance', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/opening-accounts' },
{ label: 'Sales Return', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/sales-return' },
{ label: 'Recurring Sales Invoice', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/recurring-orders-and-invoices' },
{ label: 'Sales Invoice', url: docsUrl + 'user/manual/en/accounts/sales-invoice' },
{ label: 'Accounts Opening Balance', url: docsUrl + 'user/manual/en/accounts/opening-accounts' },
{ label: 'Sales Return', url: docsUrl + 'user/manual/en/stock/sales-return' },
{ label: 'Recurring Sales Invoice', url: docsUrl + 'user/manual/en/accounts/recurring-orders-and-invoices' },
]
frappe.help.help_links['List/Sales Invoice'] = [
{ label: 'Sales Invoice', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/sales-invoice' },
{ label: 'Accounts Opening Balance', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/opening-accounts' },
{ label: 'Sales Return', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/sales-return' },
{ label: 'Recurring Sales Invoice', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/recurring-orders-and-invoices' },
{ label: 'Sales Invoice', url: docsUrl + 'user/manual/en/accounts/sales-invoice' },
{ label: 'Accounts Opening Balance', url: docsUrl + 'user/manual/en/accounts/opening-accounts' },
{ label: 'Sales Return', url: docsUrl + 'user/manual/en/stock/sales-return' },
{ label: 'Recurring Sales Invoice', url: docsUrl + 'user/manual/en/accounts/recurring-orders-and-invoices' },
]
frappe.help.help_links['pos'] = [
{ label: 'Point of Sale Invoice', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/point-of-sale-pos-invoice' },
{ label: 'Point of Sale Invoice', url: docsUrl + 'user/manual/en/accounts/point-of-sale-pos-invoice' },
]
frappe.help.help_links['List/POS Profile'] = [
{ label: 'Point of Sale Profile', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/pos-setting' },
{ label: 'Point of Sale Profile', url: docsUrl + 'user/manual/en/setting-up/pos-setting' },
]
frappe.help.help_links['List/Purchase Invoice'] = [
{ label: 'Purchase Invoice', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/purchase-invoice' },
{ label: 'Accounts Opening Balance', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/opening-accounts' },
{ label: 'Recurring Purchase Invoice', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/recurring-orders-and-invoices' },
{ label: 'Purchase Invoice', url: docsUrl + 'user/manual/en/accounts/purchase-invoice' },
{ label: 'Accounts Opening Balance', url: docsUrl + 'user/manual/en/accounts/opening-accounts' },
{ label: 'Recurring Purchase Invoice', url: docsUrl + 'user/manual/en/accounts/recurring-orders-and-invoices' },
]
frappe.help.help_links['List/Journal Entry'] = [
{ label: 'Journal Entry', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/journal-entry' },
{ label: 'Advance Payment Entry', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/advance-payment-entry' },
{ label: 'Accounts Opening Balance', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/opening-accounts' },
{ label: 'Journal Entry', url: docsUrl + 'user/manual/en/accounts/journal-entry' },
{ label: 'Advance Payment Entry', url: docsUrl + 'user/manual/en/accounts/advance-payment-entry' },
{ label: 'Accounts Opening Balance', url: docsUrl + 'user/manual/en/accounts/opening-accounts' },
]
frappe.help.help_links['List/Payment Entry'] = [
{ label: 'Payment Entry', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/payment-entry' },
{ label: 'Payment Entry', url: docsUrl + 'user/manual/en/accounts/payment-entry' },
]
frappe.help.help_links['List/Payment Request'] = [
{ label: 'Payment Request', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/payment-request' },
{ label: 'Payment Request', url: docsUrl + 'user/manual/en/accounts/payment-request' },
]
frappe.help.help_links['List/Asset'] = [
{ label: 'Managing Fixed Assets', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/managing-fixed-assets' },
{ label: 'Managing Fixed Assets', url: docsUrl + 'user/manual/en/accounts/managing-fixed-assets' },
]
frappe.help.help_links['List/Asset Category'] = [
{ label: 'Asset Category', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/managing-fixed-assets' },
{ label: 'Asset Category', url: docsUrl + 'user/manual/en/accounts/managing-fixed-assets' },
]
frappe.help.help_links['Tree/Cost Center'] = [
{ label: 'Budgeting', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/budgeting' },
{ label: 'Budgeting', url: docsUrl + 'user/manual/en/accounts/budgeting' },
]
frappe.help.help_links['List/Item'] = [
{ label: 'Item', url: 'http://frappe.github.io/erpnext/user/manual/en/stock/item' },
{ label: 'Item Price', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/item/item-price' },
{ label: 'Barcode', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/articles/track-items-using-barcode' },
{ label: 'Item Wise Taxation', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/item-wise-taxation' },
{ label: 'Managing Fixed Assets', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/managing-fixed-assets' },
{ label: 'Item Codification', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/item/item-codification' },
{ label: 'Item Variants', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/item/item-variants' },
{ label: 'Item Valuation', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/item/item-valuation-fifo-and-moving-average' },
{ label: 'Item', url: 'http://erpnext.com/docs/user/manual/en/stock/item' },
{ label: 'Item Price', url: docsUrl + 'user/manual/en/stock/item/item-price' },
{ label: 'Barcode', url: docsUrl + 'user/manual/en/stock/articles/track-items-using-barcode' },
{ label: 'Item Wise Taxation', url: docsUrl + 'user/manual/en/accounts/item-wise-taxation' },
{ label: 'Managing Fixed Assets', url: docsUrl + 'user/manual/en/accounts/managing-fixed-assets' },
{ label: 'Item Codification', url: docsUrl + 'user/manual/en/stock/item/item-codification' },
{ label: 'Item Variants', url: docsUrl + 'user/manual/en/stock/item/item-variants' },
{ label: 'Item Valuation', url: docsUrl + 'user/manual/en/stock/item/item-valuation-fifo-and-moving-average' },
]
frappe.help.help_links['Form/Item'] = [
{ label: 'Item', url: 'http://frappe.github.io/erpnext/user/manual/en/stock/item' },
{ label: 'Item Price', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/item/item-price' },
{ label: 'Barcode', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/articles/track-items-using-barcode' },
{ label: 'Item Wise Taxation', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/item-wise-taxation' },
{ label: 'Managing Fixed Assets', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/managing-fixed-assets' },
{ label: 'Item Codification', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/item/item-codification' },
{ label: 'Item Variants', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/item/item-variants' },
{ label: 'Item Valuation', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/item/item-valuation-fifo-and-moving-average' },
{ label: 'Item', url: 'http://erpnext.com/docs/user/manual/en/stock/item' },
{ label: 'Item Price', url: docsUrl + 'user/manual/en/stock/item/item-price' },
{ label: 'Barcode', url: docsUrl + 'user/manual/en/stock/articles/track-items-using-barcode' },
{ label: 'Item Wise Taxation', url: docsUrl + 'user/manual/en/accounts/item-wise-taxation' },
{ label: 'Managing Fixed Assets', url: docsUrl + 'user/manual/en/accounts/managing-fixed-assets' },
{ label: 'Item Codification', url: docsUrl + 'user/manual/en/stock/item/item-codification' },
{ label: 'Item Variants', url: docsUrl + 'user/manual/en/stock/item/item-variants' },
{ label: 'Item Valuation', url: docsUrl + 'user/manual/en/stock/item/item-valuation-fifo-and-moving-average' },
]
frappe.help.help_links['List/Purchase Receipt'] = [
{ label: 'Purchase Receipt', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/purchase-receipt' },
{ label: 'Barcode', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/articles/track-items-using-barcode' },
{ label: 'Purchase Receipt', url: docsUrl + 'user/manual/en/stock/purchase-receipt' },
{ label: 'Barcode', url: docsUrl + 'user/manual/en/stock/articles/track-items-using-barcode' },
]
frappe.help.help_links['List/Delivery Note'] = [
{ label: 'Delivery Note', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/delivery-note' },
{ label: 'Barcode', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/articles/track-items-using-barcode' },
{ label: 'Sales Return', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/sales-return' },
{ label: 'Delivery Note', url: docsUrl + 'user/manual/en/stock/delivery-note' },
{ label: 'Barcode', url: docsUrl + 'user/manual/en/stock/articles/track-items-using-barcode' },
{ label: 'Sales Return', url: docsUrl + 'user/manual/en/stock/sales-return' },
]
frappe.help.help_links['Form/Delivery Note'] = [
{ label: 'Delivery Note', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/delivery-note' },
{ label: 'Sales Return', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/sales-return' },
{ label: 'Barcode', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/articles/track-items-using-barcode' },
{ label: 'Subcontracting', url: 'https://frappe.github.io/erpnext/user/manual/en/manufacturing/subcontracting' },
{ label: 'Delivery Note', url: docsUrl + 'user/manual/en/stock/delivery-note' },
{ label: 'Sales Return', url: docsUrl + 'user/manual/en/stock/sales-return' },
{ label: 'Barcode', url: docsUrl + 'user/manual/en/stock/articles/track-items-using-barcode' },
{ label: 'Subcontracting', url: docsUrl + 'user/manual/en/manufacturing/subcontracting' },
]
frappe.help.help_links['List/Installation Note'] = [
{ label: 'Installation Note', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/installation-note' },
{ label: 'Installation Note', url: docsUrl + 'user/manual/en/stock/installation-note' },
]
frappe.help.help_links['Tree'] = [
{ label: 'Managing Tree Structure Masters', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/articles/managing-tree-structure-masters' },
{ label: 'Managing Tree Structure Masters', url: docsUrl + 'user/manual/en/setting-up/articles/managing-tree-structure-masters' },
]
frappe.help.help_links['List/Budget'] = [
{ label: 'Budgeting', url: 'https://frappe.github.io/erpnext/user/manual/en/accounts/budgeting' },
{ label: 'Budgeting', url: docsUrl + 'user/manual/en/accounts/budgeting' },
]
//Stock
frappe.help.help_links['List/Material Request'] = [
{ label: 'Material Request', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/material-request' },
{ label: 'Auto-creation of Material Request', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/articles/auto-creation-of-material-request' },
{ label: 'Material Request', url: docsUrl + 'user/manual/en/stock/material-request' },
{ label: 'Auto-creation of Material Request', url: docsUrl + 'user/manual/en/stock/articles/auto-creation-of-material-request' },
]
frappe.help.help_links['Form/Material Request'] = [
{ label: 'Material Request', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/material-request' },
{ label: 'Auto-creation of Material Request', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/articles/auto-creation-of-material-request' },
{ label: 'Material Request', url: docsUrl + 'user/manual/en/stock/material-request' },
{ label: 'Auto-creation of Material Request', url: docsUrl + 'user/manual/en/stock/articles/auto-creation-of-material-request' },
]
frappe.help.help_links['Form/Stock Entry'] = [
{ label: 'Stock Entry', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/stock-entry' },
{ label: 'Stock Entry Types', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/articles/stock-entry-purpose' },
{ label: 'Repack Entry', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/articles/repack-entry' },
{ label: 'Opening Stock', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/opening-stock' },
{ label: 'Subcontracting', url: 'https://frappe.github.io/erpnext/user/manual/en/manufacturing/subcontracting' },
{ label: 'Stock Entry', url: docsUrl + 'user/manual/en/stock/stock-entry' },
{ label: 'Stock Entry Types', url: docsUrl + 'user/manual/en/stock/articles/stock-entry-purpose' },
{ label: 'Repack Entry', url: docsUrl + 'user/manual/en/stock/articles/repack-entry' },
{ label: 'Opening Stock', url: docsUrl + 'user/manual/en/stock/opening-stock' },
{ label: 'Subcontracting', url: docsUrl + 'user/manual/en/manufacturing/subcontracting' },
]
frappe.help.help_links['List/Stock Entry'] = [
{ label: 'Stock Entry', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/stock-entry' },
{ label: 'Stock Entry', url: docsUrl + 'user/manual/en/stock/stock-entry' },
]
frappe.help.help_links['Tree/Warehouse'] = [
{ label: 'Warehouse', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/warehouse' },
{ label: 'Warehouse', url: docsUrl + 'user/manual/en/stock/warehouse' },
]
frappe.help.help_links['List/Serial No'] = [
{ label: 'Serial No', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/serial-no' },
{ label: 'Serial No', url: docsUrl + 'user/manual/en/stock/serial-no' },
]
frappe.help.help_links['Form/Serial No'] = [
{ label: 'Serial No', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/serial-no' },
{ label: 'Serial No', url: docsUrl + 'user/manual/en/stock/serial-no' },
]
frappe.help.help_links['Form/Batch'] = [
{ label: 'Batch', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/batch' },
{ label: 'Batch', url: docsUrl + 'user/manual/en/stock/batch' },
]
frappe.help.help_links['Form/Packing Slip'] = [
{ label: 'Packing Slip', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/tools/packing-slip' },
{ label: 'Packing Slip', url: docsUrl + 'user/manual/en/stock/tools/packing-slip' },
]
frappe.help.help_links['Form/Quality Inspection'] = [
{ label: 'Quality Inspection', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/tools/quality-inspection' },
{ label: 'Quality Inspection', url: docsUrl + 'user/manual/en/stock/tools/quality-inspection' },
]
frappe.help.help_links['Form/Landed Cost Voucher'] = [
{ label: 'Landed Cost Voucher', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/tools/landed-cost-voucher' },
{ label: 'Landed Cost Voucher', url: docsUrl + 'user/manual/en/stock/tools/landed-cost-voucher' },
]
frappe.help.help_links['Tree/Item Group'] = [
{ label: 'Item Group', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/setup/item-group' },
{ label: 'Item Group', url: docsUrl + 'user/manual/en/stock/setup/item-group' },
]
frappe.help.help_links['Form/Item Attribute'] = [
{ label: 'Item Attribute', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/setup/item-attribute' },
{ label: 'Item Attribute', url: docsUrl + 'user/manual/en/stock/setup/item-attribute' },
]
frappe.help.help_links['Form/UOM'] = [
{ label: 'Fractions in UOM', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/articles/managing-fractions-in-uom' },
{ label: 'Fractions in UOM', url: docsUrl + 'user/manual/en/stock/articles/managing-fractions-in-uom' },
]
frappe.help.help_links['Form/Stock Reconciliation'] = [
{ label: 'Opening Stock Entry', url: 'https://frappe.github.io/erpnext/user/manual/en/stock/opening-stock' },
{ label: 'Opening Stock Entry', url: docsUrl + 'user/manual/en/stock/opening-stock' },
]
//CRM
frappe.help.help_links['Form/Lead'] = [
{ label: 'Lead', url: 'https://frappe.github.io/erpnext/user/manual/en/CRM/lead' },
{ label: 'Lead', url: docsUrl + 'user/manual/en/CRM/lead' },
]
frappe.help.help_links['Form/Opportunity'] = [
{ label: 'Opportunity', url: 'https://frappe.github.io/erpnext/user/manual/en/CRM/opportunity' },
{ label: 'Opportunity', url: docsUrl + 'user/manual/en/CRM/opportunity' },
]
frappe.help.help_links['Form/Address'] = [
{ label: 'Address', url: 'https://frappe.github.io/erpnext/user/manual/en/CRM/contact' },
{ label: 'Address', url: docsUrl + 'user/manual/en/CRM/contact' },
]
frappe.help.help_links['Form/Contact'] = [
{ label: 'Contact', url: 'https://frappe.github.io/erpnext/user/manual/en/CRM/contact' },
{ label: 'Contact', url: docsUrl + 'user/manual/en/CRM/contact' },
]
frappe.help.help_links['Form/Newsletter'] = [
{ label: 'Newsletter', url: 'https://frappe.github.io/erpnext/user/manual/en/CRM/newsletter' },
{ label: 'Newsletter', url: docsUrl + 'user/manual/en/CRM/newsletter' },
]
frappe.help.help_links['Form/Campaign'] = [
{ label: 'Campaign', url: 'https://frappe.github.io/erpnext/user/manual/en/CRM/setup/campaign' },
{ label: 'Campaign', url: docsUrl + 'user/manual/en/CRM/setup/campaign' },
]
frappe.help.help_links['Tree/Sales Person'] = [
{ label: 'Sales Person', url: 'https://frappe.github.io/erpnext/user/manual/en/CRM/setup/sales-person' },
{ label: 'Sales Person', url: docsUrl + 'user/manual/en/CRM/setup/sales-person' },
]
frappe.help.help_links['Form/Sales Person'] = [
{ label: 'Sales Person Target', url: 'https://frappe.github.io/erpnext/user/manual/en/selling/setup/sales-person-target-allocation' },
{ label: 'Sales Person Target', url: docsUrl + 'user/manual/en/selling/setup/sales-person-target-allocation' },
]
//Support
frappe.help.help_links['List/Feedback Trigger'] = [
{ label: 'Feedback Trigger', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/feedback/setting-up-feedback' },
{ label: 'Feedback Trigger', url: docsUrl + 'user/manual/en/setting-up/feedback/setting-up-feedback' },
]
frappe.help.help_links['List/Feedback Request'] = [
{ label: 'Feedback Request', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/feedback/submit-feedback' },
{ label: 'Feedback Request', url: docsUrl + 'user/manual/en/setting-up/feedback/submit-feedback' },
]
frappe.help.help_links['List/Feedback Request'] = [
{ label: 'Feedback Request', url: 'https://frappe.github.io/erpnext/user/manual/en/setting-up/feedback/submit-feedback' },
{ label: 'Feedback Request', url: docsUrl + 'user/manual/en/setting-up/feedback/submit-feedback' },
]
//Manufacturing
frappe.help.help_links['Form/BOM'] = [
{ label: 'Bill of Material', url: 'https://frappe.github.io/erpnext/user/manual/en/manufacturing/bill-of-materials' },
{ label: 'Nested BOM Structure', url: 'https://frappe.github.io/erpnext/user/manual/en/manufacturing/articles/nested-bom-structure' },
{ label: 'Bill of Material', url: docsUrl + 'user/manual/en/manufacturing/bill-of-materials' },
{ label: 'Nested BOM Structure', url: docsUrl + 'user/manual/en/manufacturing/articles/nested-bom-structure' },
]
frappe.help.help_links['Form/Production Order'] = [
{ label: 'Production Order', url: 'https://frappe.github.io/erpnext/user/manual/en/manufacturing/production-order' },
frappe.help.help_links['Form/Work Order'] = [
{ label: 'Work Order', url: docsUrl + 'user/manual/en/manufacturing/work-order' },
]
frappe.help.help_links['Form/Workstation'] = [
{ label: 'Workstation', url: 'https://frappe.github.io/erpnext/user/manual/en/manufacturing/workstation' },
{ label: 'Workstation', url: docsUrl + 'user/manual/en/manufacturing/workstation' },
]
frappe.help.help_links['Form/Operation'] = [
{ label: 'Operation', url: 'https://frappe.github.io/erpnext/user/manual/en/manufacturing/operation' },
]
frappe.help.help_links['Form/Production Planning Tool'] = [
{ label: 'Production Planning Tool', url: 'https://frappe.github.io/erpnext/user/manual/en/manufacturing/tools/production-planning-tool' },
{ label: 'Operation', url: docsUrl + 'user/manual/en/manufacturing/operation' },
]
frappe.help.help_links['Form/BOM Update Tool'] = [
{ label: 'BOM Update Tool', url: 'https://frappe.github.io/erpnext/user/manual/en/manufacturing/tools/bom-update-tool' },
{ label: 'BOM Update Tool', url: docsUrl + 'user/manual/en/manufacturing/tools/bom-update-tool' },
]
//Customize
frappe.help.help_links['Form/Customize Form'] = [
{ label: 'Custom Field', url: 'https://frappe.github.io/erpnext/user/manual/en/customize-erpnext/custom-field' },
{ label: 'Customize Field', url: 'https://frappe.github.io/erpnext/user/manual/en/customize-erpnext/customize-form' },
{ label: 'Custom Field', url: docsUrl + 'user/manual/en/customize-erpnext/custom-field' },
{ label: 'Customize Field', url: docsUrl + 'user/manual/en/customize-erpnext/customize-form' },
]
frappe.help.help_links['Form/Custom Field'] = [
{ label: 'Custom Field', url: 'https://frappe.github.io/erpnext/user/manual/en/customize-erpnext/custom-field' },
{ label: 'Custom Field', url: docsUrl + 'user/manual/en/customize-erpnext/custom-field' },
]
frappe.help.help_links['Form/Custom Field'] = [
{ label: 'Custom Field', url: 'https://frappe.github.io/erpnext/user/manual/en/customize-erpnext/custom-field' },
{ label: 'Custom Field', url: docsUrl + 'user/manual/en/customize-erpnext/custom-field' },
]

View File

@@ -73,7 +73,7 @@
{% for(var j=i*3; j
<(i+1)*3; j++) { %} <button type="button" class="btn btn-default numeric-keypad" val="{{j+1}}">{{j+1}}</button>
{% } %}
<button type="button" {% if((!allow_user_to_edit_rate && chartData[i] == __("Price")) || (!allow_user_to_edit_discount && chartData[i] == __("Disc"))) { %} disabled {% } %} id="pos-item-{{ chartData[i].toLowerCase() }}" class="btn text-center btn-default numeric-keypad pos-operation">{{ __(chartData[i]) }}</button>
<button type="button" {% if((!allow_user_to_edit_rate && __(chartData[i]) == __("Price")) || (!allow_user_to_edit_discount && __(chartData[i]) == __("Disc"))) { %} disabled {% } %} id="pos-item-{{ chartData[i].toLowerCase() }}" class="btn text-center btn-default numeric-keypad pos-operation">{{ __(chartData[i]) }}</button>
</div>
{% } %}
<div class="row text-right">

View File

@@ -97,6 +97,9 @@ erpnext.setup.slides_settings = [
if (!this.values.company_abbr) {
return false;
}
if (this.values.company_abbr.length > 5) {
return false;
}
return true;
}
},
@@ -138,10 +141,15 @@ erpnext.setup.slides_settings = [
validate: function () {
// validate fiscal year start and end dates
if (this.values.fy_start_date == 'Invalid date' || this.values.fy_end_date == 'Invalid date') {
const invalid = this.values.fy_start_date == 'Invalid date' ||
this.values.fy_end_date == 'Invalid date';
const start_greater_than_end = this.values.fy_start_date > this.values.fy_end_date;
if (invalid || start_greater_than_end) {
frappe.msgprint(__("Please enter valid Financial Year Start and End Dates"));
return false;
}
return true;
},

View File

@@ -320,7 +320,7 @@ frappe.ui.form.ItemQuickEntryForm = frappe.ui.form.QuickEntryForm.extend({
["attribute_value", "like", e.target.value + "%"]
],
fields: ["attribute_value"],
parent: "Item"
parent: "Item Attribute"
},
callback: function(r) {
if (r.message) {

View File

@@ -412,6 +412,12 @@ body[data-route="pos"] {
.collapse-btn {
cursor: pointer;
}
@media (max-width: @screen-xs) {
.page-actions {
max-width: 110px;
}
}
}
.price-info {

View File

@@ -180,7 +180,8 @@ def make_custom_fields():
'Sales Invoice Item': [hsn_sac_field],
'Purchase Order Item': [hsn_sac_field],
'Purchase Receipt Item': [hsn_sac_field],
'Purchase Invoice Item': [hsn_sac_field]
'Purchase Invoice Item': [hsn_sac_field],
'Material Request Item': [hsn_sac_field]
}
create_custom_fields(custom_fields)

View File

@@ -5,25 +5,52 @@ from erpnext.regional.india import states, state_numbers
from erpnext.controllers.taxes_and_totals import get_itemised_tax, get_itemised_taxable_amount
def validate_gstin_for_india(doc, method):
if not hasattr(doc, 'gstin'):
if not hasattr(doc, 'gstin') or not doc.gstin:
return
if doc.gstin:
doc.gstin = doc.gstin.upper()
if doc.gstin not in ["NA", "na"]:
p = re.compile("[0-9]{2}[a-zA-Z]{5}[0-9]{4}[a-zA-Z]{1}[1-9A-Za-z]{1}[Z]{1}[0-9a-zA-Z]{1}")
if not p.match(doc.gstin):
frappe.throw(_("Invalid GSTIN or Enter NA for Unregistered"))
doc.gstin = doc.gstin.upper().strip()
if not doc.gstin or doc.gstin == 'NA':
return
if len(doc.gstin) != 15:
frappe.throw(_("Invalid GSTIN! A GSTIN must have 15 characters."))
p = re.compile("^[0-9]{2}[A-Z]{4}[0-9A-Z]{1}[0-9]{4}[A-Z]{1}[1-9A-Z]{1}[1-9A-Z]{1}[0-9A-Z]{1}$")
if not p.match(doc.gstin):
frappe.throw(_("Invalid GSTIN! The input you've entered doesn't match the format of GSTIN."))
validate_gstin_check_digit(doc.gstin)
if not doc.gst_state:
if doc.state in states:
doc.gst_state = doc.state
if not doc.state:
return
state = doc.state.lower()
states_lowercase = {s.lower():s for s in states}
if state in states_lowercase:
doc.gst_state = states_lowercase[state]
else:
return
if doc.gst_state:
doc.gst_state_number = state_numbers[doc.gst_state]
if doc.gstin and doc.gstin != "NA" and doc.gst_state_number != doc.gstin[:2]:
frappe.throw(_("First 2 digits of GSTIN should match with State number {0}")
.format(doc.gst_state_number))
doc.gst_state_number = state_numbers[doc.gst_state]
if doc.gst_state_number != doc.gstin[:2]:
frappe.throw(_("Invalid GSTIN! First 2 digits of GSTIN should match with State number {0}.")
.format(doc.gst_state_number))
def validate_gstin_check_digit(gstin):
''' Function to validate the check digit of the GSTIN.'''
factor = 1
total = 0
code_point_chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
mod = len(code_point_chars)
input_chars = gstin[:-1]
for char in input_chars:
digit = factor * code_point_chars.find(char)
digit = (digit // mod) + (digit % mod)
total += digit
factor = 2 if factor == 1 else 1
if gstin[-1] != code_point_chars[((mod - (total % mod)) % mod)]:
frappe.throw(_("Invalid GSTIN! The check digit validation has failed. " +
"Please ensure you've typed the GSTIN correctly."))
def get_itemised_tax_breakup_header(item_doctype, tax_accounts):
if frappe.get_meta(item_doctype).has_field('gst_hsn_code'):

View File

@@ -1,6 +1,11 @@
Selling management module. Includes forms for capturing / managing the sales process.
Selling management module. Includes forms for capturing / managing the sales process:
- Customer
- Campaign
- Quotation
- Sales Order
Moved to CRM Module:
- Lead
- Opportunity
- Quotation
- Sales Order

View File

@@ -173,6 +173,11 @@ class Customer(TransactionBase):
frappe.throw(_("""New credit limit is less than current outstanding amount for the customer. Credit limit has to be atleast {0}""").format(outstanding_amt))
def on_trash(self):
if self.customer_primary_contact:
frappe.db.sql("""update `tabCustomer`
set customer_primary_contact=null, mobile_no=null, email_id=null
where name=%s""", self.name)
delete_contact_and_address('Customer', self.name)
if self.lead_name:
frappe.db.sql("update `tabLead` set status='Interested' where name=%s", self.lead_name)

View File

@@ -96,6 +96,15 @@ class TestCustomer(unittest.TestCase):
so.save()
def test_delete_customer_contact(self):
customer = frappe.get_doc(
get_customer_dict('_Test Customer for delete')).insert(ignore_permissions=True)
customer.mobile_no = "8989889890"
customer.save()
self.assertTrue(customer.customer_primary_contact)
frappe.delete_doc('Customer', customer.name)
def test_disabled_customer(self):
make_test_records("Item")

View File

@@ -31,6 +31,26 @@ class TestQuotation(unittest.TestCase):
self.assertFalse(sales_order.get('payment_schedule'))
def test_make_sales_order_with_different_currency(self):
from erpnext.selling.doctype.quotation.quotation import make_sales_order
quotation = frappe.copy_doc(test_records[0])
quotation.transaction_date = nowdate()
quotation.valid_till = add_months(quotation.transaction_date, 1)
quotation.insert()
quotation.submit()
sales_order = make_sales_order(quotation.name)
sales_order.currency = "USD"
sales_order.conversion_rate = 20.0
sales_order.delivery_date = "2019-01-01"
sales_order.naming_series = "_T-Quotation-"
sales_order.transaction_date = nowdate()
sales_order.insert()
self.assertEquals(sales_order.currency, "USD")
self.assertNotEqual(sales_order.currency, quotation.currency)
def test_make_sales_order(self):
from erpnext.selling.doctype.quotation.quotation import make_sales_order

View File

@@ -15,6 +15,7 @@
"fields": [
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 1,
"collapsible": 0,
@@ -44,11 +45,13 @@
"reqd": 1,
"search_index": 1,
"set_only_once": 0,
"translatable": 0,
"unique": 0,
"width": "150px"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -74,10 +77,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -102,10 +107,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -134,11 +141,13 @@
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0,
"width": "150px"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 1,
@@ -165,10 +174,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -197,11 +208,13 @@
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0,
"width": "300px"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -227,10 +240,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -257,10 +272,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -288,10 +305,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -317,10 +336,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 1,
"collapsible": 0,
@@ -349,11 +370,13 @@
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0,
"width": "100px"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -383,11 +406,13 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0,
"width": "100px"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -412,10 +437,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -443,10 +470,12 @@
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -473,10 +502,12 @@
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -503,10 +534,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -532,10 +565,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -565,11 +600,13 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0,
"width": "100px"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -599,11 +636,13 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0,
"width": "100px"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 1,
@@ -630,10 +669,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -662,10 +703,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -693,10 +736,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -725,10 +770,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -754,10 +801,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -787,11 +836,13 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0,
"width": "100px"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -820,10 +871,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -852,10 +905,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -880,10 +935,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 1,
"collapsible": 0,
@@ -915,11 +972,13 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0,
"width": "100px"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -936,6 +995,7 @@
"label": "Net Rate",
"length": 0,
"no_copy": 0,
"options": "currency",
"permlevel": 0,
"precision": "",
"print_hide": 1,
@@ -946,10 +1006,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -979,11 +1041,13 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0,
"width": "100px"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1011,10 +1075,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1039,10 +1105,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1072,11 +1140,13 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0,
"width": "100px"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1103,10 +1173,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1136,11 +1208,13 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0,
"width": "100px"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1168,10 +1242,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1198,10 +1274,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 1,
@@ -1228,10 +1306,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1258,10 +1338,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1288,10 +1370,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1317,10 +1401,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1348,10 +1434,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 1,
@@ -1379,10 +1467,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1410,10 +1500,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1439,10 +1531,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1469,10 +1563,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1500,10 +1596,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1530,10 +1628,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1559,10 +1659,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1592,11 +1694,13 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0,
"width": "150px"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1626,11 +1730,13 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0,
"width": "150px"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1658,10 +1764,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1686,10 +1794,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
@@ -1717,10 +1827,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1750,10 +1862,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1783,6 +1897,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0,
"width": "150px"
}
@@ -1798,7 +1913,7 @@
"istable": 1,
"max_attachments": 0,
"menu_index": 0,
"modified": "2018-08-06 05:18:38.135668",
"modified": "2018-12-12 05:52:46.135944",
"modified_by": "Administrator",
"module": "Selling",
"name": "Quotation Item",
@@ -1811,5 +1926,6 @@
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1,
"track_seen": 0
"track_seen": 0,
"track_views": 0
}

View File

@@ -141,7 +141,7 @@ class SalesOrder(SellingController):
super(SalesOrder, self).validate_with_previous_doc({
"Quotation": {
"ref_dn_field": "prevdoc_docname",
"compare_fields": [["company", "="], ["currency", "="]]
"compare_fields": [["company", "="]]
}
})
@@ -552,7 +552,7 @@ def make_sales_invoice(source_name, target_doc=None, ignore_permissions=False):
def update_item(source, target, source_parent):
target.amount = flt(source.amount) - flt(source.billed_amt)
target.base_amount = target.amount * flt(source_parent.conversion_rate)
target.qty = target.amount / flt(source.rate) if (source.rate and source.billed_amt) else source.qty
target.qty = target.amount / flt(source.rate) if (source.rate and source.billed_amt) else source.qty - source.returned_qty
item = frappe.db.get_value("Item", target.item_code, ["item_group", "selling_cost_center"], as_dict=1)
target.cost_center = frappe.db.get_value("Project", source_parent.project, "cost_center") \

View File

@@ -15,19 +15,24 @@ class SMSCenter(Document):
def create_receiver_list(self):
rec, where_clause = '', ''
if self.send_to == 'All Customer Contact':
where_clause = self.customer and " and customer = '%s'" % \
self.customer.replace("'", "\'") or " and ifnull(customer, '') != ''"
where_clause = " and dl.link_doctype = 'Customer'"
if self.customer:
where_clause += " and dl.link_name = '%s'" % \
self.customer.replace("'", "\'") or " and ifnull(dl.link_name, '') != ''"
if self.send_to == 'All Supplier Contact':
where_clause = self.supplier and " and supplier = '%s'" % \
self.supplier.replace("'", "\'") or " and ifnull(supplier, '') != ''"
where_clause = " and dl.link_doctype = 'Supplier'"
if self.supplier:
where_clause += " and dl.link_name = '%s'" % \
self.supplier.replace("'", "\'") or " and ifnull(dl.link_name, '') != ''"
if self.send_to == 'All Sales Partner Contact':
where_clause = self.sales_partner and " and sales_partner = '%s'" % \
self.sales_partner.replace("'", "\'") or " and ifnull(sales_partner, '') != ''"
where_clause = " and dl.link_doctype = 'Sales Partner'"
if self.sales_partner:
where_clause += "and dl.link_name = '%s'" % \
self.sales_partner.replace("'", "\'") or " and ifnull(dl.link_name, '') != ''"
if self.send_to in ['All Contact', 'All Customer Contact', 'All Supplier Contact', 'All Sales Partner Contact']:
rec = frappe.db.sql("""select CONCAT(ifnull(first_name,''), ' ', ifnull(last_name,'')),
mobile_no from `tabContact` where ifnull(mobile_no,'')!='' and
docstatus != 2 %s""" % where_clause)
rec = frappe.db.sql("""select CONCAT(ifnull(c.first_name,''), ' ', ifnull(c.last_name,'')),
c.mobile_no from `tabContact` c, `tabDynamic Link` dl where ifnull(c.mobile_no,'')!='' and
c.docstatus != 2 and dl.parent = c.name%s""" % where_clause)
elif self.send_to == 'All Lead (Open)':
rec = frappe.db.sql("""select lead_name, mobile_no from `tabLead` where
@@ -50,7 +55,6 @@ class SMSCenter(Document):
where ifnull(tabEmployee.cell_number,'')!=''""")
rec_list = ''
for d in rec:
rec_list += d[0] + ' - ' + d[1] + '\n'
self.receiver_list = rec_list

View File

@@ -5,6 +5,7 @@ from __future__ import unicode_literals
import frappe
from frappe import msgprint, _
from frappe.utils import flt
from erpnext import get_company_currency
def execute(filters=None):
if not filters: filters = {}
@@ -14,12 +15,14 @@ def execute(filters=None):
item_details = get_item_details()
data = []
company_currency = get_company_currency(filters["company"])
for d in entries:
if d.stock_qty > 0 or filters.get('show_return_entries', 0):
data.append([
d.name, d.customer, d.territory, d.posting_date, d.item_code,
d.name, d.customer, d.territory, d.warehouse, d.posting_date, d.item_code,
item_details.get(d.item_code, {}).get("item_group"), item_details.get(d.item_code, {}).get("brand"),
d.stock_qty, d.base_net_amount, d.sales_person, d.allocated_percentage, d.contribution_amt
d.stock_qty, d.base_net_amount, d.sales_person, d.allocated_percentage, d.contribution_amt, company_currency
])
if data:
@@ -32,12 +35,105 @@ def get_columns(filters):
if not filters.get("doc_type"):
msgprint(_("Please select the document type first"), raise_exception=1)
return [filters["doc_type"] + ":Link/" + filters["doc_type"] + ":140",
_("Customer") + ":Link/Customer:140", _("Territory") + ":Link/Territory:100", _("Posting Date") + ":Date:100",
_("Item Code") + ":Link/Item:120", _("Item Group") + ":Link/Item Group:120",
_("Brand") + ":Link/Brand:120", _("Qty") + ":Float:100", _("Amount") + ":Currency:120",
_("Sales Person") + ":Link/Sales Person:140", _("Contribution %") + "::110",
_("Contribution Amount") + ":Currency:140"]
columns = [
{
"label": _(filters["doc_type"]),
"options": filters["doc_type"],
"fieldname": frappe.scrub(filters['doc_type']),
"fieldtype": "Link",
"width": 140
},
{
"label": _("Customer"),
"options": "Customer",
"fieldname": "customer",
"fieldtype": "Link",
"width": 140
},
{
"label": _("Territory"),
"options": "Territory",
"fieldname": "territory",
"fieldtype": "Link",
"width": 140
},
{
"label": _("Warehouse"),
"options": "Warehouse",
"fieldname": "warehouse",
"fieldtype": "Link",
"width": 140
},
{
"label": _("Posting Date"),
"fieldname": "posting_date",
"fieldtype": "Date",
"width": 140
},
{
"label": _("Item Code"),
"options": "Item",
"fieldname": "item_code",
"fieldtype": "Link",
"width": 140
},
{
"label": _("Item Group"),
"options": "Item Group",
"fieldname": "item_group",
"fieldtype": "Link",
"width": 140
},
{
"label": _("Brand"),
"options": "Brand",
"fieldname": "brand",
"fieldtype": "Link",
"width": 140
},
{
"label": _("Qty"),
"fieldname": "qty",
"fieldtype": "Float",
"width": 140
},
{
"label": _("Amount"),
"options": "currency",
"fieldname": "amount",
"fieldtype": "Currency",
"width": 140
},
{
"label": _("Sales Person"),
"options": "Sales Person",
"fieldname": "sales_person",
"fieldtype": "Link",
"width": 140
},
{
"label": _("Contribution %"),
"fieldname": "contribution",
"fieldtype": "Float",
"width": 140
},
{
"label": _("Contribution Amount"),
"options": "currency",
"fieldname": "contribution_amt",
"fieldtype": "Currency",
"width": 140
},
{
"label":_("Currency"),
"options": "Currency",
"fieldname":"currency",
"fieldtype":"Link",
"hidden" : 1
}
]
return columns
def get_entries(filters):
date_field = filters["doc_type"] == "Sales Order" and "transaction_date" or "posting_date"
@@ -48,10 +144,10 @@ def get_entries(filters):
conditions, values = get_conditions(filters, date_field)
entries = frappe.db.sql("""
select
SELECT
dt.name, dt.customer, dt.territory, dt.%s as posting_date, dt_item.item_code,
st.sales_person, st.allocated_percentage,
CASE
st.sales_person, st.allocated_percentage, dt_item.warehouse,
CASE
WHEN dt.status = "Closed" THEN dt_item.%s * dt_item.conversion_factor
ELSE dt_item.stock_qty
END as stock_qty,
@@ -63,9 +159,9 @@ def get_entries(filters):
WHEN dt.status = "Closed" THEN ((dt_item.base_net_rate * dt_item.%s * dt_item.conversion_factor) * st.allocated_percentage/100)
ELSE dt_item.base_net_amount * st.allocated_percentage/100
END as contribution_amt
from
FROM
`tab%s` dt, `tab%s Item` dt_item, `tabSales Team` st
where
WHERE
st.parent = dt.name and dt.name = dt_item.parent and st.parenttype = %s
and dt.docstatus = 1 %s order by st.sales_person, dt.name desc
""" %(date_field, qty_field, qty_field, qty_field, filters["doc_type"], filters["doc_type"], '%s', conditions),
@@ -115,7 +211,7 @@ def get_items(filters):
def get_item_details():
item_details = {}
for d in frappe.db.sql("""select name, item_group, brand from `tabItem`""", as_dict=1):
for d in frappe.db.sql("""SELECT `name`, `item_group`, `brand` FROM `tabItem`""", as_dict=1):
item_details.setdefault(d.name, d)
return item_details

View File

@@ -22,7 +22,7 @@
<ul class="list-unstyled">
<li><a class="text-muted" href="#">{%= __("Go to the Desktop and start using ERPNext") %}</a></li>
<li><a class="text-muted" href="#modules/Learn">{%= __("View a list of all the help videos") %}</a></li>
<li><a class="text-muted" href="https://erpnext.org/docs/user" target="_blank">{%= __("Read the ERPNext Manual") %}</a></li>
<li><a class="text-muted" href="https://erpnext.com/docs/user" target="_blank">{%= __("Read the ERPNext Manual") %}</a></li>
<li><a class="text-muted" href="https://discuss.erpnext.com" target="_blank">{%= __("Community Forum") %}</a></li>
</ul>

View File

@@ -30,7 +30,7 @@ def make_tax_account_and_template(company, account_name, tax_rate, template_name
if accounts:
make_sales_and_purchase_tax_templates(accounts, template_name)
except frappe.NameError:
frappe.message_log.pop()
if frappe.message_log: frappe.message_log.pop()
except RootNotEditable:
pass
@@ -50,7 +50,7 @@ def make_tax_account(company, account_name, tax_rate):
"tax_rate": flt(tax_rate) if tax_rate else None
}).insert(ignore_permissions=True, ignore_mandatory=True)
except frappe.NameError:
frappe.message_log.pop()
if frappe.message_log: frappe.message_log.pop()
abbr = frappe.db.get_value('Company', company, 'abbr')
account = '{0} - {1}'.format(account_name, abbr)
return frappe.get_doc('Account', account)

View File

@@ -95,7 +95,7 @@ def get_exchange_rate(from_currency, to_currency, transaction_date=None):
if not value:
import requests
api_url = "https://frankfurter.erpnext.org/{0}".format(transaction_date)
api_url = "https://frankfurter.app/{0}".format(transaction_date)
response = requests.get(api_url, params={
"base": from_currency,
"symbols": to_currency

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