Compare commits

...

223 Commits

Author SHA1 Message Date
Nabin Hait
f7d81c7a7f Merge branch 'develop' 2017-04-25 20:44:54 +05:30
Nabin Hait
5b73a4864a bumped to version 8.0.18 2017-04-25 21:14:54 +06:00
Nabin Hait
85622f9ccb Update update_status_as_paid_for_completed_expense_claim.py 2017-04-25 20:43:29 +05:30
pawan
c27d9f712b Add Report Links 2017-04-25 20:12:55 +05:30
Umair Sayyed
175646572a updated help pages 2017-04-25 16:27:50 +05:30
Nabin Hait
7cfacb315b Merge branch 'RicardoJohann-accumulated_header_std' into develop 2017-04-25 16:26:53 +05:30
Nabin Hait
d5d8db7a3f Cleanup on financial statement PR 2017-04-25 16:26:33 +05:30
Nabin Hait
39bcb3de4b Merge branch 'accumulated_header_std' of https://github.com/RicardoJohann/erpnext into RicardoJohann-accumulated_header_std 2017-04-25 16:13:54 +05:30
Ishan Loya
09fe8e0522 Add bank guarantee to Accounts module display screen 2017-04-25 16:08:22 +05:30
Ishan Loya
17737e4ab1 Change permissions, change account fieldname and add notes section 2017-04-25 16:08:22 +05:30
Ishan Loya
2fca72ae8e Change owner 2017-04-25 16:08:22 +05:30
Ishan Loya
0dbe8547e7 Add screenshot to documentation, change naming series to BG-#####, make Bank Guarantee number unique 2017-04-25 16:08:22 +05:30
Ishan Loya
e1ed5ba726 Remove commented out code 2017-04-25 16:08:22 +05:30
Ishan Loya
0fc57a7df2 Change doctype owner 2017-04-25 16:08:22 +05:30
Ishan Loya
c7a72684fd Add bank guarantee doctype with documentation 2017-04-25 16:08:22 +05:30
Nabin Hait
e0c34bfd77 Merge branch 'PawanMeh-fixes_8466' into develop 2017-04-25 16:05:28 +05:30
Nabin Hait
020dedd00e Cleaned up and commonified the campaign efficiency and lead owner efficiency report 2017-04-25 16:05:01 +05:30
Nabin Hait
28dad095fa Merge branch 'fixes_8466' of https://github.com/PawanMeh/erpnext into PawanMeh-fixes_8466 2017-04-25 15:00:45 +05:30
Nabin Hait
e7125c0ea2 Merge branch 'develop' 2017-04-25 14:30:50 +05:30
Nabin Hait
8590d5b05d bumped to version 8.0.17 2017-04-25 15:00:50 +06:00
sburanaw
66951e528f Fix an import typo in get_item_details.py 2017-04-25 14:09:51 +05:30
Nabin Hait
9b20e07431 [fix] currency field precision 2017-04-25 14:09:29 +05:30
Manas Solanki
d7afa69c6f fix 2017-04-25 14:08:43 +05:30
Manas Solanki
c61dc9c7ea Change in the assessment tool 2017-04-25 14:08:43 +05:30
mbauskar
9cf6d630e9 [minor] fixes for expense claim status 2017-04-25 13:15:50 +05:30
Faris Ansari
5687e2da9d [ui-fix] POS item list 2017-04-24 19:22:05 +05:30
Nabin Hait
e3c122d8c4 AR report: filter based on customer group and credit days based on field. Fixed #8214 2017-04-24 19:06:07 +05:30
Nabin Hait
4cc5e61f60 Update course_schedule.py 2017-04-24 19:00:49 +05:30
Manas Solanki
6293263095 test case fixed 2017-04-24 19:00:49 +05:30
Manas Solanki
810e483757 Changes in the student group 2017-04-24 19:00:49 +05:30
Nabin Hait
398f144833 Merge branch 'develop' 2017-04-24 18:59:01 +05:30
Nabin Hait
e2741e85fd bumped to version 8.0.16 2017-04-24 19:29:01 +06:00
Rohit Waghchaure
dd70fbfdae [fix] Letter head not showing in the report 2017-04-24 18:57:51 +05:30
Manas Solanki
6eaf281b2b Export and import program enrollments 2017-04-24 18:44:12 +05:30
pawan
134487ab2a Changes after review 2017-04-24 13:48:40 +05:30
pawan
7bd7df3742 Changes after review 2017-04-24 13:19:22 +05:30
Ishan Loya
56c1b2a625 Make proposed corrections 2017-04-24 10:44:36 +05:30
Ishan Loya
b12e15dcc4 Change modified by 2017-04-24 10:44:36 +05:30
Ishan Loya
e5fdd47fd8 Hide 'Qty Transferred for Manufacturing' field if skip material transfer 2017-04-24 10:44:36 +05:30
Ishan Loya
04c69fb46d Minor fix 2017-04-24 10:44:36 +05:30
Ishan Loya
f04ef8dfe0 Update documentation for Production Order skipping material transfer entry option 2017-04-24 10:44:36 +05:30
Ishan Loya
7544904857 Add option to skip material transfer for production orders 2017-04-24 10:44:36 +05:30
Rushabh Mehta
c44910370b [fix] is_sample_item 2017-04-24 10:28:38 +05:30
Rushabh Mehta
551406ab11 [enhance] automatic batch selection in Delivery Note and Stock Entry 2017-04-24 10:28:38 +05:30
Rushabh Mehta
e385b5b97b [enhance] automatic batch creation, move and split 2017-04-24 10:28:38 +05:30
mbauskar
bb2670d57a [fixes] minor fixes in bank reconciliation form and report 2017-04-24 10:23:50 +05:30
mbauskar
0b293133be [minor] fixes for unsupported operand type(s) for +=: 'int' and 'NoneType' 2017-04-21 21:40:30 +05:30
ibi
83c1c3a171 fleet_management: replace references to fleet_management by hr in vehicle_log doctype 2017-04-21 17:57:07 +05:30
mbauskar
c3d642e5d1 [minor] allow bulk edit for doctype 2017-04-21 17:50:40 +05:30
Manas Solanki
8230ce095f [Fix] fixed routing to the assessment result 2017-04-21 17:49:52 +05:30
Nabin Hait
e713a7d840 Merge branch 'develop' 2017-04-21 11:49:09 +05:30
Nabin Hait
557847a5ba bumped to version 8.0.15 2017-04-21 12:19:09 +06:00
mbauskar
9bac58cdc6 [fixes] fixes in setup wizard for education domain 2017-04-21 11:38:28 +05:30
Nabin Hait
5650bf9ba5 Merge branch 'develop' 2017-04-20 08:51:44 +05:30
Nabin Hait
9afb53203f bumped to version 8.0.14 2017-04-20 09:21:44 +06:00
Nabin Hait
825e053e66 Fixed project_copied_from patch 2017-04-20 08:50:37 +05:30
Nabin Hait
3e519770de Merge pull request #8505 from nabinhait/develop
Fixed allow_zero_valuation_rate patch
2017-04-20 08:46:30 +05:30
Nabin Hait
e42fb32f6f Fixed allow_zero_valuation_rate patch 2017-04-20 08:45:18 +05:30
Nabin Hait
00bec1c272 Merge pull request #8504 from nabinhait/allow_on_submit_fix
Fixes allowed on submit
2017-04-19 21:11:13 +05:30
Nabin Hait
68ae9f3f88 Merge branch 'develop' into allow_on_submit_fix 2017-04-19 21:10:23 +05:30
mbauskar
8f3cc81302 [minor] minor fixes in pricing_rule and set_missing_value 2017-04-19 21:05:37 +05:30
mbauskar
9e9d242a24 [minor] fixes in test cases and added the test case for multiple uom in selling 2017-04-19 21:05:37 +05:30
mbauskar
287fe81329 [minor] calculate price list rate based on items uom 2017-04-19 21:05:37 +05:30
Nabin Hait
24053478a1 Merge pull request #8486 from nabinhait/develop
Asset Depreciation Enhancements
2017-04-19 21:01:34 +05:30
Nabin Hait
f382373cf4 Merge branch 'develop' into develop 2017-04-19 21:01:19 +05:30
CH
61f4a8e757 Make the address type translatable in the Address_HTML field 2017-04-19 20:58:53 +05:30
Nabin Hait
eef55185fc Update purchase_receipt_item.json 2017-04-19 20:58:09 +05:30
Nabin Hait
8691e0777b Update purchase_invoice_item.json 2017-04-19 20:58:09 +05:30
Nabin Hait
2de3bf7a0f Fixed indexes on sales and purchase transactions 2017-04-19 20:58:09 +05:30
Julian Robbins
2e6f12b850 Update purchase-details.md 2017-04-19 20:55:04 +05:30
mbauskar
ba41242f1f [fixes] fixed the pricing rule issue https://github.com/frappe/erpnext/issues/8493 2017-04-19 20:54:23 +05:30
Kanchan Chauhan
0633df5872 Item variant searchable in website products 2017-04-19 20:51:43 +05:30
Rohit Waghchaure
f4f774d1df [fix] offline_pos_name is not defined during print from the POS 2017-04-19 20:50:35 +05:30
Faris Ansari
695327a513 Duplicate dependencies when project is duplicated
- fix frappe/erpnext#8274
2017-04-19 20:48:49 +05:30
Rohit Waghchaure
019501e4a0 [fix] Balance Sheet, linking account to general ledger is not working 2017-04-19 20:46:30 +05:30
Nabin Hait
2704162f5a Fixes allowd on submit 2017-04-19 16:25:39 +05:30
Nabin Hait
117be7ddd5 Added a settings in Accounts Settings to disable booking depreciation entry automatically 2017-04-18 14:03:06 +05:30
Nabin Hait
f59920500c Merge branch 'develop' of github.com:nabinhait/erpnext into develop 2017-04-18 13:13:38 +05:30
Nabin Hait
8a01980757 Unlink Journal Entry reference from Asset 2017-04-18 13:11:10 +05:30
mbauskar
5123a8519b [minor] check if joining date is available before validating attandance date 2017-04-18 11:08:57 +05:30
Rohit Waghchaure
d7de3c606b [fix] Pricing rule for pos 2017-04-17 17:32:36 +05:30
Rohit Waghchaure
dc981dc546 [fix] Auto serial no fecthed on the invoice even if stock update is disabled issue 2017-04-17 17:31:32 +05:30
Nabin Hait
ed019123e2 Merge branch 'develop' 2017-04-17 15:36:59 +05:30
Nabin Hait
4d1cf53466 bumped to version 8.0.13 2017-04-17 16:06:58 +06:00
Nabin Hait
e2431fd5e9 minor fix 2017-04-17 15:35:36 +05:30
Nabin Hait
d12a4f5e8c Merge branch 'develop' 2017-04-17 15:12:18 +05:30
Nabin Hait
ad65be8250 bumped to version 8.0.12 2017-04-17 15:42:17 +06:00
Manas Solanki
ae30026005 Calender view fix for course schedule 2017-04-17 14:55:54 +05:30
Manas Solanki
54c4240d9c Changes in the program enrollment 2017-04-17 14:55:54 +05:30
Manas Solanki
79683d0871 Added school setting 2017-04-17 14:55:54 +05:30
Manas Solanki
a6d1876958 Changes in course and program 2017-04-17 14:55:54 +05:30
Manas Solanki
346928f2bc changes in program enrollment and tool 2017-04-17 14:55:54 +05:30
Nabin Hait
310d238d17 Merge pull request #8460 from rohitwaghchaure/client_followup_report
Client followup report
2017-04-17 14:13:38 +05:30
Nabin Hait
5e25731188 Update crm_reports.md 2017-04-17 14:13:20 +05:30
Nabin Hait
83ca262e38 Merge pull request #8453 from StrellaGroup/develop
[fix] Stock Entry - Change "Is Sample Item" to "Allow Zero Valuation Rate"
2017-04-17 14:00:12 +05:30
mbauskar
8a2e6f427b [minor] if address is not found then set the address_field to '' instead of None 2017-04-17 13:58:52 +05:30
Faris Ansari
8371c1c4cd Text overflow fix for product text in portal 2017-04-17 13:57:19 +05:30
Julian Robbins
361e7f6ddc Remove typos and use better English 2017-04-17 13:56:53 +05:30
rohitwaghchaure
798fd3484f Merge pull request #8469 from mbauskar/pos-fixes
[minor] POS & RFQ format_number fixes
2017-04-17 13:04:24 +05:30
mbauskar
22cedeb006 [minor] POS & RFQ format_number fixes 2017-04-17 12:24:24 +05:30
pawan
83c8ed0827 ”[fix] 2017-04-17 01:02:56 +05:30
Rushabh Mehta
e3c117e32c [fix] validate preferred email if set in employee.py 2017-04-15 16:59:39 +05:30
Nabin Hait
68a8b0c2a9 Merge branch 'develop' 2017-04-14 17:32:37 +05:30
Nabin Hait
307543f968 bumped to version 8.0.11 2017-04-14 18:02:37 +06:00
Rohit Waghchaure
6681b0d2aa Documentation 2017-04-14 17:14:03 +05:30
Javier Wong
54d9c9eaf4 Merge branch 'develop' into develop 2017-04-14 18:33:44 +08:00
Javier Wong
9b11d9b45d [fix] Stock Entry - Change "Is Sample Item" to "Allow Zero Valuation Rate" 2017-04-14 18:24:04 +08:00
mbauskar
cca55ddc33 [minor][hot] fixes for KeyError: from_date for stock balance report 2017-04-14 14:54:11 +05:30
Rohit Waghchaure
1c68509426 [enhance] Report for prospects engaged but not converted 2017-04-14 12:28:59 +05:30
mbauskar
1e05077b1f [minor] sales register report fixes 2017-04-14 09:59:49 +05:30
joezsweet
b81244342f Create en-GB.csv
- added for compatibility with frappe languages
2017-04-13 19:09:06 +05:30
CH
8e92250798 Correction of issue #8354 2017-04-13 18:59:51 +05:30
CH
d20ec25c92 Removal of double brackets to setup the chart of accounts in the setup wizard 2017-04-13 18:59:06 +05:30
Nabin Hait
25bcb14c1d Merge pull request #8440 from mbauskar/cart-fixes
[minor] fides for add to card button issue
2017-04-13 18:49:22 +05:30
Nabin Hait
f6149f1507 Merge pull request #8429 from ckosiegbu/payroll_updates
Statistical Components for Salary Structure
2017-04-13 18:48:47 +05:30
Nabin Hait
2f3585f949 Update salary_slip.js 2017-04-13 18:47:25 +05:30
mbauskar
ed8ad9cfee [minor] fides for add to card button issue 2017-04-13 18:45:09 +05:30
Nabin Hait
3a2727c9eb Merge pull request #8430 from mbauskar/stock-entry-supplier-address
[minor] fetch supplier address, address_display on supplier trigger
2017-04-13 18:45:09 +05:30
Nabin Hait
16d92e7270 Update update_supplier_address_in_stock_entry.py 2017-04-13 18:44:33 +05:30
Nabin Hait
8c7eb444ef Merge pull request #8439 from mbauskar/subsciption-fixes
[minor] validate email address before get update button click
2017-04-13 18:41:49 +05:30
mbauskar
9a0efc7710 [minor] validate email address before get update button click 2017-04-13 18:18:18 +05:30
mbauskar
3ddfce4f17 [patch] move supplier_address to address_display and set supplier_address in SE 2017-04-13 16:46:41 +05:30
ckosiegbu
a236f4e586 Space to Tabs on salary_slip.py 2017-04-13 10:28:10 +01:00
Nabin Hait
0b62c6ebd4 Merge pull request #8432 from mbauskar/bom-tree-fixes
[minor] fixes in bom tree view template
2017-04-13 14:36:45 +05:30
mbauskar
40ca4c3bbb [minor] fixes in bom tree view template 2017-04-13 14:29:19 +05:30
Nabin Hait
c454dc7af5 Merge pull request #8420 from netchampfaris/pos
[POS] Show stock quantity of items
2017-04-13 13:26:58 +05:30
Rushabh Mehta
994cef5ee3 [minor] fix imports in old patches 2017-04-13 13:14:05 +05:30
Faris Ansari
185762aeeb update label 2017-04-13 12:36:08 +05:30
mbauskar
1b32d913a2 [minor] fetch supplier address, address_display on supplier trigger 2017-04-13 11:55:20 +05:30
ckosiegbu
64f29f819a Introduce the ability to specify in a Salary Structure that a component is statistical. This allows components to be used in calculations without being added/deducted from earnings deductions. 2017-04-13 00:00:37 +01:00
Nabin Hait
2efe05c1ce Merge pull request #8263 from frappe/revert-8126-issue8094
Revert "Add link field Package Code (fixes #8094)"
2017-04-12 19:50:43 +05:30
Nabin Hait
17c675547d Merge branch 'develop' 2017-04-12 19:00:52 +05:30
Nabin Hait
a220e96867 bumped to version 8.0.10 2017-04-12 19:30:52 +06:00
mbauskar
e471b02172 [minor] if packed item warehouse not found then set the parent item warehouse to packed items 2017-04-12 18:51:01 +05:30
Faris Ansari
19f90e984e [POS] Show stock quantity of items
- frappe/erpnext#8247
2017-04-12 16:06:31 +05:30
Faris Ansari
b5608f9b14 [fix] Default Print Format for Sales Invoice (#8419)
- frappe/erpnext#8416
2017-04-12 15:31:01 +05:30
rohitwaghchaure
5adce495aa Merge pull request #8417 from rohitwaghchaure/due_date_issue
[fix] POS, Due Date cannot be before Posting Date
2017-04-12 14:43:21 +05:30
Rushabh Mehta
66272a168d [minor] README.md + encode query parameter in search 2017-04-12 14:32:07 +05:30
Rohit Waghchaure
2192c244c0 [fix] POS, Due Date cannot be before Posting Date 2017-04-12 13:19:05 +05:30
Makarand Bauskar
141c244ece [minor] added order by args to get_*_list methods (#8413) 2017-04-12 13:02:28 +05:30
Nabin Hait
a57b020620 Merge branch 'develop' 2017-04-11 19:14:12 +05:30
Nabin Hait
d1fda1ff2b bumped to version 8.0.9 2017-04-11 19:44:12 +06:00
mbauskar
b9d0e7622a [translation] translation updates for - erpnext on 2017-04-04 2017-04-11 18:57:48 +05:30
mbauskar
2f9703c20e [minor] set company_currency as account_currency in general ledger if party type is employee 2017-04-11 18:56:41 +05:30
Khairil Zhafri
46b6d4ea47 Update student.json
Less binary gender option for Student
2017-04-11 18:55:31 +05:30
Khairil Zhafri
417145bec5 Update employee.json
Less binary gender options for Employee
2017-04-11 18:55:20 +05:30
Rohit Waghchaure
1ff1368280 [fix] Vehicle expense report not working 2017-04-11 18:54:32 +05:30
joezsweet
768a888bf2 [fix] validate supplier invoice
- modified to check for the selected supplier only
2017-04-11 18:52:46 +05:30
Julian Robbins
8037a0e3d5 Update assignment.md
A typo and improvement tom English
2017-04-11 18:51:34 +05:30
mbauskar
0b665ac791 [minor] don't throw error for buying transactions if price list is not selected 2017-04-11 18:51:12 +05:30
Rohit Waghchaure
87ad6d074a [enhance] Stock qty added in purchase invoice 2017-04-11 18:29:52 +05:30
Kanchan Chauhan
95108ac80b [Minor] Party validation for Employee 2017-04-11 18:29:27 +05:30
Dominik Ottenbreit
9b9777be3f Fix mistranslation "Lieferantennauftrag" -> "Bestellung"
There is the strange term of "Lieferantenauftrag" that has been used for
"Purchase Order" which translates to "Supplier Order". This is not
standard at all and should be fixed to "Bestellung".

A Google search for "Bestellung" returns 97 million results, a search
for "Lieferantenauftrag" returns 972 results so it should be clear what
is standard.
2017-04-11 18:28:35 +05:30
Nabin Hait
075b299673 bom traversing: argument mutable issue 2017-04-11 18:27:34 +05:30
mbauskar
e0271a8331 [minor] ReferenceError:doc fixes for delivery note 2017-04-11 17:54:22 +05:30
Nabin Hait
3fc3305251 bom traversing: argument mutable issue 2017-04-11 16:00:48 +05:30
mbauskar
236f7aac7f [minor] track changes for transaction documents 2017-04-10 14:48:54 +05:30
Manas Solanki
29ee263093 Fix in student attendacne tool 2017-04-10 14:33:35 +05:30
Makarand Bauskar
4782e8b751 [minor] added safe_eval for status_updater and added getdate and nowdate (#8365) 2017-04-07 17:16:16 +05:30
Rushabh Mehta
b58979fd3e [added] frappe.safe_eval 2017-04-06 18:58:39 +05:30
Rushabh Mehta
9365641777 [added] frappe.safe_eval 2017-04-06 18:24:34 +05:30
Nabin Hait
5e9d72d57b Merge branch 'develop' 2017-04-06 16:32:04 +05:30
Nabin Hait
0d230afd22 bumped to version 8.0.8 2017-04-06 17:02:03 +06:00
Makis Etzoglou
a906b3f11c add delivery date to print format Fix #8111 2017-04-06 15:47:52 +05:30
Kanchan Chauhan
aa6f00c403 Added default 'All' option to filters to differentiate all and empty filter 2017-04-06 15:22:18 +05:30
Nabin Hait
d681c88d79 validate returned qty only if there is reference qty 2017-04-06 15:20:45 +05:30
Javier Wong
fc11fce990 [enhancement] Changed Issue Description and Resolution to Text Editor (#8346) 2017-04-06 14:56:44 +05:30
Rohit Waghchaure
faf51d91b6 [fix] stock qty issue in purchase trends report 2017-04-05 14:53:26 +05:30
Rushabh Mehta
08a42e00ae [fix] salary slip eval, remove access to globals, #8313 2017-04-05 14:52:22 +05:30
Nabin Hait
549a2827e5 Merge pull request #8300 from rohitwaghchaure/customer_edit_issue_v8
[fix] Customer edit issue in offline POS
2017-04-05 14:51:44 +05:30
Rushabh Mehta
9264313f0e [fix] ordering for Edit Posting Time check 2017-04-05 12:49:01 +05:30
Nabin Hait
8013d1813a Merge pull request #8320 from manassolanki/newsl
Route to newsletter listview
2017-04-05 12:33:14 +05:30
Rushabh Mehta
ffc807cd57 [minor] check below posting date in delivery note 2017-04-05 12:27:41 +05:30
Manas Solanki
ba6559c2e9 Route to newsletter listview 2017-04-05 11:52:23 +05:30
Nabin Hait
7eea52d4e9 Merge branch 'develop' 2017-04-04 11:46:47 +05:30
Nabin Hait
93a990f006 bumped to version 8.0.7 2017-04-04 12:16:47 +06:00
Rohit Waghchaure
2861955632 [fix] Customer edit issue in offline POS 2017-04-04 09:59:29 +05:30
Nabin Hait
099163b16d Merge pull request #8296 from netchampfaris/customer-list-fix
Add `image` field to fetch in Customer List
2017-04-04 09:39:22 +05:30
Faris Ansari
0d114b4c31 Add image field to fetch in Customer List 2017-04-03 21:21:50 +05:30
Nabin Hait
fcf34dc570 Merge pull request #8295 from saurabh6790/demo_fix
[fix] demo script for setup data
2017-04-03 17:56:47 +05:30
Nabin Hait
6f038bc1f3 Validate total advance against grand total considering write off amount 2017-04-03 17:56:05 +05:30
Nabin Hait
9300013acc Validate total advance against grand total considering write off amount 2017-04-03 17:35:58 +05:30
Nabin Hait
8d8cba7faa Validate total advance against grand total considering write off amount 2017-04-03 17:26:32 +05:30
Nabin Hait
2d132e32aa Function name changed in company 2017-04-03 17:26:32 +05:30
Saurabh
2e47654f43 [fix] demo script for setup data 2017-04-03 17:25:55 +05:30
Nabin Hait
9bfa0ab7eb Merge branch 'develop' 2017-04-03 13:18:14 +05:30
Nabin Hait
17ddd8f389 bumped to version 8.0.6 2017-04-03 13:48:13 +06:00
Nabin Hait
c469f2c954 Get POS profile fix 2017-04-03 13:01:11 +05:30
Nabin Hait
731efe3a95 Minor fix in gross profit report 2017-04-03 12:11:36 +05:30
Nabin Hait
2c892c7e7f Indentation fixed in gross profit report 2017-04-03 12:05:35 +05:30
Nabin Hait
e6b5843a1f Merge branch 'develop' 2017-04-01 19:02:55 +05:30
Nabin Hait
31334328ed bumped to version 8.0.5 2017-04-01 19:32:55 +06:00
Rushabh Mehta
0d6db6c42c [fix] add user default role 2017-03-31 23:02:19 +05:30
Nabin Hait
ed0422a8d9 Merge branch 'develop' 2017-03-31 18:19:57 +05:30
Nabin Hait
d991c8666c bumped to version 8.0.4 2017-03-31 18:49:57 +06:00
Nabin Hait
85d1c07519 Merge pull request #8269 from rohitwaghchaure/v8_documentation
[Documentation] Added for custom roles for page and report, fixed some broken images
2017-03-31 18:04:44 +05:30
Nabin Hait
04ab7dfd2f Update role-permisison-for-page-and-report.md 2017-03-31 18:04:15 +05:30
Faris Ansari
eae30e5642 [fix] Show project title in kanban view (#8268)
- frappe/erpnext#8232
2017-03-31 17:46:12 +05:30
Nabin Hait
065302298f Merge pull request #8261 from rohitwaghchaure/pull_project_from_bom_to_po
[enhance] Get project from bom on production order
2017-03-31 17:40:43 +05:30
Nabin Hait
9f84a99158 Merge pull request #8258 from rohitwaghchaure/gross_profit_issue_v_8
[fix] get_valuation_rate takes 4 arguments 3 given in gross profit report
2017-03-31 17:39:58 +05:30
Nabin Hait
b15d999147 Merge branch 'develop' into gross_profit_issue_v_8 2017-03-31 17:39:45 +05:30
Rushabh Mehta
4b0381c820 [fix] tests 2017-03-31 17:36:48 +05:30
Rushabh Mehta
f0b4562a95 [refactor] move purchase_common.js -> public/js/controllers/buying.js 2017-03-31 17:36:48 +05:30
Rushabh Mehta
cc8b2b2fdb [fix] [refactor] demo for v8 and remove purchase common 2017-03-31 17:36:48 +05:30
Rohit Waghchaure
67a3e65f08 [Documentation] Added for custom roles for page and report, fixed some broken images 2017-03-31 17:22:58 +05:30
Rushabh Mehta
dc89916aa9 [fix] salary component fix for abbr 2017-03-31 17:20:57 +05:30
Rushabh Mehta
9d9cb8b7b1 Revert "Add link field Package Code (fixes #8094)" 2017-03-31 14:35:23 +05:30
Rohit Waghchaure
e7c0188732 [enhance] Get project from bom on production order 2017-03-31 13:40:06 +05:30
Rohit Waghchaure
34b1dba9aa [fix] get_valuation_rate takes 4 arguments 3 given in gross profit report 2017-03-31 12:44:10 +05:30
Nabin Hait
c040015bb5 Used db_update in patch to bypass validate and on_update method 2017-03-31 11:58:19 +05:30
Rushabh Mehta
b66edd19ca [minor] refactor transaction.js 2017-03-31 10:50:58 +05:30
Ricardo Johann
033e2fa8b6 changed accumulated header 2017-03-31 02:18:54 -03:00
Nabin Hait
b596deb57d Merge branch 'hotfix' 2017-03-30 23:50:27 +05:30
Nabin Hait
79fddcfac1 bumped to version 8.0.3 2017-03-31 00:20:27 +06:00
Revant Nandgaonkar
3d5bdeb90d [Fix] patch v7_2.contact_address_links 2017-03-30 23:14:58 +05:30
Revant Nandgaonkar
d07c041125 [Fix] Addresses linked back to Lead 2017-03-30 23:14:58 +05:30
Nabin Hait
e64b75153a Merge branch 'hotfix' 2017-03-30 19:52:42 +05:30
Nabin Hait
b207a0542a bumped to version 8.0.2 2017-03-30 20:22:42 +06:00
Nabin Hait
620bde7144 Updated modified date to reload sales uom 2017-03-30 19:50:45 +05:30
Nabin Hait
a8b2cdf65a Merge branch 'hotfix' 2017-03-30 19:35:51 +05:30
Nabin Hait
896fd1aca7 bumped to version 8.0.1 2017-03-30 20:05:51 +06:00
Nabin Hait
e503f68ec7 Merge pull request #8229 from rohitwaghchaure/pos_highlight_issue
[fix] POS cart item's highlighted issue
2017-03-30 19:26:33 +05:30
Rohit Waghchaure
a86bb69adf [fix] POS cart item's highlighted issue 2017-03-30 19:16:38 +05:30
288 changed files with 11193 additions and 8064 deletions

View File

@@ -38,6 +38,14 @@ The ERPNext code is licensed as GNU General Public License (v3) and the Document
---
## Contributing
1. [Pull Request Requirements](https://github.com/frappe/erpnext/wiki/Pull-Request-Guidelines)
1. [Translations](https://translate.erpnext.com)
1. [Chart of Accounts](https://charts.erpnext.com)
---
## Logo and Trademark
The brand name ERPNext and the logo are trademarks of Frappe Technologies Pvt. Ltd.

View File

@@ -2,7 +2,7 @@
from __future__ import unicode_literals
import frappe
__version__ = '8.0.0'
__version__ = '8.0.18'
def get_default_company(user=None):
'''Get default company for user'''
@@ -25,6 +25,14 @@ def get_default_currency():
if company:
return frappe.db.get_value('Company', company, 'default_currency')
def get_company_currency(company):
'''Returns the default company currency'''
if not frappe.flags.company_currency:
frappe.flags.company_currency = {}
if not company in frappe.flags.company_currency:
frappe.flags.company_currency[company] = frappe.db.get_value('Company', company, 'default_currency')
return frappe.flags.company_currency[company]
def set_perpetual_inventory(enable=1):
accounts_settings = frappe.get_doc("Accounts Settings")
accounts_settings.auto_accounting_for_stock = enable

View File

@@ -1,5 +1,6 @@
{
"allow_copy": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
@@ -25,7 +26,9 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Make Accounting Entry For Every Stock Movement",
"length": 0,
"no_copy": 0,
@@ -33,6 +36,7 @@
"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,
@@ -51,7 +55,9 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Accounts Frozen Upto",
"length": 0,
"no_copy": 0,
@@ -59,6 +65,7 @@
"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,
@@ -77,7 +84,9 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Role Allowed to Set Frozen Accounts & Edit Frozen Entries",
"length": 0,
"no_copy": 0,
@@ -86,6 +95,7 @@
"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,
@@ -103,7 +113,9 @@
"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,
@@ -111,6 +123,7 @@
"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,
@@ -129,7 +142,9 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Credit Controller",
"length": 0,
"no_copy": 0,
@@ -138,6 +153,7 @@
"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,
@@ -155,7 +171,9 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Check Supplier Invoice Number Uniqueness",
"length": 0,
"no_copy": 0,
@@ -164,6 +182,7 @@
"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,
@@ -181,7 +200,9 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Make Payment via Journal Entry",
"length": 0,
"no_copy": 0,
@@ -190,6 +211,7 @@
"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,
@@ -208,7 +230,9 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Unlink Payment on Cancellation of Invoice",
"length": 0,
"no_copy": 0,
@@ -217,6 +241,37 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "1",
"fieldname": "book_asset_depreciation_entry_automatically",
"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": "Book Asset Depreciation Entry Automatically",
"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,
@@ -224,18 +279,18 @@
"unique": 0
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"icon": "fa fa-cog",
"icon": "icon-cog",
"idx": 1,
"image_view": 0,
"in_create": 0,
"in_dialog": 0,
"is_submittable": 0,
"issingle": 1,
"istable": 0,
"max_attachments": 0,
"modified": "2016-10-20 16:12:38.595075",
"modified": "2017-04-18 13:35:59.166250",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Accounts Settings",
@@ -251,7 +306,6 @@
"export": 0,
"if_owner": 0,
"import": 0,
"is_custom": 0,
"permlevel": 0,
"print": 1,
"read": 1,
@@ -266,6 +320,8 @@
"quick_entry": 1,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_order": "ASC",
"track_changes": 1,
"track_seen": 0
}

View File

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

View File

@@ -166,6 +166,23 @@ class TestAsset(unittest.TestCase):
self.assertEqual(gle, expected_gle)
self.assertEqual(asset.get("value_after_depreciation"), 70000)
def test_depreciation_entry_cancellation(self):
asset = frappe.get_doc("Asset", "Macbook Pro 1")
asset.submit()
post_depreciation_entries(date="2021-01-01")
asset.load_from_db()
# cancel depreciation entry
depr_entry = asset.get("schedules")[0].journal_entry
self.assertTrue(depr_entry)
frappe.get_doc("Journal Entry", depr_entry).cancel()
asset.load_from_db()
depr_entry = asset.get("schedules")[0].journal_entry
self.assertFalse(depr_entry)
def test_scrap_asset(self):
asset = frappe.get_doc("Asset", "Macbook Pro 1")
@@ -297,4 +314,7 @@ def set_depreciation_settings_in_company():
company.depreciation_expense_account = "_Test Depreciations - _TC"
company.disposal_account = "_Test Gain/Loss on Asset Disposal - _TC"
company.depreciation_cost_center = "_Test Cost Center - _TC"
company.save()
company.save()
# Enable booking asset depreciation entry automatically
frappe.db.set_value("Accounts Settings", None, "book_asset_depreciation_entry_automatically", 1)

View File

@@ -0,0 +1,30 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Bank Guarantee', {
refresh: function(frm) {
cur_frm.set_query("account", function() {
return {
"filters": {
"account_type": "Bank",
"is_group": 0
}
};
});
cur_frm.set_query("project", function() {
return {
"filters": {
"customer": cur_frm.doc.customer
}
};
});
},
start_date: function(frm) {
end_date = frappe.datetime.add_days(cur_frm.doc.start_date, cur_frm.doc.validity - 1);
cur_frm.set_value("end_date", end_date);
},
validity: function(frm) {
end_date = frappe.datetime.add_days(cur_frm.doc.start_date, cur_frm.doc.validity - 1);
cur_frm.set_value("end_date", end_date);
}
});

View File

@@ -0,0 +1,448 @@
{
"allow_copy": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"autoname": "BG-.#####",
"beta": 0,
"creation": "2016-12-17 10:43:35.731631",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "Document",
"editable_grid": 1,
"engine": "InnoDB",
"fields": [
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "customer",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Customer",
"length": 0,
"no_copy": 0,
"options": "Customer",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "project",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Project",
"length": 0,
"no_copy": 0,
"options": "Project",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "account",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Bank Account",
"length": 0,
"no_copy": 0,
"options": "Account",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 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": 1,
"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": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_6",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "start_date",
"fieldtype": "Date",
"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": "Start Date",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"description": "",
"fieldname": "validity",
"fieldtype": "Int",
"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": "Validity in Days",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "end_date",
"fieldtype": "Date",
"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": "End Date",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "bank_guarantee_number",
"fieldtype": "Data",
"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": "Bank Guarantee Number",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 1
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 1,
"columns": 0,
"fieldname": "section_break_10",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "More Information",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "more_information",
"fieldtype": "Text Editor",
"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": "Notes",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "amended_from",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Amended From",
"length": 0,
"no_copy": 1,
"options": "Bank Guarantee",
"permlevel": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"is_submittable": 1,
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2017-04-25 13:31:49.627831",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Bank Guarantee",
"name_case": "",
"owner": "Administrator",
"permissions": [
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 0,
"email": 1,
"export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts User",
"set_user_permissions": 0,
"share": 1,
"submit": 1,
"write": 1
},
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 1,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 1,
"write": 1
}
],
"quick_entry": 1,
"read_only": 0,
"read_only_onload": 0,
"search_fields": "customer",
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"title_field": "customer",
"track_changes": 0,
"track_seen": 0
}

View File

@@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
from frappe.model.document import Document
class BankGuarantee(Document):
pass

View File

@@ -0,0 +1,12 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
from __future__ import unicode_literals
import frappe
import unittest
# test_records = frappe.get_test_records('Bank Guarantee')
class TestBankGuarantee(unittest.TestCase):
pass

View File

@@ -3,13 +3,13 @@
frappe.ui.form.on("Bank Reconciliation", {
setup: function(frm) {
frm.get_docfield("payment_entries").allow_bulk_edit = 1;
frm.add_fetch("bank_account", "account_currency", "account_currency");
},
onload: function(frm) {
var default_bank_account = locals[":Company"][frappe.defaults.get_user_default("Company")]["default_bank_account"];
let default_bank_account = frappe.defaults.get_user_default("Company")?
locals[":Company"][frappe.defaults.get_user_default("Company")]["default_bank_account"]: "";
frm.set_value("bank_account", default_bank_account);
frm.set_query("bank_account", function() {

View File

@@ -1,5 +1,6 @@
{
"allow_copy": 1,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
@@ -7,11 +8,15 @@
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "Document",
"editable_grid": 0,
"fields": [
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"description": "Select account head of the bank where cheque was deposited.",
"fieldname": "bank_account",
"fieldtype": "Link",
@@ -19,7 +24,9 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Bank Account",
"length": 0,
"no_copy": 0,
@@ -28,6 +35,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
@@ -35,16 +43,20 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "account_currency",
"fieldtype": "Link",
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Account Currency",
"length": 0,
"no_copy": 0,
@@ -53,6 +65,7 @@
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -60,16 +73,20 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "from_date",
"fieldtype": "Date",
"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": "From Date",
"length": 0,
"no_copy": 0,
@@ -77,6 +94,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
@@ -84,16 +102,20 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "to_date",
"fieldtype": "Date",
"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": "To Date",
"length": 0,
"no_copy": 0,
@@ -101,6 +123,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
@@ -108,16 +131,20 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "include_reconciled_entries",
"fieldtype": "Check",
"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": "Include Reconciled Entries",
"length": 0,
"no_copy": 0,
@@ -125,6 +152,7 @@
"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,
@@ -132,16 +160,20 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "get_payment_entries",
"fieldtype": "Button",
"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": "Get Payment Entries",
"length": 0,
"no_copy": 0,
@@ -150,6 +182,7 @@
"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,
@@ -157,16 +190,20 @@
"unique": 0
},
{
"allow_bulk_edit": 1,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "payment_entries",
"fieldtype": "Table",
"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": "Payment Entries",
"length": 0,
"no_copy": 0,
@@ -175,6 +212,7 @@
"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,
@@ -182,16 +220,20 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "update_clearance_date",
"fieldtype": "Button",
"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": "Update Clearance Date",
"length": 0,
"no_copy": 0,
@@ -200,6 +242,7 @@
"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,
@@ -207,16 +250,20 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "total_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": "Total Amount",
"length": 0,
"no_copy": 0,
@@ -225,6 +272,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -232,19 +280,19 @@
"unique": 0
}
],
"has_web_view": 0,
"hide_heading": 1,
"hide_toolbar": 1,
"icon": "fa fa-check",
"idx": 1,
"image_view": 0,
"in_create": 0,
"in_dialog": 0,
"is_submittable": 0,
"issingle": 1,
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
"modified": "2016-06-28 13:11:09.396353",
"modified": "2017-04-21 16:58:26.902732",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Bank Reconciliation",
@@ -274,7 +322,8 @@
"quick_entry": 1,
"read_only": 1,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_order": "ASC",
"track_seen": 0,
"version": 0
"track_changes": 0,
"track_seen": 0
}

View File

@@ -2,13 +2,12 @@
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe
import frappe, erpnext
from frappe import _
from frappe.utils import flt, fmt_money, getdate, formatdate
from frappe.model.document import Document
from erpnext.accounts.party import validate_party_gle_currency, validate_party_frozen_disabled
from erpnext.accounts.utils import get_account_currency
from erpnext.setup.doctype.company.company import get_company_currency
from erpnext.accounts.utils import get_fiscal_year
from erpnext.exceptions import InvalidAccountCurrency
@@ -19,7 +18,7 @@ class GLEntry(Document):
self.flags.ignore_submit_comment = True
self.check_mandatory()
self.validate_and_set_fiscal_year()
if not self.flags.from_repost:
self.pl_must_have_cost_center()
self.check_pl_account()
@@ -32,7 +31,7 @@ class GLEntry(Document):
if not from_repost:
self.validate_account_details(adv_adj)
check_freezing_date(self.posting_date, adv_adj)
validate_frozen_account(self.account, adv_adj)
validate_balance_type(self.account, adv_adj)
@@ -56,7 +55,7 @@ class GLEntry(Document):
elif account_type == "Payable":
frappe.throw(_("{0} {1}: Supplier is required against Payable account {2}")
.format(self.voucher_type, self.voucher_no, self.account))
# Zero value transaction is not allowed
if not (flt(self.debit) or flt(self.credit)):
frappe.throw(_("{0} {1}: Either debit or credit amount is required for {2}")
@@ -116,7 +115,7 @@ class GLEntry(Document):
validate_party_frozen_disabled(self.party_type, self.party)
def validate_currency(self):
company_currency = get_company_currency(self.company)
company_currency = erpnext.get_company_currency(self.company)
account_currency = get_account_currency(self.account)
if not self.account_currency:
@@ -124,7 +123,7 @@ class GLEntry(Document):
if account_currency != self.account_currency:
frappe.throw(_("{0} {1}: Accounting Entry for {2} can only be made in currency: {3}")
.format(self.voucher_type, self.voucher_no, self.account,
.format(self.voucher_type, self.voucher_no, self.account,
(account_currency or company_currency)), InvalidAccountCurrency)
if self.party_type and self.party:

View File

@@ -1,5 +1,6 @@
{
"allow_copy": 0,
"allow_guest_to_view": 0,
"allow_import": 1,
"allow_rename": 0,
"autoname": "naming_series:",
@@ -1325,19 +1326,19 @@
"unique": 0
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"icon": "fa fa-file-text",
"idx": 176,
"image_view": 0,
"in_create": 0,
"in_dialog": 0,
"is_submittable": 1,
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
"modified": "2017-02-17 16:17:48.991851",
"modified": "2017-04-10 12:07:44.599804",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Journal Entry",
@@ -1412,6 +1413,6 @@
"sort_field": "modified",
"sort_order": "DESC",
"title_field": "title",
"track_changes": 0,
"track_changes": 1,
"track_seen": 0
}

View File

@@ -2,12 +2,11 @@
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe, json
import frappe, erpnext, json
from frappe.utils import cstr, flt, fmt_money, formatdate
from frappe import msgprint, _, scrub
from erpnext.controllers.accounts_controller import AccountsController
from erpnext.accounts.utils import get_balance_on, get_account_currency
from erpnext.setup.utils import get_company_currency
from erpnext.accounts.party import get_party_account
from erpnext.hr.doctype.expense_claim.expense_claim import update_reimbursed_amount
from erpnext.hr.doctype.employee_loan.employee_loan import update_disbursement_status
@@ -73,6 +72,7 @@ class JournalEntry(AccountsController):
self.update_expense_claim()
self.update_employee_loan()
self.unlink_advance_entry_reference()
self.unlink_asset_reference()
def unlink_advance_entry_reference(self):
for d in self.get("accounts"):
@@ -82,6 +82,18 @@ class JournalEntry(AccountsController):
d.reference_type = ''
d.reference_name = ''
d.db_update()
def unlink_asset_reference(self):
for d in self.get("accounts"):
if d.reference_type=="Asset" and d.reference_name:
asset = frappe.get_doc("Asset", d.reference_name)
for s in asset.get("schedules"):
if s.journal_entry == self.name:
s.db_set("journal_entry", None)
asset.value_after_depreciation += s.depreciation_amount
asset.db_set("value_after_depreciation", asset.value_after_depreciation)
asset.set_status()
def validate_party(self):
for d in self.get("accounts"):
@@ -325,11 +337,11 @@ class JournalEntry(AccountsController):
if d.account_currency == self.company_currency:
d.exchange_rate = 1
elif not d.exchange_rate or d.exchange_rate == 1 or \
(d.reference_type in ("Sales Invoice", "Purchase Invoice")
(d.reference_type in ("Sales Invoice", "Purchase Invoice")
and d.reference_name and self.posting_date):
# Modified to include the posting date for which to retreive the exchange rate
d.exchange_rate = get_exchange_rate(self.posting_date, d.account, d.account_currency,
d.exchange_rate = get_exchange_rate(self.posting_date, d.account, d.account_currency,
self.company, d.reference_type, d.reference_name, d.debit, d.credit, d.exchange_rate)
if not d.exchange_rate:
@@ -502,7 +514,7 @@ class JournalEntry(AccountsController):
def update_expense_claim(self):
for d in self.accounts:
if d.reference_type=="Expense Claim" and d.party:
if d.reference_type=="Expense Claim" and d.reference_name:
doc = frappe.get_doc("Expense Claim", d.reference_name)
update_reimbursed_amount(doc)
@@ -656,7 +668,7 @@ def get_payment_entry(ref_doc, args):
if args.get("party_account"):
# Modified to include the posting date for which the exchange rate is required.
# Assumed to be the posting date in the reference document
exchange_rate = get_exchange_rate(ref_doc.get("posting_date") or ref_doc.get("transaction_date"),
exchange_rate = get_exchange_rate(ref_doc.get("posting_date") or ref_doc.get("transaction_date"),
args.get("party_account"), args.get("party_account_currency"),
ref_doc.company, ref_doc.doctype, ref_doc.name)
@@ -692,8 +704,8 @@ def get_payment_entry(ref_doc, args):
bank_row.update(bank_account)
# Modified to include the posting date for which the exchange rate is required.
# Assumed to be the posting date of the reference date
bank_row.exchange_rate = get_exchange_rate(ref_doc.get("posting_date")
or ref_doc.get("transaction_date"), bank_account["account"],
bank_row.exchange_rate = get_exchange_rate(ref_doc.get("posting_date")
or ref_doc.get("transaction_date"), bank_account["account"],
bank_account["account_currency"], ref_doc.company)
bank_row.cost_center = cost_center
@@ -746,7 +758,7 @@ def get_outstanding(args):
if isinstance(args, basestring):
args = json.loads(args)
company_currency = get_company_currency(args.get("company"))
company_currency = erpnext.get_company_currency(args.get("company"))
if args.get("doctype") == "Journal Entry":
condition = " and party=%(party)s" if args.get("party") else ""
@@ -805,7 +817,7 @@ def get_account_balance_and_party_type(account, date, company, debit=None, credi
if not frappe.has_permission("Account"):
frappe.msgprint(_("No Permission"), raise_exception=1)
company_currency = get_company_currency(company)
company_currency = erpnext.get_company_currency(company)
account_details = frappe.db.get_value("Account", account, ["account_type", "account_currency"], as_dict=1)
if not account_details:
@@ -853,7 +865,7 @@ def get_exchange_rate(posting_date, account=None, account_currency=None, company
if not account_currency:
account_currency = account_details.account_currency
company_currency = get_company_currency(company)
company_currency = erpnext.get_company_currency(company)
if account_currency != company_currency:
if reference_type in ("Sales Invoice", "Purchase Invoice") and reference_name:

View File

@@ -1675,7 +1675,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2017-03-14 17:12:48.816644",
"modified": "2017-04-10 12:06:22.176045",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Entry",
@@ -1730,6 +1730,6 @@
"sort_field": "modified",
"sort_order": "DESC",
"title_field": "title",
"track_changes": 0,
"track_changes": 1,
"track_seen": 0
}

View File

@@ -23,6 +23,8 @@ class PricingRule(Document):
self.validate_price_or_discount()
self.validate_max_discount()
if not self.margin_type: self.margin_rate_or_amount = 0.0
def validate_mandatory(self):
for field in ["apply_on", "applicable_for"]:
tocheck = frappe.scrub(self.get(field) or "")
@@ -143,7 +145,7 @@ def get_pricing_rule_for_item(args):
})
if args.ignore_pricing_rule or not args.item_code:
if frappe.db.exists(args.doctype, args.name) and args.get("pricing_rule"):
if args.get("pricing_rule"):
item_details = remove_pricing_rule(args, item_details)
return item_details
@@ -178,7 +180,7 @@ def get_pricing_rule_for_item(args):
item_details.margin_rate_or_amount = pricing_rule.margin_rate_or_amount
if pricing_rule.price_or_discount == "Price":
item_details.update({
"price_list_rate": pricing_rule.price/flt(args.conversion_rate) \
"price_list_rate": (pricing_rule.price/flt(args.conversion_rate)) * args.conversion_factor or 1.0 \
if args.conversion_rate else 0.0,
"discount_percentage": 0.0
})

View File

@@ -2,8 +2,7 @@
// License: GNU General Public License v3. See license.txt
frappe.provide("erpnext.accounts");
{% include 'erpnext/buying/doctype/purchase_common/purchase_common.js' %};
{% include 'erpnext/public/js/controllers/buying.js' %};
erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({
setup: function(doc) {

View File

@@ -3646,7 +3646,7 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
"modified": "2017-03-15 14:29:51.957287",
"modified": "2017-04-10 12:05:28.082020",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice",
@@ -3762,6 +3762,6 @@
"sort_order": "DESC",
"timeline_field": "supplier",
"title_field": "title",
"track_changes": 0,
"track_changes": 1,
"track_seen": 0
}

View File

@@ -2,10 +2,9 @@
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe
import frappe, erpnext
from frappe.utils import cint, formatdate, flt, getdate
from frappe import _, throw
from erpnext.setup.utils import get_company_currency
import frappe.defaults
from erpnext.controllers.buying_controller import BuyingController
@@ -15,6 +14,7 @@ from erpnext.stock.doctype.purchase_receipt.purchase_receipt import update_bille
from erpnext.controllers.stock_controller import get_warehouse_account
from erpnext.accounts.general_ledger import make_gl_entries, merge_similar_entries, delete_gl_entries
from erpnext.accounts.doctype.gl_entry.gl_entry import update_outstanding_amt
from erpnext.buying.utils import check_for_closed_status
form_grid_templates = {
"items": "templates/form_grid/item_grid.html"
@@ -93,7 +93,7 @@ class PurchaseInvoice(BuyingController):
super(PurchaseInvoice, self).set_missing_values(for_validate)
def check_conversion_rate(self):
default_currency = get_company_currency(self.company)
default_currency = erpnext.get_company_currency(self.company)
if not default_currency:
throw(_('Please enter default currency in Company Master'))
if (self.currency == default_currency and flt(self.conversion_rate) != 1.00) or not self.conversion_rate or (self.currency != default_currency and flt(self.conversion_rate) == 1.00):
@@ -113,12 +113,11 @@ class PurchaseInvoice(BuyingController):
def check_for_closed_status(self):
check_list = []
pc_obj = frappe.get_doc('Purchase Common')
for d in self.get('items'):
if d.purchase_order and not d.purchase_order in check_list and not d.purchase_receipt:
check_list.append(d.purchase_order)
pc_obj.check_for_closed_status('Purchase Order', d.purchase_order)
check_for_closed_status('Purchase Order', d.purchase_order)
def validate_with_previous_doc(self):
super(PurchaseInvoice, self).validate_with_previous_doc({
@@ -629,10 +628,12 @@ class PurchaseInvoice(BuyingController):
pi = frappe.db.sql('''select name from `tabPurchase Invoice`
where
bill_no = %(bill_no)s
and supplier = %(supplier)s
and name != %(name)s
and docstatus < 2
and posting_date between %(year_start_date)s and %(year_end_date)s''', {
"bill_no": self.bill_no,
"supplier": self.supplier,
"name": self.name,
"year_start_date": fiscal_year.year_start_date,
"year_end_date": fiscal_year.year_end_date

View File

@@ -1,5 +1,6 @@
{
"allow_copy": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"autoname": "hash",
@@ -335,6 +336,36 @@
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "stock_uom",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Stock UOM",
"length": 0,
"no_copy": 0,
"options": "UOM",
"permlevel": 0,
"precision": "",
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
@@ -419,6 +450,35 @@
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "stock_qty",
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Stock Qty",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
@@ -1362,11 +1422,11 @@
"unique": 0
},
{
"allow_on_submit": 1,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "is_sample_item",
"fieldname": "allow_zero_valuation_rate",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
@@ -1375,7 +1435,7 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Is Sample Item",
"label": "Allow Zero Valuation Rate",
"length": 0,
"no_copy": 1,
"permlevel": 0,
@@ -1448,7 +1508,7 @@
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
@@ -1869,17 +1929,17 @@
"unique": 0
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 1,
"image_view": 0,
"in_create": 0,
"in_dialog": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2017-02-17 16:28:26.719053",
"modified": "2017-04-19 11:54:16.112134",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice Item",
@@ -1893,4 +1953,4 @@
"sort_order": "DESC",
"track_changes": 0,
"track_seen": 0
}
}

View File

@@ -32,7 +32,7 @@ def get_pos_data():
'doc': doc,
'default_customer': pos_profile.get('customer'),
'items': get_items_list(pos_profile),
'item_groups': get_item_group(pos_profile),
'item_groups': get_item_groups(pos_profile),
'customers': customers,
'address': get_customers_address(customers),
'serial_no_data': get_serial_no_data(pos_profile, doc.company),
@@ -132,7 +132,7 @@ def get_items_list(pos_profile):
if pos_profile.get('item_groups'):
# Get items based on the item groups defined in the POS profile
for d in pos_profile.get('item_groups'):
item_groups.extend(get_child_nodes('Item Group', d.item_group))
item_groups.extend([d.name for d in get_child_nodes('Item Group', d.item_group)])
cond = "item_group in (%s)"%(', '.join(['%s']*len(item_groups)))
return frappe.db.sql("""
@@ -146,14 +146,19 @@ def get_items_list(pos_profile):
disabled = 0 and has_variants = 0 and is_sales_item = 1 and {cond}
""".format(cond=cond), tuple(item_groups), as_dict=1)
def get_item_group(pos_profile):
def get_item_groups(pos_profile):
item_group_dict = {}
if pos_profile.get('item_groups'):
item_groups = []
for d in pos_profile.get('item_groups'):
item_groups.extend(get_child_nodes('Item Group', d.item_group))
return item_groups
else:
return frappe.db.sql_list("""Select name from `tabItem Group` order by name""")
item_groups = frappe.db.sql("""Select name,
lft, rgt from `tabItem Group` order by lft""", as_dict=1)
for data in item_groups:
item_group_dict[data.name] = [data.lft, data.rgt]
return item_group_dict
def get_customers_list(pos_profile):
cond = "1=1"
@@ -161,7 +166,7 @@ def get_customers_list(pos_profile):
if pos_profile.get('customer_groups'):
# Get customers based on the customer groups defined in the POS profile
for d in pos_profile.get('customer_groups'):
customer_groups.extend(get_child_nodes('Customer Group', d.customer_group))
customer_groups.extend([d.name for d in get_child_nodes('Customer Group', d.customer_group)])
cond = "customer_group in (%s)"%(', '.join(['%s']*len(customer_groups)))
return frappe.db.sql(""" select name, customer_name, customer_group,
@@ -182,12 +187,13 @@ def get_customers_address(customers):
address_data = address[0]
address_data.update({'full_name': data.customer_name})
customer_address[data.name] = address_data
return customer_address
def get_child_nodes(group_type, root):
lft, rgt = frappe.db.get_value(group_type, root, ["lft", "rgt"])
return frappe.db.sql_list(""" Select name from `tab{tab}` where
lft >= {lft} and rgt <= {rgt}""".format(tab=group_type, lft=lft, rgt=rgt))
return frappe.db.sql(""" Select name, lft, rgt from `tab{tab}` where
lft >= {lft} and rgt <= {rgt} order by lft""".format(tab=group_type, lft=lft, rgt=rgt), as_dict=1)
def get_serial_no_data(pos_profile, company):
# get itemwise serial no data
@@ -295,9 +301,9 @@ def make_invoice(doc_list={}, email_queue_list={}, customers_list={}):
if not frappe.db.exists('Sales Invoice', {'offline_pos_name': name}):
validate_records(doc)
si_doc = frappe.new_doc('Sales Invoice')
si_doc.due_date = doc.get('posting_date')
si_doc.offline_pos_name = name
si_doc.update(doc)
si_doc.due_date = doc.get('posting_date')
submit_invoice(si_doc, name, doc)
name_list.append(name)
else:
@@ -337,11 +343,14 @@ def add_customer(name):
def make_address(args, customer):
if not args.get('address_line1'): return
name = args.get('name') or get_customers_address(customer)[customer].get("name")
name = args.get('name')
if not name:
data = get_customers_address(customer)
name = data[customer].get('name') if data else None
if name:
address = frappe.get_doc('Address', name)
frappe.errprint(address)
address = frappe.get_doc('Address', name)
else:
address = frappe.new_doc('Address')
address.country = frappe.db.get_value('Company', args.get('company'), 'country')
@@ -400,4 +409,5 @@ def save_invoice(e, si_doc, name):
if not frappe.db.exists('Sales Invoice', {'offline_pos_name': name}):
si_doc.docstatus = 0
si_doc.flags.ignore_mandatory = True
si_doc.due_date = si_doc.posting_date
si_doc.insert()

View File

@@ -7,7 +7,7 @@
"beta": 0,
"creation": "2013-05-24 19:29:05",
"custom": 0,
"default_print_format": "Sample Print",
"default_print_format": "",
"docstatus": 0,
"doctype": "DocType",
"document_type": "",
@@ -4417,8 +4417,8 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
"modified": "2017-03-29 05:09:56.656338",
"modified_by": "Administrator",
"modified": "2017-04-12 15:11:45.931485",
"modified_by": "faris@erpnext.com",
"module": "Accounts",
"name": "Sales Invoice",
"owner": "Administrator",
@@ -4513,6 +4513,6 @@
"sort_order": "DESC",
"timeline_field": "customer",
"title_field": "title",
"track_changes": 0,
"track_changes": 1,
"track_seen": 0
}

View File

@@ -147,9 +147,9 @@
"price_list_rate": 50,
"qty": 10,
"rate": 50,
"uom": "_Test UOM",
"uom": "_Test UOM 1",
"conversion_factor": 1,
"stock_uom": "_Test UOM"
"stock_uom": "_Test UOM 1"
},
{
"cost_center": "_Test Cost Center - _TC",
@@ -273,9 +273,9 @@
"parentfield": "items",
"price_list_rate": 62.5,
"qty": 10,
"uom": "_Test UOM",
"conversion_factor": 1,
"stock_uom": "_Test UOM"
"uom": "_Test UOM 1",
"conversion_factor": 1,
"stock_uom": "_Test UOM 1"
},
{

View File

@@ -1043,6 +1043,25 @@ class TestSalesInvoice(unittest.TestCase):
#check outstanding after advance cancellation
self.assertEqual(flt(si.outstanding_amount), flt(si.grand_total + si.total_advance, si.precision("outstanding_amount")))
def test_multiple_uom_in_selling(self):
si = frappe.copy_doc(test_records[1])
si.items[0].uom = "_Test UOM 1"
si.items[0].conversion_factor = None
si.items[0].price_list_rate = None
si.save()
expected_values = {
"keys": ["price_list_rate", "stock_uom", "uom", "conversion_factor", "rate", "amount",
"base_price_list_rate", "base_rate", "base_amount"],
"_Test Item": [1000, "_Test UOM", "_Test UOM 1", 10.0, 1000, 1000, 1000, 1000, 1000]
}
# check if the conversion_factor and price_list_rate is calculated according to uom
for d in si.get("items"):
for i, k in enumerate(expected_values["keys"]):
self.assertEquals(d.get(k), expected_values[d.item_code][i])
def create_sales_invoice(**args):
si = frappe.new_doc("Sales Invoice")
args = frappe._dict(args)

View File

@@ -1548,11 +1548,11 @@
"unique": 0
},
{
"allow_on_submit": 1,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "is_sample_item",
"fieldname": "allow_zero_valuation_rate",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
@@ -1561,7 +1561,7 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Is Sample Item",
"label": "Allow Zero Valuation Rate",
"length": 0,
"no_copy": 1,
"permlevel": 0,
@@ -2094,7 +2094,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2017-03-29 16:26:36.507924",
"modified": "2017-04-19 11:53:26.682964",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice Item",

View File

@@ -4,11 +4,10 @@
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
import frappe, erpnext
from frappe import _, msgprint, throw
from frappe.utils import flt, fmt_money
from frappe.model.document import Document
from erpnext.setup.utils import get_company_currency
class OverlappingConditionError(frappe.ValidationError): pass
class FromGreaterThanToError(frappe.ValidationError): pass
@@ -77,7 +76,7 @@ class ShippingRule(Document):
overlaps.append([d1, d2])
if overlaps:
company_currency = get_company_currency(self.company)
company_currency = erpnext.get_company_currency(self.company)
msgprint(_("Overlapping conditions found between:"))
messages = []
for d1, d2 in overlaps:

View File

@@ -407,8 +407,8 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
});
this.search_item_group = this.wrapper.find('.search-item-group');
var dropdown_html = me.item_groups.map(function(item_group) {
sorted_item_groups = this.get_sorted_item_groups()
var dropdown_html = sorted_item_groups.map(function(item_group) {
return "<li><a class='option' data-value='"+item_group+"'>"+item_group+"</a></li>";
}).join("");
@@ -437,6 +437,15 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
})
},
get_sorted_item_groups: function() {
list = {}
$.each(this.item_groups, function(i, data) {
list[i] = data[0]
})
return Object.keys(list).sort(function(a,b){return list[a]-list[b]})
},
toggle_more_btn: function() {
if(!this.items || this.items.length <= this.page_len) {
this.wrapper.find(".btn-more").hide();
@@ -951,6 +960,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
item_price: format_currency(me.price_list_data[obj.name], me.frm.doc.currency),
item_name: obj.name === obj.item_name ? "" : obj.item_name,
item_image: obj.image,
item_stock: __('Stock Qty') + ": " + me.get_actual_qty(obj),
color: frappe.get_palette(obj.item_name),
abbr: frappe.get_abbr(obj.item_name)
})).tooltip().appendTo($wrap);
@@ -1089,9 +1099,10 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
// if form is local then allow this function
// $(me.wrapper).find(".pos-item-wrapper").on("click", function () {
$(this.wrapper).on("click", ".pos-item-wrapper", function () {
me.item_code = '';
me.customer_validate();
if($(me.pos_bill).is(":hidden")) return;
me.customer_validate();
if (me.frm.doc.docstatus == 0) {
me.items = me.get_items($(this).attr("data-item-code"))
me.add_to_cart();
@@ -1354,7 +1365,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
discount_percentage: d.discount_percentage || 0.0,
actual_qty: me.actual_qty_dict[d.item_code] || 0.0,
projected_qty: d.projected_qty,
rate: format_number(d.rate, me.frm.doc.currency),
rate: format_currency(d.rate, me.frm.doc.currency),
enabled: me.pos_profile_data["allow_user_to_edit_rate"] ? true : false,
amount: format_currency(d.amount, me.frm.doc.currency),
selected_class: (me.item_code == d.item_code) ? "active" : ""
@@ -1419,6 +1430,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
},
make_new_cart: function (){
this.item_code = '';
this.page.clear_secondary_action();
this.save_previous_entry();
this.create_new();
@@ -1765,7 +1777,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
var me = this;
return $.grep(this.pricing_rules, function (data) {
if (item.qty >= data.min_qty && (item.qty <= (data.max_qty ? data.max_qty : item.qty))) {
if (data.item_code == item.item_code || in_list(['All Item Groups', item.item_group], data.item_group) || item.brand == data.brand) {
if (me.validate_item_condition(data, item)) {
if (in_list(['Customer', 'Customer Group', 'Territory', 'Campaign'], data.applicable_for)) {
return me.validate_condition(data)
} else {
@@ -1776,6 +1788,26 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
})
},
validate_item_condition: function (data, item) {
var apply_on = frappe.model.scrub(data.apply_on);
return (data.apply_on == 'Item Group')
? this.validate_item_group(data.item_group, item.item_group) : (data[apply_on] == item[apply_on]);
},
validate_item_group: function (pr_item_group, cart_item_group) {
//pr_item_group = pricing rule's item group
//cart_item_group = cart item's item group
//this.item_groups has information about item group's lft and rgt
//for example: {'Foods': [12, 19]}
pr_item_group = this.item_groups[pr_item_group]
cart_item_group = this.item_groups[cart_item_group]
return (cart_item_group[0] >= pr_item_group[0] &&
cart_item_group[1] <= pr_item_group[1])
},
validate_condition: function (data) {
//This method check condition based on applicable for
condition = this.get_mapper_for_pricing_rule(data)[data.applicable_for]
@@ -1854,4 +1886,4 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
frappe.throw(__("LocalStorage is full , did not save"))
}
}
})
})

View File

@@ -151,13 +151,6 @@ def set_account_and_due_date(party, account, party_type, company, posting_date,
}
return out
def get_company_currency():
company_currency = frappe._dict()
for d in frappe.get_all("Company", fields=["name", "default_currency"]):
company_currency.setdefault(d.name, d.default_currency)
return company_currency
@frappe.whitelist()
def get_party_account(party_type, party, company):
"""Returns the account for the given `party`.
@@ -348,7 +341,7 @@ def validate_party_frozen_disabled(party_type, party_name):
elif party_type == "Employee":
if frappe.db.get_value("Employee", party_name, "status") == "Left":
frappe.msgprint(_("{0} {1} is not active").format(party_type, party_name), PartyDisabled, alert=True)
frappe.msgprint(_("{0} {1} is not active").format(party_type, party_name), alert=True)
def get_timeline_data(doctype, name):
'''returns timeline data for the past one year'''

View File

@@ -7,10 +7,10 @@
"docstatus": 0,
"doctype": "Print Format",
"font": "Default",
"html": "<style>\n\t.print-format table, .print-format tr, \n\t.print-format td, .print-format div, .print-format p {\n\t\tfont-family: Monospace;\n\t\tline-height: 200%;\n\t\tvertical-align: middle;\n\t}\n\t@media screen {\n\t\t.print-format {\n\t\t\twidth: 4in;\n\t\t\tpadding: 0.25in;\n\t\t\tmin-height: 8in;\n\t\t}\n\t}\n</style>\n\n<p class=\"text-center\">\n\t{{ company }}<br>\n\t{{ __(\"POS No : \") }}{{offline_pos_name}}<br>\n</p>\n<p>\n\t<b>{{ __(\"Date\") }}:</b> {{ dateutil.global_date_format(posting_date) }}<br>\n</p>\n\n<hr>\n<table class=\"table table-condensed cart no-border\">\n\t<thead>\n\t\t<tr>\n\t\t\t<th width=\"50%\">{{ __(\"Item\") }}</b></th>\n\t\t\t<th width=\"25%\" class=\"text-right\">{{ __(\"Qty\") }}</th>\n\t\t\t<th width=\"25%\" class=\"text-right\">{{ __(\"Amount\") }}</th>\n\t\t</tr>\n\t</thead>\n\t<tbody>\n\t\t{% for item in items %}\n\t\t<tr>\n\t\t\t<td>\n\t\t\t\t{{ item.item_name }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">{{ format_number(item.qty, precision(\"difference\")) }}<br>@ {{ format_currency(item.rate, currency) }}</td>\n\t\t\t<td class=\"text-right\">{{ format_currency(item.amount, currency) }}</td>\n\t\t</tr>\n\t\t{% endfor %}\n\t</tbody>\n</table>\n\n<table class=\"table table-condensed no-border\">\n\t<tbody>\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t{{ __(\"Net Total\") }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ format_currency(total, currency) }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{% for row in taxes %}\n\t\t{% if not row.included_in_print_rate %}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t{{ row.description }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ format_currency(row.tax_amount, currency) }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{% endif %}\n\t\t{% endfor %}\n\t\t{% if discount_amount %}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t{{ __(\"Discount\") }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ format_currency(discount_amount, currency) }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{% endif %}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ __(\"Grand Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ format_currency(grand_total, currency) }}\n\t\t\t</td>\n\t\t</tr>\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ __(\"Paid Amount\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ format_currency(paid_amount, currency) }}\n\t\t\t</td>\n\t\t</tr>\n\t</tbody>\n</table>\n\n\n<hr>\n<p>{{ terms }}</p>\n<p class=\"text-center\">{{ __(\"Thank you, please visit again.\") }}</p>",
"html": "<style>\n\t.print-format table, .print-format tr, \n\t.print-format td, .print-format div, .print-format p {\n\t\tfont-family: Monospace;\n\t\tline-height: 200%;\n\t\tvertical-align: middle;\n\t}\n\t@media screen {\n\t\t.print-format {\n\t\t\twidth: 4in;\n\t\t\tpadding: 0.25in;\n\t\t\tmin-height: 8in;\n\t\t}\n\t}\n</style>\n\n<p class=\"text-center\">\n\t{{ company }}<br>\n\t{{ __(\"POS No : \") }} {{ offline_pos_name }}<br>\n</p>\n<p>\n\t<b>{{ __(\"Date\") }}:</b> {{ dateutil.global_date_format(posting_date) }}<br>\n</p>\n\n<hr>\n<table class=\"table table-condensed cart no-border\">\n\t<thead>\n\t\t<tr>\n\t\t\t<th width=\"50%\">{{ __(\"Item\") }}</b></th>\n\t\t\t<th width=\"25%\" class=\"text-right\">{{ __(\"Qty\") }}</th>\n\t\t\t<th width=\"25%\" class=\"text-right\">{{ __(\"Amount\") }}</th>\n\t\t</tr>\n\t</thead>\n\t<tbody>\n\t\t{% for item in items %}\n\t\t<tr>\n\t\t\t<td>\n\t\t\t\t{{ item.item_name }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">{{ format_number(item.qty, null,precision(\"difference\")) }}<br>@ {{ format_currency(item.rate, currency) }}</td>\n\t\t\t<td class=\"text-right\">{{ format_currency(item.amount, currency) }}</td>\n\t\t</tr>\n\t\t{% endfor %}\n\t</tbody>\n</table>\n\n<table class=\"table table-condensed no-border\">\n\t<tbody>\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t{{ __(\"Net Total\") }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ format_currency(total, currency) }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{% for row in taxes %}\n\t\t{% if not row.included_in_print_rate %}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t{{ row.description }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ format_currency(row.tax_amount, currency) }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{% endif %}\n\t\t{% endfor %}\n\t\t{% if discount_amount %}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t{{ __(\"Discount\") }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ format_currency(discount_amount, currency) }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{% endif %}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ __(\"Grand Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ format_currency(grand_total, currency) }}\n\t\t\t</td>\n\t\t</tr>\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ __(\"Paid Amount\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ format_currency(paid_amount, currency) }}\n\t\t\t</td>\n\t\t</tr>\n\t</tbody>\n</table>\n\n\n<hr>\n<p>{{ terms }}</p>\n<p class=\"text-center\">{{ __(\"Thank you, please visit again.\") }}</p>",
"idx": 0,
"line_breaks": 0,
"modified": "2017-01-12 14:56:12.571032",
"modified": "2017-04-19 13:28:05.129504",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Point of Sale",

View File

@@ -1,6 +1,9 @@
{% var letterhead= filters.letter_head || frappe.get_doc(":Company", filters.company).default_letter_head || frappe.defaults.get_default("letter_head"); %}
{% if(letterhead) { %}
<div style="margin-bottom: 7px;" class="text-center">
{%= frappe.boot.letter_heads[frappe.get_doc(":Company", filters.company).default_letter_head || frappe.defaults.get_default("letter_head")] %}
{%= frappe.boot.letter_heads[letterhead].header %}
</div>
{% } %}
<h2 class="text-center">{%= __(report.report_name) %}</h2>
<h4 class="text-center">{%= filters.customer || filters.supplier %} </h4>
<h5 class="text-center">

View File

@@ -16,6 +16,21 @@ frappe.query_reports["Accounts Receivable"] = {
"fieldtype": "Link",
"options": "Customer"
},
{
"fieldname":"customer_group",
"label": __("Customer Group"),
"fieldtype": "Link",
"options": "Customer Group"
},
{
"fieldname":"credit_days_based_on",
"label": __("Credit Days Based On"),
"fieldtype": "Select",
"options": "" + NEWLINE + "Fixed Days" + NEWLINE + "Last Day of the Next Month"
},
{
"fieldtype": "Break",
},
{
"fieldname":"report_date",
"label": __("As on Date"),
@@ -29,9 +44,6 @@ frappe.query_reports["Accounts Receivable"] = {
"options": 'Posting Date' + NEWLINE + 'Due Date',
"default": "Posting Date"
},
{
"fieldtype": "Break",
},
{
"fieldname":"range1",
"label": __("Ageing Range 1"),

View File

@@ -71,7 +71,10 @@ class ReceivablePayableReport(object):
"width": 100
})
if args.get("party_type") == "Customer":
columns += [_("Territory") + ":Link/Territory:80"]
columns += [
_("Territory") + ":Link/Territory:80",
_("Customer Group") + ":Link/Customer Group:120"
]
if args.get("party_type") == "Supplier":
columns += [_("Supplier Type") + ":Link/Supplier Type:80"]
@@ -139,7 +142,7 @@ class ReceivablePayableReport(object):
# customer territory / supplier type
if args.get("party_type") == "Customer":
row += [self.get_territory(gle.party)]
row += [self.get_territory(gle.party), self.get_customer_group(gle.party)]
if args.get("party_type") == "Supplier":
row += [self.get_supplier_type(gle.party)]
@@ -186,6 +189,9 @@ class ReceivablePayableReport(object):
def get_territory(self, party_name):
return self.get_party_map("Customer").get(party_name, {}).get("territory") or ""
def get_customer_group(self, party_name):
return self.get_party_map("Customer").get(party_name, {}).get("customer_group") or ""
def get_supplier_type(self, party_name):
return self.get_party_map("Supplier").get(party_name, {}).get("supplier_type") or ""
@@ -193,12 +199,12 @@ class ReceivablePayableReport(object):
def get_party_map(self, party_type):
if not hasattr(self, "party_map"):
if party_type == "Customer":
self.party_map = dict(((r.name, r) for r in frappe.db.sql("""select {0}, {1}, {2} from `tab{3}`"""
.format("name", "customer_name", "territory", party_type), as_dict=True)))
select_fields = "name, customer_name, territory, customer_group"
elif party_type == "Supplier":
self.party_map = dict(((r.name, r) for r in frappe.db.sql("""select {0}, {1}, {2} from `tab{3}`"""
.format("name", "supplier_name", "supplier_type", party_type), as_dict=True)))
select_fields = "name, supplier_name, supplier_type"
self.party_map = dict(((r.name, r) for r in frappe.db.sql("select {0} from `tab{1}`"
.format(select_fields, party_type), as_dict=True)))
return self.party_map
@@ -251,6 +257,19 @@ class ReceivablePayableReport(object):
conditions.append("party=%s")
values.append(self.filters.get(party_type_field))
if party_type_field=="customer":
if self.filters.get("customer_group"):
lft, rgt = frappe.db.get_value("Customer Group",
self.filters.get("customer_group"), ["lft", "rgt"])
conditions.append("""party in (select name from tabCustomer
where exists(select name from `tabCustomer Group` where lft >= {0} and rgt <= {1}
and name=tabCustomer.customer_group))""".format(lft, rgt))
if self.filters.get("credit_days_based_on"):
conditions.append("party in (select name from tabCustomer where credit_days_based_on=%s)")
values.append(self.filters.get("credit_days_based_on"))
return " and ".join(conditions), values
def get_gl_entries_for(self, party, party_type, against_voucher_type, against_voucher):

View File

@@ -16,6 +16,21 @@ frappe.query_reports["Accounts Receivable Summary"] = {
"fieldtype": "Link",
"options": "Customer"
},
{
"fieldname":"customer_group",
"label": __("Customer Group"),
"fieldtype": "Link",
"options": "Customer Group"
},
{
"fieldname":"credit_days_based_on",
"label": __("Credit Days Based On"),
"fieldtype": "Select",
"options": "" + NEWLINE + "Fixed Days" + NEWLINE + "Last Day of the Next Month"
},
{
"fieldtype": "Break",
},
{
"fieldname":"report_date",
"label": __("Date"),
@@ -29,9 +44,6 @@ frappe.query_reports["Accounts Receivable Summary"] = {
"options": 'Posting Date' + NEWLINE + 'Due Date',
"default": "Posting Date"
},
{
"fieldtype": "Break",
},
{
"fieldname":"range1",
"label": __("Ageing Range 1"),

View File

@@ -27,7 +27,10 @@ class AccountsReceivableSummary(ReceivablePayableReport):
str(self.filters.range3) + _("-Above") + ":Currency/currency:100"]
if args.get("party_type") == "Customer":
columns += [_("Territory") + ":Link/Territory:80"]
columns += [
_("Territory") + ":Link/Territory:80",
_("Customer Group") + ":Link/Customer Group:120"
]
if args.get("party_type") == "Supplier":
columns += [_("Supplier Type") + ":Link/Supplier Type:80"]
@@ -58,7 +61,7 @@ class AccountsReceivableSummary(ReceivablePayableReport):
]
if args.get("party_type") == "Customer":
row += [self.get_territory(party)]
row += [self.get_territory(party), self.get_customer_group(party)]
if args.get("party_type") == "Supplier":
row += [self.get_supplier_type(party)]
@@ -107,7 +110,7 @@ class AccountsReceivableSummary(ReceivablePayableReport):
if args.get("party_type") == "Supplier":
cols += ["supplier_type", "remarks"]
if args.get("party_type") == "Customer":
cols += ["territory", "remarks"]
cols += ["territory", "customer_group", "remarks"]
return self.make_data_dict(cols, voucherwise_data)

View File

@@ -3,6 +3,12 @@
frappe.require("assets/erpnext/js/financial_statements.js", function() {
frappe.query_reports["Balance Sheet"] = erpnext.financial_statements;
frappe.query_reports["Balance Sheet"]["filters"].push({
"fieldname": "accumulated_values",
"label": __("Accumulated Values"),
"fieldtype": "Check"
});
});

View File

@@ -8,11 +8,23 @@ from frappe.utils import flt, cint
from erpnext.accounts.report.financial_statements import (get_period_list, get_columns, get_data)
def execute(filters=None):
period_list = get_period_list(filters.from_fiscal_year, filters.to_fiscal_year, filters.periodicity, filters.company)
period_list = get_period_list(filters.from_fiscal_year, filters.to_fiscal_year,
filters.periodicity, filters.accumulated_values, filters.company)
asset = get_data(filters.company, "Asset", "Debit", period_list, only_current_fiscal_year=False)
liability = get_data(filters.company, "Liability", "Credit", period_list, only_current_fiscal_year=False)
equity = get_data(filters.company, "Equity", "Credit", period_list, only_current_fiscal_year=False)
asset = get_data(filters.company, "Asset", "Debit", period_list,
only_current_fiscal_year=False, filters=filters,
accumulated_values=filters.accumulated_values,
ignore_closing_entries=True, ignore_accumulated_values_for_fy=True)
liability = get_data(filters.company, "Liability", "Credit", period_list,
only_current_fiscal_year=False, filters=filters,
accumulated_values=filters.accumulated_values,
ignore_closing_entries=True, ignore_accumulated_values_for_fy=True)
equity = get_data(filters.company, "Equity", "Credit", period_list,
only_current_fiscal_year=False, filters=filters,
accumulated_values=filters.accumulated_values,
ignore_closing_entries=True, ignore_accumulated_values_for_fy=True)
provisional_profit_loss, total_credit = get_provisional_profit_loss(asset, liability, equity,
period_list, filters.company)
@@ -43,9 +55,9 @@ def execute(filters=None):
if total_credit:
data.append(total_credit)
columns = get_columns(filters.periodicity, period_list, company=filters.company)
columns = get_columns(filters.periodicity, period_list, filters.accumulated_values, company=filters.company)
chart = get_chart_data(columns, asset, liability, equity)
chart = get_chart_data(filters, columns, asset, liability, equity)
return columns, data, message, chart
@@ -107,7 +119,7 @@ def check_opening_balance(asset, liability, equity):
return _("Previous Financial Year is not closed"),opening_balance
return None,None
def get_chart_data(columns, asset, liability, equity):
def get_chart_data(filters, columns, asset, liability, equity):
x_intervals = ['x'] + [d.get("label") for d in columns[2:]]
asset_data, liability_data, equity_data = [], [], []
@@ -128,9 +140,14 @@ def get_chart_data(columns, asset, liability, equity):
if equity_data:
columns.append(["Equity"] + equity_data)
return {
chart = {
"data": {
'x': 'x',
'columns': columns
}
}
if not filters.accumulated_values:
chart["chart_type"] = "bar"
return chart

View File

@@ -22,7 +22,8 @@ frappe.query_reports["Bank Clearance Summary"] = {
"fieldtype": "Link",
"options": "Account",
"reqd": 1,
"default": locals[":Company"][frappe.defaults.get_user_default("Company")]["default_bank_account"],
"default": frappe.defaults.get_user_default("Company")?
locals[":Company"][frappe.defaults.get_user_default("Company")]["default_bank_account"]: "",
"get_query": function() {
return {
"query": "erpnext.controllers.queries.get_account_list",

View File

@@ -8,7 +8,8 @@ frappe.query_reports["Bank Reconciliation Statement"] = {
"label": __("Bank Account"),
"fieldtype": "Link",
"options": "Account",
"default": locals[":Company"][frappe.defaults.get_user_default("Company")]["default_bank_account"],
"default": frappe.defaults.get_user_default("Company")?
locals[":Company"][frappe.defaults.get_user_default("Company")]["default_bank_account"]: "",
"reqd": 1,
"get_query": function() {
return {

View File

@@ -11,7 +11,7 @@ from erpnext.accounts.utils import get_fiscal_year
def execute(filters=None):
period_list = get_period_list(filters.from_fiscal_year, filters.to_fiscal_year,
filters.periodicity, filters.company)
filters.periodicity, filters.accumulated_values, filters.company)
operation_accounts = {
"section_name": "Operations",

View File

@@ -13,12 +13,16 @@
height: 37px;
}
</style>
{% var letterhead= filters.letter_head || frappe.get_doc(":Company", filters.company).default_letter_head || frappe.defaults.get_default("letter_head"); %}
{% if(letterhead) { %}
<div style="margin-bottom: 7px;" class="text-center">
{%= frappe.boot.letter_heads[frappe.get_doc(":Company", filters.company).default_letter_head || frappe.defaults.get_default("letter_head")] %}
{%= frappe.boot.letter_heads[letterhead].header %}
</div>
{% } %}
<h2 class="text-center">{%= __(report.report_name) %}</h2>
<h4 class="text-center">{%= filters.company %}</h3>
<h4 class="text-center">{%= filters.fiscal_year %}</h3>
<h3 class="text-center">{%= filters.company %}</h3>
<h3 class="text-center">{%= filters.fiscal_year %}</h3>
<h5 class="text-center">{%= __("Currency") %} : {%= erpnext.get_currency(filters.company) %} </h4>
{% if (filters.from_date) { %}
<h4 class="text-center">{%= dateutil.str_to_user(filters.from_date) %} - {%= dateutil.str_to_user(filters.to_date) %}</h3>
{% } %}
@@ -47,7 +51,7 @@
<td class="text-right">
{% var fieldname = report.columns[i].field; %}
{% if (!is_null(row[fieldname])) { %}
{%= format_currency(row[fieldname], row.currency) %}
{%= format_number(row[fieldname], null)%}
{% } %}
</td>
{% } %}

View File

@@ -4,9 +4,10 @@
from __future__ import unicode_literals
import frappe
from frappe import _
from frappe.utils import flt, getdate, get_first_day, add_months, add_days, formatdate
from frappe.utils import (flt, getdate, get_first_day, get_last_day, date_diff,
add_months, add_days, formatdate, cint)
def get_period_list(from_fiscal_year, to_fiscal_year, periodicity, company):
def get_period_list(from_fiscal_year, to_fiscal_year, periodicity, accumulated_values=False, company=None):
"""Get a list of dict {"from_date": from_date, "to_date": to_date, "key": key, "label": label}
Periodicity can be (Yearly, Quarterly, Monthly)"""
@@ -58,11 +59,14 @@ def get_period_list(from_fiscal_year, to_fiscal_year, periodicity, company):
# common processing
for opts in period_list:
key = opts["to_date"].strftime("%b_%Y").lower()
if periodicity == "Monthly":
if periodicity == "Monthly" and not accumulated_values:
label = formatdate(opts["to_date"], "MMM YYYY")
else:
label = get_label(periodicity, opts["from_date"], opts["to_date"])
if not accumulated_values:
label = get_label(periodicity, opts["from_date"], opts["to_date"])
else:
label = get_label(periodicity, period_list[0]["from_date"], opts["to_date"])
opts.update({
"key": key.replace(" ", "_").replace("-", "_"),
"label": label,
@@ -139,7 +143,8 @@ def calculate_values(accounts_by_name, gl_entries_by_account, period_list, accum
if entry.posting_date <= period.to_date:
if (accumulated_values or entry.posting_date >= period.from_date) and \
(not ignore_accumulated_values_for_fy or entry.fiscal_year == period.to_date_fiscal_year):
(not ignore_accumulated_values_for_fy or
entry.fiscal_year == period.to_date_fiscal_year):
d[period.key] = d.get(period.key, 0.0) + flt(entry.debit) - flt(entry.credit)
if entry.posting_date < period_list[0].year_start_date:

View File

@@ -1,6 +1,9 @@
{% var letterhead= filters.letter_head || frappe.get_doc(":Company", filters.company).default_letter_head || frappe.defaults.get_default("letter_head"); %}
{% if(letterhead) { %}
<div style="margin-bottom: 7px;" class="text-center">
{%= frappe.boot.letter_heads[filters.letter_head || frappe.get_doc(":Company", filters.company).default_letter_head || frappe.defaults.get_default("letter_head")] %}
{%= frappe.boot.letter_heads[letterhead].header %}
</div>
{% } %}
<h2 class="text-center">{%= __("Statement of Account") %}</h2>
<h4 class="text-center">{%= (filters.party || filters.account) && ((filters.party || filters.account) + ", ") || "" %} {%= filters.company %}</h4>
<h5 class="text-center">

View File

@@ -66,7 +66,8 @@ def set_account_currency(filters):
if gle_currency:
account_currency = gle_currency
else:
account_currency = frappe.db.get_value(filters.party_type, filters.party, "default_currency")
account_currency = None if filters.party_type == "Employee" else \
frappe.db.get_value(filters.party_type, filters.party, "default_currency")
filters["account_currency"] = account_currency or filters.company_currency

View File

@@ -12,7 +12,7 @@ from frappe.utils import flt
def execute(filters=None):
if not filters: filters = frappe._dict()
company_currency = frappe.db.get_value("Company", filters.company, "default_currency")
filters.currency = frappe.db.get_value("Company", filters.company, "default_currency")
gross_profit_data = GrossProfitGenerator(filters)
@@ -50,7 +50,7 @@ def execute(filters=None):
for col in group_wise_columns.get(scrub(filters.group_by)):
row.append(src.get(col))
row.append(company_currency)
row.append(filters.currency)
data.append(row)
return columns, data
@@ -218,14 +218,18 @@ class GrossProfitGenerator(object):
def get_average_buying_rate(self, row, item_code):
if not item_code in self.average_buying_rate:
if item_code in self.non_stock_items:
self.average_buying_rate[item_code] = flt(frappe.db.sql("""select sum(base_net_amount) / sum(qty * conversion_factor)
self.average_buying_rate[item_code] = flt(frappe.db.sql("""
select sum(base_net_amount) / sum(qty * conversion_factor)
from `tabPurchase Invoice Item`
where item_code = %s and docstatus=1""", item_code)[0][0])
else:
average_buying_rate = get_incoming_rate(row)
if not average_buying_rate:
average_buying_rate = get_valuation_rate(item_code, row.warehouse, allow_zero_rate=True)
self.average_buying_rate[item_code] = average_buying_rate
average_buying_rate = get_valuation_rate(item_code, row.warehouse,
row.parenttype, row.parent, allow_zero_rate=True,
currency=self.filters.currency)
self.average_buying_rate[item_code] = flt(average_buying_rate)
return self.average_buying_rate[item_code]
@@ -235,7 +239,7 @@ class GrossProfitGenerator(object):
select (a.base_rate / a.conversion_factor)
from `tabPurchase Invoice Item` a
where a.item_code = %s and a.docstatus=1
and modified <= %s
and modified <= %s
order by a.modified desc limit 1""", (item_code,self.filters.to_date))
else:
last_purchase_rate = frappe.db.sql("""
@@ -253,7 +257,7 @@ class GrossProfitGenerator(object):
conditions += " and posting_date >= %(from_date)s"
if self.filters.to_date:
conditions += " and posting_date <= %(to_date)s"
if self.filters.group_by=="Sales Person":
sales_person_cols = ", sales.sales_person, sales.allocated_amount, sales.incentives"
sales_team_table = "left join `tabSales Team` sales on sales.parent = `tabSales Invoice`.name"
@@ -269,7 +273,7 @@ class GrossProfitGenerator(object):
`tabSales Invoice Item`.dn_detail, `tabSales Invoice Item`.delivery_note, `tabSales Invoice Item`.stock_qty as qty,
`tabSales Invoice Item`.base_net_rate, `tabSales Invoice Item`.base_net_amount, `tabSales Invoice Item`.name as "item_row"
{sales_person_cols}
from
from
`tabSales Invoice`
inner join `tabSales Invoice Item` on `tabSales Invoice Item`.parent = `tabSales Invoice`.name
{sales_team_table}
@@ -277,7 +281,7 @@ class GrossProfitGenerator(object):
`tabSales Invoice`.docstatus = 1 and `tabSales Invoice`.is_return != 1 {conditions} {match_cond}
order by
`tabSales Invoice`.posting_date desc, `tabSales Invoice`.posting_time desc"""
.format(conditions=conditions, sales_person_cols=sales_person_cols,
.format(conditions=conditions, sales_person_cols=sales_person_cols,
sales_team_table=sales_team_table, match_cond = get_match_cond('Sales Invoice')), self.filters, as_dict=1)
def load_stock_ledger_entries(self):

View File

@@ -9,12 +9,15 @@ from erpnext.accounts.report.financial_statements import (get_period_list, get_c
def execute(filters=None):
period_list = get_period_list(filters.from_fiscal_year, filters.to_fiscal_year,
filters.periodicity, filters.company)
filters.periodicity, filters.accumulated_values, filters.company)
income = get_data(filters.company, "Income", "Credit", period_list, filters = filters,
accumulated_values=filters.accumulated_values, ignore_closing_entries=True, ignore_accumulated_values_for_fy= True)
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)
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)

View File

@@ -7,7 +7,7 @@ from frappe.utils import flt
from frappe import msgprint, _
def execute(filters=None):
if not filters: filters = {}
if not filters: filters = frappe._dict({})
invoice_list = get_invoices(filters)
columns, income_accounts, tax_accounts = get_columns(invoice_list)

View File

@@ -4,13 +4,13 @@
from __future__ import unicode_literals
import frappe
import frappe.defaults
from frappe.utils import nowdate, cstr, flt, cint, now, getdate
from frappe import throw, _
from frappe.utils import formatdate
from frappe.utils import formatdate, get_number_format_info
# imported to enable erpnext.accounts.utils.get_account_currency
from erpnext.accounts.doctype.account.account import get_account_currency
import frappe.defaults
from erpnext.accounts.report.financial_statements import sort_root_accounts
class FiscalYearError(frappe.ValidationError): pass
@@ -537,15 +537,14 @@ def get_stock_and_account_difference(account_list=None, posting_date=None):
return difference
def get_currency_precision(currency=None):
if not currency:
currency = frappe.db.get_value("Company",
frappe.db.get_default("Company"), "default_currency", cache=True)
currency_format = frappe.db.get_value("Currency", currency, "number_format", cache=True)
from frappe.utils import get_number_format_info
return get_number_format_info(currency_format)[2]
def get_currency_precision():
precision = cint(frappe.db.get_default("currency_precision"))
if not precision:
number_format = frappe.db.get_default("number_format") or "#,###.##"
precision = get_number_format_info(number_format)[2]
return precision
def get_stock_rbnb_difference(posting_date, company):
stock_items = frappe.db.sql_list("""select distinct item_code
from `tabStock Ledger Entry` where company=%s""", company)

View File

@@ -1 +0,0 @@
Common scripts for purchase transactions.

View File

@@ -1 +0,0 @@
from __future__ import unicode_literals

View File

@@ -1,26 +0,0 @@
{
"allow_copy": 0,
"allow_import": 0,
"allow_rename": 0,
"creation": "2012-03-27 14:35:51",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"fields": [],
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 1,
"in_create": 0,
"in_dialog": 0,
"is_submittable": 0,
"issingle": 1,
"istable": 0,
"modified": "2013-12-20 19:23:27",
"modified_by": "Administrator",
"module": "Buying",
"name": "Purchase Common",
"owner": "Administrator",
"permissions": [],
"read_only": 0,
"read_only_onload": 0
}

View File

@@ -1,105 +0,0 @@
# 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, json
from frappe.utils import flt, cstr, cint
from frappe import _
from erpnext.stock.doctype.item.item import get_last_purchase_details
from erpnext.controllers.buying_controller import BuyingController
class PurchaseCommon(BuyingController):
def update_last_purchase_rate(self, obj, is_submit):
"""updates last_purchase_rate in item table for each item"""
import frappe.utils
this_purchase_date = frappe.utils.getdate(obj.get('posting_date') or obj.get('transaction_date'))
for d in obj.get("items"):
# get last purchase details
last_purchase_details = get_last_purchase_details(d.item_code, obj.name)
# compare last purchase date and this transaction's date
last_purchase_rate = None
if last_purchase_details and \
(last_purchase_details.purchase_date > this_purchase_date):
last_purchase_rate = last_purchase_details['base_rate']
elif is_submit == 1:
# even if this transaction is the latest one, it should be submitted
# for it to be considered for latest purchase rate
if flt(d.conversion_factor):
last_purchase_rate = flt(d.base_rate) / flt(d.conversion_factor)
else:
frappe.throw(_("UOM Conversion factor is required in row {0}").format(d.idx))
# update last purchsae rate
if last_purchase_rate:
frappe.db.sql("""update `tabItem` set last_purchase_rate = %s where name = %s""",
(flt(last_purchase_rate), d.item_code))
def validate_for_items(self, obj):
items = []
for d in obj.get("items"):
if not d.qty:
if obj.doctype == "Purchase Receipt" and d.rejected_qty:
continue
frappe.throw(_("Please enter quantity for Item {0}").format(d.item_code))
# udpate with latest quantities
bin = frappe.db.sql("""select projected_qty from `tabBin` where
item_code = %s and warehouse = %s""", (d.item_code, d.warehouse), as_dict=1)
f_lst ={'projected_qty': bin and flt(bin[0]['projected_qty']) or 0, 'ordered_qty': 0, 'received_qty' : 0}
if d.doctype in ('Purchase Receipt Item', 'Purchase Invoice Item'):
f_lst.pop('received_qty')
for x in f_lst :
if d.meta.get_field(x):
d.set(x, f_lst[x])
item = frappe.db.sql("""select is_stock_item,
is_sub_contracted_item, end_of_life, disabled from `tabItem` where name=%s""",
d.item_code, as_dict=1)[0]
from erpnext.stock.doctype.item.item import validate_end_of_life
validate_end_of_life(d.item_code, item.end_of_life, item.disabled)
# validate stock item
if item.is_stock_item==1 and d.qty and not d.warehouse and not d.delivered_by_supplier:
frappe.throw(_("Warehouse is mandatory for stock Item {0} in row {1}").format(d.item_code, d.idx))
items.append(cstr(d.item_code))
if items and len(items) != len(set(items)) and \
not cint(frappe.db.get_single_value("Buying Settings", "allow_multiple_items") or 0):
frappe.throw(_("Same item cannot be entered multiple times."))
def check_for_closed_status(self, doctype, docname):
status = frappe.db.get_value(doctype, docname, "status")
if status == "Closed":
frappe.throw(_("{0} {1} status is {2}").format(doctype, docname, status), frappe.InvalidStatusError)
@frappe.whitelist()
def get_linked_material_requests(items):
items = json.loads(items)
mr_list = []
for item in items:
material_request = frappe.db.sql("""SELECT distinct mr.name AS mr_name,
(mr_item.qty - mr_item.ordered_qty) AS qty,
mr_item.item_code AS item_code,
mr_item.name AS mr_item
FROM `tabMaterial Request` mr, `tabMaterial Request Item` mr_item
WHERE mr.name = mr_item.parent
AND mr_item.item_code = %(item)s
AND mr.material_request_type = 'Purchase'
AND mr.per_ordered < 99.99
AND mr.docstatus = 1
AND mr.status != 'Stopped'
ORDER BY mr_item.item_code ASC""",{"item": item}, as_dict=1)
if material_request:
mr_list.append(material_request)
return mr_list

View File

@@ -3,7 +3,7 @@
frappe.provide("erpnext.buying");
{% include 'erpnext/buying/doctype/purchase_common/purchase_common.js' %};
{% include 'erpnext/public/js/controllers/buying.js' %};
frappe.ui.form.on("Purchase Order", {
setup: function(frm) {

View File

@@ -1,5 +1,6 @@
{
"allow_copy": 0,
"allow_guest_to_view": 0,
"allow_import": 1,
"allow_rename": 0,
"autoname": "naming_series:",
@@ -341,7 +342,7 @@
"remember_last_selected_value": 1,
"report_hide": 0,
"reqd": 1,
"search_index": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
@@ -1207,6 +1208,8 @@
"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": "Link to material requests",
@@ -3185,18 +3188,18 @@
"unique": 0
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"icon": "fa fa-file-text",
"idx": 105,
"image_view": 0,
"in_create": 0,
"in_dialog": 0,
"is_submittable": 1,
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2017-02-28 18:20:15.650815",
"modified": "2017-04-18 18:49:49.535066",
"modified_by": "Administrator",
"module": "Buying",
"name": "Purchase Order",
@@ -3294,4 +3297,4 @@
"title_field": "title",
"track_changes": 0,
"track_seen": 0
}
}

View File

@@ -11,6 +11,8 @@ from erpnext.controllers.buying_controller import BuyingController
from erpnext.stock.doctype.item.item import get_last_purchase_details
from erpnext.stock.stock_balance import update_bin_qty, get_ordered_qty
from frappe.desk.notifications import clear_doctype_notifications
from erpnext.buying.utils import (validate_for_items, check_for_closed_status,
update_last_purchase_rate)
form_grid_templates = {
@@ -37,9 +39,8 @@ class PurchaseOrder(BuyingController):
super(PurchaseOrder, self).validate()
self.set_status()
pc_obj = frappe.get_doc('Purchase Common')
pc_obj.validate_for_items(self)
self.check_for_closed_status(pc_obj)
validate_for_items(self)
self.check_for_closed_status()
self.validate_uom_is_integer("uom", "qty")
self.validate_uom_is_integer("stock_uom", ["qty", "required_qty"])
@@ -111,12 +112,12 @@ class PurchaseOrder(BuyingController):
= d.rate = item_last_purchase_rate
# Check for Closed status
def check_for_closed_status(self, pc_obj):
def check_for_closed_status(self):
check_list =[]
for d in self.get('items'):
if d.meta.get_field('material_request') and d.material_request and d.material_request not in check_list:
check_list.append(d.material_request)
pc_obj.check_for_closed_status('Material Request', d.material_request)
check_for_closed_status('Material Request', d.material_request)
def update_requested_qty(self):
material_request_map = {}
@@ -155,7 +156,7 @@ class PurchaseOrder(BuyingController):
if date_diff and date_diff[0][0]:
msgprint(_("{0} {1} has been modified. Please refresh.").format(self.doctype, self.name),
raise_exception=True)
def update_status(self, status):
self.check_modified_date()
self.set_status(update=True, status=status)
@@ -168,8 +169,6 @@ class PurchaseOrder(BuyingController):
if self.is_against_so():
self.update_status_updater()
purchase_controller = frappe.get_doc("Purchase Common")
self.update_prevdoc_status()
self.update_requested_qty()
self.update_ordered_qty()
@@ -177,7 +176,7 @@ class PurchaseOrder(BuyingController):
frappe.get_doc('Authorization Control').validate_approving_authority(self.doctype,
self.company, self.base_grand_total)
purchase_controller.update_last_purchase_rate(self, is_submit = 1)
update_last_purchase_rate(self, is_submit = 1)
def on_cancel(self):
if self.is_against_so():
@@ -186,8 +185,7 @@ class PurchaseOrder(BuyingController):
if self.has_drop_ship_item():
self.update_delivered_qty_in_sales_order()
pc_obj = frappe.get_doc('Purchase Common')
self.check_for_closed_status(pc_obj)
self.check_for_closed_status()
frappe.db.set(self,'status','Cancelled')
@@ -197,7 +195,7 @@ class PurchaseOrder(BuyingController):
self.update_requested_qty()
self.update_ordered_qty()
pc_obj.update_last_purchase_rate(self, is_submit = 0)
update_last_purchase_rate(self, is_submit = 0)
def on_update(self):
pass
@@ -303,7 +301,7 @@ def make_purchase_invoice(source_name, target_doc=None):
target.amount = flt(obj.amount) - flt(obj.billed_amt)
target.base_amount = target.amount * flt(source_parent.conversion_rate)
target.qty = target.amount / flt(obj.rate) if (flt(obj.rate) and flt(obj.billed_amt)) else flt(obj.qty)
item = frappe.db.get_value("Item", target.item_code, ["item_group", "buying_cost_center"], as_dict=1)
target.cost_center = frappe.db.get_value("Project", obj.project, "cost_center") \
or item.buying_cost_center \
@@ -342,7 +340,8 @@ def make_stock_entry(purchase_order, item_code):
stock_entry.purchase_order = purchase_order.name
stock_entry.supplier = purchase_order.supplier
stock_entry.supplier_name = purchase_order.supplier_name
stock_entry.supplier_address = purchase_order.address_display
stock_entry.supplier_address = purchase_order.supplier_address
stock_entry.address_display = purchase_order.address_display
stock_entry.company = purchase_order.company
stock_entry.from_bom = 1
po_item = [d for d in purchase_order.items if d.item_code == item_code][0]

View File

@@ -1,5 +1,6 @@
{
"allow_copy": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"autoname": "hash",
@@ -98,7 +99,7 @@
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
@@ -156,7 +157,7 @@
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
@@ -799,6 +800,7 @@
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"permlevel": 0,
"precision": "",
"print_hide": 1,
"print_hide_if_no_value": 0,
"print_width": "100px",
@@ -1647,17 +1649,17 @@
"unique": 0
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 1,
"image_view": 0,
"in_create": 0,
"in_dialog": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2017-02-17 16:44:55.434162",
"modified": "2017-04-25 18:49:08.604055",
"modified_by": "Administrator",
"module": "Buying",
"name": "Purchase Order Item",

View File

@@ -2,7 +2,7 @@
// License: GNU General Public License v3. See license.txt
{% include 'erpnext/buying/doctype/purchase_common/purchase_common.js' %};
{% include 'erpnext/public/js/controllers/buying.js' %};
cur_frm.add_fetch('contact', 'email_id', 'email_id')

View File

@@ -14,13 +14,14 @@ from frappe.core.doctype.communication.email import make
from erpnext.accounts.party import get_party_account_currency, get_party_details
from erpnext.stock.doctype.material_request.material_request import set_missing_values
from erpnext.controllers.buying_controller import BuyingController
from erpnext.buying.utils import validate_for_items
STANDARD_USERS = ("Guest", "Administrator")
class RequestforQuotation(BuyingController):
def validate(self):
self.validate_duplicate_supplier()
self.validate_common()
validate_for_items(self)
self.update_email_id()
def validate_duplicate_supplier(self):
@@ -28,10 +29,6 @@ class RequestforQuotation(BuyingController):
if len(supplier_list) != len(set(supplier_list)):
frappe.throw(_("Same supplier has been entered multiple times"))
def validate_common(self):
pc = frappe.get_doc('Purchase Common')
pc.validate_for_items(self)
def update_email_id(self):
for rfq_supplier in self.suppliers:
if not rfq_supplier.email_id:
@@ -130,7 +127,7 @@ class RequestforQuotation(BuyingController):
self.send_email(data, sender, subject, message, attachments)
def send_email(self, data, sender, subject, message, attachments):
make(subject = subject, content=message,recipients=data.email_id,
make(subject = subject, content=message,recipients=data.email_id,
sender=sender,attachments = attachments, send_email=True,
doctype=self.doctype, name=self.name)["name"]
@@ -250,26 +247,26 @@ def get_rfq_doc(doctype, name, supplier_idx):
args = doc.get('suppliers')[cint(supplier_idx) - 1]
doc.update_supplier_part_no(args)
return doc
@frappe.whitelist()
def get_item_from_material_requests_based_on_supplier(source_name, target_doc = None):
mr_items_list = frappe.db.sql("""
SELECT
mr.name, mr_item.item_code
FROM
`tabItem` as item,
`tabItem Supplier` as item_supp,
`tabMaterial Request Item` as mr_item,
`tabMaterial Request` as mr
WHERE item_supp.supplier = %(supplier)s
AND item.name = item_supp.parent
AND mr_item.parent = mr.name
AND mr_item.item_code = item.name
AND mr.status != "Stopped"
AND mr.material_request_type = "Purchase"
AND mr.docstatus = 1
`tabItem` as item,
`tabItem Supplier` as item_supp,
`tabMaterial Request Item` as mr_item,
`tabMaterial Request` as mr
WHERE item_supp.supplier = %(supplier)s
AND item.name = item_supp.parent
AND mr_item.parent = mr.name
AND mr_item.item_code = item.name
AND mr.status != "Stopped"
AND mr.material_request_type = "Purchase"
AND mr.docstatus = 1
AND mr.per_ordered < 99.99""", {"supplier": source_name}, as_dict=1)
material_requests = {}
for d in mr_items_list:
material_requests.setdefault(d.name, []).append(d.item_code)
@@ -293,5 +290,5 @@ def get_item_from_material_requests_based_on_supplier(source_name, target_doc =
]
}
}, target_doc)
return target_doc

View File

@@ -2,7 +2,7 @@
// License: GNU General Public License v3. See license.txt
// attach required files
{% include 'erpnext/buying/doctype/purchase_common/purchase_common.js' %};
{% include 'erpnext/public/js/controllers/buying.js' %};
frappe.ui.form.on('Suppier Quotation', {
setup: function() {

View File

@@ -8,6 +8,7 @@ from frappe.utils import flt
from frappe.model.mapper import get_mapped_doc
from erpnext.controllers.buying_controller import BuyingController
from erpnext.buying.utils import validate_for_items
form_grid_templates = {
"items": "templates/form_grid/item_grid.html"
@@ -24,7 +25,7 @@ class SupplierQuotation(BuyingController):
validate_status(self.status, ["Draft", "Submitted", "Stopped",
"Cancelled"])
self.validate_common()
validate_for_items(self)
self.validate_with_previous_doc()
self.validate_uom_is_integer("uom", "qty")
@@ -50,11 +51,6 @@ class SupplierQuotation(BuyingController):
}
})
def validate_common(self):
pc = frappe.get_doc('Purchase Common')
pc.validate_for_items(self)
def get_list_context(context=None):
from erpnext.controllers.website_list_for_contact import get_list_context
list_context = get_list_context(context)

80
erpnext/buying/utils.py Normal file
View File

@@ -0,0 +1,80 @@
# 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
from frappe.utils import flt, cstr, cint
from frappe import _
from erpnext.stock.doctype.item.item import get_last_purchase_details
from erpnext.stock.doctype.item.item import validate_end_of_life
def update_last_purchase_rate(doc, is_submit):
"""updates last_purchase_rate in item table for each item"""
import frappe.utils
this_purchase_date = frappe.utils.getdate(doc.get('posting_date') or doc.get('transaction_date'))
for d in doc.get("items"):
# get last purchase details
last_purchase_details = get_last_purchase_details(d.item_code, doc.name)
# compare last purchase date and this transaction's date
last_purchase_rate = None
if last_purchase_details and \
(last_purchase_details.purchase_date > this_purchase_date):
last_purchase_rate = last_purchase_details['base_rate']
elif is_submit == 1:
# even if this transaction is the latest one, it should be submitted
# for it to be considered for latest purchase rate
if flt(d.conversion_factor):
last_purchase_rate = flt(d.base_rate) / flt(d.conversion_factor)
else:
frappe.throw(_("UOM Conversion factor is required in row {0}").format(d.idx))
# update last purchsae rate
if last_purchase_rate:
frappe.db.sql("""update `tabItem` set last_purchase_rate = %s where name = %s""",
(flt(last_purchase_rate), d.item_code))
def validate_for_items(doc):
items = []
for d in doc.get("items"):
if not d.qty:
if doc.doctype == "Purchase Receipt" and d.rejected_qty:
continue
frappe.throw(_("Please enter quantity for Item {0}").format(d.item_code))
# update with latest quantities
bin = frappe.db.sql("""select projected_qty from `tabBin` where
item_code = %s and warehouse = %s""", (d.item_code, d.warehouse), as_dict=1)
f_lst ={'projected_qty': bin and flt(bin[0]['projected_qty']) or 0, 'ordered_qty': 0, 'received_qty' : 0}
if d.doctype in ('Purchase Receipt Item', 'Purchase Invoice Item'):
f_lst.pop('received_qty')
for x in f_lst :
if d.meta.get_field(x):
d.set(x, f_lst[x])
item = frappe.db.sql("""select is_stock_item,
is_sub_contracted_item, end_of_life, disabled from `tabItem` where name=%s""",
d.item_code, as_dict=1)[0]
validate_end_of_life(d.item_code, item.end_of_life, item.disabled)
# validate stock item
if item.is_stock_item==1 and d.qty and not d.warehouse and not d.delivered_by_supplier:
frappe.throw(_("Warehouse is mandatory for stock Item {0} in row {1}").format(d.item_code, d.idx))
items.append(cstr(d.item_code))
if items and len(items) != len(set(items)) and \
not cint(frappe.db.get_single_value("Buying Settings", "allow_multiple_items") or 0):
frappe.throw(_("Same item cannot be entered multiple times."))
def check_for_closed_status(doctype, docname):
status = frappe.db.get_value(doctype, docname, "status")
if status == "Closed":
frappe.throw(_("{0} {1} status is {2}").format(doctype, docname, status), frappe.InvalidStatusError)

View File

@@ -159,6 +159,11 @@ def get_data():
"is_query_report": True,
"doctype": "Journal Entry"
},
{
"type": "doctype",
"name": "Bank Guarantee",
"doctype": "Bank Guarantee"
},
]
},
{

View File

@@ -32,6 +32,12 @@ def get_data():
"label": _("Reports"),
"icon": "fa fa-list",
"items": [
{
"type": "report",
"is_query_report": True,
"name": "Lead Details",
"doctype": "Lead"
},
{
"type": "page",
"name": "sales-funnel",
@@ -40,15 +46,15 @@ def get_data():
},
{
"type": "report",
"name": "Minutes to First Response for Opportunity",
"doctype": "Opportunity",
"name": "Prospects Engaged But Not Converted",
"doctype": "Lead",
"is_query_report": True
},
{
"type": "report",
"is_query_report": True,
"name": "Lead Details",
"doctype": "Lead"
"name": "Minutes to First Response for Opportunity",
"doctype": "Opportunity",
"is_query_report": True
},
{
"type": "report",
@@ -62,6 +68,18 @@ def get_data():
"name": "Inactive Customers",
"doctype": "Sales Order"
},
{
"type": "report",
"is_query_report": True,
"name": "Campaign Efficiency",
"doctype": "Lead"
},
{
"type": "report",
"is_query_report": True,
"name": "Lead Owner Efficiency",
"doctype": "Lead"
}
]
},
{

View File

@@ -106,7 +106,7 @@ def get_data():
{
"type": "doctype",
"name": "Course Schedule",
"route": "Calendar/Course Schedule"
"route": "List/Course Schedule/Calendar"
},
{
"type": "doctype",
@@ -205,6 +205,10 @@ def get_data():
{
"type": "doctype",
"name": "Academic Year"
},
{
"type": "doctype",
"name": "School Settings"
}
]
},

View File

@@ -2,10 +2,10 @@
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe
import frappe, erpnext
from frappe import _, throw
from frappe.utils import today, flt, cint, fmt_money, formatdate, getdate
from erpnext.setup.utils import get_company_currency, get_exchange_rate
from erpnext.setup.utils import get_exchange_rate
from erpnext.accounts.utils import get_fiscal_years, validate_fiscal_year, get_account_currency
from erpnext.utilities.transaction_base import TransactionBase
from erpnext.controllers.recurring_document import convert_to_recurring, validate_recurring_document
@@ -22,7 +22,7 @@ class AccountsController(TransactionBase):
@property
def company_currency(self):
if not hasattr(self, "__company_currency"):
self.__company_currency = get_company_currency(self.company)
self.__company_currency = erpnext.get_company_currency(self.company)
return self.__company_currency
@@ -186,15 +186,19 @@ class AccountsController(TransactionBase):
ret = get_item_details(args)
for fieldname, value in ret.items():
if item.meta.get_field(fieldname) and value is not None:
if (item.get(fieldname) is None or fieldname in force_item_fields):
item.set(fieldname, value)
elif fieldname == "cost_center" and not item.get("cost_center"):
elif fieldname in ['cost_center', 'conversion_factor'] and not item.get(fieldname):
item.set(fieldname, value)
elif fieldname == "serial_no":
stock_qty = item.get("stock_qty") * -1 if item.get("stock_qty") < 0 else item.get("stock_qty")
if stock_qty != len(item.get('serial_no').split('\n')):
item.set(fieldname, value)
elif fieldname == "conversion_factor" and not item.get("conversion_factor"):
item.set(fieldname, value)

View File

@@ -6,9 +6,10 @@ import frappe
from frappe import _, msgprint
from frappe.utils import flt,cint, cstr
from erpnext.setup.utils import get_company_currency
from erpnext.accounts.party import get_party_details
from erpnext.stock.get_item_details import get_conversion_factor
from erpnext.buying.utils import validate_for_items
from erpnext.stock.stock_ledger import get_valuation_rate
from erpnext.controllers.stock_controller import StockController
@@ -40,9 +41,7 @@ class BuyingController(StockController):
# self.validate_purchase_return()
self.validate_rejected_warehouse()
self.validate_accepted_rejected_qty()
pc_obj = frappe.get_doc('Purchase Common')
pc_obj.validate_for_items(self)
validate_for_items(self)
#sub-contracting
self.validate_for_subcontracting()
@@ -88,9 +87,8 @@ class BuyingController(StockController):
def set_total_in_words(self):
from frappe.utils import money_in_words
company_currency = get_company_currency(self.company)
if self.meta.get_field("base_in_words"):
self.base_in_words = money_in_words(self.base_grand_total, company_currency)
self.base_in_words = money_in_words(self.base_grand_total, self.company_currency)
if self.meta.get_field("in_words"):
self.in_words = money_in_words(self.grand_total, self.currency)
@@ -225,9 +223,8 @@ class BuyingController(StockController):
"serial_no": rm.serial_no
})
if not rm.rate:
from erpnext.stock.stock_ledger import get_valuation_rate
rm.rate = get_valuation_rate(bom_item.item_code, self.supplier_warehouse,
self.doctype, self.name)
rm.rate = get_valuation_rate(bom_item.item_code, self.supplier_warehouse,
self.doctype, self.name, currency=self.company_currency)
else:
rm.rate = bom_item.rate

View File

@@ -106,24 +106,25 @@ def validate_returned_items(doc):
def validate_quantity(doc, args, ref, valid_items, already_returned_items):
fields = ['qty']
if doc.doctype in ['Purchase Invoice', 'Purchase Receipt']:
if doc.doctype in ['Purchase Receipt', 'Purchase Invoice']:
fields.extend(['received_qty', 'rejected_qty'])
already_returned_data = already_returned_items.get(args.item_code) or {}
for column in fields:
return_qty = flt(already_returned_data.get(column, 0)) if len(already_returned_data) > 0 else 0
referenced_qty = ref.get(column)
max_return_qty = flt(referenced_qty) - return_qty
returned_qty = flt(already_returned_data.get(column, 0)) if len(already_returned_data) > 0 else 0
reference_qty = ref.get(column)
max_returnable_qty = flt(reference_qty) - returned_qty
label = column.replace('_', ' ').title()
if flt(args.get(column)) > 0:
frappe.throw(_("{0} must be negative in return document").format(label))
elif return_qty >= referenced_qty and flt(args.get(column)) != 0:
frappe.throw(_("Item {0} has already been returned").format(args.item_code), StockOverReturnError)
elif abs(args.get(column)) > max_return_qty:
frappe.throw(_("Row # {0}: Cannot return more than {1} for Item {2}")
.format(args.idx, referenced_qty, args.item_code), StockOverReturnError)
if reference_qty:
if flt(args.get(column)) > 0:
frappe.throw(_("{0} must be negative in return document").format(label))
elif returned_qty >= reference_qty and args.get(column):
frappe.throw(_("Item {0} has already been returned")
.format(args.item_code), StockOverReturnError)
elif abs(args.get(column)) > max_returnable_qty:
frappe.throw(_("Row # {0}: Cannot return more than {1} for Item {2}")
.format(args.idx, reference_qty, args.item_code), StockOverReturnError)
def get_ref_item_dict(valid_items, ref_item_row):
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos

View File

@@ -4,11 +4,9 @@
from __future__ import unicode_literals
import frappe
from frappe.utils import cint, flt, cstr, comma_or
from erpnext.setup.utils import get_company_currency
from frappe import _, throw
from erpnext.stock.get_item_details import get_bin_details
from erpnext.stock.utils import get_incoming_rate
from erpnext.stock.stock_ledger import get_valuation_rate
from erpnext.stock.get_item_details import get_conversion_factor
from erpnext.controllers.stock_controller import StockController
@@ -43,7 +41,7 @@ class SellingController(StockController):
# set contact and address details for customer, if they are not mentioned
self.set_missing_lead_customer_details()
self.set_price_list_and_item_details()
self.set_price_list_and_item_details(for_validate=for_validate)
def set_missing_lead_customer_details(self):
if getattr(self, "customer", None):
@@ -62,9 +60,9 @@ class SellingController(StockController):
posting_date=self.get('transaction_date') or self.get('posting_date'),
company=self.company))
def set_price_list_and_item_details(self):
def set_price_list_and_item_details(self, for_validate=False):
self.set_price_list_currency("Selling")
self.set_missing_item_details()
self.set_missing_item_details(for_validate=for_validate)
def apply_shipping_rule(self):
if self.shipping_rule:
@@ -113,13 +111,11 @@ class SellingController(StockController):
def set_total_in_words(self):
from frappe.utils import money_in_words
company_currency = get_company_currency(self.company)
disable_rounded_total = cint(frappe.db.get_value("Global Defaults", None, "disable_rounded_total"))
if self.meta.get_field("base_in_words"):
self.base_in_words = money_in_words(disable_rounded_total and
abs(self.base_grand_total) or abs(self.base_rounded_total), company_currency)
abs(self.base_grand_total) or abs(self.base_rounded_total), self.company_currency)
if self.meta.get_field("in_words"):
self.in_words = money_in_words(disable_rounded_total and
abs(self.grand_total) or abs(self.rounded_total), self.currency)
@@ -170,7 +166,7 @@ class SellingController(StockController):
if d.meta.get_field("stock_qty"):
if not d.conversion_factor:
frappe.throw(_("Row {0}: Conversion Factor is mandatory").format(d.idx))
d.stock_qty = flt(d.qty) * flt(d.conversion_factor)
d.stock_qty = flt(d.qty) * flt(d.conversion_factor)
def validate_selling_price(self):
def throw_message(item_name, rate, ref_rate_field):
@@ -207,7 +203,7 @@ class SellingController(StockController):
if p.parent_detail_docname == d.name and p.parent_item == d.item_code:
# the packing details table's qty is already multiplied with parent's qty
il.append(frappe._dict({
'warehouse': p.warehouse,
'warehouse': p.warehouse or d.warehouse,
'item_code': p.item_code,
'qty': flt(p.qty),
'uom': p.uom,

View File

@@ -119,7 +119,7 @@ class StatusUpdater(Document):
self.status = s[0]
break
elif s[1].startswith("eval:"):
if eval(s[1][5:]):
if frappe.safe_eval(s[1][5:], None, { "self": self.as_dict(), "getdate": getdate, "nowdate": nowdate }):
self.status = s[0]
break
elif getattr(self, s[1])():

View File

@@ -54,14 +54,14 @@ class StockController(AccountsController):
self.check_expense_account(item_row)
# If item is not a sample item
# If the item does not have the allow zero valuation rate flag set
# and ( valuation rate not mentioned in an incoming entry
# or incoming entry not found while delivering the item),
# or incoming entry not found while delivering the item),
# try to pick valuation rate from previous sle or Item master and update in SLE
# Otherwise, throw an exception
if not sle.stock_value_difference and self.doctype != "Stock Reconciliation" \
and not item_row.get("is_sample_item"):
and not item_row.get("allow_zero_valuation_rate"):
sle = self.update_stock_ledger_entries(sle)
@@ -96,25 +96,25 @@ class StockController(AccountsController):
return process_gl_map(gl_list)
def update_stock_ledger_entries(self, sle):
sle.valuation_rate = get_valuation_rate(sle.item_code, sle.warehouse,
self.doctype, self.name)
sle.valuation_rate = get_valuation_rate(sle.item_code, sle.warehouse,
self.doctype, self.name, currency=self.company_currency)
sle.stock_value = flt(sle.qty_after_transaction) * flt(sle.valuation_rate)
sle.stock_value_difference = flt(sle.actual_qty) * flt(sle.valuation_rate)
if sle.name:
frappe.db.sql("""
update
`tabStock Ledger Entry`
set
update
`tabStock Ledger Entry`
set
stock_value = %(stock_value)s,
valuation_rate = %(valuation_rate)s,
stock_value_difference = %(stock_value_difference)s
where
valuation_rate = %(valuation_rate)s,
stock_value_difference = %(stock_value_difference)s
where
name = %(name)s""", (sle))
return sle
def get_voucher_details(self, default_expense_account, default_cost_center, sle_map):
if self.doctype == "Stock Reconciliation":
return [frappe._dict({ "name": voucher_detail_no, "expense_account": default_expense_account,
@@ -163,9 +163,9 @@ class StockController(AccountsController):
def get_stock_ledger_details(self):
stock_ledger = {}
stock_ledger_entries = frappe.db.sql("""
select
select
name, warehouse, stock_value_difference, valuation_rate,
voucher_detail_no, item_code, posting_date, posting_time,
voucher_detail_no, item_code, posting_date, posting_time,
actual_qty, qty_after_transaction
from
`tabStock Ledger Entry`
@@ -177,6 +177,19 @@ class StockController(AccountsController):
stock_ledger.setdefault(sle.voucher_detail_no, []).append(sle)
return stock_ledger
def make_batches(self, warehouse_field):
'''Create batches if required. Called before submit'''
for d in self.items:
if d.get(warehouse_field) and not d.batch_no:
has_batch_no, create_new_batch = frappe.db.get_value('Item', d.item_code, ['has_batch_no', 'create_new_batch'])
if has_batch_no and create_new_batch:
d.batch_no = frappe.get_doc(dict(
doctype='Batch',
item=d.item_code,
supplier=getattr(self, 'supplier', None),
reference_doctype=self.doctype,
reference_name=self.name)).insert().name
def make_adjustment_entry(self, expected_gle, voucher_obj):
from erpnext.accounts.utils import get_stock_and_account_difference
account_list = [d.account for d in expected_gle]

View File

@@ -3,10 +3,9 @@
from __future__ import unicode_literals
import json
import frappe
import frappe, erpnext
from frappe import _, scrub
from frappe.utils import cint, flt, round_based_on_smallest_currency_fraction
from erpnext.setup.utils import get_company_currency
from erpnext.controllers.accounts_controller import validate_conversion_rate, \
validate_taxes_and_charges, validate_inclusive_tax
@@ -38,7 +37,7 @@ class calculate_taxes_and_totals(object):
def validate_conversion_rate(self):
# validate conversion rate
company_currency = get_company_currency(self.doc.company)
company_currency = erpnext.get_company_currency(self.doc.company)
if not self.doc.currency or self.doc.currency == company_currency:
self.doc.currency = company_currency
self.doc.conversion_rate = 1.0
@@ -61,6 +60,7 @@ class calculate_taxes_and_totals(object):
if item.doctype in ['Quotation Item', 'Sales Order Item', 'Delivery Note Item', 'Sales Invoice Item']:
item.total_margin = self.calculate_margin(item)
item.rate = flt(item.total_margin * (1.0 - (item.discount_percentage / 100.0)), item.precision("rate"))\
if item.total_margin > 0 else item.rate
@@ -327,7 +327,7 @@ class calculate_taxes_and_totals(object):
self.doc.rounded_total = round_based_on_smallest_currency_fraction(self.doc.grand_total,
self.doc.currency, self.doc.precision("rounded_total"))
if self.doc.meta.get_field("base_rounded_total"):
company_currency = get_company_currency(self.doc.company)
company_currency = erpnext.get_company_currency(self.doc.company)
self.doc.base_rounded_total = \
round_based_on_smallest_currency_fraction(self.doc.base_grand_total,
@@ -405,11 +405,14 @@ class calculate_taxes_and_totals(object):
self.doc.total_advance = flt(total_allocated_amount, self.doc.precision("total_advance"))
if self.doc.party_account_currency == self.doc.currency:
invoice_total = self.doc.grand_total
else:
invoice_total = flt(self.doc.grand_total * self.doc.conversion_rate,
invoice_total = flt(self.doc.grand_total - flt(self.doc.write_off_amount),
self.doc.precision("grand_total"))
else:
base_write_off_amount = flt(flt(self.doc.write_off_amount) * self.doc.conversion_rate,
self.doc.precision("base_write_off_amount"))
invoice_total = flt(self.doc.grand_total * self.doc.conversion_rate,
self.doc.precision("grand_total")) - base_write_off_amount
if invoice_total > 0 and self.doc.total_advance > invoice_total:
frappe.throw(_("Advance amount cannot be greater than {0} {1}")
.format(self.doc.party_account_currency, invoice_total))

View File

@@ -18,7 +18,7 @@ def get_list_context(context=None):
"get_list": get_transaction_list
}
def get_transaction_list(doctype, txt=None, filters=None, limit_start=0, limit_page_length=20):
def get_transaction_list(doctype, txt=None, filters=None, limit_start=0, limit_page_length=20, order_by="modified"):
from frappe.www.list import get_list
user = frappe.session.user
key = None

View File

@@ -574,7 +574,7 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Territory",
"length": 0,
@@ -1152,7 +1152,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2017-03-12 21:55:21.598112",
"modified": "2017-04-04 01:21:02.165730",
"modified_by": "Administrator",
"module": "CRM",
"name": "Opportunity",

View File

@@ -194,11 +194,12 @@ def make_quotation(source_name, target_doc=None):
quotation.transaction_date)
quotation.conversion_rate = exchange_rate
# get default taxes
taxes = get_default_taxes_and_charges("Sales Taxes and Charges Template")
quotation.extend("taxes", taxes)
if taxes:
quotation.extend("taxes", taxes)
quotation.run_method("set_missing_values")
quotation.run_method("calculate_taxes_and_totals")

View File

@@ -0,0 +1,19 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.query_reports["Campaign Efficiency"] = {
"filters": [
{
"fieldname": "from_date",
"label": __("From Date"),
"fieldtype": "Date",
"default": frappe.defaults.get_user_default("year_start_date"),
},
{
"fieldname": "to_date",
"label": __("To Date"),
"fieldtype": "Date",
"default": frappe.defaults.get_user_default("year_end_date"),
}
]
};

View File

@@ -0,0 +1,30 @@
{
"add_total_row": 0,
"apply_user_permissions": 1,
"creation": "2017-04-17 00:20:27.248275",
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"idx": 0,
"is_standard": "Yes",
"letter_head": "",
"modified": "2017-04-17 00:20:27.248275",
"modified_by": "Administrator",
"module": "CRM",
"name": "Campaign Efficiency",
"owner": "Administrator",
"ref_doctype": "Lead",
"report_name": "Campaign Efficiency",
"report_type": "Script Report",
"roles": [
{
"role": "Sales User"
},
{
"role": "Sales Manager"
},
{
"role": "System Manager"
}
]
}

View File

@@ -0,0 +1,89 @@
# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
from frappe import _
def execute(filters=None):
columns, data = [], []
columns=get_columns()
data=get_lead_data(filters, "Campaign Name")
return columns, data
def get_columns():
return [
_("Campaign Name") + ":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"
]
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}
""".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 = {
based_on: based_on_value,
"Lead Count": len(leads)
}
row["Quot Count"]= get_lead_quotation_count(leads)
row["Opp Count"] = get_lead_opp_count(leads)
row["Order Count"] = get_quotation_ordered_count(leads)
row["Order Value"] = get_order_amount(leads)
row["Opp/Lead %"] = row["Opp Count"] / row["Lead Count"] * 100
row["Quot/Lead %"] = row["Quot Count"] / row["Lead Count"] * 100
row["Order/Quot %"] = row["Order Count"] / (row["Quot Count"] or 1) * 100
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]
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]
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]
def get_order_amount(leads):
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)
)""" % ', '.join(["%s"]*len(leads)), tuple(leads))[0][0]

View File

@@ -0,0 +1,17 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.query_reports["Lead Owner Efficiency"] = {
"filters": [
{
"fieldname": "from_date",
"label": __("From Date"),
"fieldtype": "Date",
"default": frappe.defaults.get_user_default("year_start_date"),
},
{
"fieldname": "to_date",
"label": __("To Date"),
"fieldtype": "Date",
"default": frappe.defaults.get_user_default("year_end_date"),
}
]};

View File

@@ -0,0 +1,30 @@
{
"add_total_row": 0,
"apply_user_permissions": 1,
"creation": "2017-04-17 00:39:39.885905",
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"idx": 0,
"is_standard": "Yes",
"letter_head": "",
"modified": "2017-04-17 00:45:10.139004",
"modified_by": "Administrator",
"module": "CRM",
"name": "Lead Owner Efficiency",
"owner": "Administrator",
"ref_doctype": "Lead",
"report_name": "Lead Owner Efficiency",
"report_type": "Script Report",
"roles": [
{
"role": "Sales User"
},
{
"role": "Sales Manager"
},
{
"role": "System Manager"
}
]
}

View File

@@ -0,0 +1,26 @@
# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
from frappe import _
from erpnext.crm.report.campaign_efficiency.campaign_efficiency import get_lead_data
def execute(filters=None):
columns, data = [], []
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"
]

View File

@@ -0,0 +1,25 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.query_reports["Prospects Engaged But Not Converted"] = {
"filters": [
{
"fieldname": "lead",
"label": __("Lead"),
"fieldtype": "Link",
"options": "Lead"
},
{
"fieldname": "no_of_interaction",
"label": __("Number of Interaction"),
"fieldtype": "Int",
"default": 1
},
{
"fieldname": "lead_age",
"label": __("Minimum Lead Age (Days)"),
"fieldtype": "Int",
"default": 60
},
]
}

View File

@@ -0,0 +1,29 @@
{
"add_total_row": 0,
"apply_user_permissions": 1,
"creation": "2017-04-04 08:25:40.491063",
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"idx": 0,
"is_standard": "Yes",
"modified": "2017-04-04 10:00:10.253224",
"modified_by": "Administrator",
"module": "CRM",
"name": "Prospects Engaged But Not Converted",
"owner": "Administrator",
"ref_doctype": "Lead",
"report_name": "Prospects Engaged But Not Converted",
"report_type": "Script Report",
"roles": [
{
"role": "Sales User"
},
{
"role": "Sales Manager"
},
{
"role": "System Manager"
}
]
}

View File

@@ -0,0 +1,74 @@
# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
from frappe import _
from frappe.utils import add_days, now
def execute(filters=None):
columns, data = [], []
set_defaut_value_for_filters(filters)
columns = get_columns()
data = get_data(filters)
return columns, data
def set_defaut_value_for_filters(filters):
if not filters.get('no_of_interaction'): filters["no_of_interaction"] = 1
if not filters.get('lead_age'): filters["lead_age"] = 60
def get_columns():
return [
_("Lead") + ":Link/Lead:100",
_("Name") + "::100",
_("Organization") + "::100",
_("Reference Document") + "::150",
_("Reference Name") + ":Dynamic Link/"+_("Reference Document")+":120",
_("Last Communication") + ":Data:200",
_("Last Communication Date") + ":Date:180"
]
def get_data(filters):
lead_details = []
lead_filters = get_lead_filters(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,
`tabCommunication`.content, `tabCommunication`.communication_date
from
(
(select name, lead from `tabOpportunity` where lead = %(lead)s)
union
(select name, lead from `tabQuotation` where lead = %(lead)s)
union
(select name, lead from `tabIssue` where lead = %(lead)s and status!='Closed')
union
(select %(lead)s, %(lead)s)
)
as ref_document, `tabCommunication`
where
`tabCommunication`.reference_name = ref_document.name and
`tabCommunication`.sent_or_received = 'Received'
order by
ref_document.lead, `tabCommunication`.creation desc limit %(limit)s""",
{'lead': lead.name, 'limit': filters.get('no_of_interaction')})
for lead_info in data:
lead_data = [lead.name, lead.lead_name, lead.company_name] + list(lead_info)
lead_details.append(lead_data)
return lead_details
def get_lead_filters(filters):
lead_creation_date = get_creation_date_based_on_lead_age(filters)
lead_filters = [["status", "!=", "Converted"], ["creation", ">", lead_creation_date]]
if filters.get('lead'):
lead_filters.append(["name", "=", filters.get('lead')])
return lead_filters
def get_creation_date_based_on_lead_age(filters):
return add_days(now(), (filters.get('lead_age') * -1))

View File

@@ -63,6 +63,13 @@ def complete_setup(domain='Manufacturing'):
"language": "english"
})
company = erpnext.get_default_company()
if company:
company_doc = frappe.get_doc("Company", company)
company_doc.db_set('default_payroll_payable_account',
frappe.db.get_value('Account', dict(account_name='Payroll Payable')))
def setup_demo_page():
# home page should always be "start"
website_settings = frappe.get_doc("Website Settings", "Website Settings")

View File

@@ -18,6 +18,9 @@ def work():
# fixed_asset.work() already run
return
# Enable booking asset depreciation entry automatically
frappe.db.set_value("Accounts Settings", None, "book_asset_depreciation_entry_automatically", 1)
# post depreciation entries as on today
post_depreciation_entries()

View File

@@ -34,14 +34,16 @@ def work():
process_payroll.salary_slip_based_on_timesheet = 0
process_payroll.create_salary_slips()
process_payroll.submit_salary_slips()
process_payroll.make_journal_entry(reference_date=frappe.flags.current_date,
reference_number=random_string(10))
process_payroll.make_accural_jv_entry()
# process_payroll.make_journal_entry(reference_date=frappe.flags.current_date,
# reference_number=random_string(10))
process_payroll.salary_slip_based_on_timesheet = 1
process_payroll.create_salary_slips()
process_payroll.submit_salary_slips()
process_payroll.make_journal_entry(reference_date=frappe.flags.current_date,
reference_number=random_string(10))
process_payroll.make_accural_jv_entry()
# process_payroll.make_journal_entry(reference_date=frappe.flags.current_date,
# reference_number=random_string(10))
if frappe.db.get_global('demo_hr_user'):
make_timesheet_records()

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

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