Compare commits

..

237 Commits

Author SHA1 Message Date
Saurabh
25eff13d35 Merge branch 'hotfix' 2019-06-27 12:51:14 +05:30
Saurabh
415c90d9d0 bumped to version 11.1.42 2019-06-27 13:21:14 +06:00
rohitwaghchaure
97a49185c5 Merge pull request #18091 from rohitwaghchaure/same_taxes_adding_multiple_times_in_pos
fix: same taxes adding multiple times in pos
2019-06-27 12:14:23 +05:30
Rohit Waghchaure
c2e5e569a0 fix: same taxes adding multiple times in pos 2019-06-27 11:15:18 +05:30
rohitwaghchaure
d5384a110d Merge pull request #18084 from rohitwaghchaure/fix_test_cases_for_sales_invoice_for_dn
fix: dn test cases
2019-06-26 22:52:10 +05:30
Rohit Waghchaure
4e9f1a08fe fix: dn test cases 2019-06-26 21:57:03 +05:30
Saurabh
79f2779574 Merge branch 'hotfix' 2019-06-26 17:18:50 +05:30
Saurabh
23251d9e4d bumped to version 11.1.41 2019-06-26 17:48:50 +06:00
Aditya Hase
e2652b9cc5 fix(item): moving reload_doc up in item barcode patch (#18078)
fix(item): moving reload_doc up in item barcode patch
2019-06-26 17:14:37 +05:30
karthikeyan5
beca677276 fix(item): fixing broken patch item_barcode_childtable_migrate 2019-06-26 17:11:14 +05:30
Sahil Khan
1202dc1dd3 Merge branch 'hotfix' 2019-06-26 15:53:52 +05:30
Sahil Khan
e2ddc82637 bumped to version 11.1.40 2019-06-26 16:13:52 +05:50
rohitwaghchaure
f269b66f39 fix: returned qty issue while making sales invoice from dn if same item added multiple times (#18074) 2019-06-26 13:39:52 +05:30
Rushabh Mehta
850284abee Merge pull request #18073 from hrwX/att_gantt_fix
fix(Attendance): Attendance gantt view
2019-06-26 13:36:49 +05:30
Faris Ansari
a6a6171225 fix: Don't append None values in against_account (#18032) 2019-06-26 13:30:54 +05:30
Himanshu Warekar
836aa5a1e6 fix: attendance gantt view 2019-06-26 11:35:53 +05:30
Mangesh-Khairnar
453d484a96 fix: precision for certain calculations in buying controller (#18009)
* fix: precision for certain numbers

* fix: check precision of the received_qty

* Update buying_controller.py
2019-06-26 11:09:39 +05:30
Deepesh Garg
3957880370 fix: Removed submitted status from quotation (#18054)
* fix: Change in list view and status updater

* fix: Change status in doctype

* fix: Patch for submitted status
2019-06-26 11:06:14 +05:30
Mangesh-Khairnar
840bfa87e8 fix: change the department to tree view (#18056) 2019-06-26 11:03:36 +05:30
Karthikeyan S
b2c43ee2d9 fix(item): fix patch for barcode childtable migration in item (#18066)
* fix(item): fix patch for barcode childtable migration in item

* fix(item): fix patch for barcode childtable migration in item

> adding condition so this patch will not execute for the site where it was executed perfectly the first time
2019-06-26 11:00:17 +05:30
Nabin Hait
10878c4d0e fix: Show close button if per_ordered is less than 99.999999 (#18068) 2019-06-26 10:57:39 +05:30
rohitwaghchaure
7cb940b179 Merge pull request #18043 from rohitwaghchaure/closed_job_opening_disaplying_in_job_applicant_hotfix
fix: Closed job opening disaplying in job applicant
2019-06-25 16:51:30 +05:30
rohitwaghchaure
01c85e0420 Merge pull request #18048 from deepeshgarg007/rounded_total
fix: Currency symbol fix for rounded total
2019-06-25 16:50:45 +05:30
rohitwaghchaure
41f36a6d92 Merge pull request #18027 from adityahase/fix-remove-imports
style: Remove unused imports
2019-06-25 15:41:44 +05:30
rohitwaghchaure
2aff5384ec Merge pull request #18044 from deepeshgarg007/accounts-controller
fix: Float division by zero error handling in group similar item
2019-06-25 15:25:17 +05:30
rohitwaghchaure
e592891121 Merge pull request #18039 from Mangesh-Khairnar/price-list-fix
fix(price list): change the field name
2019-06-25 15:23:13 +05:30
Deepesh Garg
e263a10fdd Merge pull request #18051 from karthikeyan5/hotfix-woocommerce-log
fix(integrations): Adding Error Logs for Woocommerce
2019-06-25 15:11:33 +05:30
rohitwaghchaure
db8b6c59bc Merge pull request #18018 from frappe/fix_bom_include_exploded_item
fix(BOM): set default value of include_exploded_item to 0
2019-06-25 14:19:00 +05:30
sahil28297
e1f3da2c2d Merge branch 'hotfix' into fix_bom_include_exploded_item 2019-06-25 14:09:47 +05:30
karthikeyan5
ae255d6328 Fix(integrations): Adding Error Logs for Woocommerce 2019-06-25 14:01:13 +05:30
Deepesh Garg
c283329581 Merge branch 'hotfix' into accounts-controller 2019-06-25 13:15:50 +05:30
Deepesh Garg
f85e344ed4 Merge branch 'hotfix' into rounded_total 2019-06-25 13:15:33 +05:30
rohitwaghchaure
aece8056f8 Merge pull request #18041 from rohitwaghchaure/fixed_test_case_for_payment_terms_in_so_hotfix
fix: test cases for quotation
2019-06-25 06:38:55 +05:30
deepeshgarg007
5d6ccafac9 fix: Currency symbol fix for rounded total 2019-06-24 21:12:16 +05:30
Rohit Waghchaure
ee22706182 fix: Closed job opening disaplying in job applicant 2019-06-24 18:04:28 +05:30
rohitwaghchaure
013ae1172a Merge pull request #17986 from rohitwaghchaure/all_default_values_not_moved_to_item_default_table
fix: as limit 100 was set in the query therefore not all item's default value moved to the Item Default table
2019-06-24 17:59:44 +05:30
deepeshgarg007
069276473f fix: Division by zero error fix in group similar item 2019-06-24 17:46:44 +05:30
Rohit Waghchaure
a8289d4fd5 fix: test case for payment terms in quotation 2019-06-24 17:45:22 +05:30
Mangesh-Khairnar
2ed653f433 fix(price list): change the field name 2019-06-24 17:29:11 +05:30
sahil28297
b724e080b0 fix(BOM): update modified field 2019-06-23 20:05:02 +05:30
Aditya Hase
9de95528ef style: Remove unused imports 2019-06-21 22:57:31 +05:30
Aditya Hase
3cab94f130 chore: Python 3 Tests on Travis (#18016)
chore: Python 3 Tests on Travis
2019-06-21 22:33:10 +05:30
Aditya Hase
b2cf38bbf4 Merge branch 'hotfix' into py3-hotfix 2019-06-21 21:36:03 +05:30
Aditya Hase
6c7bfb37c1 fix: Python 3 compatibility fixes (#18024)
fix: Python 3 compatibility fixes
2019-06-21 21:35:46 +05:30
Aditya Hase
6edd2b7f9f fix(py3): Convert filter to list 2019-06-21 17:58:45 +05:30
Aditya Hase
b47caf6642 fix(py3): Convert dict.values() to list 2019-06-21 17:56:58 +05:30
Aditya Hase
67476e7e09 fix(py3): Convert filter to list 2019-06-21 17:52:51 +05:30
Aditya Hase
3bafada5a6 fix(py3): Convert per_billed explicitly to int before comparing 2019-06-21 17:51:45 +05:30
Aditya Hase
0743610487 Merge branch 'hotfix' into py3-hotfix 2019-06-21 12:58:16 +05:30
Aditya Hase
bc7d39a16b fix: Python 3 compatibility fixes (#18019)
fix: Python 3 compatibility fixes
2019-06-21 12:57:52 +05:30
Aditya Hase
618146cc63 fix(py3): Replace unicode with six.text_type 2019-06-21 12:09:44 +05:30
Aditya Hase
4acd39b6a4 fix(py3): Convert filter to list 2019-06-21 12:08:23 +05:30
Aditya Hase
72056c26a8 fix(py3): Undefined variable 2019-06-21 12:06:05 +05:30
Aditya Hase
fbab41668d fix(py3): Undefined variable 2019-06-21 12:06:05 +05:30
Aditya Hase
14b5c96c58 fix(py3): Use range instead of xrange 2019-06-21 12:06:05 +05:30
Aditya Hase
d48d5c7cbd fix: Replace unicode with six.text_type 2019-06-21 12:06:05 +05:30
Aditya Hase
3d59ab5c55 fix(tests): Do not test order of features in Location 2019-06-21 12:06:05 +05:30
Aditya Hase
12cb0ea633 fix(tests): Timesheet tests 2019-06-21 12:06:05 +05:30
sahil28297
c5e959fe9c fix(BOM): set default value of include_exploded_item to 0 2019-06-21 11:42:58 +05:30
Aditya Hase
13d01dd690 fix: Run script with bash 2019-06-21 11:24:56 +05:30
Aditya Hase
4e94e26ef8 fix: Minor 2019-06-21 11:24:47 +05:30
Aditya Hase
8738f2e1c9 fix: Set file permissions 755 on travis/run-tests.sh 2019-06-21 11:24:39 +05:30
Aditya Hase
508b3ab8de fix(travis): Refactor .travis.yml 2019-06-21 11:24:28 +05:30
Aditya Hase
8f1f6a89f1 feat(travis): Python 3.6 tests 2019-06-21 11:24:14 +05:30
Rohit Waghchaure
523d89a2d9 fix: as limit 100 was set in the query therefore not all item's default value moved to the Item Default table 2019-06-21 10:24:08 +05:30
Rushabh Mehta
8d45d5c4a7 Merge pull request #16896 from Alchez/hotfix-shipping-override
fix(transaction): Fix shipping rule charge override by tax template
2019-06-21 09:25:14 +05:30
Rushabh Mehta
437edb1f01 Merge pull request #17391 from ashish-greycube/copy_payment_schedule_from_quot_to_SO
fix: copy_payment_schedule_from_quot_to_SO
2019-06-21 09:19:41 +05:30
Deepesh Garg
ac57edf7d3 fix: Default cost center fix for delivery note item (#17988) 2019-06-20 19:12:16 +05:30
Rushabh Mehta
3a2fec1ffb Merge pull request #17917 from Alchez/hotfix-item-code-gen
fix(stock): Remove hardcoded validation for Item
2019-06-20 14:21:46 +05:30
Deepesh Garg
e2cf17e106 Merge pull request #17994 from deepeshgarg007/hsn_summary
fix: From date and to date filters in HSN wise summary of outward supplies
2019-06-19 21:48:33 +05:30
deepeshgarg007
e5c7f3e542 fix: From date and to date filters in HSN wise summary of out ward supplies 2019-06-19 18:25:38 +05:30
rohitwaghchaure
d2bbc3ef3e Merge pull request #17966 from Alchez/fix-delivery-email
fix(delivery): Add items to context for dispatch notification email
2019-06-19 14:36:34 +05:30
rohitwaghchaure
96b6cfd810 Merge pull request #17979 from rohitwaghchaure/added_include_default_finance_book_in_reports
fix: finance book filters includes the gl data which don't have finance book
2019-06-19 14:09:35 +05:30
rohitwaghchaure
b3cf5f0caa Merge pull request #17977 from rohitwaghchaure/employee_attendance_tool_ux_issue
fix: could not find company all
2019-06-19 14:08:33 +05:30
Rohit Waghchaure
072948e827 fix: finance book filters includes the gl data which don't have finance book 2019-06-18 18:34:14 +05:30
Rohit Waghchaure
8ef80fb669 fix: could not find company all 2019-06-18 16:09:17 +05:30
Sahil Khan
4de1083096 Merge branch 'hotfix' 2019-06-18 14:41:56 +05:30
Sahil Khan
e5647f7441 bumped to version 11.1.39 2019-06-18 15:01:56 +05:50
Suraj Shetty
f9318f82ae Merge pull request #17971 from Mangesh-Khairnar/benefit-application
fix(employee-benefit-application): remove query from setup
2019-06-18 14:37:11 +05:30
rohitwaghchaure
4f78d14471 Merge pull request #17963 from rohitwaghchaure/bank_guarantee_project_not_found_error
fix: bank guarantee, not able to select the purchase order
2019-06-18 11:30:42 +05:30
rohitwaghchaure
d41771b4b1 Merge pull request #17961 from rohitwaghchaure/not_able_to_save_asset_for_manual_method
fix: not able to save asset if depreciation method is manual
2019-06-18 11:29:39 +05:30
Anurag Mishra
0c7afb389d fix: Company Filter in Total Stock Summary Report (#17973) 2019-06-17 20:48:11 +05:30
Mangesh-Khairnar
77ed46242f fix: change formatting 2019-06-17 19:04:13 +05:30
Mangesh-Khairnar
acbdeb833f fix(employee-benefit-application): remove query from setup 2019-06-17 18:08:48 +05:30
Rohit Waghchaure
2493d5e0d3 fix: bank guarantee, not able to select the purchase order 2019-06-17 17:39:37 +05:30
rohitwaghchaure
820d66b42e Merge pull request #17968 from rohitwaghchaure/enabled_disabled_buttons_on_change_of_pos_profile
fix: allow edit is enabled in the pos profile still user not able to edit the rates
2019-06-17 17:24:14 +05:30
Rohit Waghchaure
8fb018de47 fix: allow edit is enabled in the pos profile still user not able to edit the rates 2019-06-17 16:19:23 +05:30
Rohan Bansal
7987b1a681 fix(delivery): Add more context for dispatch notification email + formatting fixes 2019-06-17 16:13:52 +05:30
Rushabh Mehta
750526b138 Merge pull request #17928 from nabinhait/get-items-from
fix: Fixed setters for getting items from quotation/opportunity
2019-06-17 14:31:49 +05:30
Rohit Waghchaure
6b5c365cb6 fix: not able to save asset if depreciation method is manual 2019-06-17 13:32:36 +05:30
rohitwaghchaure
1a5c0b3ae2 Merge pull request #17957 from rohitwaghchaure/revert_group_by_voucher_general_ledger
fix: revert group by voucher general ledger changes
2019-06-17 07:43:53 +05:30
Rohit Waghchaure
740c954679 fix: revert group by voucher general ledger changes 2019-06-17 07:40:21 +05:30
Rohan
c8b1fbd9e6 Merge branch 'hotfix' into hotfix-item-code-gen 2019-06-14 15:53:11 +05:30
Khadija Tul Kubra Zaki
dc24fe60be fix: leave without pay spelling in salary register (#17938)
* leave without pay spelling in salary register

* fixed typo
2019-06-14 11:59:45 +05:30
Rushabh Mehta
86b33b2a10 Merge pull request #17369 from alyf-de/datev_report
feat(regional): Report for German tax consultants (DATEV)
2019-06-14 11:49:20 +05:30
Anurag Mishra
1450a7b408 fix column width (#17936) 2019-06-14 11:29:29 +05:30
rohitwaghchaure
f7af9b8745 fix: trial balance opening balance not showing in the debit side for the liability account (#17786) 2019-06-14 11:22:23 +05:30
Saurabh
87a09d2bb3 Merge pull request #17940 from nabinhait/salary-slip-amount
fix: salary slip amount calculation based on formula
2019-06-14 11:20:01 +05:30
Rushabh Mehta
c5283903be Merge pull request #17893 from deepeshgarg007/serial_no_batch_selector
fix: Available qty not shown in item batch selector for batch
2019-06-14 10:51:08 +05:30
sahil28297
cfd6ec0dcb Merge branch 'hotfix' into serial_no_batch_selector 2019-06-13 19:51:47 +05:30
Nabin Hait
a59aaf48f2 fix: salary slip amount calculation based on formula 2019-06-13 19:43:47 +05:30
Shivam Mishra
c40d832e5e Merge pull request #17934 from Anurag810/billing_summary_fixes_v11
fix: column sequence and width
2019-06-13 17:27:12 +05:30
rohitwaghchaure
23f901c29a Merge pull request #17931 from rohitwaghchaure/fixed_pos_not_overriding_the_taxes
fix: taxes are not overriding after changing the tax template for the POS invoice
2019-06-13 16:25:56 +05:30
Shivam Mishra
c06d1ec73d Merge pull request #17926 from Mangesh-Khairnar/get-bom-items-fix
fix: Check fields before making BOM items
2019-06-13 16:17:58 +05:30
Anurag Mishra
2fc6d1d210 fix: column sequence and width 2019-06-13 16:09:30 +05:30
Rohit Waghchaure
49c6c909f8 fix: taxes are not overriding after changing the taxes template 2019-06-13 15:42:13 +05:30
Nabin Hait
ffd6b27f4b fix: Fixed setters for getting items from quotation/opportunity 2019-06-13 14:33:47 +05:30
Mangesh-Khairnar
860b6bac75 fix: get bom item when company is not passed 2019-06-13 14:28:46 +05:30
Rohan
9c3729b4ba Merge branch 'hotfix' into hotfix-item-code-gen 2019-06-13 14:23:36 +05:30
Rohan Bansal
1174e5a127 fix(stock): Remove hardcoded validation for Item 2019-06-12 17:56:17 +05:30
sahil28297
fe802a97a2 Merge branch 'hotfix' into serial_no_batch_selector 2019-06-12 13:11:32 +05:30
Sahil Khan
60f1750c96 Merge branch 'hotfix' 2019-06-11 17:03:41 +05:30
Sahil Khan
6a198acd2f bumped to version 11.1.38 2019-06-11 17:23:41 +05:50
rohitwaghchaure
40968c78a8 Merge pull request #17901 from rohitwaghchaure/general_leder_report_for_group_by_voucher_consolidated
fix: group by voucher condition for the general ledger report
2019-06-11 16:17:34 +05:30
Rohit Waghchaure
e03892b130 fix: group by voucher condition for the general ledger report 2019-06-11 14:17:06 +05:30
rohitwaghchaure
844bbcdb1d Merge pull request #17898 from rohitwaghchaure/general_ledger_group_by_voucher_consolidated_issue
fix: debit and credit showing in the same row if the group by is set as group by voucher (consolidated)
2019-06-11 11:39:33 +05:30
Nabin Hait
d77cd79262 Merge branch 'hotfix' 2019-06-10 19:16:11 +05:30
Nabin Hait
6e97f7fbd8 bumped to version 11.1.37 2019-06-10 19:36:10 +05:50
Rohit Waghchaure
de04941ddb fix: debit and credit showing in the same row if the group by is set as group by voucher (consolidated) 2019-06-10 18:31:41 +05:30
deepeshgarg007
2de80fdc3e fix: Codacy 2019-06-10 17:51:47 +05:30
Deepesh Garg
832884a7ea fix: Total Amount fix in journal entry (#17879) 2019-06-10 17:43:08 +05:30
sahil28297
4bc86c7e9d fix(patch): escape illegal characters to avoid SQL syntax error (#17889) 2019-06-10 17:38:42 +05:30
rohitwaghchaure
cd2938e2d0 fix: accounts receivable for PDC not showing 120 days column (#17892) 2019-06-10 17:38:17 +05:30
deepeshgarg007
1d11ddc235 fix: Available qty not shown in item batch selector for batch 2019-06-10 17:33:36 +05:30
rohitwaghchaure
f37a09d9fe Merge pull request #17618 from rohitwaghchaure/user_cogs_only_for_material_issue
feat: set COGS for material issue only
2019-06-10 16:56:34 +05:30
Rohit Waghchaure
978bc1352e stock_entry: set COGS for material issue only 2019-06-07 13:34:59 +05:30
rohitwaghchaure
ab669ad055 Merge pull request #17875 from rohitwaghchaure/salary_slip_update_component_row_error
fix: Not able to save salary slip
2019-06-07 12:58:07 +05:30
Deepesh Garg
443f9ed5f1 Merge pull request #17873 from sagarvora/ewb_fix
fix(regional): remove "Generate" from button text as button now under "Make" heading
2019-06-07 12:43:23 +05:30
Rohit Waghchaure
d72f4d7959 fix: Not able to save salary slip 2019-06-07 11:44:51 +05:30
Sagar Vora
4c23c2ddec fix (regional): remove "Generate" from button text as button now under "Make" heading 2019-06-07 10:37:26 +05:30
Prasann Shah
e0333c0756 [Add] GSTIN filter in HSN summary report (#17836)
* [Add] GSTIN filter in HSN summary report

* [Add] Same filter in GST Itemised Sales Register
2019-06-06 11:22:06 +05:30
Saurabh
066ae71581 Merge pull request #17863 from adityahase/fix-error-report-email-hotfix
fix(error-report): Do not send error reports to support@erpnext.com
2019-06-06 10:36:12 +05:30
Aditya Hase
2898c94f08 fix(error-report): Do not send error reports to support@erpnext.com 2019-06-05 23:31:13 +05:30
Nabin Hait
fc0df994b8 fix: Removed unwanted total row from financial statement and general ledger print (#17859) 2019-06-05 20:29:15 +05:30
Deepesh Garg
c5a4e423c6 fix: NoneType fixes in Lab test (#17856) 2019-06-05 20:23:41 +05:30
Sahil Khan
949f170b48 Merge branch 'hotfix' 2019-06-05 15:15:01 +05:30
Sahil Khan
576e68eef0 bumped to version 11.1.36 2019-06-05 15:35:01 +05:50
Deepesh Garg
63af463a9a fix: Patch for renaming enquiry_from to opportunity_from (#17785)
* fix: Patch for renaming enquiry_from to opportunity_from

* fix: Patch fix

* fix: patch fix

* fix: Use has_column instead of exists

* fix: Handled ifnull
2019-06-05 14:22:59 +05:30
Rohan
b20eda9996 fix(projects): Remove hardcode of expected end date for new Tasks (#17716) 2019-06-05 14:16:57 +05:30
Nabin Hait
88832daae4 feat: Rounding based on settings on salary component (#17851) 2019-06-05 13:20:18 +05:30
rohitwaghchaure
3aa2df29f5 Merge pull request #17850 from deepeshgarg007/italy-xml
fix: Update currency in Italy e-invoice XML
2019-06-05 11:42:37 +05:30
deepeshgarg007
42d0ee7431 fix: Update Italy e-invoice XML 2019-06-05 11:12:32 +05:30
rohitwaghchaure
15e128f321 Merge pull request #17838 from rohitwaghchaure/fix_payment_period_based_on_invoice_date_error
fix: report Payment Period Based On Invoice Date not working
2019-06-03 20:12:01 +05:30
Rohit Waghchaure
56757866f3 fix: report Payment Period Based On Invoice Date not working 2019-06-03 18:20:46 +05:30
Nabin Hait
c3f3c156b1 Merge pull request #17834 from deepeshgarg007/serial-no-fix
fix: Serial no filtering issue for delivered items
2019-06-03 14:25:17 +05:30
Nabin Hait
62e8955b39 Merge pull request #17806 from nabinhait/discount-rounding-adjustment
fix: Rounding adjustment while additional discount amount is applied on grand total
2019-06-03 13:08:57 +05:30
deepeshgarg007
fad3789f64 fix: Pass delivery document no as empty string 2019-06-03 13:04:57 +05:30
deepeshgarg007
a0b85d060b fix: Serial no filtering issue for delivered items 2019-06-03 11:57:00 +05:30
Saurabh
fd5d3f551b Merge pull request #17808 from Alchez/hotfix-sales-analytics-total
fix(selling): Remove Totals row for Sales Analytics
2019-05-31 14:28:10 +05:30
Saurabh
019014070d Merge pull request #17810 from nabinhait/pr-expense-account
fix: Added Expense Account field to push value from PO-PR-PI
2019-05-31 14:18:33 +05:30
Saurabh
97f5dff656 Merge pull request #17812 from rohitwaghchaure/allow_import_for_packing_slip
fix: allow import for packing slip
2019-05-31 14:15:16 +05:30
Deepesh Garg
0d28802485 Merge pull request #17815 from deepeshgarg007/ar_translation
fix: Add translations for missing labels in AR report
2019-05-31 12:37:18 +05:30
Saurabh
254774f7a3 Merge pull request #17817 from rohitwaghchaure/fixed_pos_cash_payment_modal
fix: POS cash mode of payment css
2019-05-31 12:28:53 +05:30
Rohit Waghchaure
6f1e624465 fix: POS cash mode of payment css 2019-05-30 23:19:55 +05:30
deepeshgarg007
2dcd03d17d fix: Label translations 2019-05-30 22:33:02 +05:30
deepeshgarg007
ffcb7aa6ed fix: Add translations for missing labels in AR report 2019-05-30 22:26:52 +05:30
Rohit Waghchaure
9350b5a533 fix: allow import for packing slip 2019-05-30 21:52:13 +05:30
Nabin Hait
8cb2c7a89c fix: Set query for expense account in PO and PR 2019-05-30 18:13:11 +05:30
Nabin Hait
50bdaa6d1a fix: Added Expense Account field to push value from PO-PR-PI 2019-05-30 18:08:22 +05:30
Rohan Bansal
20a4cf1290 fix(selling): Remove Totals row for tree-based Sales Analytics 2019-05-30 17:24:19 +05:30
Suraj Shetty
fc092d0df4 Merge pull request #17807 from deepeshgarg007/gstr-1-condition-fix
fix: GSTR-1 report B2B condition fix
2019-05-30 17:24:04 +05:30
Rushabh Mehta
51bb2909c3 Merge pull request #17790 from deepeshgarg007/customer_lead_dashboard
fix: Customer and Lead dashboard fixes for opportunity and quotation
2019-05-30 17:21:25 +05:30
Suraj Shetty
cab0cd55b3 Merge branch 'hotfix' into gstr-1-condition-fix 2019-05-30 16:38:45 +05:30
deepeshgarg007
4f579639c6 fix: Use AND instead of OR 2019-05-30 16:26:38 +05:30
Nabin Hait
c5b68ef386 fix: Rounding adjustment while additional discount amount is aplied on grand total 2019-05-30 16:05:03 +05:30
deepeshgarg007
95dc4e4dc5 fix: Use make methods to override 2019-05-30 15:28:15 +05:30
Sahil Khan
dc35138356 Merge branch 'hotfix' 2019-05-30 12:09:35 +05:30
Sahil Khan
08617f7700 bumped to version 11.1.35 2019-05-30 12:29:35 +05:50
Anurag Mishra
cfecf3c5b1 fix: Added description if item variants does not have description in map (#17795)
* fix: variant item description based on attribute

* fix: requested changes

* fix: refactor
2019-05-29 17:16:48 +05:30
Shivam Mishra
831100b657 Merge pull request #17792 from adityahase/remove-manifest-hotfix
perf: Remove MANIFEST.in
2019-05-29 15:31:26 +05:30
Aditya Hase
f296a2f58a 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:05 +05:30
deepeshgarg007
18a0120fc1 fix: Customer and Lead dashboard fixes for opportunity and quotation 2019-05-29 14:20:24 +05:30
Nabin Hait
aae557e8a1 Merge pull request #17779 from sunnyakaxd/patch-1
fix (performance): Dont fetch all orders to update a few
2019-05-29 10:04:37 +05:30
Nabin Hait
0f92c4b85b Merge pull request #17778 from deepeshgarg007/lead_owner
fix: Lead owner efficiency report query and column fixes
2019-05-29 09:57:08 +05:30
deepeshgarg007
217df1761d fix: Styling fixes 2019-05-29 08:10:07 +05:30
Himanshu Mishra
d355741462 Python 2 compatibility -_- 2019-05-28 23:54:03 +05:30
Himanshu Mishra
7b6ed4f16e Update status_updater.py 2019-05-28 23:51:22 +05:30
deepeshgarg007
c5a682e9d9 fix: Lead owner efficiency report query and column fixes 2019-05-28 23:40:05 +05:30
Sahil Khan
b4fa105555 Merge branch 'hotfix' 2019-05-28 14:50:05 +05:30
Sahil Khan
e1aef6f0db bumped to version 11.1.34 2019-05-28 15:10:05 +05:50
Nabin Hait
6f35d2b52d Merge pull request #17764 from nabinhait/salary-slip-tax-calc
fix: Tax calculation on salary slip
2019-05-28 11:16:40 +05:30
rohitwaghchaure
197f57c050 Merge pull request #17766 from rohitwaghchaure/renamed_delayed_item_report
fix: rename delayed order item report
2019-05-27 19:33:41 +05:30
Rohit Waghchaure
c74fa7546b fix: rename delayed order item report 2019-05-27 19:32:43 +05:30
Raffael Meyer
0261472ecd add default filters 2019-05-27 16:01:05 +02:00
Nabin Hait
233ef8752d Merge pull request #17550 from dimanex/bugfix/17547-Pricing-Rules-are-broken
Pricing Rules are not queried correctly after removing 'customer' and adding 'party_name' in Quotation #17547
2019-05-27 19:24:24 +05:30
Nabin Hait
afd9e7546f Merge branch 'hotfix' into bugfix/17547-Pricing-Rules-are-broken 2019-05-27 19:22:34 +05:30
Nabin Hait
8b1532d691 Merge pull request #17758 from saurabh6790/custom_field_fix_hotfix
fix: add shopify_supplier_id custom field while setting up shopify
2019-05-27 19:12:16 +05:30
Nabin Hait
a887c29e06 Merge pull request #17760 from nabinhait/multi-fixes99
fix: Error due to merging of lead/customer to party_name
2019-05-27 19:11:01 +05:30
Nabin Hait
7114b72be8 fix: Tax calculation on salary slip 2019-05-27 18:42:20 +05:30
Raffael Meyer
1c1a5958bc more pleasant icon color 2019-05-27 15:05:32 +02:00
Raffael Meyer
b7b5bcbd85 fix: em dash cannot be encoded in latin-1 2019-05-27 15:05:08 +02:00
Raffael Meyer
9638f0ef2b Add columns to CSV, add comments and docstrings 2019-05-27 14:42:52 +02:00
Nabin Hait
92ab345daf Merge pull request #17018 from chdecultot/fec_improvement
fix: Addition of third party types in FEC
2019-05-27 17:18:42 +05:30
Nabin Hait
79dd4d707b fix: Error fixed due to merging of lead/customer to party_name 2019-05-27 15:44:12 +05:30
Nabin Hait
a3a733fa91 fix: error because of non-mandatory fields 2019-05-27 15:43:26 +05:30
Nabin Hait
7a9b014f72 fix: Made item code non-mandatory in item 2019-05-27 15:41:06 +05:30
Saurabh
61b4a98356 fix: add shopify_supplier_id custom field while setting up shopify 2019-05-27 15:25:47 +05:30
Don-Leopardo
46db69b304 fix: Make from Lead to Opportunity (#17727)
* fix: lead to oportunity error

* fix: one more missmatched field
2019-05-27 14:22:52 +05:30
Joe Paul
a0be41322d fix(subscription): Remove property decorator (#17395) 2019-05-27 14:11:52 +05:30
Nabin Hait
39d30718e2 Merge branch 'hotfix' into copy_payment_schedule_from_quot_to_SO 2019-05-27 14:10:07 +05:30
Saif
05f29988f4 fix: Status updater for Credit/Debit Note Issued (#16998)
* fix: Status updater for Credit/Debit Note Issued higher precendence than Return

* style: linting
2019-05-27 14:05:14 +05:30
Deepesh Garg
d7903de51c fix: Do not fetch batch items and serialized items in stock reconciliation (#17726) 2019-05-27 13:41:58 +05:30
Kenneth Sequeira
0e31cc9ff8 improve error message (#17745)
Change ```Allocated amount can not greater than unadjusted amount```  to ```Allocated amount cannot be greater than unadjusted amount```

```Allocated amount can not be negative``` to ```Allocated amount cannot be negative```
2019-05-27 13:40:40 +05:30
rohitwaghchaure
32280a11aa fix: customer item code not fetched on selection of the item in the sales order (#17755) 2019-05-27 13:32:44 +05:30
Anurag Mishra
a2f9d2f89c fix: holidays was showing on same date in calendar view (#17753) 2019-05-27 13:20:06 +05:30
Nabin Hait
5fc5355b96 fix: Opening accounting entry for stock entry (#17710)
* fix: Opening accounting entry for stock entry

* test: Add test case for opening stock entry gle

* fix: validate expense account for opening stock entry

* fix: validate expense account for opening stock reco
2019-05-27 11:50:08 +05:30
Deepesh Garg
30c73e6b35 fix: Only show registered customers for GSTR-1 B2B Report (#17719) 2019-05-27 11:48:40 +05:30
Nabin Hait
7a6b88c791 fix: payment reconciliation against expense claim (#17728)
* feat: Added dashboard in expense claim

* fix: payment reconciliation against expense claim
2019-05-27 11:41:05 +05:30
rohitwaghchaure
9c42124fbc Merge pull request #17720 from rohitwaghchaure/reverting_method_to_show_stock_value
fix: warehouse tree view taking lot of time to load
2019-05-23 16:36:34 +05:30
Rohit Waghchaure
0378b15412 fix: warehouse tree view taking lot of time to load 2019-05-23 16:34:32 +05:30
rohitwaghchaure
3f86369604 fix: range 4 for ageing filter added in the AP/AR report (#17714) 2019-05-23 15:27:17 +05:30
rohitwaghchaure
cc99d92116 Merge pull request #17705 from rohitwaghchaure/not_able_to_submit_sales_invoice
fix: not able to submit sales invoice
2019-05-22 22:31:37 +05:30
Rohit Waghchaure
f880975438 fix: not able to submit sales invoice for italy 2019-05-22 22:30:26 +05:30
Saurabh
daa8db4d95 Merge branch 'hotfix' 2019-05-22 22:24:17 +05:30
Saurabh
9ff39e2d1b bumped to version 11.1.33 2019-05-22 22:54:17 +06:00
Saurabh
9d70c5d13f Merge pull request #17704 from rohitwaghchaure/typo_pos_not_working
fix: typo
2019-05-22 22:21:51 +05:30
Rohit Waghchaure
a9a82919e7 fix: typo 2019-05-22 22:15:01 +05:30
Raffael Meyer
31f5055287 fix sql for multi-company case 2019-05-22 00:03:16 +02:00
Raffael Meyer
ce9239af83 fix error when downloading empty report 2019-05-21 22:49:59 +02:00
Raffael Meyer
50de88417c fix filename 2019-05-21 21:59:04 +02:00
Raffael Meyer
2701f94491 add remarks and voucher info 2019-05-21 21:58:35 +02:00
Raffael Meyer
13c9d041d9 Merge branch 'hotfix' of https://github.com/frappe/erpnext into datev_report 2019-05-21 00:33:45 +02:00
Rohan
7178218821 Merge branch 'hotfix' into hotfix-shipping-override 2019-05-12 22:28:45 +05:30
Raffael Meyer
9eef60754d remove unused import 2019-05-12 02:24:39 +02:00
Mohammad Noureldin
8908d4ee8f 17547:
- Filling in 'customer' arg field if not already set and if 'party_name' is available
- This will fix the logic during which Pricing Rule is constructing the SQL query to list all Pricing Rules related to an item
- The reason to put it in accounts_controller is:
-# This is the palce when args are made before making call which will end using Pricing Rule logic, which means we don't have to go all over the place to add the proper arg field
-# IMHO, it is clean enough in contrast to the case where that code is added to pricing_rule.py for example, cause doing this exposes Pricing Rule to the knowledge about a field called 'party_name' while a Pricing Rule document doesn't have any
2019-05-09 18:21:32 +02:00
Raffael Meyer
3799aabc46 Merge branch 'hotfix' of https://github.com/frappe/erpnext into datev_report 2019-05-09 04:04:33 +02:00
Raffael Meyer
4b2901704c Add download button 2019-05-09 04:03:23 +02:00
Raffael Meyer
e5f7af9e9f Use pandas, more columns, filter by date 2019-05-09 03:54:49 +02:00
Anurag Mishra
6fc136fcb8 Merge branch 'hotfix' into copy_payment_schedule_from_quot_to_SO 2019-05-08 23:07:31 +05:30
Saurabh
f94951a51b Merge branch 'hotfix' into copy_payment_schedule_from_quot_to_SO 2019-05-03 16:48:14 +05:30
Nabin Hait
9ef79d6c6b Merge branch 'hotfix' into copy_payment_schedule_from_quot_to_SO 2019-05-02 01:00:04 +05:30
ashish-greycube
e82ab87f1c fix: copy_payment_schedule_from_quot_to_SO 2019-04-26 12:12:53 +05:30
Raffael Meyer
9c923ae418 feat(regional): Report for german tax consultants (DATEV) 2019-04-25 01:09:56 +02:00
Nabin Hait
8fd90410f1 Merge branch 'hotfix' into hotfix-shipping-override 2019-04-11 11:46:56 +05:30
Nabin Hait
f62e789173 Merge branch 'hotfix' into fec_improvement 2019-04-11 11:46:43 +05:30
Charles-Henri Decultot
91578757ff Addition of third party types in FEC 2019-03-26 08:57:36 +00:00
Rohan Bansal
eac87b4764 fix(transaction): Avoid shipping rule charge override by tax template 2019-03-11 15:02:39 +05:30
149 changed files with 8371 additions and 6953 deletions

View File

@@ -3,6 +3,11 @@ dist: trusty
python:
- "2.7"
- "3.6"
env:
- TEST_TYPE="Server Side Test"
- TEST_TYPE="Patch Test"
services:
- mysql
@@ -39,18 +44,8 @@ before_script:
- bench start &
- sleep 10
jobs:
include:
- stage: test
script:
- set -e
- bench run-tests --app erpnext --coverage
after_script:
- coveralls -b apps/erpnext -d ../../sites/.coverage
env: Server Side Test
- # stage
script:
- wget http://build.erpnext.com/20171108_190013_955977f8_database.sql.gz
- bench --force restore ~/frappe-bench/20171108_190013_955977f8_database.sql.gz --mariadb-root-password travis
- bench migrate
env: Patch Testing
script:
- bash $TRAVIS_BUILD_DIR/travis/run-tests.sh
after_script:
- coveralls -b apps/erpnext -d ../../sites/.coverage

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

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

View File

@@ -43,8 +43,13 @@ frappe.ui.form.on('Bank Guarantee', {
reference_docname: function(frm) {
if (frm.doc.reference_docname && frm.doc.reference_doctype) {
let fields_to_fetch = ["project", "grand_total"];
let fields_to_fetch = ["grand_total"];
let party_field = frm.doc.reference_doctype == "Sales Order" ? "customer" : "supplier";
if (frm.doc.reference_doctype == "Sales Order") {
fields_to_fetch.push("project");
}
fields_to_fetch.push(party_field);
frappe.call({
method: "erpnext.accounts.doctype.bank_guarantee.bank_guarantee.get_vouchar_detials",

View File

@@ -425,8 +425,9 @@ class JournalEntry(AccountsController):
pay_to_recd_from = frappe.db.get_value(d.party_type, d.party,
"customer_name" if d.party_type=="Customer" else "supplier_name")
party_amount += (d.debit_in_account_currency or d.credit_in_account_currency)
party_account_currency = d.account_currency
if pay_to_recd_from and pay_to_recd_from == d.party:
party_amount += (d.debit_in_account_currency or d.credit_in_account_currency)
party_account_currency = d.account_currency
elif frappe.db.get_value("Account", d.account, "account_type") in ["Bank", "Cash"]:
bank_amount += (d.debit_in_account_currency or d.credit_in_account_currency)

View File

@@ -350,7 +350,7 @@ def filter_pricing_rules(args, pricing_rules):
if len(pricing_rules) > 1:
rate_or_discount = list(set([d.rate_or_discount for d in pricing_rules]))
if len(rate_or_discount) == 1 and rate_or_discount[0] == "Discount Percentage":
pricing_rules = filter(lambda x: x.for_price_list==args.price_list, pricing_rules) \
pricing_rules = list(filter(lambda x: x.for_price_list==args.price_list, pricing_rules)) \
or pricing_rules
if len(pricing_rules) > 1 and not args.for_shopping_cart:
@@ -373,7 +373,7 @@ def apply_internal_priority(pricing_rules, field_set, args):
filtered_rules = []
for field in field_set:
if args.get(field):
filtered_rules = filter(lambda x: x[field]==args[field], pricing_rules)
filtered_rules = list(filter(lambda x: x[field]==args[field], pricing_rules))
if filtered_rules: break
return filtered_rules or pricing_rules

View File

@@ -18,9 +18,6 @@ class TestPricingRule(unittest.TestCase):
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
test_record = {
"doctype": "Pricing Rule",
"title": "_Test Pricing Rule",
@@ -94,9 +91,6 @@ class TestPricingRule(unittest.TestCase):
self.assertEquals(details.get("discount_percentage"), 15)
def test_pricing_rule_for_margin(self):
from erpnext.stock.get_item_details import get_item_details
from frappe import MandatoryError
test_record = {
"doctype": "Pricing Rule",
"title": "_Test Pricing Rule",
@@ -139,9 +133,6 @@ class TestPricingRule(unittest.TestCase):
self.assertEquals(details.get("margin_rate_or_amount"), 10)
def test_pricing_rule_for_variants(self):
from erpnext.stock.get_item_details import get_item_details
from frappe import MandatoryError
if not frappe.db.exists("Item", "Test Variant PRT"):
frappe.get_doc({
"doctype": "Item",

View File

@@ -6,8 +6,8 @@ frappe.listview_settings['Purchase Invoice'] = {
add_fields: ["supplier", "supplier_name", "base_grand_total", "outstanding_amount", "due_date", "company",
"currency", "is_return", "release_date", "on_hold"],
get_indicator: function(doc) {
if(cint(doc.is_return)==1) {
return [__("Return"), "darkgrey", "is_return,=,Yes"];
if(flt(doc.outstanding_amount) < 0 && doc.docstatus == 1) {
return [__("Debit Note Issued"), "darkgrey", "outstanding_amount,<,0"]
} else if(flt(doc.outstanding_amount) > 0 && doc.docstatus==1) {
if(cint(doc.on_hold) && !doc.release_date) {
return [__("On Hold"), "darkgrey"];
@@ -18,9 +18,9 @@ frappe.listview_settings['Purchase Invoice'] = {
} else {
return [__("Unpaid"), "orange", "outstanding_amount,>,0|due,>=,Today"];
}
} else if(flt(doc.outstanding_amount) < 0 && doc.docstatus == 1) {
return [__("Debit Note Issued"), "darkgrey", "outstanding_amount,<,0"]
}else if(flt(doc.outstanding_amount)==0 && doc.docstatus==1) {
} else if(cint(doc.is_return)) {
return [__("Return"), "darkgrey", "is_return,=,Yes"];
} else if(flt(doc.outstanding_amount)==0 && doc.docstatus==1) {
return [__("Paid"), "green", "outstanding_amount,=,0"];
}
}

View File

@@ -21,7 +21,7 @@ frappe.ui.form.on("Sales Invoice", {
if(frm.doc.docstatus == 1 && !frm.is_dirty()
&& !frm.doc.is_return && !frm.doc.ewaybill) {
frm.add_custom_button('Generate e-Way Bill JSON', () => {
frm.add_custom_button('e-Way Bill JSON', () => {
var w = window.open(
frappe.urllib.get_full_url(
"/api/method/erpnext.regional.india.utils.generate_ewb_json?"

View File

@@ -371,6 +371,10 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
me.frm.pos_print_format = r.message.print_format;
}
me.frm.script_manager.trigger("update_stock");
if(me.frm.doc.taxes_and_charges) {
me.frm.script_manager.trigger("taxes_and_charges");
}
frappe.model.set_default_values(me.frm.doc);
me.set_dynamic_labels();
me.calculate_taxes_and_totals();

View File

@@ -54,8 +54,8 @@ class SalesInvoice(SellingController):
def set_indicator(self):
"""Set indicator for portal"""
if cint(self.is_return) == 1:
self.indicator_title = _("Return")
if self.outstanding_amount < 0:
self.indicator_title = _("Credit Note Issued")
self.indicator_color = "darkgrey"
elif self.outstanding_amount > 0 and getdate(self.due_date) >= getdate(nowdate()):
self.indicator_color = "orange"
@@ -63,8 +63,8 @@ class SalesInvoice(SellingController):
elif self.outstanding_amount > 0 and getdate(self.due_date) < getdate(nowdate()):
self.indicator_color = "red"
self.indicator_title = _("Overdue")
elif self.outstanding_amount < 0:
self.indicator_title = _("Credit Note Issued")
elif cint(self.is_return) == 1:
self.indicator_title = _("Return")
self.indicator_color = "darkgrey"
else:
self.indicator_color = "green"
@@ -487,7 +487,7 @@ class SalesInvoice(SellingController):
"""Set against account for debit to account"""
against_acc = []
for d in self.get('items'):
if d.income_account not in against_acc:
if d.income_account and d.income_account not in against_acc:
against_acc.append(d.income_account)
self.against_income_account = ','.join(against_acc)

View File

@@ -6,16 +6,16 @@ frappe.listview_settings['Sales Invoice'] = {
add_fields: ["customer", "customer_name", "base_grand_total", "outstanding_amount", "due_date", "company",
"currency", "is_return"],
get_indicator: function(doc) {
if(cint(doc.is_return)==1) {
return [__("Return"), "darkgrey", "is_return,=,Yes"];
} else if(flt(doc.outstanding_amount)==0) {
return [__("Paid"), "green", "outstanding_amount,=,0"]
} else if(flt(doc.outstanding_amount) < 0) {
if(flt(doc.outstanding_amount) < 0) {
return [__("Credit Note Issued"), "darkgrey", "outstanding_amount,<,0"]
}else if (flt(doc.outstanding_amount) > 0 && doc.due_date >= frappe.datetime.get_today()) {
} else if (flt(doc.outstanding_amount) > 0 && doc.due_date >= frappe.datetime.get_today()) {
return [__("Unpaid"), "orange", "outstanding_amount,>,0|due_date,>,Today"]
} else if (flt(doc.outstanding_amount) > 0 && doc.due_date < frappe.datetime.get_today()) {
return [__("Overdue"), "red", "outstanding_amount,>,0|due_date,<=,Today"]
} else if(cint(doc.is_return)) {
return [__("Return"), "darkgrey", "is_return,=,Yes"];
} else if(flt(doc.outstanding_amount)==0) {
return [__("Paid"), "green", "outstanding_amount,=,0"]
}
},
right_column: "grand_total"

View File

@@ -314,13 +314,11 @@ class Subscription(Document):
self.save()
@property
def is_postpaid_to_invoice(self):
return getdate(nowdate()) > getdate(self.current_invoice_end) or \
(getdate(nowdate()) >= getdate(self.current_invoice_end) and getdate(self.current_invoice_end) == getdate(self.current_invoice_start)) and \
not self.has_outstanding_invoice()
@property
def is_prepaid_to_invoice(self):
if not self.generate_invoice_at_period_start:
return False
@@ -340,7 +338,7 @@ class Subscription(Document):
2. Change the `Subscription` status to 'Past Due Date'
3. Change the `Subscription` status to 'Cancelled'
"""
if self.is_postpaid_to_invoice or self.is_prepaid_to_invoice:
if self.is_postpaid_to_invoice() or self.is_prepaid_to_invoice():
self.generate_invoice()
if self.current_invoice_is_past_due():
self.status = 'Past Due Date'

View File

@@ -22,7 +22,7 @@ class TestTaxWithholdingCategory(unittest.TestCase):
invoices = []
# create invoices for lower than single threshold tax rate
for _ in xrange(2):
for _ in range(2):
pi = create_purchase_invoice(supplier = "Test TDS Supplier")
pi.submit()
invoices.append(pi)

View File

@@ -44,6 +44,13 @@ frappe.query_reports["Accounts Payable"] = {
"default": "90",
"reqd": 1
},
{
"fieldname":"range4",
"label": __("Ageing Range 4"),
"fieldtype": "Int",
"default": "120",
"reqd": 1
},
{
"fieldname":"finance_book",
"label": __("Finance Book"),

View File

@@ -44,6 +44,13 @@ frappe.query_reports["Accounts Payable Summary"] = {
"default": "90",
"reqd": 1
},
{
"fieldname":"range4",
"label": __("Ageing Range 4"),
"fieldtype": "Int",
"default": "120",
"reqd": 1
},
{
"fieldname":"finance_book",
"label": __("Finance Book"),

View File

@@ -46,6 +46,8 @@
var range2 = report.columns[12].label;
var range3 = report.columns[13].label;
var range4 = report.columns[14].label;
var range5 = report.columns[15].label;
var range6 = report.columns[16].label;
%}
{% if(balance_row) { %}
<table class="table table-bordered table-condensed">
@@ -56,8 +58,10 @@
<col style="width: 18mm;">
<col style="width: 18mm;">
<col style="width: 18mm;">
<col style="width: 18mm;">
<col style="width: 18mm;">
<col style="width: 18mm;">
<col style="width: 18mm;">
<col style="width: 18mm;">
<col style="width: 18mm;">
</colgroup>
<thead>
@@ -67,16 +71,20 @@
<th>{%= __(range2) %}</th>
<th>{%= __(range3) %}</th>
<th>{%= __(range4) %}</th>
<th>{%= __(range5) %}</th>
<th>{%= __(range6) %}</th>
<th>{%= __("Total") %}</th>
</tr>
</thead>
<tbody>
<tr>
<td>{%= __("Total Outstanding") %}</td>
<td class="text-right">{%= format_currency(balance_row[range1]) %}</td>
<td class="text-right">{%= format_number(balance_row[range1], null, 2) %}</td>
<td class="text-right">{%= format_currency(balance_row[range2]) %}</td>
<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(balance_row[range5]) %}</td>
<td class="text-right">{%= format_currency(balance_row[range6]) %}</td>
<td class="text-right">
{%= format_currency(flt(balance_row[("outstanding_amount")]), data[data.length-1]["currency"]) %}
</td>
@@ -86,6 +94,8 @@
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td class="text-right">
{%= format_currency(flt(balance_row[("pdc/lc_amount")]), data[data.length-1]["currency"]) %}
</td>
@@ -95,6 +105,8 @@
<th></th>
<th></th>
<th></th>
<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>
</tr>

View File

@@ -44,6 +44,13 @@ frappe.query_reports["Accounts Receivable"] = {
"default": "90",
"reqd": 1
},
{
"fieldname":"range4",
"label": __("Ageing Range 4"),
"fieldtype": "Int",
"default": "120",
"reqd": 1
},
{
"fieldname":"finance_book",
"label": __("Finance Book"),

View File

@@ -68,13 +68,13 @@ class ReceivablePayableReport(object):
if self.filters.based_on_payment_terms:
columns.append({
"label": "Payment Term",
"label": _("Payment Term"),
"fieldname": "payment_term",
"fieldtype": "Data",
"width": 120
})
columns.append({
"label": "Invoice Grand Total",
"label": _("Invoice Grand Total"),
"fieldname": "invoice_grand_total",
"fieldtype": "Currency",
"options": "currency",
@@ -83,7 +83,7 @@ class ReceivablePayableReport(object):
for label in ("Invoiced Amount", "Paid Amount", credit_or_debit_note, "Outstanding Amount"):
columns.append({
"label": label,
"label": _(label),
"fieldname": frappe.scrub(label),
"fieldtype": "Currency",
"options": "currency",
@@ -100,11 +100,14 @@ class ReceivablePayableReport(object):
self.filters["range2"] = "60"
if not "range3" in self.filters:
self.filters["range3"] = "90"
if not "range4" in self.filters:
self.filters["range4"] = "120"
for label in ("0-{range1}".format(range1=self.filters["range1"]),
"{range1}-{range2}".format(range1=cint(self.filters["range1"])+ 1, range2=self.filters["range2"]),
"{range2}-{range3}".format(range2=cint(self.filters["range2"])+ 1, range3=self.filters["range3"]),
"{range3}-{above}".format(range3=cint(self.filters["range3"])+ 1, above=_("Above"))):
"{range3}-{range4}".format(range3=cint(self.filters["range3"])+ 1, range4=self.filters["range4"]),
"{range4}-{above}".format(range4=cint(self.filters["range4"])+ 1, above=_("Above"))):
columns.append({
"label": label,
"fieldname":label,
@@ -328,18 +331,17 @@ class ReceivablePayableReport(object):
entry_date = gle.posting_date
row += get_ageing_data(cint(self.filters.range1), cint(self.filters.range2),
cint(self.filters.range3), self.age_as_on, entry_date, outstanding_amount)
cint(self.filters.range3), cint(self.filters.range4), self.age_as_on, entry_date, outstanding_amount)
# issue 6371-Ageing buckets should not have amounts if due date is not reached
if self.filters.ageing_based_on == "Due Date" \
and getdate(due_date) > getdate(self.filters.report_date):
row[-1]=row[-2]=row[-3]=row[-4]=0
row[-1]=row[-2]=row[-3]=row[-4]=row[-5]=0
if self.filters.ageing_based_on == "Supplier Invoice Date" \
and getdate(bill_date) > getdate(self.filters.report_date):
row[-1]=row[-2]=row[-3]=row[-4]=0
row[-1]=row[-2]=row[-3]=row[-4]=row[-5]=0
if self.filters.get(scrub(args.get("party_type"))):
row.append(gle.account_currency)
@@ -585,13 +587,13 @@ class ReceivablePayableReport(object):
return payment_term_map
def get_chart_data(self, columns, data):
ageing_columns = columns[self.ageing_col_idx_start : self.ageing_col_idx_start+4]
ageing_columns = columns[self.ageing_col_idx_start : self.ageing_col_idx_start+5]
rows = []
for d in data:
rows.append(
{
'values': d[self.ageing_col_idx_start : self.ageing_col_idx_start+4]
'values': d[self.ageing_col_idx_start : self.ageing_col_idx_start+5]
}
)
@@ -610,21 +612,22 @@ def execute(filters=None):
}
return ReceivablePayableReport(filters).run(args)
def get_ageing_data(first_range, second_range, third_range, age_as_on, entry_date, outstanding_amount):
# [0-30, 30-60, 60-90, 90-above]
outstanding_range = [0.0, 0.0, 0.0, 0.0]
def get_ageing_data(first_range, second_range, third_range,
fourth_range, age_as_on, entry_date, outstanding_amount):
# [0-30, 30-60, 60-90, 90-120, 120-above]
outstanding_range = [0.0, 0.0, 0.0, 0.0, 0.0]
if not (age_as_on and entry_date):
return [0] + outstanding_range
age = (getdate(age_as_on) - getdate(entry_date)).days or 0
index = None
for i, days in enumerate([first_range, second_range, third_range]):
for i, days in enumerate([first_range, second_range, third_range, fourth_range]):
if age <= days:
index = i
break
if index is None: index = 3
if index is None: index = 4
outstanding_range[index] = outstanding_amount
return [age] + outstanding_range

View File

@@ -44,6 +44,13 @@ frappe.query_reports["Accounts Receivable Summary"] = {
"default": "90",
"reqd": 1
},
{
"fieldname":"range4",
"label": __("Ageing Range 4"),
"fieldtype": "Int",
"default": "120",
"reqd": 1
},
{
"fieldname":"finance_book",
"label": __("Finance Book"),

View File

@@ -82,8 +82,15 @@ class AccountsReceivableSummary(ReceivablePayableReport):
"width": 160
},
{
"label": _(str(self.filters.range3) + _("-Above")),
"fieldname": scrub(str(self.filters.range3) + _("-Above")),
"label": _(str(self.filters.range3) + "-" + str(self.filters.range4)),
"fieldname": scrub(str(self.filters.range3) + "-" + str(self.filters.range4)),
"fieldtype": "Currency",
"options": "currency",
"width": 160
},
{
"label": _(str(self.filters.range4) + _("-Above")),
"fieldname": scrub(str(self.filters.range4) + _("-Above")),
"fieldtype": "Currency",
"options": "currency",
"width": 160
@@ -152,7 +159,7 @@ class AccountsReceivableSummary(ReceivablePayableReport):
row += [
party_dict.invoiced_amt, paid_amt, party_dict.credit_amt, party_dict.outstanding_amt,
party_dict.range1, party_dict.range2, party_dict.range3, party_dict.range4,
party_dict.range1, party_dict.range2, party_dict.range3, party_dict.range4, party_dict.range5
]
if args.get("party_type") == "Customer":
@@ -178,6 +185,7 @@ class AccountsReceivableSummary(ReceivablePayableReport):
"range2": 0,
"range3": 0,
"range4": 0,
"range5": 0,
"sales_person": []
})
)
@@ -209,7 +217,7 @@ class AccountsReceivableSummary(ReceivablePayableReport):
cols += ["bill_no", "bill_date"]
cols += ["invoiced_amt", "paid_amt", "credit_amt",
"outstanding_amt", "age", "range1", "range2", "range3", "range4", "currency", "pdc/lc_date", "pdc/lc_ref",
"outstanding_amt", "age", "range1", "range2", "range3", "range4", "range5", "currency", "pdc/lc_date", "pdc/lc_ref",
"pdc/lc_amount"]
if args.get("party_type") == "Supplier":

View File

@@ -10,4 +10,10 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() {
"fieldtype": "Check",
"default": 1
});
frappe.query_reports["Balance Sheet"]["filters"].push({
"fieldname": "include_default_book_entries",
"label": __("Include Default Book Entries"),
"fieldtype": "Check"
});
});

View File

@@ -45,8 +45,8 @@ def execute(filters=None):
if(filters.get("show_cumulative")):
last_total = period_data[0] - period_data[1]
period_data[2] = period_data[0] - period_data[1]
period_data[2] = period_data[0] - period_data[1]
row += period_data
totals[2] = totals[0] - totals[1]
if filters["period"] != "Yearly" :
@@ -60,7 +60,7 @@ def validate_filters(filters):
frappe.throw(_("Filter based on Cost Center is only applicable if Budget Against is selected as Cost Center"))
def get_columns(filters):
columns = [_(filters.get("budget_against")) + ":Link/%s:80"%(filters.get("budget_against")), _("Account") + ":Link/Account:80"]
columns = [_(filters.get("budget_against")) + ":Link/%s:150"%(filters.get("budget_against")), _("Account") + ":Link/Account:150"]
group_months = False if filters["period"] == "Monthly" else True
@@ -71,7 +71,7 @@ def get_columns(filters):
if filters["period"] == "Yearly":
labels = [_("Budget") + " " + str(year[0]), _("Actual ") + " " + str(year[0]), _("Varaiance ") + " " + str(year[0])]
for label in labels:
columns.append(label+":Float:80")
columns.append(label+":Float:150")
else:
for label in [_("Budget") + " (%s)" + " " + str(year[0]), _("Actual") + " (%s)" + " " + str(year[0]), _("Variance") + " (%s)" + " " + str(year[0])]:
if group_months:
@@ -79,20 +79,20 @@ def get_columns(filters):
else:
label = label % formatdate(from_date, format_string="MMM")
columns.append(label+":Float:80")
columns.append(label+":Float:150")
if filters["period"] != "Yearly" :
return columns + [_("Total Budget") + ":Float:80", _("Total Actual") + ":Float:80",
_("Total Variance") + ":Float:80"]
return columns + [_("Total Budget") + ":Float:150", _("Total Actual") + ":Float:150",
_("Total Variance") + ":Float:150"]
else:
return columns
def get_cost_centers(filters):
cond = "and 1=1"
if filters.get("budget_against") == "Cost Center":
cond = "order by lft"
return frappe.db.sql_list("""select name from `tab{tab}` where company=%s
return frappe.db.sql_list("""select name from `tab{tab}` where company=%s
{cond}""".format(tab=filters.get("budget_against"), cond=cond), filters.get("company"))
#Get cost center & target details
@@ -109,7 +109,7 @@ def get_cost_center_target_details(filters):
""".format(budget_against=filters.get("budget_against").replace(" ", "_").lower(), cond=cond),
(filters.from_fiscal_year,filters.to_fiscal_year,filters.budget_against, filters.company), as_dict=True)
#Get target distribution details of accounts of cost center
def get_target_distribution_details(filters):
@@ -118,7 +118,7 @@ def get_target_distribution_details(filters):
from `tabMonthly Distribution Percentage` mdp, `tabMonthly Distribution` md
where mdp.parent=md.name and md.fiscal_year between %s and %s order by md.fiscal_year""",(filters.from_fiscal_year, filters.to_fiscal_year), as_dict=1):
target_details.setdefault(d.name, {}).setdefault(d.month, flt(d.percentage_allocation))
return target_details
#Get actual details from gl entry
@@ -129,7 +129,7 @@ def get_actual_details(name, filters):
if filters.get("budget_against") == "Cost Center":
cc_lft, cc_rgt = frappe.db.get_value("Cost Center", name, ["lft", "rgt"])
cond = "lft>='{lft}' and rgt<='{rgt}'".format(lft = cc_lft, rgt=cc_rgt)
ac_details = frappe.db.sql("""select gl.account, gl.debit, gl.credit,gl.fiscal_year,
MONTHNAME(gl.posting_date) as month_name, b.{budget_against} as budget_against
from `tabGL Entry` gl, `tabBudget Account` ba, `tabBudget` b
@@ -159,7 +159,7 @@ def get_cost_center_account_month_map(filters):
for ccd in cost_center_target_details:
actual_details = get_actual_details(ccd.budget_against, filters)
for month_id in range(1, 13):
month = datetime.date(2013, month_id, 1).strftime('%B')
cam_map.setdefault(ccd.budget_against, {}).setdefault(ccd.account, {}).setdefault(ccd.fiscal_year,{})\
@@ -172,7 +172,7 @@ def get_cost_center_account_month_map(filters):
if ccd.monthly_distribution else 100.0/12
tav_dict.target = flt(ccd.budget_amount) * month_percentage / 100
for ad in actual_details.get(ccd.account, []):
if ad.month_name == month:
tav_dict.actual += flt(ad.debit) - flt(ad.credit)

View File

@@ -15,4 +15,10 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() {
"label": __("Accumulated Values"),
"fieldtype": "Check"
});
frappe.query_reports["Cash Flow"]["filters"].push({
"fieldname": "include_default_book_entries",
"label": __("Include Default Book Entries"),
"fieldtype": "Check"
});
});

View File

@@ -14,8 +14,8 @@ def execute(filters=None):
if cint(frappe.db.get_single_value('Accounts Settings', 'use_custom_cash_flow')):
from erpnext.accounts.report.cash_flow.custom_cash_flow import execute as execute_custom
return execute_custom(filters=filters)
period_list = get_period_list(filters.from_fiscal_year, filters.to_fiscal_year,
period_list = get_period_list(filters.from_fiscal_year, filters.to_fiscal_year,
filters.periodicity, filters.accumulated_values, filters.company)
cash_flow_accounts = get_cash_flow_accounts()
@@ -25,18 +25,18 @@ def execute(filters=None):
accumulated_values=filters.accumulated_values, ignore_closing_entries=True, ignore_accumulated_values_for_fy= True)
expense = get_data(filters.company, "Expense", "Debit", period_list, filters=filters,
accumulated_values=filters.accumulated_values, ignore_closing_entries=True, ignore_accumulated_values_for_fy= True)
net_profit_loss = get_net_profit_loss(income, expense, period_list, filters.company)
data = []
company_currency = frappe.get_cached_value('Company', filters.company, "default_currency")
for cash_flow_account in cash_flow_accounts:
section_data = []
data.append({
"account_name": cash_flow_account['section_header'],
"account_name": cash_flow_account['section_header'],
"parent_account": None,
"indent": 0.0,
"indent": 0.0,
"account": cash_flow_account['section_header']
})
@@ -44,18 +44,18 @@ def execute(filters=None):
# add first net income in operations section
if net_profit_loss:
net_profit_loss.update({
"indent": 1,
"indent": 1,
"parent_account": cash_flow_accounts[0]['section_header']
})
data.append(net_profit_loss)
section_data.append(net_profit_loss)
for account in cash_flow_account['account_types']:
account_data = get_account_type_based_data(filters.company,
account['account_type'], period_list, filters.accumulated_values)
account_data = get_account_type_based_data(filters.company,
account['account_type'], period_list, filters.accumulated_values, filters)
account_data.update({
"account_name": account['label'],
"account": account['label'],
"account": account['label'],
"indent": 1,
"parent_account": cash_flow_account['section_header'],
"currency": company_currency
@@ -63,7 +63,7 @@ def execute(filters=None):
data.append(account_data)
section_data.append(account_data)
add_total_row_account(data, section_data, cash_flow_account['section_footer'],
add_total_row_account(data, section_data, cash_flow_account['section_footer'],
period_list, company_currency)
add_total_row_account(data, data, _("Net Change in Cash"), period_list, company_currency)
@@ -105,13 +105,15 @@ def get_cash_flow_accounts():
# combine all cash flow accounts for iteration
return [operation_accounts, investing_accounts, financing_accounts]
def get_account_type_based_data(company, account_type, period_list, accumulated_values):
def get_account_type_based_data(company, account_type, period_list, accumulated_values, filters):
data = {}
total = 0
for period in period_list:
start_date = get_start_date(period, accumulated_values, company)
amount = get_account_type_based_gl_data(company, start_date, period['to_date'], account_type)
amount = get_account_type_based_gl_data(company, start_date,
period['to_date'], account_type, filters)
if amount and account_type == "Depreciation":
amount *= -1
@@ -121,14 +123,24 @@ def get_account_type_based_data(company, account_type, period_list, accumulated_
data["total"] = total
return data
def get_account_type_based_gl_data(company, start_date, end_date, account_type):
def get_account_type_based_gl_data(company, start_date, end_date, account_type, filters):
cond = ""
if filters.finance_book:
cond = " and finance_book = '%s'" %(frappe.db.escape(filters.finance_book))
if filters.include_default_book_entries:
company_fb = frappe.db.get_value("Company", company, 'default_finance_book')
cond = """ and finance_book in ('%s', '%s')
""" %(frappe.db.escape(filters.finance_book), frappe.db.escape(company_fb))
gl_sum = frappe.db.sql_list("""
select sum(credit) - sum(debit)
from `tabGL Entry`
where company=%s and posting_date >= %s and posting_date <= %s
and voucher_type != 'Period Closing Voucher'
and account in ( SELECT name FROM tabAccount WHERE account_type = %s)
""", (company, start_date, end_date, account_type))
and account in ( SELECT name FROM tabAccount WHERE account_type = %s) {cond}
""".format(cond=cond), (company, start_date, end_date, account_type))
return gl_sum[0] if gl_sum and gl_sum[0] else 0
@@ -154,7 +166,7 @@ def add_total_row_account(out, data, label, period_list, currency, consolidated
key = period if consolidated else period['key']
total_row.setdefault(key, 0.0)
total_row[key] += row.get(key, 0.0)
total_row.setdefault("total", 0.0)
total_row["total"] += row["total"]

View File

@@ -55,5 +55,10 @@ frappe.query_reports["Consolidated Financial Statement"] = {
"fieldtype": "Check",
"default": 0
},
{
"fieldname": "include_default_book_entries",
"label": __("Include Default Book Entries"),
"fieldtype": "Check"
}
]
}

View File

@@ -355,7 +355,8 @@ def set_gl_entries_by_account(from_date, to_date, root_lft, root_rgt, filters, g
"lft": root_lft,
"rgt": root_rgt,
"company": d.name,
"finance_book": filters.get("finance_book")
"finance_book": filters.get("finance_book"),
"company_fb": frappe.db.get_value("Company", d.name, 'default_finance_book')
},
as_dict=True)
@@ -386,7 +387,10 @@ def get_additional_conditions(from_date, ignore_closing_entries, filters):
additional_conditions.append("gl.posting_date >= %(from_date)s")
if filters.get("finance_book"):
additional_conditions.append("ifnull(finance_book, '') in (%(finance_book)s, '')")
if filters.get("include_default_book_entries"):
additional_conditions.append("finance_book in (%(finance_book)s, %(company_fb)s)")
else:
additional_conditions.append("finance_book in (%(finance_book)s)")
return " and {}".format(" and ".join(additional_conditions)) if additional_conditions else ""

View File

@@ -39,7 +39,7 @@
</tr>
</thead>
<tbody>
{% for(var j=0, k=data.length; j<k; j++) { %}
{% for(var j=0, k=data.length-1; j<k; j++) { %}
{%
var row = data[j];
var row_class = data[j].parent_account ? "" : "financial-statements-important";

View File

@@ -359,7 +359,8 @@ def set_gl_entries_by_account(
"to_date": to_date,
"cost_center": filters.cost_center,
"project": filters.project,
"finance_book": filters.get("finance_book")
"finance_book": filters.get("finance_book"),
"company_fb": frappe.db.get_value("Company", company, 'default_finance_book')
},
as_dict=True)
@@ -393,7 +394,10 @@ def get_additional_conditions(from_date, ignore_closing_entries, filters):
additional_conditions.append("cost_center in %(cost_center)s")
if filters.get("finance_book"):
additional_conditions.append("ifnull(finance_book, '') in (%(finance_book)s, '')")
if filters.get("include_default_book_entries"):
additional_conditions.append("finance_book in (%(finance_book)s, %(company_fb)s)")
else:
additional_conditions.append("finance_book in (%(finance_book)s)")
return " and {}".format(" and ".join(additional_conditions)) if additional_conditions else ""

View File

@@ -33,7 +33,7 @@
</tr>
</thead>
<tbody>
{% for(var i=0, l=data.length; i<l; i++) { %}
{% for(var i=0, l=data.length-1; i<l; i++) { %}
<tr>
{% if(data[i].posting_date) { %}
<td>{%= frappe.datetime.str_to_user(data[i].posting_date) %}</td>

View File

@@ -216,6 +216,11 @@ frappe.query_reports["General Ledger"] = {
"fieldname": "show_opening_entries",
"label": __("Show Opening Entries"),
"fieldtype": "Check"
},
{
"fieldname": "include_default_book_entries",
"label": __("Include Default Book Entries"),
"fieldtype": "Check"
}
]
}

View File

@@ -128,10 +128,15 @@ def get_gl_entries(filters):
if filters.get("group_by") == _("Group by Voucher (Consolidated)"):
group_by_statement = "group by voucher_type, voucher_no, account, cost_center"
select_fields = """, sum(debit) as debit, sum(credit) as credit,
sum(debit_in_account_currency) as debit_in_account_currency,
sum(credit_in_account_currency) as credit_in_account_currency"""
if filters.get("include_default_book_entries"):
filters['company_fb'] = frappe.db.get_value("Company",
filters.get("company"), 'default_finance_book')
gl_entries = frappe.db.sql(
"""
select
@@ -187,7 +192,10 @@ def get_conditions(filters):
conditions.append("project in %(project)s")
if filters.get("finance_book"):
conditions.append("ifnull(finance_book, '') in (%(finance_book)s, '')")
if filters.get("include_default_book_entries"):
conditions.append("finance_book in (%(finance_book)s, %(company_fb)s)")
else:
conditions.append("finance_book in (%(finance_book)s)")
from frappe.desk.reportview import build_match_conditions
match_conditions = build_match_conditions("GL Entry")

View File

@@ -102,7 +102,9 @@ def get_conditions(filters):
("customer", " and `tabSales Invoice`.customer = %(customer)s"),
("item_code", " and `tabSales Invoice Item`.item_code = %(item_code)s"),
("from_date", " and `tabSales Invoice`.posting_date>=%(from_date)s"),
("to_date", " and `tabSales Invoice`.posting_date<=%(to_date)s")):
("to_date", " and `tabSales Invoice`.posting_date<=%(to_date)s"),
("company_gstin", " and `tabSales Invoice`.company_gstin = %(company_gstin)s"),
("invoice_type", " and `tabSales Invoice`.invoice_type = %(invoice_type)s")):
if filters.get(opts[0]):
conditions += opts[1]

View File

@@ -12,20 +12,21 @@ def get_ordered_to_be_billed_data(args):
child_tab = doctype + " Item"
precision = get_field_precision(frappe.get_meta(child_tab).get_field("billed_amt"),
currency=get_default_currency()) or 2
project_field = get_project_field(doctype, party)
return frappe.db.sql("""
Select
`{parent_tab}`.name, `{parent_tab}`.{date_field}, `{parent_tab}`.{party}, `{parent_tab}`.{party}_name,
{project_field}, `{child_tab}`.item_code, `{child_tab}`.base_amount,
(`{child_tab}`.billed_amt * ifnull(`{parent_tab}`.conversion_rate, 1)),
(`{child_tab}`.billed_amt * ifnull(`{parent_tab}`.conversion_rate, 1)),
(`{child_tab}`.base_amount - (`{child_tab}`.billed_amt * ifnull(`{parent_tab}`.conversion_rate, 1))),
`{child_tab}`.item_name, `{child_tab}`.description, `{parent_tab}`.company
from
`{parent_tab}`, `{child_tab}`
where
`{parent_tab}`.name = `{child_tab}`.parent and `{parent_tab}`.docstatus = 1 and `{parent_tab}`.status != 'Closed'
`{parent_tab}`.name = `{child_tab}`.parent and `{parent_tab}`.docstatus = 1
and `{parent_tab}`.status not in ('Closed', 'Completed')
and `{child_tab}`.amount > 0 and round(`{child_tab}`.billed_amt *
ifnull(`{parent_tab}`.conversion_rate, 1), {precision}) < `{child_tab}`.base_amount
order by

View File

@@ -18,22 +18,22 @@ def execute(filters=None):
data = []
for d in entries:
invoice = invoice_details.get(d.against_voucher) or frappe._dict()
if d.reference_type=="Purchase Invoice":
payment_amount = flt(d.debit) or -1 * flt(d.credit)
else:
payment_amount = flt(d.credit) or -1 * flt(d.debit)
row = [d.voucher_type, d.voucher_no, d.party_type, d.party, d.posting_date, d.against_voucher,
row = [d.voucher_type, d.voucher_no, d.party_type, d.party, d.posting_date, d.against_voucher,
invoice.posting_date, invoice.due_date, d.debit, d.credit, d.remarks]
if d.against_voucher:
row += get_ageing_data(30, 60, 90, d.posting_date, invoice.posting_date, payment_amount)
row += get_ageing_data(30, 60, 90, 120, d.posting_date, invoice.posting_date, payment_amount)
else:
row += ["", "", "", "", ""]
if invoice.due_date:
row.append((getdate(d.posting_date) - getdate(invoice.due_date)).days or 0)
data.append(row)
return columns, data
@@ -48,19 +48,19 @@ def get_columns(filters):
return [
_("Payment Document") + ":: 100",
_("Payment Entry") + ":Dynamic Link/"+_("Payment Document")+":140",
_("Party Type") + "::100",
_("Party Type") + "::100",
_("Party") + ":Dynamic Link/Party Type:140",
_("Posting Date") + ":Date:100",
_("Invoice") + (":Link/Purchase Invoice:130" if filters.get("payment_type") == "Outgoing" else ":Link/Sales Invoice:130"),
_("Invoice Posting Date") + ":Date:130",
_("Payment Due Date") + ":Date:130",
_("Debit") + ":Currency:120",
_("Invoice Posting Date") + ":Date:130",
_("Payment Due Date") + ":Date:130",
_("Debit") + ":Currency:120",
_("Credit") + ":Currency:120",
_("Remarks") + "::150",
_("Remarks") + "::150",
_("Age") +":Int:40",
"0-30:Currency:100",
"30-60:Currency:100",
"60-90:Currency:100",
"0-30:Currency:100",
"30-60:Currency:100",
"60-90:Currency:100",
_("90-Above") + ":Currency:100",
_("Delay in payment (Days)") + "::150"
]
@@ -79,21 +79,21 @@ def get_conditions(filters):
if filters.party:
conditions.append("party=%(party)s")
if filters.party_type:
conditions.append("against_voucher_type=%(reference_type)s")
filters["reference_type"] = "Sales Invoice" if filters.party_type=="Customer" else "Purchase Invoice"
if filters.get("from_date"):
conditions.append("posting_date >= %(from_date)s")
if filters.get("to_date"):
conditions.append("posting_date <= %(to_date)s")
return "and " + " and ".join(conditions) if conditions else ""
def get_entries(filters):
return frappe.db.sql("""select
return frappe.db.sql("""select
voucher_type, voucher_no, party_type, party, posting_date, debit, credit, remarks, against_voucher
from `tabGL Entry`
where company=%(company)s and voucher_type in ('Journal Entry', 'Payment Entry') {0}

View File

@@ -41,6 +41,11 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() {
"fieldname": "accumulated_values",
"label": __("Accumulated Values"),
"fieldtype": "Check"
},
{
"fieldname": "include_default_book_entries",
"label": __("Include Default Book Entries"),
"fieldtype": "Check"
}
);
});

View File

@@ -47,8 +47,8 @@ class TestSalesPaymentSummary(unittest.TestCase):
pe.submit()
mop = get_mode_of_payments(filters)
self.assertTrue('Credit Card' in mop.values()[0])
self.assertTrue('Cash' in mop.values()[0])
self.assertTrue('Credit Card' in list(mop.values())[0])
self.assertTrue('Cash' in list(mop.values())[0])
# Cancel all Cash payment entry and check if this mode of payment is still fetched.
payment_entries = frappe.get_all("Payment Entry", filters={"mode_of_payment": "Cash", "docstatus": 1}, fields=["name", "docstatus"])
@@ -57,8 +57,8 @@ class TestSalesPaymentSummary(unittest.TestCase):
pe.cancel()
mop = get_mode_of_payments(filters)
self.assertTrue('Credit Card' in mop.values()[0])
self.assertTrue('Cash' not in mop.values()[0])
self.assertTrue('Credit Card' in list(mop.values())[0])
self.assertTrue('Cash' not in list(mop.values())[0])
def test_get_mode_of_payments_details(self):
filters = get_filters()
@@ -84,7 +84,7 @@ class TestSalesPaymentSummary(unittest.TestCase):
mopd = get_mode_of_payment_details(filters)
mopd_values = mopd.values()[0]
mopd_values = list(mopd.values())[0]
for mopd_value in mopd_values:
if mopd_value[0] == "Credit Card":
cc_init_amount = mopd_value[1]
@@ -96,7 +96,7 @@ class TestSalesPaymentSummary(unittest.TestCase):
pe.cancel()
mopd = get_mode_of_payment_details(filters)
mopd_values = mopd.values()[0]
mopd_values = list(mopd.values())[0]
for mopd_value in mopd_values:
if mopd_value[0] == "Credit Card":
cc_final_amount = mopd_value[1]

View File

@@ -105,7 +105,7 @@ def get_rootwise_opening_balances(filters, report_type):
if filters.finance_book:
fb_conditions = " and finance_book = %(finance_book)s"
if filters.include_default_book_entries:
fb_conditions = " and (finance_book in (%(finance_book)s, %(company_fb)s) or finance_book is null)"
fb_conditions = " and (finance_book in (%(finance_book)s, %(company_fb)s))"
additional_conditions += fb_conditions
@@ -180,20 +180,28 @@ def calculate_values(accounts, gl_entries_by_account, opening_balances, filters,
if d["root_type"] == "Asset" or d["root_type"] == "Equity" or d["root_type"] == "Expense":
d["opening_debit"] -= d["opening_credit"]
d["opening_credit"] = 0.0
total_row["opening_debit"] += d["opening_debit"]
d["closing_debit"] -= d["closing_credit"]
# For opening
check_opening_closing_has_negative_value(d, "opening_debit", "opening_credit")
# For closing
check_opening_closing_has_negative_value(d, "closing_debit", "closing_credit")
if d["root_type"] == "Liability" or d["root_type"] == "Income":
d["opening_credit"] -= d["opening_debit"]
d["opening_debit"] = 0.0
total_row["opening_credit"] += d["opening_credit"]
if d["root_type"] == "Asset" or d["root_type"] == "Equity" or d["root_type"] == "Expense":
d["closing_debit"] -= d["closing_credit"]
d["closing_credit"] = 0.0
total_row["closing_debit"] += d["closing_debit"]
if d["root_type"] == "Liability" or d["root_type"] == "Income":
d["closing_credit"] -= d["closing_debit"]
d["closing_debit"] = 0.0
total_row["closing_credit"] += d["closing_credit"]
# For opening
check_opening_closing_has_negative_value(d, "opening_credit", "opening_debit")
# For closing
check_opening_closing_has_negative_value(d, "closing_credit", "closing_debit")
total_row["opening_debit"] += d["opening_debit"]
total_row["closing_debit"] += d["closing_debit"]
total_row["opening_credit"] += d["opening_credit"]
total_row["closing_credit"] += d["closing_credit"]
return total_row
@@ -219,8 +227,6 @@ def prepare_data(accounts, filters, total_row, parent_children_map, company_curr
if d.account_number else d.account_name)
}
prepare_opening_and_closing(d)
for key in value_fields:
row[key] = flt(d.get(key, 0.0), 3)
@@ -295,22 +301,11 @@ def get_columns():
}
]
def prepare_opening_and_closing(d):
d["closing_debit"] = d["opening_debit"] + d["debit"]
d["closing_credit"] = d["opening_credit"] + d["credit"]
def check_opening_closing_has_negative_value(d, dr_or_cr, switch_to_column):
# If opening debit has negetive value then move it to opening credit and vice versa.
if d["root_type"] == "Asset" or d["root_type"] == "Equity" or d["root_type"] == "Expense":
d["opening_debit"] -= d["opening_credit"]
d["opening_credit"] = 0.0
if d["root_type"] == "Liability" or d["root_type"] == "Income":
d["opening_credit"] -= d["opening_debit"]
d["opening_debit"] = 0.0
if d["root_type"] == "Asset" or d["root_type"] == "Equity" or d["root_type"] == "Expense":
d["closing_debit"] -= d["closing_credit"]
d["closing_credit"] = 0.0
if d["root_type"] == "Liability" or d["root_type"] == "Income":
d["closing_credit"] -= d["closing_debit"]
d["closing_debit"] = 0.0
if d[dr_or_cr] < 0:
d[switch_to_column] = abs(d[dr_or_cr])
d[dr_or_cr] = 0.0
else:
d[switch_to_column] = 0.0

View File

@@ -333,7 +333,7 @@ def reconcile_against_document(args):
doc = frappe.get_doc(d.voucher_type, d.voucher_no)
doc.make_gl_entries(cancel = 0, adv_adj =1)
if d.voucher_type == 'Payment Entry':
if d.voucher_type in ('Payment Entry', 'Journal Entry'):
doc.update_expense_claim()
def check_if_advance_entry_modified(args):
@@ -378,9 +378,9 @@ def check_if_advance_entry_modified(args):
def validate_allocated_amount(args):
if args.get("allocated_amount") < 0:
throw(_("Allocated amount can not be negative"))
throw(_("Allocated amount cannot be negative"))
elif args.get("allocated_amount") > args.get("unadjusted_amount"):
throw(_("Allocated amount can not greater than unadjusted amount"))
throw(_("Allocated amount cannot be greater than unadjusted amount"))
def update_reference_in_journal_entry(d, jv_obj):
"""

View File

@@ -6,7 +6,6 @@ from __future__ import unicode_literals
import frappe
from frappe import _
from frappe.model.document import Document
from frappe import _
class Disease(Document):
def validate(self):

View File

@@ -7,7 +7,6 @@ import frappe
from frappe import _
from frappe.model.document import Document
from frappe.utils import flt, cint
from frappe import _
class SoilTexture(Document):
soil_edit_order = [2, 1, 0]
@@ -35,8 +34,8 @@ class SoilTexture(Document):
if sum(self.soil_edit_order) < 5: return
last_edit_index = self.soil_edit_order.index(min(self.soil_edit_order))
# set composition of the last edited soil
self.set( self.soil_types[last_edit_index],
# set composition of the last edited soil
self.set( self.soil_types[last_edit_index],
100 - sum(cint(self.get(soil_type)) for soil_type in self.soil_types) + cint(self.get(self.soil_types[last_edit_index])))
# calculate soil type

View File

@@ -6,7 +6,6 @@ from __future__ import unicode_literals
import frappe
from frappe import _
from frappe.model.document import Document
from frappe import _
class WaterAnalysis(Document):
def load_contents(self):

View File

@@ -291,16 +291,19 @@ class Asset(AccountsController):
def validate_expected_value_after_useful_life(self):
for row in self.get('finance_books'):
accumulated_depreciation_after_full_schedule = max([d.accumulated_depreciation_amount
for d in self.get("schedules") if cint(d.finance_book_id) == row.idx])
accumulated_depreciation_after_full_schedule = [d.accumulated_depreciation_amount
for d in self.get("schedules") if cint(d.finance_book_id) == row.idx]
asset_value_after_full_schedule = flt(flt(self.gross_purchase_amount) -
flt(accumulated_depreciation_after_full_schedule),
self.precision('gross_purchase_amount'))
if accumulated_depreciation_after_full_schedule:
accumulated_depreciation_after_full_schedule = max(accumulated_depreciation_after_full_schedule)
if row.expected_value_after_useful_life < asset_value_after_full_schedule:
frappe.throw(_("Depreciation Row {0}: Expected value after useful life must be greater than or equal to {1}")
.format(row.idx, asset_value_after_full_schedule))
asset_value_after_full_schedule = flt(flt(self.gross_purchase_amount) -
flt(accumulated_depreciation_after_full_schedule),
self.precision('gross_purchase_amount'))
if row.expected_value_after_useful_life < asset_value_after_full_schedule:
frappe.throw(_("Depreciation Row {0}: Expected value after useful life must be greater than or equal to {1}")
.format(row.idx, asset_value_after_full_schedule))
def validate_cancellation(self):
if self.status not in ("Submitted", "Partially Depreciated", "Fully Depreciated"):

View File

@@ -36,7 +36,7 @@ class AssetValueAdjustment(Document):
fixed_asset_account, accumulated_depreciation_account, depreciation_expense_account = \
get_depreciation_accounts(asset)
depreciation_cost_center, depreciation_series = frappe.get_cached_value('Company', asset.company,
depreciation_cost_center, depreciation_series = frappe.get_cached_value('Company', asset.company,
["depreciation_cost_center", "series_for_depreciation_entry"])
je = frappe.new_doc("Journal Entry")
@@ -75,8 +75,8 @@ class AssetValueAdjustment(Document):
rate_per_day = flt(d.value_after_depreciation) / flt(total_days)
from_date = self.date
else:
no_of_depreciations = len([e.name for e in asset.schedules
if (cint(s.finance_book_id) == d.idx and not e.journal_entry)])
no_of_depreciations = len([s.name for s in asset.schedules
if (cint(s.finance_book_id) == d.idx and not s.journal_entry)])
value_after_depreciation = d.value_after_depreciation
for data in asset.schedules:

View File

@@ -25,9 +25,12 @@ class TestLocation(unittest.TestCase):
temp['features'][0]['properties']['feature_of'] = location
formatted_locations.extend(temp['features'])
formatted_location_string = str(formatted_locations)
test_location = frappe.get_doc('Location', 'Test Location Area')
test_location.save()
self.assertEqual(formatted_location_string, str(json.loads(test_location.get('location'))['features']))
test_location_features = json.loads(test_location.get('location'))['features']
ordered_test_location_features = sorted(test_location_features, key=lambda x: x['properties']['feature_of'])
ordered_formatted_locations = sorted(formatted_locations, key=lambda x: x['properties']['feature_of'])
self.assertEqual(ordered_formatted_locations, ordered_test_location_features)
self.assertEqual(area, test_location.get('area'))

View File

@@ -33,6 +33,14 @@ frappe.ui.form.on("Purchase Order", {
}
}
});
frm.set_query("expense_account", "items", function() {
return {
query: "erpnext.controllers.queries.get_expense_account",
filters: {'company': frm.doc.company}
}
});
},
refresh: function(frm) {
@@ -96,7 +104,7 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend(
if(doc.docstatus == 1 && !in_list(["Closed", "Delivered"], doc.status)) {
if (this.frm.has_perm("submit")) {
if(flt(doc.per_billed, 2) < 100 || doc.per_received < 100) {
if(flt(doc.per_billed, 6) < 100 || flt(doc.per_received, 6) < 100) {
cur_frm.add_custom_button(__('Close'), this.close_purchase_order, __("Status"));
}
}

View File

@@ -20,6 +20,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "supplier_section",
"fieldtype": "Section Break",
"hidden": 0,
@@ -53,6 +54,7 @@
"collapsible": 0,
"columns": 0,
"default": "{supplier_name}",
"fetch_if_empty": 0,
"fieldname": "title",
"fieldtype": "Data",
"hidden": 1,
@@ -86,6 +88,7 @@
"collapsible": 0,
"columns": 0,
"default": "",
"fetch_if_empty": 0,
"fieldname": "naming_series",
"fieldtype": "Select",
"hidden": 0,
@@ -121,6 +124,7 @@
"collapsible": 0,
"columns": 0,
"description": "",
"fetch_if_empty": 0,
"fieldname": "supplier",
"fieldtype": "Link",
"hidden": 0,
@@ -156,6 +160,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.supplier && doc.docstatus===0 && (!(doc.items && doc.items.length) || (doc.items.length==1 && !doc.items[0].item_code))",
"fetch_if_empty": 0,
"fieldname": "get_items_from_open_material_requests",
"fieldtype": "Button",
"hidden": 0,
@@ -189,6 +194,7 @@
"collapsible": 0,
"columns": 0,
"fetch_from": "supplier.supplier_name",
"fetch_if_empty": 0,
"fieldname": "supplier_name",
"fieldtype": "Data",
"hidden": 0,
@@ -222,6 +228,7 @@
"collapsible": 0,
"columns": 0,
"description": "",
"fetch_if_empty": 0,
"fieldname": "company",
"fieldtype": "Link",
"hidden": 0,
@@ -256,6 +263,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break1",
"fieldtype": "Column Break",
"hidden": 0,
@@ -290,6 +298,7 @@
"collapsible": 0,
"columns": 0,
"default": "Today",
"fetch_if_empty": 0,
"fieldname": "transaction_date",
"fieldtype": "Date",
"hidden": 0,
@@ -324,6 +333,7 @@
"collapsible": 0,
"columns": 0,
"default": "",
"fetch_if_empty": 0,
"fieldname": "schedule_date",
"fieldtype": "Date",
"hidden": 0,
@@ -357,6 +367,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.docstatus===1",
"fetch_if_empty": 0,
"fieldname": "order_confirmation_no",
"fieldtype": "Data",
"hidden": 0,
@@ -390,6 +401,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.order_confirmation_no",
"fetch_if_empty": 0,
"fieldname": "order_confirmation_date",
"fieldtype": "Date",
"hidden": 0,
@@ -422,6 +434,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "amended_from",
"fieldtype": "Link",
"hidden": 0,
@@ -457,6 +470,7 @@
"collapsible": 0,
"collapsible_depends_on": "",
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "drop_ship",
"fieldtype": "Section Break",
"hidden": 0,
@@ -490,6 +504,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "",
"fetch_if_empty": 0,
"fieldname": "customer",
"fieldtype": "Link",
"hidden": 0,
@@ -524,6 +539,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "",
"fetch_if_empty": 0,
"fieldname": "customer_name",
"fieldtype": "Data",
"hidden": 0,
@@ -556,6 +572,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_19",
"fieldtype": "Column Break",
"hidden": 0,
@@ -588,6 +605,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "",
"fetch_if_empty": 0,
"fieldname": "customer_contact_person",
"fieldtype": "Link",
"hidden": 0,
@@ -621,6 +639,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "customer_contact_display",
"fieldtype": "Small Text",
"hidden": 1,
@@ -653,6 +672,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "customer_contact_mobile",
"fieldtype": "Small Text",
"hidden": 1,
@@ -685,6 +705,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "customer_contact_email",
"fieldtype": "Code",
"hidden": 1,
@@ -718,6 +739,7 @@
"bold": 0,
"collapsible": 1,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "section_addresses",
"fieldtype": "Section Break",
"hidden": 0,
@@ -750,6 +772,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "supplier_address",
"fieldtype": "Link",
"hidden": 0,
@@ -782,6 +805,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "contact_person",
"fieldtype": "Link",
"hidden": 0,
@@ -815,6 +839,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "",
"fetch_if_empty": 0,
"fieldname": "address_display",
"fieldtype": "Small Text",
"hidden": 0,
@@ -846,6 +871,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "contact_display",
"fieldtype": "Small Text",
"hidden": 0,
@@ -877,6 +903,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "contact_mobile",
"fieldtype": "Small Text",
"hidden": 0,
@@ -908,6 +935,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "contact_email",
"fieldtype": "Small Text",
"hidden": 0,
@@ -939,6 +967,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "col_break_address",
"fieldtype": "Column Break",
"hidden": 0,
@@ -971,6 +1000,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "",
"fetch_if_empty": 0,
"fieldname": "shipping_address",
"fieldtype": "Link",
"hidden": 0,
@@ -1004,6 +1034,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "shipping_address_display",
"fieldtype": "Small Text",
"hidden": 0,
@@ -1036,6 +1067,7 @@
"bold": 0,
"collapsible": 1,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "currency_and_price_list",
"fieldtype": "Section Break",
"hidden": 0,
@@ -1068,6 +1100,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "currency",
"fieldtype": "Link",
"hidden": 0,
@@ -1103,6 +1136,7 @@
"collapsible": 0,
"columns": 0,
"description": "",
"fetch_if_empty": 0,
"fieldname": "conversion_rate",
"fieldtype": "Float",
"hidden": 0,
@@ -1137,6 +1171,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "cb_price_list",
"fieldtype": "Column Break",
"hidden": 0,
@@ -1167,6 +1202,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "buying_price_list",
"fieldtype": "Link",
"hidden": 0,
@@ -1199,6 +1235,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "price_list_currency",
"fieldtype": "Link",
"hidden": 0,
@@ -1231,6 +1268,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "plc_conversion_rate",
"fieldtype": "Float",
"hidden": 0,
@@ -1263,6 +1301,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "ignore_pricing_rule",
"fieldtype": "Check",
"hidden": 0,
@@ -1294,6 +1333,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "sec_warehouse",
"fieldtype": "Section Break",
"hidden": 0,
@@ -1325,6 +1365,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "set_warehouse",
"fieldtype": "Link",
"hidden": 0,
@@ -1358,6 +1399,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "col_break_warehouse",
"fieldtype": "Column Break",
"hidden": 0,
@@ -1390,6 +1432,7 @@
"collapsible": 0,
"columns": 0,
"default": "No",
"fetch_if_empty": 0,
"fieldname": "is_subcontracted",
"fieldtype": "Select",
"hidden": 0,
@@ -1423,6 +1466,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.is_subcontracted==\"Yes\"",
"fetch_if_empty": 0,
"fieldname": "supplier_warehouse",
"fieldtype": "Link",
"hidden": 0,
@@ -1456,6 +1500,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "items_section",
"fieldtype": "Section Break",
"hidden": 0,
@@ -1489,6 +1534,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "scan_barcode",
"fieldtype": "Data",
"hidden": 0,
@@ -1521,6 +1567,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "items",
"fieldtype": "Table",
"hidden": 0,
@@ -1556,6 +1603,7 @@
"collapsible": 0,
"collapsible_depends_on": "supplied_items",
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "raw_material_details",
"fieldtype": "Section Break",
"hidden": 0,
@@ -1589,6 +1637,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "",
"fetch_if_empty": 0,
"fieldname": "supplied_items",
"fieldtype": "Table",
"hidden": 0,
@@ -1623,6 +1672,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "sb_last_purchase",
"fieldtype": "Section Break",
"hidden": 0,
@@ -1653,6 +1703,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "total_qty",
"fieldtype": "Float",
"hidden": 0,
@@ -1685,6 +1736,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "base_total",
"fieldtype": "Currency",
"hidden": 0,
@@ -1718,6 +1770,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "base_net_total",
"fieldtype": "Currency",
"hidden": 0,
@@ -1752,6 +1805,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_26",
"fieldtype": "Column Break",
"hidden": 0,
@@ -1782,6 +1836,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "total",
"fieldtype": "Currency",
"hidden": 0,
@@ -1815,6 +1870,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "net_total",
"fieldtype": "Currency",
"hidden": 0,
@@ -1849,6 +1905,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "total_net_weight",
"fieldtype": "Float",
"hidden": 0,
@@ -1881,6 +1938,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "taxes_section",
"fieldtype": "Section Break",
"hidden": 0,
@@ -1915,6 +1973,7 @@
"collapsible": 0,
"columns": 0,
"description": "",
"fetch_if_empty": 0,
"fieldname": "taxes_and_charges",
"fieldtype": "Link",
"hidden": 0,
@@ -1949,6 +2008,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_50",
"fieldtype": "Column Break",
"hidden": 0,
@@ -1980,6 +2040,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "shipping_rule",
"fieldtype": "Link",
"hidden": 0,
@@ -2013,6 +2074,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "section_break_52",
"fieldtype": "Section Break",
"hidden": 0,
@@ -2044,6 +2106,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "taxes",
"fieldtype": "Table",
"hidden": 0,
@@ -2078,6 +2141,7 @@
"bold": 0,
"collapsible": 1,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "sec_tax_breakup",
"fieldtype": "Section Break",
"hidden": 0,
@@ -2110,6 +2174,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "other_charges_calculation",
"fieldtype": "Text",
"hidden": 0,
@@ -2142,6 +2207,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "totals",
"fieldtype": "Section Break",
"hidden": 0,
@@ -2175,6 +2241,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "base_taxes_and_charges_added",
"fieldtype": "Currency",
"hidden": 0,
@@ -2209,6 +2276,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "base_taxes_and_charges_deducted",
"fieldtype": "Currency",
"hidden": 0,
@@ -2243,6 +2311,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "base_total_taxes_and_charges",
"fieldtype": "Currency",
"hidden": 0,
@@ -2277,6 +2346,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_39",
"fieldtype": "Column Break",
"hidden": 0,
@@ -2308,6 +2378,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "taxes_and_charges_added",
"fieldtype": "Currency",
"hidden": 0,
@@ -2342,6 +2413,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "taxes_and_charges_deducted",
"fieldtype": "Currency",
"hidden": 0,
@@ -2376,6 +2448,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "total_taxes_and_charges",
"fieldtype": "Currency",
"hidden": 0,
@@ -2410,6 +2483,7 @@
"collapsible": 1,
"collapsible_depends_on": "discount_amount",
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "discount_section",
"fieldtype": "Section Break",
"hidden": 0,
@@ -2443,6 +2517,7 @@
"collapsible": 0,
"columns": 0,
"default": "Grand Total",
"fetch_if_empty": 0,
"fieldname": "apply_discount_on",
"fieldtype": "Select",
"hidden": 0,
@@ -2476,6 +2551,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "base_discount_amount",
"fieldtype": "Currency",
"hidden": 0,
@@ -2509,6 +2585,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_45",
"fieldtype": "Column Break",
"hidden": 0,
@@ -2540,6 +2617,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "additional_discount_percentage",
"fieldtype": "Float",
"hidden": 0,
@@ -2572,6 +2650,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "discount_amount",
"fieldtype": "Currency",
"hidden": 0,
@@ -2605,6 +2684,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "totals_section",
"fieldtype": "Section Break",
"hidden": 0,
@@ -2636,6 +2716,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "base_grand_total",
"fieldtype": "Currency",
"hidden": 0,
@@ -2670,6 +2751,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "base_rounding_adjustment",
"fieldtype": "Currency",
"hidden": 0,
@@ -2704,6 +2786,7 @@
"collapsible": 0,
"columns": 0,
"description": "In Words will be visible once you save the Purchase Order.",
"fetch_if_empty": 0,
"fieldname": "base_in_words",
"fieldtype": "Data",
"hidden": 0,
@@ -2737,6 +2820,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "base_rounded_total",
"fieldtype": "Currency",
"hidden": 0,
@@ -2771,6 +2855,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break4",
"fieldtype": "Column Break",
"hidden": 0,
@@ -2802,6 +2887,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "grand_total",
"fieldtype": "Currency",
"hidden": 0,
@@ -2836,6 +2922,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "rounding_adjustment",
"fieldtype": "Currency",
"hidden": 0,
@@ -2869,6 +2956,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "rounded_total",
"fieldtype": "Currency",
"hidden": 0,
@@ -2881,6 +2969,7 @@
"label": "Rounded Total",
"length": 0,
"no_copy": 0,
"options": "currency",
"permlevel": 0,
"precision": "",
"print_hide": 0,
@@ -2901,6 +2990,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "disable_rounded_total",
"fieldtype": "Check",
"hidden": 0,
@@ -2933,6 +3023,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "in_words",
"fieldtype": "Data",
"hidden": 0,
@@ -2966,6 +3057,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "advance_paid",
"fieldtype": "Currency",
"hidden": 0,
@@ -2998,6 +3090,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "payment_schedule_section",
"fieldtype": "Section Break",
"hidden": 0,
@@ -3030,6 +3123,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "payment_terms_template",
"fieldtype": "Link",
"hidden": 0,
@@ -3063,6 +3157,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "payment_schedule",
"fieldtype": "Table",
"hidden": 0,
@@ -3097,6 +3192,7 @@
"collapsible": 1,
"collapsible_depends_on": "terms",
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "terms_section_break",
"fieldtype": "Section Break",
"hidden": 0,
@@ -3130,6 +3226,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "tc_name",
"fieldtype": "Link",
"hidden": 0,
@@ -3164,6 +3261,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "terms",
"fieldtype": "Text Editor",
"hidden": 0,
@@ -3197,6 +3295,7 @@
"bold": 0,
"collapsible": 1,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "more_info",
"fieldtype": "Section Break",
"hidden": 0,
@@ -3230,6 +3329,7 @@
"collapsible": 0,
"columns": 0,
"default": "Draft",
"fetch_if_empty": 0,
"fieldname": "status",
"fieldtype": "Select",
"hidden": 0,
@@ -3264,6 +3364,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "ref_sq",
"fieldtype": "Data",
"hidden": 1,
@@ -3297,6 +3398,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "party_account_currency",
"fieldtype": "Link",
"hidden": 1,
@@ -3330,6 +3432,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_74",
"fieldtype": "Column Break",
"hidden": 0,
@@ -3363,6 +3466,7 @@
"columns": 0,
"depends_on": "eval:!doc.__islocal",
"description": "",
"fetch_if_empty": 0,
"fieldname": "per_received",
"fieldtype": "Percent",
"hidden": 0,
@@ -3398,6 +3502,7 @@
"columns": 0,
"depends_on": "eval:!doc.__islocal",
"description": "",
"fetch_if_empty": 0,
"fieldname": "per_billed",
"fieldtype": "Percent",
"hidden": 0,
@@ -3431,6 +3536,7 @@
"bold": 0,
"collapsible": 1,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break5",
"fieldtype": "Section Break",
"hidden": 0,
@@ -3465,6 +3571,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "letter_head",
"fieldtype": "Link",
"hidden": 0,
@@ -3499,6 +3606,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "select_print_heading",
"fieldtype": "Link",
"hidden": 0,
@@ -3533,6 +3641,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_86",
"fieldtype": "Column Break",
"hidden": 0,
@@ -3565,6 +3674,7 @@
"collapsible": 0,
"columns": 0,
"description": "",
"fetch_if_empty": 0,
"fieldname": "group_same_items",
"fieldtype": "Check",
"hidden": 0,
@@ -3598,6 +3708,7 @@
"collapsible": 0,
"columns": 0,
"default": "",
"fetch_if_empty": 0,
"fieldname": "language",
"fieldtype": "Data",
"hidden": 0,
@@ -3631,6 +3742,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "subscription_section",
"fieldtype": "Section Break",
"hidden": 0,
@@ -3665,6 +3777,7 @@
"columns": 0,
"depends_on": "",
"description": "",
"fetch_if_empty": 0,
"fieldname": "from_date",
"fieldtype": "Date",
"hidden": 0,
@@ -3698,6 +3811,7 @@
"columns": 0,
"depends_on": "",
"description": "",
"fetch_if_empty": 0,
"fieldname": "to_date",
"fieldtype": "Date",
"hidden": 0,
@@ -3729,6 +3843,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_97",
"fieldtype": "Column Break",
"hidden": 0,
@@ -3760,6 +3875,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "auto_repeat",
"fieldtype": "Link",
"hidden": 0,
@@ -3794,6 +3910,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval: doc.auto_repeat",
"fetch_if_empty": 0,
"fieldname": "update_auto_repeat_reference",
"fieldtype": "Button",
"hidden": 0,
@@ -3831,7 +3948,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2019-01-07 16:51:56.739693",
"modified": "2019-06-24 20:55:03.466766",
"modified_by": "Administrator",
"module": "Buying",
"name": "Purchase Order",

View File

@@ -1915,7 +1915,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "1",
"default": "0",
"depends_on": "eval:parent.is_subcontracted == 'Yes'",
"fieldname": "include_exploded_items",
"fieldtype": "Check",
@@ -2344,7 +2344,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2019-01-07 16:51:57.546323",
"modified": "2019-06-23 20:03:13.818917",
"modified_by": "Administrator",
"module": "Buying",
"name": "Purchase Order Item",
@@ -2359,4 +2359,4 @@
"track_changes": 1,
"track_seen": 0,
"track_views": 0
}
}

View File

@@ -237,6 +237,10 @@ class AccountsController(TransactionBase):
document_type = "{} Item".format(self.doctype)
parent_dict.update({"document_type": document_type})
# party_name field used for customer in quotation
if self.doctype == "Quotation" and self.quotation_to == "Customer" and parent_dict.get("party_name"):
parent_dict.update({"customer": parent_dict.get("party_name")})
for item in self.get("items"):
if item.get("item_code"):
args = parent_dict.copy()
@@ -344,7 +348,7 @@ class AccountsController(TransactionBase):
'fiscal_year': fiscal_year,
'voucher_type': self.doctype,
'voucher_no': self.name,
'remarks': self.get("remarks"),
'remarks': self.get("remarks") or self.get("remark"),
'debit': 0,
'credit': 0,
'debit_in_account_currency': 0,
@@ -743,7 +747,12 @@ class AccountsController(TransactionBase):
count += 1
item.qty = group_item_qty[item.item_code]
item.amount = group_item_amount[item.item_code]
item.rate = flt(flt(item.amount) / flt(item.qty), item.precision("rate"))
if item.qty:
item.rate = flt(flt(item.amount) / flt(item.qty), item.precision("rate"))
else:
item.rate = 0
item.idx = count
del group_item_qty[item.item_code]
else:

View File

@@ -428,8 +428,9 @@ class BuyingController(StockController):
elif not flt(d.rejected_qty):
d.rejected_qty = flt(d.received_qty) - flt(d.qty)
val = flt(d.qty) + flt(d.rejected_qty)
# Check Received Qty = Accepted Qty + Rejected Qty
if ((flt(d.qty) + flt(d.rejected_qty)) != flt(d.received_qty)):
if (flt(val, d.precision("received_qty")) != flt(d.received_qty, d.precision("received_qty"))):
frappe.throw(_("Accepted + Rejected Qty must be equal to Received quantity for Item {0}").format(d.item_code))
def validate_negative_quantity(self, item_row, field_list):

View File

@@ -288,14 +288,18 @@ def copy_attributes_to_variant(item, variant):
variant.variant_of = item.name
if not variant.description:
variant.description = ""
if 'description' not in allow_fields:
if item.variant_based_on == 'Item Attribute' and not variant.description:
variant.description = "<div><b>" + item.name + "</b></div>"
for d in variant.attributes:
variant.description += "<div><b>" + d.attribute + "</b>: " + cstr(d.attribute_value) + "</div>"
if not variant.description:
variant.description = ""
if item.variant_based_on=='Item Attribute':
if variant.attributes:
attributes_description = item.description + " "
for d in variant.attributes:
attributes_description += "<div>" + d.attribute + ": " + cstr(d.attribute_value) + "</div>"
if attributes_description not in variant.description:
variant.description += attributes_description
def make_variant_item_code(template_item_code, template_item_name, variant):
"""Uses template's item code and abbreviations to make variant's item code"""

View File

@@ -27,7 +27,7 @@ status_map = {
],
"Quotation": [
["Draft", None],
["Submitted", "eval:self.docstatus==1"],
["Open", "eval:self.docstatus==1"],
["Lost", "eval:self.status=='Lost'"],
["Ordered", "has_sales_order"],
["Cancelled", "eval:self.docstatus==2"],
@@ -45,9 +45,9 @@ status_map = {
"Sales Invoice": [
["Draft", None],
["Submitted", "eval:self.docstatus==1"],
["Paid", "eval:self.outstanding_amount==0 and self.docstatus==1"],
["Return", "eval:self.is_return==1 and self.docstatus==1"],
["Paid", "eval:self.outstanding_amount<=0 and self.docstatus==1 and self.is_return==0"],
["Credit Note Issued", "eval:self.outstanding_amount < 0 and self.docstatus==1 and self.is_return==0 and get_value('Sales Invoice', {'is_return': 1, 'return_against': self.name, 'docstatus': 1})"],
["Credit Note Issued", "eval:self.outstanding_amount < 0 and self.docstatus==1"],
["Unpaid", "eval:self.outstanding_amount > 0 and getdate(self.due_date) >= getdate(nowdate()) and self.docstatus==1"],
["Overdue", "eval:self.outstanding_amount > 0 and getdate(self.due_date) < getdate(nowdate()) and self.docstatus==1"],
["Cancelled", "eval:self.docstatus==2"],
@@ -55,9 +55,9 @@ status_map = {
"Purchase Invoice": [
["Draft", None],
["Submitted", "eval:self.docstatus==1"],
["Paid", "eval:self.outstanding_amount==0 and self.docstatus==1"],
["Return", "eval:self.is_return==1 and self.docstatus==1"],
["Paid", "eval:self.outstanding_amount<=0 and self.docstatus==1 and self.is_return==0"],
["Debit Note Issued", "eval:self.outstanding_amount < 0 and self.docstatus==1 and self.is_return==0 and get_value('Purchase Invoice', {'is_return': 1, 'return_against': self.name, 'docstatus': 1})"],
["Debit Note Issued", "eval:self.outstanding_amount < 0 and self.docstatus==1"],
["Unpaid", "eval:self.outstanding_amount > 0 and getdate(self.due_date) >= getdate(nowdate()) and self.docstatus==1"],
["Overdue", "eval:self.outstanding_amount > 0 and getdate(self.due_date) < getdate(nowdate()) and self.docstatus==1"],
["Cancelled", "eval:self.docstatus==2"],
@@ -316,19 +316,27 @@ class StatusUpdater(Document):
.format(frappe.db.escape(frappe.session.user))
def update_billing_status_for_zero_amount_refdoc(self, ref_dt):
ref_fieldname = ref_dt.lower().replace(" ", "_")
zero_amount_refdoc = []
all_zero_amount_refdoc = frappe.db.sql_list("""select name from `tab%s`
where docstatus=1 and base_net_total = 0""" % ref_dt)
ref_fieldname = frappe.scrub(ref_dt)
for item in self.get("items"):
if item.get(ref_fieldname) \
and item.get(ref_fieldname) in all_zero_amount_refdoc \
and item.get(ref_fieldname) not in zero_amount_refdoc:
zero_amount_refdoc.append(item.get(ref_fieldname))
ref_docs = [item.get(ref_fieldname) for item in (self.get('items') or []) if item.get(ref_fieldname)]
if not ref_docs:
return
if zero_amount_refdoc:
self.update_billing_status(zero_amount_refdoc, ref_dt, ref_fieldname)
zero_amount_refdocs = frappe.db.sql_list("""
SELECT
name
from
`tab{ref_dt}`
where
docstatus = 1
and base_net_total = 0
and name in %(ref_docs)s
""".format(ref_dt=ref_dt), {
'ref_docs': ref_docs
})
if zero_amount_refdocs:
self.update_billing_status(zero_amount_refdocs, ref_dt, ref_fieldname)
def update_billing_status(self, zero_amount_refdoc, ref_dt, ref_fieldname):
for ref_dn in zero_amount_refdoc:

View File

@@ -80,7 +80,7 @@ class StockController(AccountsController):
"cost_center": item_row.cost_center,
"remarks": self.get("remarks") or "Accounting Entry for Stock",
"debit": flt(sle.stock_value_difference, 2),
"is_opening": item_row.get("is_opening"),
"is_opening": item_row.get("is_opening") or self.get("is_opening") or "No",
}, warehouse_account[sle.warehouse]["account_currency"]))
# to target warehouse / expense account
@@ -91,7 +91,7 @@ class StockController(AccountsController):
"remarks": self.get("remarks") or "Accounting Entry for Stock",
"credit": flt(sle.stock_value_difference, 2),
"project": item_row.get("project") or self.get("project"),
"is_opening": item_row.get("is_opening")
"is_opening": item_row.get("is_opening") or self.get("is_opening") or "No"
}))
elif sle.warehouse not in warehouse_with_no_account:
warehouse_with_no_account.append(sle.warehouse)

View File

@@ -390,7 +390,7 @@ class calculate_taxes_and_totals(object):
net_total += item.net_amount
# discount amount rounding loss adjustment if no taxes
if (not taxes or self.doc.apply_discount_on == "Net Total") \
if (self.doc.apply_discount_on == "Net Total" or not taxes or total_for_discount_amount==self.doc.net_total) \
and i == len(self.doc.get("items")) - 1:
discount_amount_loss = flt(self.doc.net_total - net_total - self.doc.discount_amount,
self.doc.precision("net_total"))

View File

@@ -6,6 +6,18 @@ cur_frm.email_field = "email_id";
erpnext.LeadController = frappe.ui.form.Controller.extend({
setup: function () {
this.frm.make_methods = {
'Quotation': () => erpnext.utils.create_new_doc('Quotation', {
'quotation_to': this.frm.doc.doctype,
'party_name': this.frm.doc.name
}),
'Opportunity': () => erpnext.utils.create_new_doc('Opportunity', {
'opportunity_from': this.frm.doc.doctype,
'party_name': this.frm.doc.name
})
}
this.frm.fields_dict.customer.get_query = function (doc, cdt, cdn) {
return { query: "erpnext.controllers.queries.customer_query" }
}

View File

@@ -150,8 +150,8 @@ def make_opportunity(source_name, target_doc=None):
"doctype": "Opportunity",
"field_map": {
"campaign_name": "campaign",
"doctype": "enquiry_from",
"name": "lead",
"doctype": "opportunity_from",
"name": "party_name",
"lead_name": "contact_display",
"company_name": "customer_name",
"email_id": "contact_email",

View File

@@ -11,7 +11,7 @@ def execute(filters=None):
columns=get_columns("Campaign Name")
data=get_lead_data(filters or {}, "Campaign Name")
return columns, data
def get_columns(based_on):
return [
{
@@ -69,21 +69,21 @@ def get_columns(based_on):
"width": 100
}
]
def get_lead_data(filters, based_on):
based_on_field = frappe.scrub(based_on)
conditions = get_filter_conditions(filters)
lead_details = frappe.db.sql("""
select {based_on_field}, name
from `tabLead`
where {based_on_field} is not null and {based_on_field} != '' {conditions}
from `tabLead`
where {based_on_field} is not null and {based_on_field} != '' {conditions}
""".format(based_on_field=based_on_field, conditions=conditions), filters, as_dict=1)
lead_map = frappe._dict()
for d in lead_details:
lead_map.setdefault(d.get(based_on_field), []).append(d.name)
data = []
for based_on_value, leads in lead_map.items():
row = {
@@ -94,42 +94,42 @@ def get_lead_data(filters, based_on):
row["opp_count"] = get_lead_opp_count(leads)
row["order_count"] = get_quotation_ordered_count(leads)
row["order_value"] = get_order_amount(leads) or 0
row["opp_lead"] = flt(row["opp_count"]) / flt(row["lead_count"] or 1.0) * 100.0
row["quot_lead"] = flt(row["quot_count"]) / flt(row["lead_count"] or 1.0) * 100.0
row["order_quot"] = flt(row["order_count"]) / flt(row["quot_count"] or 1.0) * 100.0
data.append(row)
return data
def get_filter_conditions(filters):
conditions=""
if filters.from_date:
conditions += " and date(creation) >= %(from_date)s"
if filters.to_date:
conditions += " and date(creation) <= %(to_date)s"
return conditions
def get_lead_quotation_count(leads):
return frappe.db.sql("""select count(name) from `tabQuotation`
where lead in (%s)""" % ', '.join(["%s"]*len(leads)), tuple(leads))[0][0]
return frappe.db.sql("""select count(name) from `tabQuotation`
where quotation_to = 'Lead' and party_name in (%s)""" % ', '.join(["%s"]*len(leads)), tuple(leads))[0][0] #nosec
def get_lead_opp_count(leads):
return frappe.db.sql("""select count(name) from `tabOpportunity`
where lead in (%s)""" % ', '.join(["%s"]*len(leads)), tuple(leads))[0][0]
return frappe.db.sql("""select count(name) from `tabOpportunity`
where opportunity_from = 'Lead' and party_name in (%s)""" % ', '.join(["%s"]*len(leads)), tuple(leads))[0][0]
def get_quotation_ordered_count(leads):
return frappe.db.sql("""select count(name)
from `tabQuotation` where status = 'Ordered'
and lead in (%s)""" % ', '.join(["%s"]*len(leads)), tuple(leads))[0][0]
return frappe.db.sql("""select count(name)
from `tabQuotation` where status = 'Ordered' and quotation_to = 'Lead'
and party_name in (%s)""" % ', '.join(["%s"]*len(leads)), tuple(leads))[0][0]
def get_order_amount(leads):
return frappe.db.sql("""select sum(base_net_amount)
return frappe.db.sql("""select sum(base_net_amount)
from `tabSales Order Item`
where prevdoc_docname in (
select name from `tabQuotation` where status = 'Ordered'
and lead in (%s)
select name from `tabQuotation` where status = 'Ordered'
and quotation_to = 'Lead' and party_name in (%s)
)""" % ', '.join(["%s"]*len(leads)), tuple(leads))[0][0]

View File

@@ -11,16 +11,61 @@ def execute(filters=None):
columns=get_columns()
data=get_lead_data(filters, "Lead Owner")
return columns, data
def get_columns():
return [
_("Lead Owner") + ":Data:130",
_("Lead Count") + ":Int:80",
_("Opp Count") + ":Int:80",
_("Quot Count") + ":Int:80",
_("Order Count") + ":Int:100",
_("Order Value") + ":Float:100",
_("Opp/Lead %") + ":Float:100",
_("Quot/Lead %") + ":Float:100",
_("Order/Quot %") + ":Float:100"
{
"fieldname": "lead_owner",
"label": _("Lead Owner"),
"fieldtype": "Data",
"width": "130"
},
{
"fieldname": "lead_count",
"label": _("Lead Count"),
"fieldtype": "Int",
"width": "80"
},
{
"fieldname": "opp_count",
"label": _("Opp Count"),
"fieldtype": "Int",
"width": "80"
},
{
"fieldname": "quot_count",
"label": _("Quot Count"),
"fieldtype": "Int",
"width": "80"
},
{
"fieldname": "order_count",
"label": _("Order Count"),
"fieldtype": "Int",
"width": "100"
},
{
"fieldname": "order_value",
"label": _("Order Value"),
"fieldtype": "Float",
"width": "100"
},
{
"fieldname": "opp_lead",
"label": _("Opp/Lead %"),
"fieldtype": "Float",
"width": "100"
},
{
"fieldname": "quot_lead",
"label": _("Quot/Lead %"),
"fieldtype": "Float",
"width": "100"
},
{
"fieldname": "order_quot",
"label": _("Order/Quot %"),
"fieldtype": "Float",
"width": "100"
}
]

View File

@@ -35,14 +35,14 @@ def get_data(filters):
for lead in frappe.get_all('Lead', fields = ['name', 'lead_name', 'company_name'], filters=lead_filters):
data = frappe.db.sql("""
select
`tabCommunication`.reference_doctype, `tabCommunication`.reference_name,
select
`tabCommunication`.reference_doctype, `tabCommunication`.reference_name,
`tabCommunication`.content, `tabCommunication`.communication_date
from
from
(
(select name, lead from `tabOpportunity` where lead = %(lead)s)
union
(select name, lead from `tabQuotation` where lead = %(lead)s)
(select name, party_name as lead from `tabOpportunity` where opportunity_from='Lead' and party_name = %(lead)s)
union
(select name, party_name as lead from `tabQuotation` where quotation_to = 'Lead' and party_name = %(lead)s)
union
(select name, lead from `tabIssue` where lead = %(lead)s and status!='Closed')
union

View File

@@ -22,7 +22,16 @@ def verify_request():
frappe.set_user(woocommerce_settings.creation_user)
@frappe.whitelist(allow_guest=True)
def order():
def order(*args, **kwargs):
try:
_order(*args, **kwargs)
except Exception:
error_message = frappe.get_traceback()+"\n\n Request Data: \n"+json.loads(frappe.request.data).__str__()
frappe.log_error(error_message, "WooCommerce Error")
raise
def _order(*args, **kwargs):
woocommerce_settings = frappe.get_doc("Woocommerce Settings")
if frappe.flags.woocomm_test_order_data:
fd = frappe.flags.woocomm_test_order_data

View File

@@ -40,7 +40,7 @@ def get_products_details():
products_response = call_mws_method(products.get_matching_product,marketplaceid=marketplace,
asins=asin_list)
matching_products_list = products_response.parsed
matching_products_list = products_response.parsed
for product in matching_products_list:
skus = [row["sku"] for row in sku_asin if row["asin"]==product.ASIN]
for sku in skus:
@@ -116,7 +116,7 @@ def call_mws_method(mws_method, *args, **kwargs):
mws_settings = frappe.get_doc("Amazon MWS Settings")
max_retries = mws_settings.max_retry_limit
for x in xrange(0, max_retries):
for x in range(0, max_retries):
try:
response = mws_method(*args, **kwargs)
return response

View File

@@ -107,10 +107,18 @@ def get_series():
def setup_custom_fields():
custom_fields = {
"Customer": [dict(fieldname='shopify_customer_id', label='Shopify Customer Id',
fieldtype='Data', insert_after='series', read_only=1, print_hide=1)],
"Address": [dict(fieldname='shopify_address_id', label='Shopify Address Id',
fieldtype='Data', insert_after='fax', read_only=1, print_hide=1)],
"Customer": [
dict(fieldname='shopify_customer_id', label='Shopify Customer Id',
fieldtype='Data', insert_after='series', read_only=1, print_hide=1)
],
"Supplier": [
dict(fieldname='shopify_supplier_id', label='Shopify Supplier Id',
fieldtype='Data', insert_after='supplier_name', read_only=1, print_hide=1)
],
"Address": [
dict(fieldname='shopify_address_id', label='Shopify Address Id',
fieldtype='Data', insert_after='fax', read_only=1, print_hide=1)
],
"Item": [
dict(fieldname='shopify_variant_id', label='Shopify Variant Id',
fieldtype='Data', insert_after='item_code', read_only=1, print_hide=1),
@@ -119,16 +127,20 @@ def setup_custom_fields():
dict(fieldname='shopify_description', label='Shopify Description',
fieldtype='Text Editor', insert_after='description', read_only=1, print_hide=1)
],
"Sales Order": [dict(fieldname='shopify_order_id', label='Shopify Order Id',
fieldtype='Data', insert_after='title', read_only=1, print_hide=1)],
"Sales Order": [
dict(fieldname='shopify_order_id', label='Shopify Order Id',
fieldtype='Data', insert_after='title', read_only=1, print_hide=1)
],
"Delivery Note":[
dict(fieldname='shopify_order_id', label='Shopify Order Id',
fieldtype='Data', insert_after='title', read_only=1, print_hide=1),
dict(fieldname='shopify_fulfillment_id', label='Shopify Fulfillment Id',
fieldtype='Data', insert_after='title', read_only=1, print_hide=1)
],
"Sales Invoice": [dict(fieldname='shopify_order_id', label='Shopify Order Id',
fieldtype='Data', insert_after='title', read_only=1, print_hide=1)]
"Sales Invoice": [
dict(fieldname='shopify_order_id', label='Shopify Order Id',
fieldtype='Data', insert_after='title', read_only=1, print_hide=1)
]
}
create_custom_fields(custom_fields)

View File

@@ -300,11 +300,15 @@ def insert_lab_test_to_medical_record(doc):
elif doc.special_test_items:
item = doc.special_test_items[0]
table_row = item.lab_test_particulars +" "+ item.result_value
if item.lab_test_particulars and item.result_value:
table_row = item.lab_test_particulars +" "+ item.result_value
elif doc.sensitivity_test_items:
item = doc.sensitivity_test_items[0]
table_row = item.antibiotic +" "+ item.antibiotic_sensitivity
if item.antibiotic and item.antibiotic_sensitivity:
table_row = item.antibiotic +" "+ item.antibiotic_sensitivity
if table_row:
subject += "<br/>"+table_row

View File

@@ -13,8 +13,6 @@ source_link = "https://github.com/frappe/erpnext"
develop_version = '12.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"
@@ -44,7 +42,7 @@ update_and_get_user_progress = "erpnext.utilities.user_progress_utils.update_def
on_session_creation = "erpnext.shopping_cart.utils.set_cart_count"
on_logout = "erpnext.shopping_cart.utils.clear_cart_count"
treeviews = ['Account', 'Cost Center', 'Warehouse', 'Item Group', 'Customer Group', 'Sales Person', 'Territory', 'Assessment Group']
treeviews = ['Account', 'Cost Center', 'Warehouse', 'Item Group', 'Customer Group', 'Sales Person', 'Territory', 'Assessment Group', 'Department']
# website
update_website_context = "erpnext.shopping_cart.utils.update_website_context"

View File

@@ -2,8 +2,8 @@
// For license information, please see license.txt
frappe.views.calendar["Attendance"] = {
field_map: {
"start": "date",
"end": "date",
"start": "attendance_date",
"end": "attendance_date",
"id": "name",
"docstatus": 1
},

View File

@@ -4,7 +4,7 @@
frappe.ui.form.on('Department', {
refresh: function(frm) {
// read-only for root department
if(!frm.doc.parent_department) {
if(!frm.doc.parent_department && !frm.is_new()) {
frm.set_read_only();
frm.set_intro(__("This is a root department and cannot be edited."));
}

View File

@@ -1,5 +1,6 @@
{
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 1,
"allow_rename": 1,
@@ -19,6 +20,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "department_name",
"fieldtype": "Data",
"hidden": 0,
@@ -52,6 +54,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "parent_department",
"fieldtype": "Link",
"hidden": 0,
@@ -85,6 +88,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "company",
"fieldtype": "Link",
"hidden": 0,
@@ -118,6 +122,7 @@
"bold": 1,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "is_group",
"fieldtype": "Check",
"hidden": 0,
@@ -150,6 +155,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "disabled",
"fieldtype": "Check",
"hidden": 0,
@@ -182,6 +188,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "section_break_4",
"fieldtype": "Section Break",
"hidden": 0,
@@ -214,6 +221,7 @@
"collapsible": 0,
"columns": 0,
"description": "Days for which Holidays are blocked for this department.",
"fetch_if_empty": 0,
"fieldname": "leave_block_list",
"fieldtype": "Link",
"hidden": 0,
@@ -246,6 +254,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "leave_section",
"fieldtype": "Section Break",
"hidden": 0,
@@ -279,6 +288,7 @@
"collapsible": 0,
"columns": 0,
"description": "The first Leave Approver in the list will be set as the default Leave Approver.",
"fetch_if_empty": 0,
"fieldname": "leave_approvers",
"fieldtype": "Table",
"hidden": 0,
@@ -312,6 +322,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "expense_section",
"fieldtype": "Section Break",
"hidden": 0,
@@ -345,6 +356,7 @@
"collapsible": 0,
"columns": 0,
"description": "The first Expense Approver in the list will be set as the default Expense Approver.",
"fetch_if_empty": 0,
"fieldname": "expense_approvers",
"fieldtype": "Table",
"hidden": 0,
@@ -378,6 +390,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "lft",
"fieldtype": "Int",
"hidden": 1,
@@ -410,6 +423,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "rgt",
"fieldtype": "Int",
"hidden": 1,
@@ -442,6 +456,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "old_parent",
"fieldtype": "Data",
"hidden": 1,
@@ -479,7 +494,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2018-08-29 06:26:12.995703",
"modified": "2019-06-25 18:43:05.550387",
"modified_by": "Administrator",
"module": "HR",
"name": "Department",
@@ -543,7 +558,7 @@
"write": 1
}
],
"quick_entry": 1,
"quick_entry": 0,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 1,

View File

@@ -2,9 +2,8 @@ frappe.ui.form.on("Employee Attendance Tool", {
refresh: function(frm) {
frm.disable_save();
},
onload: function(frm) {
frm.doc.department = frm.doc.branch = frm.doc.company = "All";
frm.set_value("date", frappe.datetime.get_today());
erpnext.employee_attendance_tool.load_employees(frm);
},
@@ -24,7 +23,7 @@ frappe.ui.form.on("Employee Attendance Tool", {
company: function(frm) {
erpnext.employee_attendance_tool.load_employees(frm);
}
});

View File

@@ -17,12 +17,11 @@ def get_employees(date, department = None, branch = None, company = None):
attendance_not_marked = []
attendance_marked = []
filters = {"status": "Active", "date_of_joining": ["<=", date]}
if department != "All":
filters["department"] = department
if branch != "All":
filters["branch"] = branch
if company != "All":
filters["company"] = company
for field, value in {'department': department,
'branch': branch, 'company': company}.items():
if value:
filters[field] = value
employee_list = frappe.get_list("Employee", fields=["employee", "employee_name"], filters=filters, order_by="employee_name")
marked_employee = {}

View File

@@ -2,20 +2,8 @@
// For license information, please see license.txt
frappe.ui.form.on('Employee Benefit Application', {
setup: function(frm) {
if(!frm.doc.employee || !frm.doc.date) {
frappe.throw(__("Please select Employee and Date first"));
} else {
frm.set_query("earning_component", "employee_benefits", function() {
return {
query : "erpnext.hr.doctype.employee_benefit_application.employee_benefit_application.get_earning_components",
filters: {date: frm.doc.date, employee: frm.doc.employee}
};
});
}
},
employee: function(frm) {
frm.trigger('set_earning_component');
var method, args;
if(frm.doc.employee && frm.doc.date && frm.doc.payroll_period){
method = "erpnext.hr.doctype.employee_benefit_application.employee_benefit_application.get_max_benefits_remaining";
@@ -35,6 +23,21 @@ frappe.ui.form.on('Employee Benefit Application', {
get_max_benefits(frm, method, args);
}
},
date: function(frm) {
frm.trigger('set_earning_component');
},
set_earning_component: function(frm) {
if(!frm.doc.employee && !frm.doc.date) return;
frm.set_query("earning_component", "employee_benefits", function() {
return {
query : "erpnext.hr.doctype.employee_benefit_application.employee_benefit_application.get_earning_components",
filters: {date: frm.doc.date, employee: frm.doc.employee}
};
});
},
payroll_period: function(frm) {
var method, args;
if(frm.doc.employee && frm.doc.date && frm.doc.payroll_period){

View File

@@ -219,7 +219,8 @@ frappe.ui.form.on("Expense Claim", {
frm.fields_dict["cost_center"].get_query = function() {
return {
filters: {
"company": frm.doc.company
"company": frm.doc.company,
"is_group": 0
}
};
};
@@ -230,7 +231,9 @@ frappe.ui.form.on("Expense Claim", {
return {
filters: {
"report_type": "Balance Sheet",
"account_type": "Payable"
"account_type": "Payable",
"company": frm.doc.company,
"is_group": 0
}
};
};

View File

@@ -4,10 +4,17 @@ from frappe import _
def get_data():
return {
'fieldname': 'reference_name',
'internal_links': {
'Employee Advance': ['advances', 'employee_advance']
},
'transactions': [
{
'label': _('Payment'),
'items': ['Payment Entry']
'items': ['Payment Entry', 'Journal Entry']
},
{
'label': _('Reference'),
'items': ['Employee Advance']
},
]
}

View File

@@ -79,6 +79,7 @@ def get_events(start, end, filters=None):
filters.append(['Holiday', 'holiday_date', '>', getdate(start)])
if end:
filters.append(['Holiday', 'holiday_date', '<', getdate(end)])
return frappe.get_list('Holiday List',
fields=['name', '`tabHoliday`.holiday_date', '`tabHoliday`.description', '`tabHoliday List`.color'],
filters = filters,

View File

@@ -3,8 +3,8 @@
frappe.views.calendar["Holiday List"] = {
field_map: {
"start": "from_date",
"end": "to_date",
"start": "holiday_date",
"end": "holiday_date",
"id": "name",
"title": "description",
"allDay": "allDay"

View File

@@ -25,5 +25,13 @@ frappe.ui.form.on("Job Applicant", {
}
}
frm.set_query("job_title", function() {
return {
filters: {
'status': 'Open'
}
};
});
}
});

View File

@@ -122,11 +122,42 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "1",
"depends_on": "eval:doc.type == \"Earning\"",
"fetch_if_empty": 0,
"fieldname": "is_tax_applicable",
"fieldtype": "Check",
"fieldname": "description",
"fieldtype": "Small Text",
"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": "Description",
"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,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_4",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -134,7 +165,6 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Is Tax Applicable",
"length": 0,
"no_copy": 0,
"permlevel": 0,
@@ -225,8 +255,10 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "1",
"depends_on": "eval:doc.type == \"Earning\"",
"fetch_if_empty": 0,
"fieldname": "do_not_include_in_total",
"fieldname": "is_tax_applicable",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
@@ -235,7 +267,7 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Do not include in total",
"label": "Is Tax Applicable",
"length": 0,
"no_copy": 0,
"permlevel": 0,
@@ -258,6 +290,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "is_tax_applicable",
"fetch_if_empty": 0,
"fieldname": "deduct_full_tax_on_selected_payroll_date",
"fieldtype": "Check",
@@ -292,39 +325,7 @@
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 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,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "disabled",
"fieldname": "round_to_the_nearest_integer",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
@@ -333,40 +334,7 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Disabled",
"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,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "description",
"fieldtype": "Small Text",
"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": "Description",
"label": "Round to the Nearest Integer",
"length": 0,
"no_copy": 0,
"permlevel": 0,
@@ -416,6 +384,72 @@
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "do_not_include_in_total",
"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": "Do Not Include in Total",
"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,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "disabled",
"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": "Disabled",
"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,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
@@ -854,6 +888,40 @@
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.amount_based_on_formula!==1",
"fetch_if_empty": 0,
"fieldname": "amount",
"fieldtype": "Currency",
"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": "Amount",
"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,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
@@ -895,7 +963,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.amount_based_on_formula!==0",
"depends_on": "amount_based_on_formula",
"fetch_if_empty": 0,
"fieldname": "formula",
"fieldtype": "Code",
@@ -922,40 +990,6 @@
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.amount_based_on_formula!==1",
"fetch_if_empty": 0,
"fieldname": "amount",
"fieldtype": "Currency",
"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": "Amount",
"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,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
@@ -1034,7 +1068,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2019-05-13 12:55:55.424370",
"modified": "2019-06-05 11:19:15.926608",
"modified_by": "Administrator",
"module": "HR",
"name": "Salary Component",

View File

@@ -5,7 +5,7 @@ from __future__ import unicode_literals
import frappe, erpnext
import datetime, math
from frappe.utils import add_days, cint, cstr, flt, getdate, rounded, date_diff, money_in_words, getdate
from frappe.utils import add_days, cint, cstr, flt, getdate, rounded, date_diff, money_in_words
from frappe.model.naming import make_autoname
from frappe import msgprint, _
@@ -119,7 +119,7 @@ class SalarySlip(TransactionBase):
if not self.salary_slip_based_on_timesheet:
self.get_date_details()
self.validate_dates()
joining_date, relieving_date = frappe.db.get_value("Employee", self.employee,
joining_date, relieving_date = frappe.get_cached_value("Employee", self.employee,
["date_of_joining", "relieving_date"])
self.get_leave_details(joining_date, relieving_date)
@@ -183,7 +183,7 @@ class SalarySlip(TransactionBase):
def get_leave_details(self, joining_date=None, relieving_date=None, lwp=None, for_preview=0):
if not joining_date:
joining_date, relieving_date = frappe.db.get_value("Employee", self.employee,
joining_date, relieving_date = frappe.get_cached_value("Employee", self.employee,
["date_of_joining", "relieving_date"])
working_days = date_diff(self.end_date, self.start_date) + 1
@@ -297,9 +297,6 @@ class SalarySlip(TransactionBase):
self.net_pay = flt(self.gross_pay) - (flt(self.total_deduction) + flt(self.total_loan_repayment))
self.rounded_total = rounded(self.net_pay)
if self.net_pay < 0:
frappe.throw(_("Net Pay cannnot be negative"))
def calculate_component_amounts(self):
if not getattr(self, '_salary_structure_doc', None):
self._salary_structure_doc = frappe.get_doc('Salary Structure', self.salary_structure)
@@ -310,6 +307,7 @@ class SalarySlip(TransactionBase):
self.add_employee_benefits(payroll_period)
self.add_additional_salary_components()
self.add_tax_components(payroll_period)
self.set_component_amounts_based_on_payment_days()
def add_structure_components(self):
data = self.get_data_for_eval()
@@ -401,14 +399,18 @@ class SalarySlip(TransactionBase):
def add_tax_components(self, payroll_period):
# Calculate variable_based_on_taxable_salary after all components updated in salary slip
struct_tax_components = [d.salary_component for d in self._salary_structure_doc.get("deductions")
if d.variable_based_on_taxable_salary == 1 and not d.formula and not d.amount]
tax_components, other_deduction_components = [], []
for d in self._salary_structure_doc.get("deductions"):
if d.variable_based_on_taxable_salary == 1 and not d.formula and not flt(d.amount):
tax_components.append(d.salary_component)
else:
other_deduction_components.append(d.salary_component)
if not struct_tax_components:
struct_tax_components = [d.name for d in
frappe.get_all("Salary Component", filters={"variable_based_on_taxable_salary": 1})]
if not tax_components:
tax_components = [d.name for d in frappe.get_all("Salary Component", filters={"variable_based_on_taxable_salary": 1})
if d.name not in other_deduction_components]
for d in struct_tax_components:
for d in tax_components:
tax_amount = self.calculate_variable_based_on_taxable_salary(d, payroll_period)
tax_row = self.get_salary_slip_row(d)
self.update_component_row(tax_row, tax_amount, "deductions")
@@ -441,8 +443,10 @@ class SalarySlip(TransactionBase):
else:
component_row.additional_amount = amount
if not overwrite:
if not overwrite and component_row.default_amount:
amount += component_row.default_amount
else:
component_row.default_amount = amount
component_row.amount = amount
component_row.deduct_full_tax_on_selected_payroll_date = struct_row.deduct_full_tax_on_selected_payroll_date
@@ -474,8 +478,7 @@ class SalarySlip(TransactionBase):
future_structured_taxable_earnings = current_taxable_earnings.taxable_earnings * (math.ceil(remaining_sub_periods) - 1)
# get taxable_earnings, addition_earnings for current actual payment days
self.set_component_amounts_based_on_payment_days()
current_taxable_earnings_for_payment_days = self.get_taxable_earnings()
current_taxable_earnings_for_payment_days = self.get_taxable_earnings(based_on_payment_days=1)
current_structured_taxable_earnings = current_taxable_earnings_for_payment_days.taxable_earnings
current_additional_earnings = current_taxable_earnings_for_payment_days.additional_income
current_additional_earnings_with_full_tax = current_taxable_earnings_for_payment_days.additional_income_with_full_tax
@@ -498,7 +501,6 @@ class SalarySlip(TransactionBase):
# Structured tax amount
total_structured_tax_amount = self.calculate_tax_by_tax_slab(payroll_period, total_taxable_earnings_without_full_tax_addl_components)
current_structured_tax_amount = (total_structured_tax_amount - previous_total_paid_taxes) / remaining_sub_periods
# Total taxable earnings with additional earnings with full tax
@@ -557,25 +559,39 @@ class SalarySlip(TransactionBase):
return total_tax_paid
def get_taxable_earnings(self, only_flexi=0):
def get_taxable_earnings(self, based_on_payment_days=0):
joining_date, relieving_date = frappe.get_cached_value("Employee", self.employee,
["date_of_joining", "relieving_date"])
if not relieving_date:
relieving_date = getdate(self.end_date)
if not joining_date:
frappe.throw(_("Please set the Date Of Joining for employee {0}").format(frappe.bold(self.employee_name)))
taxable_earnings = 0
additional_income = 0
additional_income_with_full_tax = 0
flexi_benefits = 0
for earning in self.earnings:
if based_on_payment_days:
amount, additional_amount = self.get_amount_based_on_payment_days(earning, joining_date, relieving_date)
else:
amount, additional_amount = earning.amount, earning.additional_amount
if earning.is_tax_applicable:
if flt(earning.additional_amount):
taxable_earnings += (earning.amount - earning.additional_amount)
additional_income += earning.additional_amount
if additional_amount:
taxable_earnings += (amount - additional_amount)
additional_income += additional_amount
if earning.deduct_full_tax_on_selected_payroll_date:
additional_income_with_full_tax += earning.additional_amount
additional_income_with_full_tax += additional_amount
continue
if earning.is_flexible_benefit:
flexi_benefits += earning.amount
flexi_benefits += amount
else:
taxable_earnings += earning.amount
taxable_earnings += amount
return frappe._dict({
"taxable_earnings": taxable_earnings,
@@ -584,6 +600,30 @@ class SalarySlip(TransactionBase):
"flexi_benefits": flexi_benefits
})
def get_amount_based_on_payment_days(self, row, joining_date, relieving_date):
amount, additional_amount = row.amount, row.additional_amount
if (self.salary_structure and
cint(row.depends_on_payment_days) and cint(self.total_working_days) and
(not self.salary_slip_based_on_timesheet or
getdate(self.start_date) < joining_date or
getdate(self.end_date) > relieving_date
)):
additional_amount = flt((flt(row.additional_amount) * flt(self.payment_days)
/ cint(self.total_working_days)), row.precision("additional_amount"))
amount = flt((flt(row.default_amount) * flt(self.payment_days)
/ cint(self.total_working_days)), row.precision("amount")) + additional_amount
elif not self.payment_days and not self.salary_slip_based_on_timesheet and cint(row.depends_on_payment_days):
amount, additional_amount = 0, 0
elif not row.amount:
amount = row.default_amount + row.additional_amount
# apply rounding
if frappe.get_cached_value("Salary Component", row.salary_component, "round_to_the_nearest_integer"):
amount, additional_amount = rounded(amount), rounded(additional_amount)
return amount, additional_amount
def calculate_unclaimed_taxable_benefits(self, payroll_period):
# get total sum of benefits paid
total_benefits_paid = flt(frappe.db.sql("""
@@ -685,7 +725,7 @@ class SalarySlip(TransactionBase):
return total
def set_component_amounts_based_on_payment_days(self):
joining_date, relieving_date = frappe.db.get_value("Employee", self.employee,
joining_date, relieving_date = frappe.get_cached_value("Employee", self.employee,
["date_of_joining", "relieving_date"])
if not relieving_date:
@@ -696,22 +736,7 @@ class SalarySlip(TransactionBase):
for component_type in ("earnings", "deductions"):
for d in self.get(component_type):
if (self.salary_structure and
cint(d.depends_on_payment_days) and cint(self.total_working_days) and
(not self.salary_slip_based_on_timesheet or
getdate(self.start_date) < joining_date or
getdate(self.end_date) > relieving_date
)):
d.amount = flt(
(flt(d.default_amount + d.additional_amount) * flt(self.payment_days)
/ cint(self.total_working_days))
, d.precision("amount"))
elif not self.payment_days and not self.salary_slip_based_on_timesheet and cint(d.depends_on_payment_days):
d.amount = 0
elif not d.amount:
d.amount = d.default_amount + d.additional_amount
d.amount = self.get_amount_based_on_payment_days(d, joining_date, relieving_date)[0]
def set_loan_repayment(self):
self.set('loans', [])

View File

@@ -211,7 +211,7 @@ class TestSalarySlip(unittest.TestCase):
tax_paid = get_tax_paid_in_period(employee)
# total taxable income 586000, 250000 @ 5%, 86000 @ 20% ie. 12500 + 17200
annual_tax = 113567.79
annual_tax = 113568
try:
self.assertEqual(tax_paid, annual_tax)
except AssertionError:
@@ -250,7 +250,7 @@ class TestSalarySlip(unittest.TestCase):
# total taxable income 416000, 166000 @ 5% ie. 8300
try:
self.assertEqual(tax_paid, 88607.79)
self.assertEqual(tax_paid, 88608)
except AssertionError:
print("\nSalary Slip - Tax calculation failed on following case\n", data, "\n")
raise
@@ -265,7 +265,7 @@ class TestSalarySlip(unittest.TestCase):
# total taxable income 566000, 250000 @ 5%, 66000 @ 20%, 12500 + 13200
tax_paid = get_tax_paid_in_period(employee)
try:
self.assertEqual(tax_paid, 121211.48)
self.assertEqual(tax_paid, 121211)
except AssertionError:
print("\nSalary Slip - Tax calculation failed on following case\n", data, "\n")
raise
@@ -442,7 +442,9 @@ def make_deduction_salary_component(setup=False, test_tax=False):
"formula": 'base*.1',
"type": "Deduction",
"amount_based_on_formula": 1,
"depends_on_payment_days": 0
"depends_on_payment_days": 0,
"variable_based_on_taxable_salary": 1,
"round_to_the_nearest_integer": 1
}
]
if not test_tax:
@@ -452,7 +454,8 @@ def make_deduction_salary_component(setup=False, test_tax=False):
"condition": 'employment_type=="Intern"',
"formula": 'base*.1',
"type": "Deduction",
"amount_based_on_formula": 1
"amount_based_on_formula": 1,
"round_to_the_nearest_integer": 1
})
if setup or test_tax:
make_salary_component(data, test_tax)

View File

@@ -19,12 +19,12 @@ def execute(filters=None):
data = []
for ss in salary_slips:
row = [ss.name, ss.employee, ss.employee_name, ss.branch, ss.department, ss.designation,
ss.company, ss.start_date, ss.end_date, ss.leave_withut_pay, ss.payment_days]
ss.company, ss.start_date, ss.end_date, ss.leave_without_pay, ss.payment_days]
if not ss.branch == None:columns[3] = columns[3].replace('-1','120')
if not ss.department == None: columns[4] = columns[4].replace('-1','120')
if not ss.designation == None: columns[5] = columns[5].replace('-1','120')
if not ss.leave_withut_pay == None: columns[9] = columns[9].replace('-1','130')
if not ss.leave_without_pay == None: columns[9] = columns[9].replace('-1','130')
for e in earning_types:
@@ -117,4 +117,4 @@ def get_ss_ded_map(salary_slips):
ss_ded_map.setdefault(d.parent, frappe._dict()).setdefault(d.salary_component, [])
ss_ded_map[d.parent][d.salary_component] = flt(d.amount)
return ss_ded_map
return ss_ded_map

View File

@@ -90,7 +90,7 @@ class TestBOM(unittest.TestCase):
self.assertEqual(bom.base_total_cost, 486000)
def test_bom_cost_multi_uom_multi_currency_based_on_price_list(self):
frappe.db.set_value("Price List", "_Test Price List", "price_not_uom_dependant", 1)
frappe.db.set_value("Price List", "_Test Price List", "price_not_uom_dependent", 1)
for item_code, rate in (("_Test Item", 3600), ("_Test Item Home Desktop Manufactured", 3000)):
frappe.db.sql("delete from `tabItem Price` where price_list='_Test Price List' and item_code=%s",
item_code)

View File

@@ -18,21 +18,22 @@ class JobCard(Document):
self.total_completed_qty = 0.0
self.total_time_in_mins = 0.0
for d in self.get('time_logs'):
if get_datetime(d.from_time) > get_datetime(d.to_time):
frappe.throw(_("Row {0}: From time must be less than to time").format(d.idx))
if self.get('time_logs'):
for d in self.get('time_logs'):
if get_datetime(d.from_time) > get_datetime(d.to_time):
frappe.throw(_("Row {0}: From time must be less than to time").format(d.idx))
data = self.get_overlap_for(d)
if data:
frappe.throw(_("Row {0}: From Time and To Time of {1} is overlapping with {2}")
.format(d.idx, self.name, data.name))
data = self.get_overlap_for(d)
if data:
frappe.throw(_("Row {0}: From Time and To Time of {1} is overlapping with {2}")
.format(d.idx, self.name, data.name))
if d.from_time and d.to_time:
d.time_in_mins = time_diff_in_hours(d.to_time, d.from_time) * 60
self.total_time_in_mins += d.time_in_mins
if d.from_time and d.to_time:
d.time_in_mins = time_diff_in_hours(d.to_time, d.from_time) * 60
self.total_time_in_mins += d.time_in_mins
if d.completed_qty:
self.total_completed_qty += d.completed_qty
if d.completed_qty:
self.total_completed_qty += d.completed_qty
def get_overlap_for(self, args):
existing = frappe.db.sql("""select jc.name as name from
@@ -112,8 +113,10 @@ class JobCard(Document):
for_quantity += doc.total_completed_qty
time_in_mins += doc.total_time_in_mins
for time_log in doc.time_logs:
from_time_list.append(time_log.from_time)
to_time_list.append(time_log.to_time)
if time_log.from_time:
from_time_list.append(time_log.from_time)
if time_log.to_time:
to_time_list.append(time_log.to_time)
if for_quantity:
wo = frappe.get_doc('Work Order', self.work_order)

View File

@@ -18,6 +18,7 @@ from erpnext.stock.stock_balance import get_planned_qty, update_bin_qty
from frappe.utils.csvutils import getlink
from erpnext.stock.utils import get_bin, validate_warehouse_company, get_latest_stock_qty
from erpnext.utilities.transaction_base import validate_uom_is_integer
from six import text_type
class OverProductionError(frappe.ValidationError): pass
class StockOverProductionError(frappe.ValidationError): pass
@@ -591,10 +592,10 @@ def make_timesheet(production_order, company):
@frappe.whitelist()
def add_timesheet_detail(timesheet, args):
if isinstance(timesheet, unicode):
if isinstance(timesheet, text_type):
timesheet = frappe.get_doc('Timesheet', timesheet)
if isinstance(args, unicode):
if isinstance(args, text_type):
args = json.loads(args)
timesheet.append('time_logs', args)

View File

@@ -533,7 +533,7 @@ erpnext.patches.v11_0.create_department_records_for_each_company
erpnext.patches.v11_0.make_location_from_warehouse
erpnext.patches.v11_0.make_asset_finance_book_against_old_entries
erpnext.patches.v11_0.check_buying_selling_in_currency_exchange
erpnext.patches.v11_0.move_item_defaults_to_child_table_for_multicompany #02-07-2018
erpnext.patches.v11_0.move_item_defaults_to_child_table_for_multicompany #02-07-2018 #19-06-2019
erpnext.patches.v11_0.refactor_erpnext_shopify #2018-09-07
erpnext.patches.v11_0.rename_overproduction_percent_field
erpnext.patches.v11_0.update_backflush_subcontract_rm_based_on_bom
@@ -586,7 +586,7 @@ erpnext.patches.v11_0.add_permissions_in_gst_settings
erpnext.patches.v11_1.setup_guardian_role
execute:frappe.delete_doc('DocType', 'Notification Control')
erpnext.patches.v11_0.remove_barcodes_field_from_copy_fields_to_variants
erpnext.patches.v10_0.item_barcode_childtable_migrate # 16-02-2019
erpnext.patches.v10_0.item_barcode_childtable_migrate # 16-02-2019 #25-06-2019
erpnext.patches.v11_0.make_italian_localization_fields # 26-03-2019
erpnext.patches.v11_1.make_job_card_time_logs
erpnext.patches.v11_1.set_variant_based_on
@@ -599,4 +599,7 @@ erpnext.patches.v11_1.rename_depends_on_lwp
erpnext.patches.v11_1.set_missing_title_for_quotation
execute:frappe.delete_doc("Report", "Inactive Items")
erpnext.patches.v11_1.delete_scheduling_tool
erpnext.patches.v11_1.update_bank_transaction_status
erpnext.patches.v11_1.update_bank_transaction_status
erpnext.patches.v11_1.renamed_delayed_item_report
erpnext.patches.v11_1.set_missing_opportunity_from
erpnext.patches.v11_1.set_quotation_status

View File

@@ -8,8 +8,10 @@ import frappe
def execute():
frappe.reload_doc("stock", "doctype", "item_barcode")
if frappe.get_all("Item Barcode", limit=1): return
if "barcode" not in frappe.db.get_table_columns("Item"): return
items_barcode = frappe.get_all('Item', ['name', 'barcode'], { 'barcode': ('!=', '') })
items_barcode = frappe.db.sql("select name, barcode from tabItem where barcode is not null", as_dict=True)
frappe.reload_doc("stock", "doctype", "item")

View File

@@ -17,10 +17,8 @@ def execute():
frappe.reload_doc('stock', 'doctype', 'item_default')
frappe.reload_doc('stock', 'doctype', 'item')
if frappe.db.a_row_exists('Item Default'): return
companies = frappe.get_all("Company")
if len(companies) == 1:
if len(companies) == 1 and not frappe.get_all("Item Default", limit=1):
try:
frappe.db.sql('''
INSERT INTO `tabItem Default`
@@ -35,32 +33,64 @@ def execute():
except:
pass
else:
item_details = frappe.get_all("Item", fields=["name", "default_warehouse", "buying_cost_center",
"expense_account", "selling_cost_center", "income_account"], limit=100)
item_details = frappe.db.sql(""" SELECT name, default_warehouse,
buying_cost_center, expense_account, selling_cost_center, income_account
FROM tabItem
WHERE
name not in (select distinct parent from `tabItem Default`) and ifnull(disabled, 0) = 0"""
, as_dict=1)
for item in item_details:
item_defaults = []
items_default_data = {}
for item_data in item_details:
for d in [["default_warehouse", "Warehouse"], ["expense_account", "Account"],
["income_account", "Account"], ["buying_cost_center", "Cost Center"],
["selling_cost_center", "Cost Center"]]:
if item_data.get(d[0]):
company = frappe.get_value(d[1], item_data.get(d[0]), "company", cache=True)
def insert_into_item_defaults(doc_field_name, doc_field_value, company):
for d in item_defaults:
if d.get("company") == company:
d[doc_field_name] = doc_field_value
return
item_defaults.append({
"company": company,
doc_field_name: doc_field_value
})
if item_data.name not in items_default_data:
items_default_data[item_data.name] = {}
for d in [
["default_warehouse", "Warehouse"], ["expense_account", "Account"], ["income_account", "Account"],
["buying_cost_center", "Cost Center"], ["selling_cost_center", "Cost Center"]
]:
if item.get(d[0]):
company = frappe.get_value(d[1], item.get(d[0]), "company", cache=True)
insert_into_item_defaults(d[0], item.get(d[0]), company)
company_wise_data = items_default_data[item_data.name]
doc = frappe.get_doc("Item", item.name)
doc.extend("item_defaults", item_defaults)
if company not in company_wise_data:
company_wise_data[company] = {}
for child_doc in doc.item_defaults:
child_doc.db_insert()
default_data = company_wise_data[company]
default_data[d[0]] = item_data.get(d[0])
to_insert_data = []
# items_default_data data structure will be as follow
# {
# 'item_code 1': {'company 1': {'default_warehouse': 'Test Warehouse 1'}},
# 'item_code 2': {
# 'company 1': {'default_warehouse': 'Test Warehouse 1'},
# 'company 2': {'default_warehouse': 'Test Warehouse 1'}
# }
# }
for item_code, companywise_item_data in items_default_data.items():
for company, item_default_data in companywise_item_data.items():
to_insert_data.append((
frappe.generate_hash("", 10),
item_code,
'Item',
'item_defaults',
company,
item_default_data.get('default_warehouse'),
item_default_data.get('expense_account'),
item_default_data.get('income_account'),
item_default_data.get('buying_cost_center'),
item_default_data.get('selling_cost_center'),
))
if to_insert_data:
frappe.db.sql('''
INSERT INTO `tabItem Default`
(
`name`, `parent`, `parenttype`, `parentfield`, `company`, `default_warehouse`,
`expense_account`, `income_account`, `buying_cost_center`, `selling_cost_center`
)
VALUES {}
'''.format(', '.join(['%s'] * len(to_insert_data))), tuple(to_insert_data))

View File

@@ -40,7 +40,7 @@ def execute():
# This is probably never used anywhere else as of now, but should be
values = []
for d in batch_transactions:
values.append("('{}', {})".format(d.parent, d.qty))
values.append("('{}', {})".format(frappe.db.escape(d.parent), d.qty))
conditions = ",".join(values)
frappe.db.sql("""
INSERT INTO `tab{}` (name, total_qty) VALUES {}

View File

@@ -0,0 +1,10 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe
def execute():
for report in ["Delayed Order Item Summary", "Delayed Order Summary"]:
if frappe.db.exists("Report", report):
frappe.delete_doc("Report", report)

View File

@@ -0,0 +1,17 @@
from __future__ import unicode_literals
import frappe
def execute():
frappe.reload_doctype("Opportunity")
if frappe.db.has_column("Opportunity", "enquiry_from"):
frappe.db.sql(""" UPDATE `tabOpportunity` set opportunity_from = enquiry_from
where ifnull(opportunity_from, '') = '' and ifnull(enquiry_from, '') != ''""")
if frappe.db.has_column("Opportunity", "lead") and frappe.db.has_column("Opportunity", "enquiry_from"):
frappe.db.sql(""" UPDATE `tabOpportunity` set party_name = lead
where enquiry_from = 'Lead' and ifnull(party_name, '') = '' and ifnull(lead, '') != ''""")
if frappe.db.has_column("Opportunity", "customer") and frappe.db.has_column("Opportunity", "enquiry_from"):
frappe.db.sql(""" UPDATE `tabOpportunity` set party_name = customer
where enquiry_from = 'Customer' and ifnull(party_name, '') = '' and ifnull(customer, '') != ''""")

View File

@@ -0,0 +1,7 @@
from __future__ import unicode_literals
import frappe
def execute():
frappe.db.sql(""" UPDATE `tabQuotation` set status = 'Open'
where docstatus = 1 and status = 'Submitted' """)

View File

@@ -19,43 +19,38 @@ frappe.ui.form.on("Task", {
},
refresh: function(frm) {
frm.fields_dict['parent_task'].get_query = function() {
frm.fields_dict['parent_task'].get_query = function () {
return {
filters: {
"is_group": 1,
}
}
}
if(!frm.is_group){
var doc = frm.doc;
if(doc.__islocal) {
if(!frm.doc.exp_end_date) {
frm.set_value("exp_end_date", frappe.datetime.add_days(new Date(), 7));
}
}
if(!doc.__islocal) {
if(frappe.model.can_read("Timesheet")) {
frm.add_custom_button(__("Timesheet"), function() {
frappe.route_options = {"project": doc.project, "task": doc.name}
if (!frm.doc.is_group) {
if (!frm.is_new()) {
if (frappe.model.can_read("Timesheet")) {
frm.add_custom_button(__("Timesheet"), () => {
frappe.route_options = { "project": frm.doc.project, "task": frm.doc.name }
frappe.set_route("List", "Timesheet");
}, __("View"), true);
}
if(frappe.model.can_read("Expense Claim")) {
frm.add_custom_button(__("Expense Claims"), function() {
frappe.route_options = {"project": doc.project, "task": doc.name}
if (frappe.model.can_read("Expense Claim")) {
frm.add_custom_button(__("Expense Claims"), () => {
frappe.route_options = { "project": frm.doc.project, "task": frm.doc.name }
frappe.set_route("List", "Expense Claim");
}, __("View"), true);
}
if(frm.perm[0].write) {
if(frm.doc.status!=="Closed" && frm.doc.status!=="Cancelled") {
frm.add_custom_button(__("Close"), function() {
if (frm.perm[0].write) {
if (!["Closed", "Cancelled"].includes(frm.doc.status)) {
frm.add_custom_button(__("Close"), () => {
frm.set_value("status", "Closed");
frm.save();
});
} else {
frm.add_custom_button(__("Reopen"), function() {
frm.add_custom_button(__("Reopen"), () => {
frm.set_value("status", "Open");
frm.save();
});

View File

@@ -103,8 +103,8 @@ class TestTimesheet(unittest.TestCase):
{
"billable": 1,
"activity_type": "_Test Activity Type",
"from_type": now_datetime(),
"hours": 3,
"from_time": now_datetime(),
"to_time": now_datetime() + datetime.timedelta(hours=3),
"company": "_Test Company"
}
)
@@ -113,8 +113,8 @@ class TestTimesheet(unittest.TestCase):
{
"billable": 1,
"activity_type": "_Test Activity Type",
"from_type": now_datetime(),
"hours": 3,
"from_time": now_datetime(),
"to_time": now_datetime() + datetime.timedelta(hours=3),
"company": "_Test Company"
}
)

View File

@@ -30,23 +30,23 @@ def get_columns():
"options": "Timesheet",
"width": 150
},
{
"label": _("Billable Hours"),
"fieldtype": "Float",
"fieldname": "total_billable_hours",
"width": 50
},
{
"label": _("Working Hours"),
"fieldtype": "Float",
"fieldname": "total_hours",
"width": 50
"width": 150
},
{
"label": _("Billable Hours"),
"fieldtype": "Float",
"fieldname": "total_billable_hours",
"width": 150
},
{
"label": _("Billing Amount"),
"fieldtype": "Currency",
"fieldname": "amount",
"width": 100
"width": 150
}
]

View File

@@ -514,7 +514,7 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
net_total += item.net_amount;
// discount amount rounding loss adjustment if no taxes
if ((!(me.frm.doc.taxes || []).length || (me.frm.doc.apply_discount_on == "Net Total"))
if ((!(me.frm.doc.taxes || []).length || total_for_discount_amount==me.frm.doc.net_total || (me.frm.doc.apply_discount_on == "Net Total"))
&& i == (me.frm.doc.items || []).length - 1) {
var discount_amount_loss = flt(me.frm.doc.net_total - net_total
- me.frm.doc.discount_amount, precision("net_total"));

View File

@@ -1121,7 +1121,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
return {
"items": this._get_item_list(item),
"customer": me.frm.doc.customer || me.frm.doc.party_name,
"quotation_to": me.doc.frm.quotation_to,
"quotation_to": me.frm.doc.quotation_to,
"customer_group": me.frm.doc.customer_group,
"territory": me.frm.doc.territory,
"supplier": me.frm.doc.supplier,
@@ -1291,7 +1291,12 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
callback: function(r) {
if(!r.exc) {
me.frm.set_value("taxes", r.message);
me.calculate_taxes_and_totals();
if(me.frm.doc.shipping_rule) {
me.frm.script_manager.trigger("shipping_rule");
} else {
me.calculate_taxes_and_totals();
}
}
}
});

View File

@@ -21,7 +21,7 @@
<hr>
<div class="row">
<div class="col-sm-6 ">
<div class ="row multimode-payments">
<div class ="row multimode-payments" style = "margin-right:10px">
</div>
</div>
<div class="col-sm-6 payment-toolbar">

View File

@@ -286,6 +286,16 @@ $.extend(erpnext.utils, {
refresh_field(table_fieldname);
},
create_new_doc: function (doctype, update_fields) {
frappe.model.with_doctype(doctype, function() {
var new_doc = frappe.model.get_new_doc(doctype);
for (let [key, value] of Object.entries(update_fields)) {
new_doc[key] = value;
}
frappe.ui.form.make_quick_entry(doctype, null, null, new_doc);
});
}
});
erpnext.utils.select_alternate_items = function(opts) {

View File

@@ -233,30 +233,32 @@ erpnext.SerialNoBatchSelector = Class.extend({
get_batch_fields: function() {
var me = this;
return [
{fieldtype:'Section Break', label: __('Batches')},
{fieldname: 'batches', fieldtype: 'Table',
{ fieldtype: 'Section Break', label: __('Batches') },
{
fieldname: 'batches', fieldtype: 'Table',
fields: [
{
fieldtype:'Link',
fieldname:'batch_no',
options: 'Batch',
label: __('Select Batch'),
in_list_view:1,
get_query: function() {
'fieldtype': 'Link',
'read_only': 0,
'fieldname': 'batch_no',
'options': 'Batch',
'label': __('Select Batch'),
'in_list_view': 1,
get_query: function () {
return {
filters: {item: me.item_code },
query: 'erpnext.controllers.queries.get_batch_numbers'
};
filters: { item: me.item_code },
query: 'erpnext.controllers.queries.get_batch_numbers'
};
},
onchange: function(e) {
change: function () {
let val = this.get_value();
if(val.length === 0) {
if (val.length === 0) {
this.grid_row.on_grid_fields_dict
.available_qty.set_value(0);
return;
}
let selected_batches = this.grid.grid_rows.map((row) => {
if(row === this.grid_row) {
if (row === this.grid_row) {
return "";
}
@@ -264,12 +266,12 @@ erpnext.SerialNoBatchSelector = Class.extend({
return row.on_grid_fields_dict.batch_no.get_value();
}
});
if(selected_batches.includes(val)) {
if (selected_batches.includes(val)) {
this.set_value("");
frappe.throw(__(`Batch ${val} already selected.`));
return;
}
if(me.warehouse_details.name) {
if (me.warehouse_details.name) {
frappe.call({
method: 'erpnext.stock.doctype.batch.batch.get_batch_qty',
args: {
@@ -292,31 +294,32 @@ erpnext.SerialNoBatchSelector = Class.extend({
}
},
{
fieldtype:'Float',
read_only:1,
fieldname:'available_qty',
label: __('Available'),
in_list_view:1,
default: 0,
onchange: function() {
'fieldtype': 'Float',
'read_only': 1,
'fieldname': 'available_qty',
'label': __('Available'),
'in_list_view': 1,
'default': 0,
change: function () {
this.grid_row.on_grid_fields_dict.selected_qty.set_value('0');
}
},
{
fieldtype:'Float',
fieldname:'selected_qty',
label: __('Qty'),
in_list_view:1,
'fieldtype': 'Float',
'read_only': 0,
'fieldname': 'selected_qty',
'label': __('Qty'),
'in_list_view': 1,
'default': 0,
onchange: function(e) {
change: function () {
var batch_no = this.grid_row.on_grid_fields_dict.batch_no.get_value();
var available_qty = this.grid_row.on_grid_fields_dict.available_qty.get_value();
var selected_qty = this.grid_row.on_grid_fields_dict.selected_qty.get_value();
if(batch_no.length === 0 && parseInt(selected_qty)!==0) {
if (batch_no.length === 0 && parseInt(selected_qty) !== 0) {
frappe.throw(__("Please select a batch"));
}
if(me.warehouse_details.type === 'Source Warehouse' &&
if (me.warehouse_details.type === 'Source Warehouse' &&
parseFloat(available_qty) < parseFloat(selected_qty)) {
this.set_value('0');
@@ -332,7 +335,7 @@ erpnext.SerialNoBatchSelector = Class.extend({
],
in_place_edit: true,
data: this.data,
get_data: function() {
get_data: function () {
return this.data;
},
}
@@ -342,13 +345,24 @@ erpnext.SerialNoBatchSelector = Class.extend({
get_serial_no_fields: function() {
var me = this;
this.serial_list = [];
let serial_no_filters = {
item_code: me.item_code,
delivery_document_no: ""
}
if (me.warehouse_details.name) {
serial_no_filters['warehouse'] = me.warehouse_details.name;
}
return [
{fieldtype: 'Section Break', label: __('Serial No')},
{
fieldtype: 'Link', fieldname: 'serial_no_select', options: 'Serial No',
label: __('Select'),
get_query: function() {
return { filters: {item_code: me.item_code, warehouse: me.warehouse_details.name}};
return {
filters: serial_no_filters
};
},
onchange: function(e) {
if(this.in_local_change) return;

View File

@@ -367,6 +367,20 @@ def generate_ewb_json(dt, dn):
frappe.local.response.filename = '{0}_e-WayBill_Data_{1}.json'.format(doc_name, frappe.utils.random_string(5))
@frappe.whitelist()
def get_gstins_for_company(company):
company_gstins =[]
if company:
company_gstins = frappe.db.sql("""select
distinct `tabAddress`.gstin
from
`tabAddress`, `tabDynamic Link`
where
`tabDynamic Link`.parent = `tabAddress`.name and
`tabDynamic Link`.parenttype = 'Address' and
`tabDynamic Link`.link_doctype = 'Company' and
`tabDynamic Link`.link_name = '{0}'""".format(company))
return company_gstins
def get_address_details(data, doc, company_address, billing_address):
data.fromPincode = validate_pincode(company_address.pincode, 'Company Address')

View File

@@ -118,7 +118,7 @@
<DatiGenerali>
<DatiGeneraliDocumento>
<TipoDocumento>{{ doc.type_of_document }}</TipoDocumento>
<Divisa>EUR</Divisa>
<Divisa>{{ doc.currency }}</Divisa>
<Data>{{ doc.posting_date }}</Data>
<Numero>{{ doc.unamended_name }}</Numero>
{%- if doc.stamp_duty %}

View File

@@ -80,8 +80,7 @@ def prepare_invoice(invoice, progressive_number):
invoice.stamp_duty = stamp_duty_charge_row.tax_amount
for item in invoice.e_invoice_items:
if (item.tax_rate == 0.0 and item.tax_amount == 0.0
and item.charge_type != 'Actual' and tax_data.get("0.0")):
if item.tax_rate == 0.0 and item.tax_amount == 0.0 and tax_data.get("0.0"):
item.tax_exemption_reason = tax_data["0.0"]["tax_exemption_reason"]
customer_po_data = {}

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