Compare commits

...

217 Commits

Author SHA1 Message Date
Nabin Hait
50e363b24e Merge branch 'develop' 2015-07-02 15:28:49 +05:30
Nabin Hait
bc176b6bf8 bumped to version 5.1.0 2015-07-02 15:58:49 +06:00
Nabin Hait
784b49e54e change log 2015-07-02 15:28:15 +05:30
Nabin Hait
04fb6e1a45 Merge pull request #3558 from nabinhait/develop
Change log
2015-07-02 15:22:20 +05:30
Nabin Hait
dffd7c3889 Change log 2015-07-02 15:21:25 +05:30
Nabin Hait
0c7594e5ed Merge pull request #3557 from rmehta/item-description-in-form
[fix] show item description in form grid based on in_list_view
2015-07-02 15:19:24 +05:30
Rushabh Mehta
5105f909d6 [fix] show item description in form grid based on in_list_view 2015-07-02 15:09:18 +05:30
Nabin Hait
2ab9d6e92c Merge pull request #3552 from nabinhait/develop
Recurring docs should not consider Stopped documents and should be scheduled for hourly
2015-07-02 14:42:57 +05:30
Nabin Hait
7580723ab3 Recurring docs should not consider Stopped documents and should be scheduled for hourly 2015-07-02 14:41:27 +05:30
Nabin Hait
52fef71c14 Merge pull request #3543 from rmehta/against-account-fix
Fix against account to show party instead of account
2015-07-02 14:28:11 +05:30
Rushabh Mehta
2cd02af80a [fix] patch date 2015-07-02 14:25:51 +05:30
Rushabh Mehta
0b0ec3536c [change-log] added 2015-07-02 14:25:51 +05:30
Rushabh Mehta
6b35ea873b [fix] against account in general ledger will show party 2015-07-02 14:25:51 +05:30
Nabin Hait
ecf220a721 Merge pull request #3549 from neilLasrado/item-varients
Validation changed for Item Template cannot have Stock
2015-07-02 14:18:31 +05:30
Nabin Hait
04fb1c7fe4 Merge pull request #3550 from neilLasrado/item-desc
Image feild added to Sales Invoice & Purchase Invoice
2015-07-02 14:17:52 +05:30
Neil Trini Lasrado
53bd62eafc Validation changed for Item Template cannot have Stock 2015-07-02 14:15:23 +05:30
Nabin Hait
ff68bf2609 Merge pull request #3551 from nabinhait/develop
Fixes
2015-07-02 14:10:58 +05:30
Nabin Hait
fdd0db3459 Update project completion percentage and costing after syncing task 2015-07-02 14:09:49 +05:30
Nabin Hait
f92465981c datetime issue fixed in maintenance schedule 2015-07-02 14:09:49 +05:30
Nabin Hait
885c70984d [fix] Always show Sales invoice in Gross profit report 2015-07-02 14:09:49 +05:30
Neil Trini Lasrado
9c15ef903d Image feild added to Sales Invoice & Purchase Invoice 2015-07-02 13:09:57 +05:30
Rushabh Mehta
bc799885d0 [fix] bom client script 2015-07-02 12:44:16 +05:30
Nabin Hait
cb129264cb Merge pull request #3386 from neilLasrado/item-varients
[redesign] Manage Item varients
2015-07-01 18:29:04 +05:30
Neil Trini Lasrado
fe9cd1d875 More Fixes in Manage Varients 2015-07-01 14:41:30 +05:30
Neil Trini Lasrado
64fbe955c7 Modified Date changed for Item Doctype 2015-07-01 14:04:00 +05:30
Neil Trini Lasrado
0988440fd9 Fixes for Manage Variants 2015-07-01 13:17:15 +05:30
Neil Trini Lasrado
274dd4ada0 Fixed Manage Variants Attribute autocomplete appearance. 2015-07-01 12:51:40 +05:30
Neil Trini Lasrado
724fd82419 Fixes in Manage Variants 2015-07-01 12:51:40 +05:30
Neil Trini Lasrado
3f2604eff6 Patch for Item Variants 2015-07-01 12:51:40 +05:30
Neil Trini Lasrado
c761fefb78 more fixes in test records 2015-07-01 12:51:11 +05:30
Neil Trini Lasrado
203cb10ef7 fixes in test cases 2015-07-01 12:51:11 +05:30
Neil Trini Lasrado
90c66b1998 test cases added 2015-07-01 12:51:11 +05:30
Neil Trini Lasrado
fed431f908 Code Fixes in Manage Variants 2015-07-01 12:51:11 +05:30
Neil Trini Lasrado
bd9745ba72 Rename Item Variant from Manage Variants feature Added. 2015-07-01 12:51:11 +05:30
Neil Trini Lasrado
8fb123b20e item variants, creation, deleation and update logic added.
logic added to copy changes in template to variants
2015-07-01 12:51:11 +05:30
Neil Trini Lasrado
333ccd212b variants combination generation logic added 2015-07-01 12:51:10 +05:30
Neil Trini Lasrado
c8cc8b7115 manage variants new doctype created 2015-07-01 12:51:10 +05:30
Nabin Hait
ec44fa95ce Merge pull request #3537 from neilLasrado/project
Fixed Issues in Project Task
2015-06-30 17:29:19 +05:30
Neil Trini Lasrado
a25e8ea0bc Fixed Issues in Project Task 2015-06-30 17:15:13 +05:30
Rushabh Mehta
ea02b9a5c3 Merge pull request #3530 from anandpdoshi/anand-june-29
[fix] Item Variant Attribute autocomplete appearance. Fixes #3488, #3515, #3525
2015-06-30 13:05:19 +05:30
Rushabh Mehta
74a63bf003 Merge pull request #3531 from pdvyas/exchange-rate-api
Change currency exchange rate api to fixer.io
2015-06-30 12:46:52 +05:30
Pratik Vyas
a0f2510b01 Change currency exchange rate api to fixer.io 2015-06-30 12:36:17 +05:30
Anand Doshi
0820161157 [fix] Item Variant Attribute autocomplete appearance. Fixes #3488, #3515, #3525 2015-06-29 20:57:06 -07:00
Nabin Hait
56bc215855 Merge pull request #3505 from neilLasrado/print-format
Recurring Invoice Print Format
2015-06-29 18:54:24 +05:30
Nabin Hait
8687d25f7e Merge pull request #3526 from neilLasrado/minor-fixes
Minor fixes
2015-06-29 18:53:10 +05:30
Nabin Hait
9cea01fa8b Merge pull request #3527 from nabinhait/develop
Journal Entry list view and delete events via query
2015-06-29 18:39:43 +05:30
Nabin Hait
e06d01e3ed Delete events via query instead of delete_doc function, to save time 2015-06-29 18:38:38 +05:30
Nabin Hait
11243a4fb4 Show amount in Journal Entry list view 2015-06-29 18:38:38 +05:30
Neil Trini Lasrado
b9e5cd0df4 Fixed lead status not updating on Creation of oppurtunity issue 2015-06-29 17:01:32 +05:30
Neil Trini Lasrado
a1f1edc786 Typo fixes in Sales Person 2015-06-29 16:04:12 +05:30
Neil Trini Lasrado
e2d8dd0663 added recurring print format to sales/purchase invoice and order 2015-06-29 12:50:41 +05:30
Nabin Hait
d1605c5cb2 Merge branch 'develop' 2015-06-27 13:09:05 +05:30
Nabin Hait
64ca52fb77 bumped to version 5.0.29 2015-06-27 13:39:05 +06:00
Nabin Hait
2f11a3bdaf Merge pull request #3523 from nabinhait/develop
Multiple fixes
2015-06-27 13:07:44 +05:30
Nabin Hait
943dc1f59c Merge branch 'develop' 2015-06-27 13:07:01 +05:30
Nabin Hait
6d1c994bc9 bumped to version 5.0.28 2015-06-27 13:37:01 +06:00
Nabin Hait
93cdee4503 [fix] Escape values in queries 2015-06-27 12:51:00 +05:30
Nabin Hait
dfac6848cc In list view property added in BOM 2015-06-26 14:42:51 +05:30
Nabin Hait
8ad0b4e0b9 Show Issue id in list view from customer login 2015-06-26 14:42:51 +05:30
Nabin Hait
b8cd92f1aa Merge pull request #3517 from neilLasrado/batch
Added validation to prevent transfer of raw material from an expired …
2015-06-25 18:20:46 +05:30
Nabin Hait
1fe48cb820 Merge pull request #3514 from anandpdoshi/anand-june-24
[fix] Use per_billed instead of per_delivered and per_received for open notification
2015-06-25 18:04:26 +05:30
Anand Doshi
723b046c5b [fix] Use per_billed instead of per_delivered and per_received for open notification 2015-06-24 19:21:52 -04:00
Neil Trini Lasrado
035160c9a6 Added validation to prevent transfer of raw material from an expired batch for manufacturing 2015-06-24 15:25:57 +05:30
Nabin Hait
01c7ce1da3 Merge pull request #3508 from nabinhait/develop
[fix] validate items in stock entry for subcontracting against PO
2015-06-23 11:12:23 +05:30
Nabin Hait
9cf2910ba1 [fix] validate items in stock entry for subcontracting against purchase order 2015-06-23 11:07:34 +05:30
Nabin Hait
c8da7b7d32 Merge branch 'develop' 2015-06-23 10:27:59 +05:30
Nabin Hait
9679d31397 bumped to version 5.0.27 2015-06-23 10:57:59 +06:00
Nabin Hait
38bebe1b83 Merge pull request #3503 from neilLasrado/leave-application
Fixed bugs in Calender View for Leave Application
2015-06-22 19:32:16 +05:30
Nabin Hait
ffbc11e8de Merge pull request #3504 from nabinhait/develop
Multiple fixes
2015-06-22 19:29:32 +05:30
Nabin Hait
818d9674d9 [fix] Update outstanding amount function fixed if party not mentioned 2015-06-22 18:21:38 +05:30
Neil Trini Lasrado
086f8942eb Fixed bugs in Calender View for Leave Application 2015-06-22 13:51:56 +05:30
Nabin Hait
c3b492b237 [fix] Auto remarks in Journal Entry based on company currency 2015-06-22 07:52:38 +05:30
Nabin Hait
9d0dd5066a Removed 'Root Type' validation for receivable/payable account in sales/purchase invoice 2015-06-22 07:32:46 +05:30
Nabin Hait
e7f479b26a Validate accounting entry agaist Stock account if perpetual inventory enabled 2015-06-22 07:31:49 +05:30
Nabin Hait
7ee45b4af2 [fix] Batch-wise balance history: show records only with batch-id 2015-06-18 15:29:14 +05:30
Nabin Hait
5cce1e0929 Merge pull request #3489 from nabinhait/develop
Opening balance
2015-06-18 10:34:31 +05:30
Nabin Hait
be496bc91c [fix] Trial Balance opening 2015-06-18 10:33:20 +05:30
Nabin Hait
59f063e5c3 [fix] opening balance in general ledger report 2015-06-18 10:33:20 +05:30
Nabin Hait
af5820874c Merge branch 'develop' 2015-06-17 15:51:00 +05:30
Nabin Hait
495db99719 bumped to version 5.0.26 2015-06-17 16:21:00 +06:00
Nabin Hait
123beb5a07 Merge pull request #3484 from rmehta/bom-search-report
[report] BOM Search
2015-06-17 15:38:39 +05:30
Nabin Hait
7ed4e080a2 Merge pull request #3486 from nabinhait/develop
Opening balance
2015-06-17 15:36:06 +05:30
Nabin Hait
e91025c0aa [fix] Opening balance in trial balance and general ledger based on is_opening 2015-06-17 15:35:06 +05:30
Nabin Hait
1ac9f2f50d [fix] Opening balance in trial balance and general ledger based on is_opening 2015-06-17 15:09:40 +05:30
Nabin Hait
bd9aa13db3 Minor issue in naming series 2015-06-17 15:09:40 +05:30
Rushabh Mehta
ed9d5cfdaf [minor] cleanup 2015-06-17 02:13:03 +05:30
Rushabh Mehta
bf4547ca5f [fix] dynamic link in BOM Search report 2015-06-17 02:12:06 +05:30
Rushabh Mehta
b45a6bcb88 [report] BOM Search 2015-06-17 01:54:56 +05:30
Anand Doshi
ac59c2b300 [minor] clear Item's introduction section on refresh 2015-06-16 13:06:48 -04:00
Nabin Hait
6a8d7a1b91 Merge branch 'develop' 2015-06-16 16:50:49 +05:30
Nabin Hait
5d71a28e97 bumped to version 5.0.25 2015-06-16 17:20:49 +06:00
Nabin Hait
7d100a1ee7 Merge pull request #3480 from nabinhait/develop
Indexes
2015-06-16 16:49:26 +05:30
Nabin Hait
81dca110eb Change log added 2015-06-16 16:48:47 +05:30
Nabin Hait
9c852108d0 Added index in sales/purchase invoice and fix in index patch 2015-06-16 16:48:47 +05:30
Nabin Hait
e3ac032696 Merge pull request #3472 from neilLasrado/po
Multiple Fixes
2015-06-16 15:52:48 +05:30
Neil Trini Lasrado
64cacfb077 Fixes in Activity Cost 2015-06-16 15:42:40 +05:30
Neil Trini Lasrado
ae4cc078ea Activity Cost - Mandatory removed for Employee. 2015-06-16 15:30:08 +05:30
Nabin Hait
0ee543e932 Merge pull request #3479 from nabinhait/develop
[fix][report] Payment period based on invoice date
2015-06-16 15:29:14 +05:30
Nabin Hait
a123638d37 [fix][report] Payment period based on invoice date 2015-06-16 15:21:00 +05:30
Nabin Hait
58996985ed Merge pull request #3476 from nabinhait/develop
Expense Approver Query and discount label
2015-06-16 15:01:08 +05:30
Nabin Hait
5d0ce7939f Show only users with Expense Approver role in Expense Claim Approver field 2015-06-15 17:59:37 +05:30
Neil Trini Lasrado
4abf552d7b Over Production Allowance Percentage Setting added to Manufacturing Settings 2015-06-15 15:58:45 +05:30
Nabin Hait
7c5ba957ac Label changed for discount amount in base currency 2015-06-15 15:47:07 +05:30
Nabin Hait
77f04e293a Merge branch 'develop' 2015-06-15 10:35:39 +05:30
Nabin Hait
d1d3237784 bumped to version 5.0.24 2015-06-15 11:05:39 +06:00
Nabin Hait
76f0d26f1e Merge pull request #3471 from nabinhait/develop
Hotfix
2015-06-15 10:32:23 +05:30
Nabin Hait
65922d3079 [fix] supplier invoice date can not be after posting date 2015-06-15 10:23:53 +05:30
Nabin Hait
810041cbe3 [fix] Fixed error due to performance upgrade cleanup 2015-06-15 10:20:11 +05:30
Nabin Hait
b9626659ea Merge pull request #3465 from neilLasrado/po
Po
2015-06-15 10:04:36 +05:30
Nabin Hait
e3d13bee36 Merge pull request #3467 from anandpdoshi/anand-june-12
Fixes
2015-06-15 10:03:20 +05:30
Nabin Hait
13bd538aca Merge branch 'develop' 2015-06-14 22:04:51 +05:30
Nabin Hait
d72a24965b bumped to version 5.0.23 2015-06-14 22:34:51 +06:00
Nabin Hait
dc633fe360 Merge pull request #3470 from nabinhait/develop
Performance upgrade in reports and indexing
2015-06-14 22:01:30 +05:30
Nabin Hait
39046d663d [patch] Add index on Account and GL Entry table 2015-06-14 20:59:28 +05:30
Nabin Hait
6b01abe9ad [report][performance] Speed increased by approx 10 times in Trial Balance, General Ledger, AR/AP, Balance Sheet and P&L Statement 2015-06-14 20:59:28 +05:30
Anand Doshi
63e4d31aa6 [fix] Task should be mandatory in Time Log only when Project is mentioned but Production Order is not 2015-06-12 18:59:18 -04:00
Anand Doshi
f2a0161709 [fix] Don't create Time Logs against Production Order if Workstation is not specified in Operations 2015-06-12 18:58:36 -04:00
Neil Trini Lasrado
3c1a4a0b9b percent_complete made no-copy in Project 2015-06-12 18:34:08 +05:30
Neil Trini Lasrado
82cc2921d1 Validation added to prevent user from creating salary structure with 'From Date' before employee 'Date of joining' 2015-06-12 18:34:08 +05:30
Nabin Hait
87edd86854 Merge branch 'develop' 2015-06-12 18:06:21 +05:30
Nabin Hait
e37dd77923 bumped to version 5.0.22 2015-06-12 18:36:21 +06:00
Nabin Hait
e4f689184f Merge pull request #3459 from neilLasrado/po
Multiple Fixes.
2015-06-12 17:55:23 +05:30
Nabin Hait
85f825e98c Merge pull request #3463 from nabinhait/develop
multiple issues
2015-06-12 17:48:54 +05:30
Nabin Hait
89592c5180 Load tasks in project for printing purpose 2015-06-12 17:37:28 +05:30
Neil Trini Lasrado
587bd144d5 Added Customers Not Buying Since Long Time against Sales Invoice 2015-06-11 18:36:52 +05:30
Neil Trini Lasrado
1f048b2426 Fixes in Activity Cost 2015-06-11 18:36:52 +05:30
Neil Trini Lasrado
1792ff3be7 Validation added in Purchase Invoice to check if Supplier Invoice Date is greater than Posting Date
Check Supplier Invoice Number Uniqueness setting added to Accounts Settings
Validation added in Purchase Invoice to check Supplier Invoice Number Uniqueness if Check Supplier Invoice Number Uniqueness is enabled in Accounts Settings
2015-06-11 18:36:52 +05:30
Neil Trini Lasrado
fc595064e0 validation added to prevent Delivery Date in Porduction Order to be lesser than Planned Start Date 2015-06-11 18:36:52 +05:30
Nabin Hait
804b4acb9b [fix] Issue fixed in C-Form related to field renaming 2015-06-11 16:56:36 +05:30
Nabin Hait
5c7557914b Removed BOM No from mandatory from Stock Entry against Production Order 2015-06-11 16:50:35 +05:30
Nabin Hait
381a9377d9 Merge branch 'develop' 2015-06-11 16:14:48 +05:30
Nabin Hait
9bdd1aa1ed bumped to version 5.0.21 2015-06-11 16:44:48 +06:00
Nabin Hait
d0df28bfa0 Merge pull request #3458 from nabinhait/develop
[fix] load tasks in project via __setup__ instead of onload function, to return tasks via get_doc
2015-06-11 16:12:05 +05:30
Nabin Hait
1966225450 [fix] load tasks in project via __setup__ instead of onload function, to return tasks via get_doc 2015-06-11 15:31:47 +05:30
Nabin Hait
4cee27eec0 Merge pull request #3446 from anandpdoshi/anand-june-9
POS - search by Item Group
2015-06-10 18:42:14 +05:30
Nabin Hait
c7d4eaee79 Merge pull request #3442 from nabinhait/develop
fixes in stock entry and report
2015-06-10 18:40:42 +05:30
Nabin Hait
43c1a9b502 [fix] Quote url for item image in product listing page 2015-06-10 18:23:17 +05:30
Nabin Hait
b937fac3ce [report] Warehouse column added in 'Ordered Items to be Delivered' report 2015-06-10 18:21:57 +05:30
Nabin Hait
53d94996ad [fix] Query for Against Journal Entry 2015-06-10 18:20:18 +05:30
Anand Doshi
26f6752c1e POS - search by Item Group 2015-06-09 16:33:46 -04:00
Nabin Hait
bb429745c0 [fix] Blank option in naming series 2015-06-09 18:59:51 +05:30
Nabin Hait
909f0c38f1 [report][enhancement] Payment period based on invoice date: show party columns and filter based on party 2015-06-09 18:42:52 +05:30
Nabin Hait
a790ba05f4 [fix] Item name, description should not be overwritten on saving of stock entry 2015-06-09 18:42:52 +05:30
Nabin Hait
11fc4f85d0 Merge branch 'develop' 2015-06-09 15:56:20 +05:30
Nabin Hait
17452a1695 bumped to version 5.0.20 2015-06-09 16:26:20 +06:00
Nabin Hait
7c3d48e353 Merge pull request #3434 from neilLasrado/material-request
Status Indicators fixed in Material Request List
2015-06-09 15:47:46 +05:30
Neil Trini Lasrado
5d288e407c item variants patch removed 2015-06-09 15:46:57 +05:30
Neil Trini Lasrado
f64fae752f fixes 2015-06-09 15:46:57 +05:30
Neil Trini Lasrado
82763f052f Status Indicators fixed in Material Request List 2015-06-09 15:46:57 +05:30
Nabin Hait
bafc73568a Merge pull request #3435 from neilLasrado/barcode
Barcode added to Purchase Receipt
2015-06-09 15:44:09 +05:30
Neil Trini Lasrado
d015195617 fixes in barcode 2015-06-09 15:21:50 +05:30
Neil Trini Lasrado
b2f550ccb3 Barcode added to Purchase Receipt 2015-06-09 15:18:58 +05:30
Nabin Hait
41413af42d Merge pull request #3437 from anandpdoshi/task-close-assignment
[fix] Close assignment (ToDo) when Task status is changed to Closed
2015-06-09 15:00:06 +05:30
Anand Doshi
ec60ebde6f [fix] Close assignment (ToDo) when Task status is changed to Closed 2015-06-08 12:48:11 -04:00
Nabin Hait
ce81a61fe7 Merge branch 'develop' 2015-06-08 14:45:13 +05:30
Nabin Hait
dc76b3fa20 bumped to version 5.0.19 2015-06-08 15:15:13 +06:00
Nabin Hait
828cbee12a Merge pull request #3429 from neilLasrado/quality-inspection
Get Item Details in Quality Inspection.
2015-06-08 14:24:11 +05:30
Nabin Hait
5f5ef16b91 Merge pull request #3430 from nabinhait/develop
Multiple fixes
2015-06-08 14:23:52 +05:30
Nabin Hait
686ef8308a Show item name in item grid view based 'In List View' property 2015-06-08 14:22:56 +05:30
Nabin Hait
b63ad44b10 Book in round-off account upto max 0.05 2015-06-08 14:15:12 +05:30
Nabin Hait
5ef121bc10 get party details only if party exists 2015-06-08 14:15:11 +05:30
Neil Trini Lasrado
42c1836db5 function changed to add fetch 2015-06-08 13:09:11 +05:30
Neil Trini Lasrado
9dbdef3bd5 added code to fetch item name and desc on change of item code 2015-06-08 12:29:12 +05:30
Nabin Hait
9fd42ed2f7 Merge pull request #3428 from nabinhait/develop
[fix] Fiscal year issue due to missing field in Material Request
2015-06-08 12:27:27 +05:30
Nabin Hait
000835c454 [fix] Fiscal year issue due to missing field in Material Request 2015-06-08 12:10:43 +05:30
Nabin Hait
de1f934e22 Merge pull request #3422 from nabinhait/develop
Manufactured qty in Stock Entry
2015-06-08 12:07:47 +05:30
Nabin Hait
7cbd916b00 [fix] Fiscal year issue due to missing field in Material Request 2015-06-08 12:06:33 +05:30
Nabin Hait
56fcf30cb9 [Patch] Update material transferred for manufacturing for existing entries 2015-06-05 18:21:35 +05:30
Nabin Hait
ebbdd772a9 [fix] Validate and update manufactured qty in Stock Entry 2015-06-05 18:21:35 +05:30
Pratik Vyas
6268d83173 Merge branch 'develop' 2015-06-05 15:56:49 +05:30
Pratik Vyas
4599467939 bumped to version 5.0.18 2015-06-05 16:26:49 +06:00
Nabin Hait
d3613479c6 Merge pull request #3421 from nabinhait/develop
pos link and item description
2015-06-05 15:51:03 +05:30
Nabin Hait
6bf301f53c Show item description in grid view based on 'In List View' property 2015-06-05 15:49:25 +05:30
Nabin Hait
27d7f21553 [fix] pos profile link in Start POS page 2015-06-05 15:09:44 +05:30
Nabin Hait
8f87cff4bd Merge pull request #3411 from nabinhait/develop
journal entry against expense claim and bank reco
2015-06-05 14:31:23 +05:30
Nabin Hait
8f39766924 Merge pull request #3419 from neilLasrado/time-log
operation made non mandatory in time log
2015-06-05 14:30:22 +05:30
Neil Trini Lasrado
39669f2717 operation made non mandatory in time log 2015-06-05 12:17:46 +05:30
Nabin Hait
3c1017c43b Removed deprecated page users 2015-06-05 12:15:01 +05:30
Nabin Hait
0b18a2d347 Reset values in tools like Payment Tool 2015-06-05 12:01:29 +05:30
Nabin Hait
6262496e70 [fix] item test case 2015-06-03 18:33:47 +05:30
Nabin Hait
c9963f1805 [fix] journal entry against expense claim: pending amount validation 2015-06-03 18:01:09 +05:30
Nabin Hait
8a2b1bcb97 [fix] bank reconciliation: fetch journal entry order by posting date asc 2015-06-03 18:01:09 +05:30
Pratik Vyas
b8ecf7c757 Merge branch 'develop' 2015-06-03 17:43:38 +05:30
Pratik Vyas
cf89fa2253 bumped to version 5.0.17 2015-06-03 18:13:38 +06:00
Nabin Hait
419c1eb90d Merge pull request #3410 from nabinhait/develop
[fix][patch] force reload web-form-field in portal fixes patch
2015-06-03 17:43:01 +05:30
Nabin Hait
2c214e0362 [fix][patch] force reload web-form-field in portal fixes patch 2015-06-03 17:42:12 +05:30
Nabin Hait
7d04dd0bfd Merge pull request #3408 from williamjmorenor/patch-1
Update Chart of Account for Nicaragua
2015-06-03 17:17:09 +05:30
Nabin Hait
f1371a7ee7 Merge pull request #3409 from nabinhait/develop
Multiple fixes
2015-06-03 17:15:42 +05:30
Nabin Hait
995a78421a [fix] Stock analytics report fixed for fifo stack related to stock reco 2015-06-03 16:44:26 +05:30
Nabin Hait
352187bee6 purchase register fix 2015-06-03 12:06:19 +05:30
Nabin Hait
c6d8121f4a delete fields inline description 2015-06-03 11:24:37 +05:30
Nabin Hait
030ade428b dont reset company on deleting company transactions 2015-06-03 11:24:37 +05:30
Nabin Hait
c87595b2da show item description in item grid view if marked for 'In List View' 2015-06-03 11:24:37 +05:30
Nabin Hait
42f2674cba dynamic link in quotation item 2015-06-03 11:24:37 +05:30
Nabin Hait
5359f2651a [fix] sales register report 2015-06-03 11:24:37 +05:30
William Moreno
42dcffdad4 Update Chart of Account for Nicaragua
Hi

The Law 891 reform some taxes rates, please update the Chart of Account for Nicaragua so it can reflect the new tax rates.
2015-06-02 16:48:47 -06:00
Anand Doshi
f7c1743b28 [hotfix] cart - get_address_docs 2015-06-02 15:20:25 -04:00
Anand Doshi
64aa6620be [hotfix] portal fixes patch 2015-06-02 11:53:17 -04:00
Rushabh Mehta
ed43f8015c [lang] let locale be en in setup wizard (?) 2015-06-02 12:31:03 +05:30
Rushabh Mehta
d3fe7ec858 [cleanup] customer not buying since long time report 2015-06-02 12:21:17 +05:30
Rushabh Mehta
c8b406d050 [fix] duplicate status for Submitted, Cancelled 2015-06-02 12:17:14 +05:30
Rushabh Mehta
2aa577f110 [hot] patch-fix 2015-06-02 11:12:25 +05:30
Pratik Vyas
f06d175061 Merge branch 'develop' 2015-06-02 10:45:28 +05:30
Pratik Vyas
74b2116adb bumped to version 5.0.16 2015-06-02 11:15:28 +06:00
Rushabh Mehta
2204d0af94 Merge pull request #3397 from rmehta/portal-fixes
Portal fixes
2015-06-02 10:42:59 +05:30
Pratik Vyas
b8a568765d Update translations 2015-06-01 23:49:15 +05:30
Rushabh Mehta
cf29f6468d [minor] add attachment to issue via portal: 2015-06-01 17:47:03 +05:30
Rushabh Mehta
aded46d33e [fix] product search in new block header_actions 2015-06-01 17:23:42 +05:30
Pratik Vyas
b8dd046c84 Merge branch 'develop' 2015-06-01 17:17:46 +05:30
Pratik Vyas
e5fa5e6111 bumped to version 5.0.15 2015-06-01 17:47:46 +06:00
Nabin Hait
b89cf1b3ec Merge pull request #3396 from nabinhait/develop
item table print template
2015-06-01 17:16:00 +05:30
Rushabh Mehta
a33d468d30 [fixes] portal, issues, addresses etc 2015-06-01 17:15:42 +05:30
Nabin Hait
e481a211b1 item table print template 2015-06-01 17:12:55 +05:30
Rushabh Mehta
ca23b5ecfd Merge pull request #3395 from nabinhait/develop
GL Entries for Journal Entries with multiple Party
2015-06-01 16:35:36 +05:30
Nabin Hait
11190268ab [fix][patch] GL Entries for Journal Entries with multiple Party, merge entries considering party 2015-06-01 16:21:25 +05:30
Nabin Hait
a19150ddaf default account's custom query in company 2015-06-01 15:32:57 +05:30
Nabin Hait
c17dff4b01 default account's custom query in company 2015-06-01 15:32:57 +05:30
193 changed files with 4522 additions and 3602 deletions

View File

@@ -1,2 +1,2 @@
from __future__ import unicode_literals
__version__ = '5.0.14'
__version__ = '5.1.0'

View File

@@ -35,7 +35,7 @@
"permlevel": 0,
"read_only": 1,
"reqd": 1,
"search_index": 1
"search_index": 0
},
{
"default": "0",
@@ -44,7 +44,7 @@
"label": "Is Group",
"permlevel": 0,
"precision": "",
"search_index": 1
"search_index": 0
},
{
"fieldname": "company",
@@ -57,7 +57,7 @@
"permlevel": 0,
"read_only": 1,
"reqd": 1,
"search_index": 1
"search_index": 0
},
{
"fieldname": "root_type",
@@ -147,7 +147,8 @@
"label": "Lft",
"permlevel": 0,
"print_hide": 1,
"read_only": 1
"read_only": 1,
"search_index": 1
},
{
"fieldname": "rgt",
@@ -156,7 +157,8 @@
"label": "Rgt",
"permlevel": 0,
"print_hide": 1,
"read_only": 1
"read_only": 1,
"search_index": 1
},
{
"fieldname": "old_parent",
@@ -171,7 +173,7 @@
"icon": "icon-money",
"idx": 1,
"in_create": 0,
"modified": "2015-05-28 14:10:40.606010",
"modified": "2015-06-14 20:57:55.471334",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Account",

View File

@@ -1,6 +1,6 @@
{
"country_code": "ni",
"name": "Catalogo de Cuentas",
"name": "Catalogo de Cuentas Nicaragua",
"is_active": "Yes",
"tree": {
"Activo": {
@@ -72,7 +72,7 @@
"IVA Acreditable por Importaciones": {
"account_type": "Tax"
},
"IVA Acreditable por Prestacion de Servicios": {
"IVA Acreditable por Prestacion de Servicios y Uso y Goce de Bienes": {
"account_type": "Tax"
},
"Acreditacion Proporcional": {}
@@ -229,11 +229,19 @@
"Impuesto al Valor Agregado por Pagar": {
"account_type": "Tax"
},
"Impuesto sobre la Renta": {
"Impuesto sobre la Renta por Actividades Economicas": {
"account_type": "Tax"
},
"Impuestos Municipales": {
"account_type": "Tax"
"Impuesto Municipal Sobre Ingresos": {
"account_type": "Tax"
},
"Recoleccion Basura": {
"account_type": "Tax"
},
"Matricula Municipal": {
"account_type": "Tax"
}
}
},
"Retenciones por Pagar": {
@@ -241,7 +249,13 @@
"Retencion Rentas del Trabajo Tarifa Progresiva": {
"account_type": "Tax"
},
"Retencion Definitiva por Rentas del Trabajo": {
"Retencion Definitiva 10% por Rentas del Trabajo - Indemnizacion Adicional": {
"account_type": "Tax"
},
"Retencion Definitiva 12.5% por Rentas del Trabajo - Dietas": {
"account_type": "Tax"
},
"Retencion Definitiva 15% por Rentas del Trabajo - No Residentes": {
"account_type": "Tax"
}
},
@@ -258,11 +272,26 @@
"Retencion 5% compra Madera en Rollo": {
"account_type": "Tax"
},
"Retencion Definitiva 1.5% Actividades Economicas No Residentes": {
"account_type": "Tax"
},
"Retencion Definitiva 3% Actividades Economicas No Residentes": {
"account_type": "Tax"
},
"Retencion Definitiva 10% Actividades Economicas No Residentes": {
"account_type": "Tax"
},
"Retencion Definitiva 15% Actividades Economicas No Residentes": {
"account_type": "Tax"
},
"Otras Retenciones 10%": {
"account_type": "Tax"
}
},
"Rentas y Ganancias de Capital": {
"Retencion Defintiva 15% por Rentas de Capital": {
"account_type": "Tax"
},
"Retencion Defintiva 10% por Rentas de Capital": {
"account_type": "Tax"
},
@@ -272,10 +301,16 @@
"Retencion Definitiva 10% por Ganancia de Capital": {
"account_type": "Tax"
},
"Retencion Definitiva Actividades Economicas No Residentes": {
"Retencion Definitiva 0.25% Transacciones Bursatiles": {
"account_type": "Tax"
},
"Retencion Definitiva Transacciones Bursatiles": {
"Retencion Definitiva 1% Transacciones Bursatiles": {
"account_type": "Tax"
},
"Retencion Definitiva 1.5% Transacciones Bursatiles": {
"account_type": "Tax"
},
"Retencion Definitiva 2% Transacciones Bursatiles": {
"account_type": "Tax"
},
"Retenciones Defintiva 5% Fondos de Inversion": {

View File

@@ -4,6 +4,13 @@
"docstatus": 0,
"doctype": "DocType",
"fields": [
{
"fieldname": "check_supplier_invoice_uniqueness",
"fieldtype": "Check",
"label": "Check Supplier Invoice Number Uniqueness",
"permlevel": 0,
"precision": ""
},
{
"default": "1",
"description": "If enabled, the system will post accounting entries for inventory automatically.",
@@ -43,7 +50,7 @@
"icon": "icon-cog",
"idx": 1,
"issingle": 1,
"modified": "2015-02-05 05:11:34.163902",
"modified": "2015-06-11 06:06:34.047890",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Accounts Settings",

View File

@@ -2,6 +2,10 @@
// License: GNU General Public License v3. See license.txt
frappe.ui.form.on("Bank Reconciliation", {
refresh: function(frm) {
frm.disable_save();
},
update_clearance_date: function(frm) {
return frappe.call({
method: "update_details",
@@ -33,5 +37,4 @@ cur_frm.cscript.onload = function(doc, cdt, cdn) {
cur_frm.set_value("from_date", frappe.datetime.month_start());
cur_frm.set_value("to_date", frappe.datetime.month_end());
}
}

View File

@@ -25,7 +25,8 @@ class BankReconciliation(Document):
where
t2.parent = t1.name and t2.account = %s
and t1.posting_date >= %s and t1.posting_date <= %s and t1.docstatus=1
and ifnull(t1.is_opening, 'No') = 'No' %s""" %
and ifnull(t1.is_opening, 'No') = 'No' %s
order by t1.posting_date""" %
('%s', '%s', '%s', condition), (self.bank_account, self.from_date, self.to_date), as_dict=1)
self.set('journal_entries', [])

View File

@@ -54,7 +54,7 @@ class CForm(Document):
frappe.throw(_("Please enter atleast 1 invoice in the table"))
def set_total_invoiced_amount(self):
total = sum([flt(d.base_grand_total) for d in self.get('invoices')])
total = sum([flt(d.grand_total) for d in self.get('invoices')])
frappe.db.set(self, 'total_invoiced_amount', total)
def get_invoice_details(self, invoice_no):

View File

@@ -48,7 +48,8 @@
"fieldtype": "Dynamic Link",
"label": "Party",
"options": "party_type",
"permlevel": 0
"permlevel": 0,
"search_index": 1
},
{
"fieldname": "cost_center",
@@ -192,7 +193,7 @@
"icon": "icon-list",
"idx": 1,
"in_create": 1,
"modified": "2015-04-27 20:32:48.246818",
"modified": "2015-06-14 20:57:19.800276",
"modified_by": "Administrator",
"module": "Accounts",
"name": "GL Entry",

View File

@@ -4,7 +4,7 @@
from __future__ import unicode_literals
import frappe
from frappe.utils import flt, fmt_money, getdate, formatdate
from frappe.utils import flt, fmt_money, getdate, formatdate, cstr
from frappe import _
from frappe.model.document import Document
@@ -118,7 +118,7 @@ def update_outstanding_amt(account, party_type, party, against_voucher_type, aga
bal = flt(frappe.db.sql("""select sum(ifnull(debit, 0)) - sum(ifnull(credit, 0))
from `tabGL Entry`
where against_voucher_type=%s and against_voucher=%s
and account = %s and party_type=%s and party=%s""",
and account = %s and ifnull(party_type, '')=%s and ifnull(party, '')=%s""",
(against_voucher_type, against_voucher, account, party_type, party))[0][0] or 0.0)
if against_voucher_type == 'Purchase Invoice':
@@ -127,8 +127,9 @@ def update_outstanding_amt(account, party_type, party, against_voucher_type, aga
against_voucher_amount = flt(frappe.db.sql("""
select sum(ifnull(debit, 0)) - sum(ifnull(credit, 0))
from `tabGL Entry` where voucher_type = 'Journal Entry' and voucher_no = %s
and account = %s and party_type=%s and party=%s and ifnull(against_voucher, '') = ''""",
(against_voucher, account, party_type, party))[0][0])
and account = %s and ifnull(party_type, '')=%s and ifnull(party, '')=%s
and ifnull(against_voucher, '') = ''""",
(against_voucher, account, cstr(party_type), cstr(party)))[0][0])
if not against_voucher_amount:
frappe.throw(_("Against Journal Entry {0} is already adjusted against some other voucher")
@@ -157,3 +158,22 @@ def validate_frozen_account(account, adv_adj=None):
frappe.throw(_("Account {0} is frozen").format(account))
elif frozen_accounts_modifier not in frappe.get_roles():
frappe.throw(_("Not authorized to edit frozen Account {0}").format(account))
def update_against_account(voucher_type, voucher_no):
entries = frappe.db.get_all("GL Entry",
filters={"voucher_type": voucher_type, "voucher_no": voucher_no},
fields=["name", "party", "against", "debit", "credit", "account"])
accounts_debited, accounts_credited = [], []
for d in entries:
if flt(d.debit > 0): accounts_debited.append(d.party or d.account)
if flt(d.credit) > 0: accounts_credited.append(d.party or d.account)
for d in entries:
if flt(d.debit > 0):
new_against = ", ".join(list(set(accounts_credited)))
if flt(d.credit > 0):
new_against = ", ".join(list(set(accounts_debited)))
if d.against != new_against:
frappe.db.set_value("GL Entry", d.name, "against", new_against)

View File

@@ -53,7 +53,7 @@
"fieldname": "posting_date",
"fieldtype": "Date",
"in_filter": 1,
"in_list_view": 1,
"in_list_view": 0,
"label": "Posting Date",
"no_copy": 1,
"oldfieldname": "posting_date",
@@ -445,7 +445,7 @@
"icon": "icon-file-text",
"idx": 1,
"is_submittable": 1,
"modified": "2015-04-27 20:32:31.655580",
"modified": "2015-06-29 15:28:12.529019",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Journal Entry",

View File

@@ -3,7 +3,7 @@
from __future__ import unicode_literals
import frappe
from frappe.utils import cstr, flt, fmt_money, formatdate, getdate, cint
from frappe.utils import cstr, flt, fmt_money, formatdate, getdate
from frappe import msgprint, _, scrub
from erpnext.setup.utils import get_company_currency
from erpnext.controllers.accounts_controller import AccountsController
@@ -81,7 +81,7 @@ class JournalEntry(AccountsController):
frappe.throw(_("Row {0}: Party Type and Party is only applicable against Receivable / Payable account").format(d.idx))
def check_credit_limit(self):
customers = list(set([d.party for d in self.get("accounts")
customers = list(set([d.party for d in self.get("accounts")
if d.party_type=="Customer" and d.party and flt(d.debit) > 0]))
if customers:
from erpnext.selling.doctype.customer.customer import check_credit_limit
@@ -243,8 +243,8 @@ class JournalEntry(AccountsController):
def set_against_account(self):
accounts_debited, accounts_credited = [], []
for d in self.get("accounts"):
if flt(d.debit > 0): accounts_debited.append(d.account)
if flt(d.credit) > 0: accounts_credited.append(d.account)
if flt(d.debit > 0): accounts_debited.append(d.party or d.account)
if flt(d.credit) > 0: accounts_credited.append(d.party or d.account)
for d in self.get("accounts"):
if flt(d.debit > 0): d.against_account = ", ".join(list(set(accounts_credited)))
@@ -275,29 +275,27 @@ class JournalEntry(AccountsController):
else:
msgprint(_("Please enter Reference date"), raise_exception=frappe.MandatoryError)
company_currency = get_company_currency(self.company)
for d in self.get('accounts'):
if d.against_invoice and d.credit:
currency = frappe.db.get_value("Sales Invoice", d.against_invoice, "currency")
r.append(_("{0} against Sales Invoice {1}").format(fmt_money(flt(d.credit), currency = currency), \
r.append(_("{0} against Sales Invoice {1}").format(fmt_money(flt(d.credit), currency = company_currency), \
d.against_invoice))
if d.against_sales_order and d.credit:
currency = frappe.db.get_value("Sales Order", d.against_sales_order, "currency")
r.append(_("{0} against Sales Order {1}").format(fmt_money(flt(d.credit), currency = currency), \
r.append(_("{0} against Sales Order {1}").format(fmt_money(flt(d.credit), currency = company_currency), \
d.against_sales_order))
if d.against_voucher and d.debit:
bill_no = frappe.db.sql("""select bill_no, bill_date, currency
bill_no = frappe.db.sql("""select bill_no, bill_date
from `tabPurchase Invoice` where name=%s""", d.against_voucher)
if bill_no and bill_no[0][0] and bill_no[0][0].lower().strip() \
not in ['na', 'not applicable', 'none']:
r.append(_('{0} against Bill {1} dated {2}').format(fmt_money(flt(d.debit), currency=bill_no[0][2]), bill_no[0][0],
r.append(_('{0} against Bill {1} dated {2}').format(fmt_money(flt(d.debit), currency=company_currency), bill_no[0][0],
bill_no[0][1] and formatdate(bill_no[0][1].strftime('%Y-%m-%d'))))
if d.against_purchase_order and d.debit:
currency = frappe.db.get_value("Purchase Order", d.against_purchase_order, "currency")
r.append(_("{0} against Purchase Order {1}").format(fmt_money(flt(d.credit), currency = currency), \
r.append(_("{0} against Purchase Order {1}").format(fmt_money(flt(d.credit), currency = company_currency), \
d.against_purchase_order))
if self.user_remark:
@@ -428,12 +426,11 @@ class JournalEntry(AccountsController):
def validate_expense_claim(self):
for d in self.accounts:
if d.against_expense_claim:
sanctioned_amount, reimbursed_amount = frappe.db.get_value("Expense Claim", d.against_expense_claim,
("total_sanctioned_amount", "total_amount_reimbursed"))
pending_amount = cint(sanctioned_amount) - cint(reimbursed_amount)
sanctioned_amount, reimbursed_amount = frappe.db.get_value("Expense Claim",
d.against_expense_claim, ("total_sanctioned_amount", "total_amount_reimbursed"))
pending_amount = flt(sanctioned_amount) - flt(reimbursed_amount)
if d.debit > pending_amount:
frappe.throw(_("Row No {0}: Amount cannot be greater than Pending Amount against Expense Claim {1}. \
Pending Amount is {2}".format(d.idx, d.against_expense_claim, pending_amount)))
frappe.throw(_("Row No {0}: Amount cannot be greater than Pending Amount against Expense Claim {1}. Pending Amount is {2}".format(d.idx, d.against_expense_claim, pending_amount)))
def validate_credit_debit_note(self):
if self.stock_entry:
@@ -459,11 +456,11 @@ def get_default_bank_cash_account(company, voucher_type, mode_of_payment=None):
if voucher_type=="Bank Entry":
account = frappe.db.get_value("Company", company, "default_bank_account")
if not account:
account = frappe.db.get_value("Account", {"company": company, "account_type": "Bank"})
account = frappe.db.get_value("Account", {"company": company, "account_type": "Bank", "is_group": 0})
elif voucher_type=="Cash Entry":
account = frappe.db.get_value("Company", company, "default_cash_account")
if not account:
account = frappe.db.get_value("Account", {"company": company, "account_type": "Cash"})
account = frappe.db.get_value("Account", {"company": company, "account_type": "Cash", "is_group": 0})
if account:
return {
@@ -539,15 +536,13 @@ def get_opening_accounts(company):
def get_against_jv(doctype, txt, searchfield, start, page_len, filters):
if not filters.get("party"):
return []
return frappe.db.sql("""select jv.name, jv.posting_date, jv.user_remark
from `tabJournal Entry` jv, `tabJournal Entry Account` jv_detail
where jv_detail.parent = jv.name and jv_detail.account = %s and jv_detail.party = %s
where jv_detail.parent = jv.name and jv_detail.account = %s and ifnull(jv_detail.party, '') = %s
and (ifnull(jv_detail.against_invoice, '') = '' and ifnull(jv_detail.against_voucher, '') = ''
and ifnull(jv_detail.against_jv, '') = '' )
and jv.docstatus = 1 and jv.{0} like %s order by jv.name desc limit %s, %s""".format(searchfield),
(filters["account"], filters["party"], "%{0}%".format(txt), start, page_len))
(filters.get("account"), cstr(filters.get("party")), "%{0}%".format(txt), start, page_len))
@frappe.whitelist()
def get_outstanding(args):

View File

@@ -44,6 +44,10 @@ erpnext.accounts.PaymentReconciliationController = frappe.ui.form.Controller.ext
}
});
},
refresh: function() {
this.frm.disable_save();
},
party: function() {
var me = this

View File

@@ -32,6 +32,7 @@ frappe.ui.form.on("Payment Tool", "onload", function(frm) {
});
frappe.ui.form.on("Payment Tool", "refresh", function(frm) {
frm.disable_save();
frappe.ui.form.trigger("Payment Tool", "party_type");
});

View File

@@ -312,7 +312,7 @@
"is_submittable": 0,
"issingle": 1,
"istable": 0,
"modified": "2015-02-21 03:59:08.154966",
"modified": "2015-06-05 11:17:33.843334",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Tool",

View File

@@ -224,3 +224,4 @@ cur_frm.cscript.select_print_heading = function(doc,cdt,cdn){
else
cur_frm.pformat.print_heading = __("Purchase Invoice");
}

File diff suppressed because it is too large Load Diff

View File

@@ -3,7 +3,7 @@
from __future__ import unicode_literals
import frappe
from frappe.utils import cint, formatdate, flt
from frappe.utils import cint, formatdate, flt, getdate
from frappe import msgprint, _, throw
from erpnext.setup.utils import get_company_currency
import frappe.defaults
@@ -39,6 +39,7 @@ class PurchaseInvoice(BuyingController):
self.po_required()
self.pr_required()
self.validate_supplier_invoice()
self.check_active_purchase_items()
self.check_conversion_rate()
self.validate_credit_to_acc()
@@ -87,9 +88,7 @@ class PurchaseInvoice(BuyingController):
throw(_("Conversion rate cannot be 0 or 1"))
def validate_credit_to_acc(self):
root_type, account_type = frappe.db.get_value("Account", self.credit_to, ["root_type", "account_type"])
if root_type != "Liability":
frappe.throw(_("Credit To account must be a liability account"))
account_type = frappe.db.get_value("Account", self.credit_to, "account_type")
if account_type != "Payable":
frappe.throw(_("Credit To account must be a Payable account"))
@@ -165,7 +164,7 @@ class PurchaseInvoice(BuyingController):
elif item.expense_account not in against_accounts:
# if no auto_accounting_for_stock or not a stock item
against_accounts.append(item.expense_account)
self.against_expense_account = ",".join(against_accounts)
def po_required(self):
@@ -272,7 +271,7 @@ class PurchaseInvoice(BuyingController):
gl_entries.append(
self.get_gl_dict({
"account": tax.account_head,
"against": self.credit_to,
"against": self.supplier,
"debit": tax.add_deduct_tax == "Add" and tax.base_tax_amount_after_discount_amount or 0,
"credit": tax.add_deduct_tax == "Deduct" and tax.base_tax_amount_after_discount_amount or 0,
"remarks": self.remarks,
@@ -296,7 +295,7 @@ class PurchaseInvoice(BuyingController):
gl_entries.append(
self.get_gl_dict({
"account": item.expense_account,
"against": self.credit_to,
"against": self.supplier,
"debit": item.base_net_amount,
"remarks": self.remarks,
"cost_center": item.cost_center
@@ -316,7 +315,7 @@ class PurchaseInvoice(BuyingController):
gl_entries.append(
self.get_gl_dict({
"account": stock_received_but_not_billed,
"against": self.credit_to,
"against": self.supplier,
"debit": flt(item.item_tax_amount, self.precision("item_tax_amount", item)),
"remarks": self.remarks or "Accounting Entry for Stock"
})
@@ -342,7 +341,7 @@ class PurchaseInvoice(BuyingController):
self.get_gl_dict({
"account": expenses_included_in_valuation,
"cost_center": cost_center,
"against": self.credit_to,
"against": self.supplier,
"credit": applicable_amount,
"remarks": self.remarks or "Accounting Entry for Stock"
})
@@ -356,7 +355,7 @@ class PurchaseInvoice(BuyingController):
gl_entries.append(
self.get_gl_dict({
"account": self.write_off_account,
"against": self.credit_to,
"against": self.supplier,
"credit": flt(self.write_off_amount),
"remarks": self.remarks,
"cost_center": self.write_off_cost_center
@@ -375,7 +374,7 @@ class PurchaseInvoice(BuyingController):
self.update_billing_status_for_zero_amount_refdoc("Purchase Order")
self.make_gl_entries_on_cancel()
self.update_project()
def update_project(self):
project_list = []
for d in self.items:
@@ -386,6 +385,16 @@ class PurchaseInvoice(BuyingController):
project.save()
project_list.append(d.project_name)
def validate_supplier_invoice(self):
if self.bill_date:
if getdate(self.bill_date) > getdate(self.posting_date):
frappe.throw("Supplier Invoice Date cannot be greater than Posting Date")
if self.bill_no:
if cint(frappe.db.get_single_value("Accounts Settings", "check_supplier_invoice_uniqueness")):
pi = frappe.db.exists("Purchase Invoice", {"bill_no": self.bill_no, "fiscal_year": self.fiscal_year})
if pi:
frappe.throw("Supplier Invoice No exists in Purchase Invoice {0}".format(pi))
@frappe.whitelist()
def get_expense_account(doctype, txt, searchfield, start, page_len, filters):
from erpnext.controllers.queries import get_match_cond
@@ -401,4 +410,4 @@ def get_expense_account(doctype, txt, searchfield, start, page_len, filters):
and tabAccount.company = '%(company)s'
and tabAccount.%(key)s LIKE '%(txt)s'
%(mcond)s""" % {'company': filters['company'], 'key': searchfield,
'txt': "%%%s%%" % txt, 'mcond':get_match_cond(doctype)})
'txt': "%%%s%%" % frappe.db.escape(txt), 'mcond':get_match_cond(doctype)})

View File

@@ -40,7 +40,7 @@
{
"fieldname": "description",
"fieldtype": "Text",
"in_list_view": 1,
"in_list_view": 0,
"label": "Description",
"oldfieldname": "description",
"oldfieldtype": "Text",
@@ -49,6 +49,23 @@
"read_only": 0,
"width": "300px"
},
{
"fieldname": "image",
"fieldtype": "Attach",
"hidden": 1,
"label": "Image",
"permlevel": 0,
"precision": ""
},
{
"fieldname": "image_view",
"fieldtype": "Image",
"label": "Image View",
"options": "image",
"permlevel": 0,
"precision": "",
"print_hide": 1
},
{
"fieldname": "quantity_and_rate",
"fieldtype": "Section Break",
@@ -452,7 +469,7 @@
],
"idx": 1,
"istable": 1,
"modified": "2015-05-27 02:47:16.341373",
"modified": "2015-07-02 03:00:44.496683",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice Item",

View File

@@ -7,6 +7,7 @@ import frappe
@frappe.whitelist()
def get_items(price_list, sales_or_purchase, item=None):
condition = ""
order_by = ""
args = {"price_list": price_list}
if sales_or_purchase == "Sales":
@@ -30,16 +31,25 @@ def get_items(price_list, sales_or_purchase, item=None):
item_code[0]["barcode"] = item
return item_code
condition += " and (CONCAT(i.name, i.item_name) like %(name)s or (i.variant_of like %(name)s))"
args["name"] = "%%%s%%" % item
condition += " and ((CONCAT(i.name, i.item_name) like %(name)s) or (i.variant_of like %(name)s) or (i.item_group like %(name)s))"
order_by = """if(locate(%(_name)s, i.name), locate(%(_name)s, i.name), 99999),
if(locate(%(_name)s, i.item_name), locate(%(_name)s, i.item_name), 99999),
if(locate(%(_name)s, i.variant_of), locate(%(_name)s, i.variant_of), 99999),
if(locate(%(_name)s, i.item_group), locate(%(_name)s, i.item_group), 99999),"""
args["name"] = "%%%s%%" % frappe.db.escape(item)
args["_name"] = item.replace("%", "")
# locate function is used to sort by closest match from the beginning of the value
return frappe.db.sql("""select i.name, i.item_name, i.image,
item_det.price_list_rate, item_det.currency
from `tabItem` i LEFT JOIN
(select item_code, price_list_rate, currency from
`tabItem Price` where price_list=%s) item_det
`tabItem Price` where price_list=%(price_list)s) item_det
ON
(item_det.item_code=i.name or item_det.item_code=i.variant_of)
where
ifnull(i.has_variants, 0) = 0 and
%s""" % ('%(price_list)s', condition), args, as_dict=1)
{condition}
order by
{order_by}
i.name""".format(condition=condition, order_by=order_by), args, as_dict=1)

View File

@@ -392,8 +392,6 @@ cur_frm.cscript.on_submit = function(doc, cdt, cdn) {
}
}
cur_frm.set_query("debit_to", function(doc) {
return{
filters: [

View File

@@ -38,7 +38,8 @@
"options": "Customer",
"permlevel": 0,
"print_hide": 1,
"read_only": 0
"read_only": 0,
"search_index": 1
},
{
"depends_on": "customer",
@@ -502,7 +503,7 @@
{
"fieldname": "base_discount_amount",
"fieldtype": "Currency",
"label": "Discount Amount (Company Currency)",
"label": "Additional Discount Amount (Company Currency)",
"options": "Company:company:default_currency",
"permlevel": 0,
"precision": "",
@@ -880,7 +881,7 @@
"options": "Project",
"permlevel": 0,
"read_only": 0,
"search_index": 1
"search_index": 0
},
{
"depends_on": "eval:doc.source == 'Campaign'",
@@ -1226,6 +1227,15 @@
"print_hide": 1,
"read_only": 0
},
{
"depends_on": "eval:doc.is_recurring==1",
"fieldname": "recurring_print_format",
"fieldtype": "Link",
"label": "Recurring Print Format",
"options": "Print Format",
"permlevel": 0,
"precision": ""
},
{
"fieldname": "against_income_account",
"fieldtype": "Small Text",
@@ -1243,7 +1253,7 @@
"icon": "icon-file-text",
"idx": 1,
"is_submittable": 1,
"modified": "2015-05-27 02:48:02.897865",
"modified": "2015-06-22 06:39:22.072544",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice",

View File

@@ -65,8 +65,7 @@ class SalesInvoice(SellingController):
self.set_against_income_account()
self.validate_c_form()
self.validate_time_logs_are_submitted()
self.validate_multiple_billing("Delivery Note", "dn_detail", "amount",
"items")
self.validate_multiple_billing("Delivery Note", "dn_detail", "amount", "items")
def on_submit(self):
super(SalesInvoice, self).on_submit()
@@ -236,9 +235,7 @@ class SalesInvoice(SellingController):
reconcile_against_document(lst)
def validate_debit_to_acc(self):
root_type, account_type = frappe.db.get_value("Account", self.debit_to, ["root_type", "account_type"])
if root_type != "Asset":
frappe.throw(_("Debit To account must be a liability account"))
account_type = frappe.db.get_value("Account", self.debit_to, "account_type")
if account_type != "Receivable":
frappe.throw(_("Debit To account must be a Receivable account"))
@@ -506,7 +503,7 @@ class SalesInvoice(SellingController):
gl_entries.append(
self.get_gl_dict({
"account": tax.account_head,
"against": self.debit_to,
"against": self.customer,
"credit": flt(tax.base_tax_amount_after_discount_amount),
"remarks": self.remarks,
"cost_center": tax.cost_center
@@ -520,7 +517,7 @@ class SalesInvoice(SellingController):
gl_entries.append(
self.get_gl_dict({
"account": item.income_account,
"against": self.debit_to,
"against": self.customer,
"credit": item.base_net_amount,
"remarks": self.remarks,
"cost_center": item.cost_center
@@ -551,7 +548,7 @@ class SalesInvoice(SellingController):
gl_entries.append(
self.get_gl_dict({
"account": self.cash_bank_account,
"against": self.debit_to,
"against": self.customer,
"debit": self.paid_amount,
"remarks": self.remarks,
})
@@ -575,7 +572,7 @@ class SalesInvoice(SellingController):
gl_entries.append(
self.get_gl_dict({
"account": self.write_off_account,
"against": self.debit_to,
"against": self.customer,
"debit": self.write_off_amount,
"remarks": self.remarks,
"cost_center": self.write_off_cost_center
@@ -590,7 +587,7 @@ def get_list_context(context=None):
@frappe.whitelist()
def get_bank_cash_account(mode_of_payment, company):
account = frappe.db.get_value("Mode of Payment Account",
account = frappe.db.get_value("Mode of Payment Account",
{"parent": mode_of_payment, "company": company}, "default_account")
if not account:
frappe.msgprint(_("Please set default Cash or Bank account in Mode of Payment {0}").format(mode_of_payment))
@@ -614,7 +611,7 @@ def get_income_account(doctype, txt, searchfield, start, page_len, filters):
and tabAccount.company = '%(company)s'
and tabAccount.%(key)s LIKE '%(txt)s'
%(mcond)s""" % {'company': filters['company'], 'key': searchfield,
'txt': "%%%s%%" % txt, 'mcond':get_match_cond(doctype)})
'txt': "%%%s%%" % frappe.db.escape(txt), 'mcond':get_match_cond(doctype)})
@frappe.whitelist()
def make_delivery_note(source_name, target_doc=None):

View File

@@ -58,7 +58,7 @@
{
"fieldname": "description",
"fieldtype": "Text",
"in_list_view": 1,
"in_list_view": 0,
"label": "Description",
"oldfieldname": "description",
"oldfieldtype": "Text",
@@ -68,6 +68,23 @@
"reqd": 1,
"width": "200px"
},
{
"fieldname": "image",
"fieldtype": "Attach",
"hidden": 1,
"label": "Image",
"permlevel": 0,
"precision": ""
},
{
"fieldname": "image_view",
"fieldtype": "Image",
"label": "Image View",
"options": "image",
"permlevel": 0,
"precision": "",
"print_hide": 1
},
{
"fieldname": "quantity_and_rate",
"fieldtype": "Section Break",
@@ -505,7 +522,7 @@
],
"idx": 1,
"istable": 1,
"modified": "2015-05-27 02:47:15.645114",
"modified": "2015-07-02 02:59:08.413213",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice Item",

View File

@@ -3,7 +3,7 @@
from __future__ import unicode_literals
import frappe
from frappe.utils import flt, cstr
from frappe.utils import flt, cstr, cint
from frappe import _
from frappe.model.meta import get_field_precision
from erpnext.accounts.utils import validate_expense_against_budget
@@ -56,12 +56,13 @@ def merge_similar_entries(gl_map):
def check_if_in_list(gle, gl_map):
for e in gl_map:
if e.account == gle.account and \
cstr(e.get('against_voucher'))==cstr(gle.get('against_voucher')) \
and cstr(e.get('against_voucher_type')) == \
cstr(gle.get('against_voucher_type')) \
and cstr(e.get('cost_center')) == cstr(gle.get('cost_center')):
return e
if e.account == gle.account \
and cstr(e.get('party_type'))==cstr(gle.get('party_type')) \
and cstr(e.get('party'))==cstr(gle.get('party')) \
and cstr(e.get('against_voucher'))==cstr(gle.get('against_voucher')) \
and cstr(e.get('against_voucher_type')) == cstr(gle.get('against_voucher_type')) \
and cstr(e.get('cost_center')) == cstr(gle.get('cost_center')):
return e
def save_entries(gl_map, adv_adj, update_outstanding):
validate_account_for_auto_accounting_for_stock(gl_map)
@@ -81,14 +82,15 @@ def make_entry(args, adv_adj, update_outstanding):
gle.submit()
def validate_account_for_auto_accounting_for_stock(gl_map):
if gl_map[0].voucher_type=="Journal Entry":
aii_accounts = [d[0] for d in frappe.db.sql("""select name from tabAccount
where account_type = 'Warehouse' and ifnull(warehouse, '')!=''""")]
if cint(frappe.db.get_single_value("Accounts Settings", "auto_accounting_for_stock")) \
and gl_map[0].voucher_type=="Journal Entry":
aii_accounts = [d[0] for d in frappe.db.sql("""select name from tabAccount
where account_type = 'Warehouse' and ifnull(warehouse, '')!=''""")]
for entry in gl_map:
if entry.account in aii_accounts:
frappe.throw(_("Account: {0} can only be updated via Stock Transactions")
.format(entry.account), StockAccountInvalidTransaction)
for entry in gl_map:
if entry.account in aii_accounts:
frappe.throw(_("Account: {0} can only be updated via Stock Transactions")
.format(entry.account), StockAccountInvalidTransaction)
def round_off_debit_credit(gl_map):
precision = get_field_precision(frappe.get_meta("GL Entry").get_field("debit"),
@@ -101,7 +103,7 @@ def round_off_debit_credit(gl_map):
debit_credit_diff += entry.debit - entry.credit
debit_credit_diff = flt(debit_credit_diff, precision)
if abs(debit_credit_diff) >= (2.0 / (10**precision)):
if abs(debit_credit_diff) >= (5.0 / (10**precision)):
frappe.throw(_("Debit and Credit not equal for {0} #{1}. Difference is {2}.")
.format(gl_map[0].voucher_type, gl_map[0].voucher_no, debit_credit_diff))

View File

@@ -9,7 +9,7 @@
<button class="btn btn-primary btn-lg">{%= __("Start") %}</button>
</p>
<p class="pos-setting-message hide">
<a class="btn btn-default btn-sm" href="#Form/POS Setting/New POS Setting">
{%= __("Make new POS Setting") %}</a>
<a class="btn btn-default btn-sm" href="#Form/POS Profile/New POS Profile">
{%= __("Make new POS Profile") %}</a>
</p>
</div>

View File

@@ -16,12 +16,16 @@ def get_party_details(party=None, account=None, party_type="Customer", company=N
if not party:
return {}
if not frappe.db.exists(party_type, party):
frappe.throw(_("{0}: {1} does not exists").format(party_type, party))
return _get_party_details(party, account, party_type,
company, posting_date, price_list, currency, doctype)
def _get_party_details(party=None, account=None, party_type="Customer", company=None,
posting_date=None, price_list=None, currency=None, doctype=None, ignore_permissions=False):
out = frappe._dict(set_account_and_due_date(party, account, party_type, company, posting_date, doctype))
party = out[party_type.lower()]

View File

@@ -51,7 +51,7 @@ class ReceivablePayableReport(object):
currency_precision = get_currency_precision() or 2
dr_or_cr = "debit" if args.get("party_type") == "Customer" else "credit"
voucher_details = self.get_voucher_details()
voucher_details = self.get_voucher_details(args.get("party_type"))
future_vouchers = self.get_entries_after(self.filters.report_date, args.get("party_type"))
@@ -153,23 +153,26 @@ class ReceivablePayableReport(object):
return self.party_map
def get_voucher_details(self):
def get_voucher_details(self, party_type):
voucher_details = frappe._dict()
if party_type == "Customer":
for si in frappe.db.sql("""select name, due_date
from `tabSales Invoice` where docstatus=1""", as_dict=1):
voucher_details.setdefault(si.name, si)
for si in frappe.db.sql("""select name, due_date
from `tabSales Invoice` where docstatus=1""", as_dict=1):
voucher_details.setdefault(si.name, si)
for pi in frappe.db.sql("""select name, due_date, bill_no, bill_date
from `tabPurchase Invoice` where docstatus=1""", as_dict=1):
voucher_details.setdefault(pi.name, pi)
if party_type == "Supplier":
for pi in frappe.db.sql("""select name, due_date, bill_no, bill_date
from `tabPurchase Invoice` where docstatus=1""", as_dict=1):
voucher_details.setdefault(pi.name, pi)
return voucher_details
def get_gl_entries(self, party_type):
if not hasattr(self, "gl_entries"):
conditions, values = self.prepare_conditions(party_type)
self.gl_entries = frappe.db.sql("""select * from `tabGL Entry`
self.gl_entries = frappe.db.sql("""select name, posting_date, account, party_type, party, debit, credit,
voucher_type, voucher_no, against_voucher_type, against_voucher from `tabGL Entry`
where docstatus < 2 and party_type=%s {0} order by posting_date, party"""
.format(conditions), values, as_dict=True)
@@ -187,7 +190,7 @@ class ReceivablePayableReport(object):
if self.filters.get(party_type_field):
conditions.append("party=%s")
values.append(self.filters.get(party_type_field))
values.append(self.filters.get(party_type_field))
return " and ".join(conditions), values

View File

@@ -83,7 +83,7 @@ def get_data(company, root_type, balance_must_be, period_list, ignore_closing_en
gl_entries_by_account = get_gl_entries(company, period_list[0]["from_date"], period_list[-1]["to_date"],
accounts[0].lft, accounts[0].rgt, ignore_closing_entries=ignore_closing_entries)
calculate_values(accounts, gl_entries_by_account, period_list)
calculate_values(accounts_by_name, gl_entries_by_account, period_list)
accumulate_values_into_parents(accounts, accounts_by_name, period_list)
out = prepare_data(accounts, balance_must_be, period_list)
@@ -92,16 +92,14 @@ def get_data(company, root_type, balance_must_be, period_list, ignore_closing_en
return out
def calculate_values(accounts, gl_entries_by_account, period_list):
for d in accounts:
for name in ([d.name] + (d.collapsed_children or [])):
for entry in gl_entries_by_account.get(name, []):
for period in period_list:
entry.posting_date = getdate(entry.posting_date)
# check if posting date is within the period
if entry.posting_date <= period.to_date:
d[period.key] = d.get(period.key, 0.0) + flt(entry.debit) - flt(entry.credit)
def calculate_values(accounts_by_name, gl_entries_by_account, period_list):
for entries in gl_entries_by_account.values():
for entry in entries:
d = accounts_by_name.get(entry.account)
for period in period_list:
# check if posting date is within the period
if entry.posting_date <= period.to_date:
d[period.key] = d.get(period.key, 0.0) + flt(entry.debit) - flt(entry.credit)
def accumulate_values_into_parents(accounts, accounts_by_name, period_list):
@@ -159,22 +157,8 @@ def add_total_row(out, balance_must_be, period_list):
out.append({})
def get_accounts(company, root_type):
# root lft, rgt
root_account = frappe.db.sql("""select lft, rgt from `tabAccount`
where company=%s and root_type=%s and ifnull(parent_account, '') = ''
order by lft limit 1""",
(company, root_type), as_dict=True)
if not root_account:
return None
lft, rgt = root_account[0].lft, root_account[0].rgt
accounts = frappe.db.sql("""select * from `tabAccount`
where company=%(company)s and lft >= %(lft)s and rgt <= %(rgt)s order by lft""",
{ "company": company, "lft": lft, "rgt": rgt }, as_dict=True)
return accounts
return frappe.db.sql("""select name, parent_account, lft, rgt, root_type, report_type, account_name from `tabAccount`
where company=%s and root_type=%s order by lft""", (company, root_type), as_dict=True)
def filter_accounts(accounts, depth=10):
parent_children_map = {}
@@ -196,14 +180,6 @@ def filter_accounts(accounts, depth=10):
filtered_accounts.append(child)
add_to_list(child.name, level + 1)
else:
# include all children at level lower than the depth
parent_account = accounts_by_name[parent]
parent_account["collapsed_children"] = []
for d in accounts:
if d.lft > parent_account.lft and d.rgt < parent_account.rgt:
parent_account["collapsed_children"].append(d.name)
add_to_list(None, 0)
return filtered_accounts, accounts_by_name
@@ -234,7 +210,7 @@ def get_gl_entries(company, from_date, to_date, root_lft, root_rgt, ignore_closi
if from_date:
additional_conditions.append("and posting_date >= %(from_date)s")
gl_entries = frappe.db.sql("""select * from `tabGL Entry`
gl_entries = frappe.db.sql("""select posting_date, account, debit, credit, is_opening from `tabGL Entry`
where company=%(company)s
{additional_conditions}
and posting_date <= %(to_date)s

View File

@@ -3,7 +3,7 @@
from __future__ import unicode_literals
import frappe
from frappe.utils import flt, getdate
from frappe.utils import flt, getdate, cstr
from frappe import _
def execute(filters=None):
@@ -66,7 +66,7 @@ def get_gl_entries(filters):
gl_entries = frappe.db.sql("""select posting_date, account, party_type, party,
sum(ifnull(debit, 0)) as debit, sum(ifnull(credit, 0)) as credit,
voucher_type, voucher_no, cost_center, remarks, is_opening, against
voucher_type, voucher_no, cost_center, remarks, against, is_opening
from `tabGL Entry`
where company=%(company)s {conditions}
{group_by_condition}
@@ -91,6 +91,9 @@ def get_conditions(filters):
if filters.get("party"):
conditions.append("party=%(party)s")
if not (filters.get("account") or filters.get("party") or filters.get("group_by_account")):
conditions.append("posting_date >=%(from_date)s")
from frappe.desk.reportview import build_match_conditions
match_conditions = build_match_conditions("GL Entry")
@@ -148,14 +151,15 @@ def initialize_gle_map(gl_entries):
def get_accountwise_gle(filters, gl_entries, gle_map):
opening, total_debit, total_credit = 0, 0, 0
from_date, to_date = getdate(filters.from_date), getdate(filters.to_date)
for gle in gl_entries:
amount = flt(gle.debit, 3) - flt(gle.credit, 3)
if gle.posting_date < getdate(filters.from_date):
if (filters.get("account") or filters.get("party") or filters.get("group_by_account")) \
and (gle.posting_date < from_date or cstr(gle.is_opening) == "Yes"):
gle_map[gle.account].opening += amount
if filters.get("account") or filters.get("party"):
opening += amount
elif gle.posting_date <= getdate(filters.to_date):
elif gle.posting_date <= to_date:
gle_map[gle.account].entries.append(gle)
gle_map[gle.account].total_debit += flt(gle.debit, 3)
gle_map[gle.account].total_credit += flt(gle.credit, 3)

View File

@@ -14,7 +14,7 @@ def execute(filters=None):
source = gross_profit_data.grouped_data if filters.get("group_by") != "Invoice" else gross_profit_data.data
group_wise_columns = frappe._dict({
"invoice": ["parent", "posting_date", "posting_time", "item_code", "item_name", "brand", "description", \
"invoice": ["parent", "customer", "posting_date", "posting_time", "item_code", "item_name", "brand", "description", \
"warehouse", "qty", "base_rate", "buying_rate", "base_amount",
"buying_amount", "gross_profit", "gross_profit_percent", "project"],
"item_code": ["item_code", "item_name", "brand", "description", "warehouse", "qty", "base_rate",
@@ -175,16 +175,15 @@ class GrossProfitGenerator(object):
else:
if row.update_stock or row.dn_detail:
parenttype, parent, item_row = row.parenttype, row.parent, row.item_row
if row.dn_detail:
row.parenttype = "Delivery Note"
row.parent = row.delivery_note
row.item_row = row.dn_detail
parenttype, parent, item_row = "Delivery Note", row.delivery_note, row.dn_detail
my_sle = self.sle.get((item_code, row.warehouse))
for i, sle in enumerate(my_sle):
# find the stock valution rate from stock ledger entry
if sle.voucher_type == row.parenttype and row.parent == sle.voucher_no and \
sle.voucher_detail_no == row.item_row:
if sle.voucher_type == parenttype and parent == sle.voucher_no and \
sle.voucher_detail_no == item_row:
previous_stock_value = len(my_sle) > i+1 and \
flt(my_sle[i+1].stock_value) or 0.0
return previous_stock_value - flt(sle.stock_value)

View File

@@ -3,6 +3,14 @@
frappe.query_reports["Payment Period Based On Invoice Date"] = {
"filters": [
{
fieldname:"company",
label: __("Company"),
fieldtype: "Link",
options: "Company",
reqd: 1,
default: frappe.defaults.get_user_default("company")
},
{
fieldname: "from_date",
label: __("From Date"),
@@ -23,27 +31,28 @@ frappe.query_reports["Payment Period Based On Invoice Date"] = {
default: "Incoming"
},
{
fieldname:"account",
label: __("Account"),
fieldtype: "Link",
options: "Account",
get_query: function() {
"fieldname":"party_type",
"label": __("Party Type"),
"fieldtype": "Link",
"options": "DocType",
"get_query": function() {
return {
query: "erpnext.controllers.queries.get_account_list",
filters: {
"report_type": "Balance Sheet",
company: frappe.query_report.filters_by_name.company.get_value()
}
filters: {"name": ["in", ["Customer", "Supplier"]]}
}
}
},
{
fieldname:"company",
label: __("Company"),
fieldtype: "Link",
options: "Company",
reqd: 1,
default: frappe.defaults.get_user_default("company")
"fieldname":"party",
"label": __("Party"),
"fieldtype": "Dynamic Link",
"get_options": function() {
var party_type = frappe.query_report.filters_by_name.party_type.get_value();
var party = frappe.query_report.filters_by_name.party.get_value();
if(party && !party_type) {
frappe.throw(__("Please select Party Type first"));
}
return party_type;
}
},
]
}

View File

@@ -9,8 +9,9 @@ from frappe.utils import flt
def execute(filters=None):
if not filters: filters = {}
columns = get_columns()
validate_filters(filters)
columns = get_columns(filters)
entries = get_entries(filters)
invoice_posting_date_map = get_invoice_posting_date_map(filters)
against_date = ""
@@ -20,67 +21,72 @@ def execute(filters=None):
for d in entries:
if d.against_voucher:
against_date = d.against_voucher and invoice_posting_date_map[d.against_voucher] or ""
outstanding_amount = flt(d.debit) or -1 * flt(d.credit)
payment_amount = flt(d.debit) or -1 * flt(d.credit)
else:
against_date = d.against_invoice and invoice_posting_date_map[d.against_invoice] or ""
outstanding_amount = flt(d.credit) or -1 * flt(d.debit)
payment_amount = flt(d.credit) or -1 * flt(d.debit)
row = [d.name, d.account, d.posting_date, d.against_voucher or d.against_invoice,
row = [d.name, d.party_type, d.party, d.posting_date, d.against_voucher or d.against_invoice,
against_date, d.debit, d.credit, d.cheque_no, d.cheque_date, d.remark]
if d.against_voucher or d.against_invoice:
row += get_ageing_data(30, 60, 90, d.posting_date, against_date, outstanding_amount)
row += get_ageing_data(30, 60, 90, d.posting_date, against_date, payment_amount)
else:
row += ["", "", "", "", ""]
data.append(row)
return columns, data
def validate_filters(filters):
if (filters.get("payment_type") == "Incoming" and filters.get("party_type") == "Supplier") or \
(filters.get("payment_type") == "Outgoing" and filters.get("party_type") == "Customer"):
frappe.throw(_("{0} payment entries can not be filtered by {1}")\
.format(filters.payment_type, filters.party_type))
def get_columns():
return [_("Journal Entry") + ":Link/Journal Entry:140", _("Account") + ":Link/Account:140",
_("Posting Date") + ":Date:100", _("Against Invoice") + ":Link/Purchase Invoice:130",
def get_columns(filters):
return [_("Journal Entry") + ":Link/Journal Entry:140",
_("Party Type") + ":Link/DocType:100", _("Party") + ":Dynamic Link/Party Type:140",
_("Posting Date") + ":Date:100",
_("Against Invoice") + (":Link/Purchase Invoice:130" if filters.get("payment_type") == "Outgoing" else ":Link/Sales Invoice:130"),
_("Against Invoice Posting Date") + ":Date:130", _("Debit") + ":Currency:120", _("Credit") + ":Currency:120",
_("Reference No") + "::100", _("Reference Date") + ":Date:100", _("Remarks") + "::150", _("Age") +":Int:40",
"0-30:Currency:100", "30-60:Currency:100", "60-90:Currency:100", _("90-Above") + ":Currency:100"
]
def get_conditions(filters):
conditions = ""
party = None
conditions = []
if filters.get("account"):
party = filters["account"]
else:
conditions += " and company = '%s'" % frappe.db.escape(filters["company"])
if not filters.get("party_type"):
if filters.get("payment_type") == "Outgoing":
filters["party_type"] = "Supplier"
else:
filters["party_type"] = "Customer"
if filters.get("party_type"):
conditions.append("jvd.party_type=%(party_type)s")
account_type = "Receivable" if filters.get("payment_type") == "Incoming" else "Payable"
if filters.get("party"):
conditions.append("jvd.party=%(party)s")
conditions += """ and account in
(select name from tabAccount
where account_type = '{0}'
and company='{1}')""".format(account_type, frappe.db.escape(filters["company"]))
if party:
conditions += " and jvd.party = '%s'" % frappe.db.escape(party)
else:
conditions += " and ifnull(jvd.party, '') != ''"
if filters.get("company"):
conditions.append("jv.company=%(company)s")
if filters.get("from_date"):
conditions += " and jv.posting_date >= '%s'" % filters["from_date"]
conditions.append("jv.posting_date >= %(from_date)s")
if filters.get("to_date"):
conditions += " and jv.posting_date <= '%s'" % filters["to_date"]
conditions.append("jv.posting_date <= %(to_date)s")
return conditions
return "and {}".format(" and ".join(conditions)) if conditions else ""
def get_entries(filters):
conditions = get_conditions(filters)
entries = frappe.db.sql("""select jv.name, jvd.account, jv.posting_date,
entries = frappe.db.sql("""select jv.name, jvd.party_type, jvd.party, jv.posting_date,
jvd.against_voucher, jvd.against_invoice, jvd.debit, jvd.credit,
jv.cheque_no, jv.cheque_date, jv.remark
from `tabJournal Entry Account` jvd, `tabJournal Entry` jv
where jvd.parent = jv.name and jv.docstatus=1 %s order by jv.name DESC""" %
conditions, as_dict=1, debug=1)
conditions, filters, as_dict=1)
return entries

View File

@@ -12,7 +12,6 @@ def execute(filters=None):
invoice_list = get_invoices(filters)
columns, expense_accounts, tax_accounts = get_columns(invoice_list)
if not invoice_list:
msgprint(_("No record found"))
return columns, invoice_list
@@ -30,7 +29,8 @@ def execute(filters=None):
purchase_receipt = list(set(invoice_po_pr_map.get(inv.name, {}).get("purchase_receipt", [])))
project_name = list(set(invoice_po_pr_map.get(inv.name, {}).get("project_name", [])))
row = [inv.name, inv.posting_date, inv.supplier, inv.supplier_name, supplier_details.get(inv.supplier),
row = [inv.name, inv.posting_date, inv.supplier, inv.supplier_name,
supplier_details.get(inv.supplier),
inv.credit_to, ", ".join(project_name), inv.bill_no, inv.bill_date, inv.remarks,
", ".join(purchase_order), ", ".join(purchase_receipt)]
@@ -54,8 +54,7 @@ def execute(filters=None):
# total tax, grand total, outstanding amount & rounded total
row += [total_tax, inv.base_grand_total, flt(inv.base_grand_total, 2), inv.outstanding_amount]
data.append(row)
# raise Exception
data.append(row)
return columns, data
@@ -107,7 +106,7 @@ def get_conditions(filters):
def get_invoices(filters):
conditions = get_conditions(filters)
return frappe.db.sql("""select name, posting_date, credit_to, supplier, supplier_name
return frappe.db.sql("""select name, posting_date, credit_to, supplier, supplier_name,
bill_no, bill_date, remarks, base_net_total, base_grand_total, outstanding_amount
from `tabPurchase Invoice` where docstatus = 1 %s
order by posting_date desc, name desc""" % conditions, filters, as_dict=1)

View File

@@ -30,7 +30,8 @@ def execute(filters=None):
delivery_note = list(set(invoice_so_dn_map.get(inv.name, {}).get("delivery_note", [])))
row = [inv.name, inv.posting_date, inv.customer, inv.customer_name,
customer_map.get(inv.customer)["customer_group"], customer_map.get(inv.customer)["territory"],
customer_map.get(inv.customer, {}).get("customer_group"),
customer_map.get(inv.customer, {}).get("territory"),
inv.debit_to, inv.project_name, inv.remarks, ", ".join(sales_order), ", ".join(delivery_note)]
# map income values

View File

@@ -4,12 +4,12 @@
from __future__ import unicode_literals
import frappe
from frappe import _
from frappe.utils import cint, flt, getdate, formatdate
from frappe.utils import cint, flt, getdate, formatdate, cstr
from erpnext.accounts.report.financial_statements import filter_accounts, get_gl_entries
value_fields = ("opening_debit", "opening_credit", "debit", "credit", "closing_debit", "closing_credit")
def execute(filters):
def execute(filters=None):
validate_filters(filters)
data = get_data(filters)
columns = get_columns()
@@ -45,8 +45,8 @@ def validate_filters(filters):
filters.to_date = filters.year_end_date
def get_data(filters):
accounts = frappe.db.sql("""select * from `tabAccount` where company=%s order by lft""",
filters.company, as_dict=True)
accounts = frappe.db.sql("""select name, parent_account, account_name, root_type, report_type, lft, rgt
from `tabAccount` where company=%s order by lft""", filters.company, as_dict=True)
if not accounts:
return None
@@ -56,17 +56,58 @@ def get_data(filters):
min_lft, max_rgt = frappe.db.sql("""select min(lft), max(rgt) from `tabAccount`
where company=%s""", (filters.company,))[0]
gl_entries_by_account = get_gl_entries(filters.company, None, filters.to_date, min_lft, max_rgt,
gl_entries_by_account = get_gl_entries(filters.company, filters.from_date, filters.to_date, min_lft, max_rgt,
ignore_closing_entries=not flt(filters.with_period_closing_entry))
total_row = calculate_values(accounts, gl_entries_by_account, filters)
opening_balances = get_opening_balances(filters)
total_row = calculate_values(accounts, gl_entries_by_account, opening_balances, filters)
accumulate_values_into_parents(accounts, accounts_by_name)
data = prepare_data(accounts, filters, total_row)
return data
def get_opening_balances(filters):
balance_sheet_opening = get_rootwise_opening_balances(filters, "Balance Sheet")
pl_opening = get_rootwise_opening_balances(filters, "Profit and Loss")
balance_sheet_opening.update(pl_opening)
return balance_sheet_opening
def get_rootwise_opening_balances(filters, report_type):
additional_conditions = " and posting_date >= %(year_start_date)s" \
if report_type == "Profit and Loss" else ""
if not flt(filters.with_period_closing_entry):
additional_conditions += " and ifnull(voucher_type, '')!='Period Closing Voucher'"
gle = frappe.db.sql("""
select
account, sum(ifnull(debit, 0)) as opening_debit, sum(ifnull(credit, 0)) as opening_credit
from `tabGL Entry`
where
company=%(company)s
{additional_conditions}
and (posting_date < %(from_date)s or ifnull(is_opening, 'No') = 'Yes')
and account in (select name from `tabAccount` where report_type=%(report_type)s)
group by account""".format(additional_conditions=additional_conditions),
{
"company": filters.company,
"from_date": filters.from_date,
"report_type": report_type,
"year_start_date": filters.year_start_date
},
as_dict=True)
opening = frappe._dict()
for d in gle:
opening.setdefault(d.account, d)
return opening
def calculate_values(accounts, gl_entries_by_account, filters):
def calculate_values(accounts, gl_entries_by_account, opening_balances, filters):
init = {
"opening_debit": 0.0,
"opening_credit": 0.0,
@@ -87,30 +128,18 @@ def calculate_values(accounts, gl_entries_by_account, filters):
for d in accounts:
d.update(init.copy())
# add opening
d["opening_debit"] = opening_balances.get(d.name, {}).get("opening_debit", 0)
d["opening_credit"] = opening_balances.get(d.name, {}).get("opening_credit", 0)
for entry in gl_entries_by_account.get(d.name, []):
posting_date = getdate(entry.posting_date)
# opening
if posting_date < filters.from_date:
is_valid_opening = (d.root_type in ("Asset", "Liability", "Equity") or
(filters.year_start_date <= posting_date < filters.from_date))
if is_valid_opening:
d["opening_debit"] += flt(entry.debit)
d["opening_credit"] += flt(entry.credit)
elif posting_date <= filters.to_date:
if entry.is_opening == "Yes" and d.root_type in ("Asset", "Liability", "Equity"):
d["opening_debit"] += flt(entry.debit)
d["opening_credit"] += flt(entry.credit)
else:
d["debit"] += flt(entry.debit)
d["credit"] += flt(entry.credit)
if cstr(entry.is_opening) != "Yes":
d["debit"] += flt(entry.debit)
d["credit"] += flt(entry.credit)
total_row["debit"] += d["debit"]
total_row["credit"] += d["credit"]
return total_row

View File

@@ -91,7 +91,7 @@ def get_balance_on(account=None, date=None, party_type=None, party=None):
# different filter for group and ledger - improved performance
if acc.is_group:
cond.append("""exists (
select * from `tabAccount` ac where ac.name = gle.account
select name from `tabAccount` ac where ac.name = gle.account
and ac.lft >= %s and ac.rgt <= %s
)""" % (acc.lft, acc.rgt))
else:
@@ -397,7 +397,7 @@ def get_outstanding_invoices(amount_query, account, party_type, party):
for d in outstanding_voucher_list:
payment_amount = frappe.db.sql("""
select ifnull(sum(ifnull({amount_query}, 0)), 0)
select ifnull(sum({amount_query}), 0)
from
`tabGL Entry`
where

View File

@@ -26,7 +26,7 @@
"reqd": 1
},
{
"description": "Supplier (vendor) name as entered in supplier master",
"description": "",
"fieldname": "supplier",
"fieldtype": "Link",
"in_filter": 1,
@@ -457,7 +457,7 @@
{
"fieldname": "base_discount_amount",
"fieldtype": "Currency",
"label": "Discount Amount (Company Currency)",
"label": "Additional Discount Amount (Company Currency)",
"options": "Company:company:default_currency",
"permlevel": 0,
"precision": "",
@@ -868,12 +868,21 @@
"no_copy": 1,
"permlevel": 0,
"print_hide": 1
},
{
"depends_on": "eval:doc.is_recurring==1",
"fieldname": "recurring_print_format",
"fieldtype": "Link",
"label": "Recurring Print Format",
"options": "Print Format",
"permlevel": 0,
"precision": ""
}
],
"icon": "icon-file-text",
"idx": 1,
"is_submittable": 1,
"modified": "2015-05-27 02:48:02.452899",
"modified": "2015-06-22 07:30:36.259753",
"modified_by": "Administrator",
"module": "Buying",
"name": "Purchase Order",

View File

@@ -75,7 +75,7 @@
{
"fieldname": "description",
"fieldtype": "Small Text",
"in_list_view": 1,
"in_list_view": 0,
"label": "Description",
"oldfieldname": "description",
"oldfieldtype": "Small Text",
@@ -538,7 +538,7 @@
],
"idx": 1,
"istable": 1,
"modified": "2015-05-27 02:47:16.553472",
"modified": "2015-06-02 14:19:21.459032",
"modified_by": "Administrator",
"module": "Buying",
"name": "Purchase Order Item",

View File

@@ -57,3 +57,7 @@ cur_frm.fields_dict['item_serial_no'].get_query = function(doc, cdt, cdn) {
return { filters: filter }
}
cur_frm.add_fetch('item_code', 'item_name', 'item_name');
cur_frm.add_fetch('item_code', 'description', 'description');

View File

@@ -127,6 +127,14 @@
"permlevel": 0,
"width": "50%"
},
{
"fieldname": "item_name",
"fieldtype": "Data",
"label": "Item Name",
"permlevel": 0,
"precision": "",
"read_only": 1
},
{
"fieldname": "description",
"fieldtype": "Small Text",
@@ -219,7 +227,7 @@
"icon": "icon-search",
"idx": 1,
"is_submittable": 1,
"modified": "2015-04-14 07:37:07.331291",
"modified": "2015-06-08 02:40:25.121948",
"modified_by": "Administrator",
"module": "Buying",
"name": "Quality Inspection",

View File

@@ -31,7 +31,6 @@ class QualityInspection(Document):
(self.name, self.modified, self.purchase_receipt_no,
self.item_code))
def on_cancel(self):
if self.purchase_receipt_no:
frappe.db.sql("""update `tabPurchase Receipt Item` t1, `tabPurchase Receipt` t2
@@ -39,7 +38,6 @@ class QualityInspection(Document):
where t1.parent = %s and t1.item_code = %s and t1.parent = t2.name""",
(self.modified, self.purchase_receipt_no, self.item_code))
def item_query(doctype, txt, searchfield, start, page_len, filters):
if filters.get("from"):
from frappe.desk.reportview import get_match_cond

View File

@@ -26,7 +26,7 @@
"reqd": 1
},
{
"description": "Supplier (vendor) name as entered in supplier master",
"description": "",
"fieldname": "supplier",
"fieldtype": "Link",
"in_filter": 1,
@@ -439,7 +439,7 @@
{
"fieldname": "base_discount_amount",
"fieldtype": "Currency",
"label": "Discount Amount (Company Currency)",
"label": "Additional Discount Amount (Company Currency)",
"options": "Company:company:default_currency",
"permlevel": 0,
"precision": "",
@@ -660,7 +660,7 @@
"icon": "icon-shopping-cart",
"idx": 1,
"is_submittable": 1,
"modified": "2015-05-27 02:48:02.098540",
"modified": "2015-06-15 15:39:08.954248",
"modified_by": "Administrator",
"module": "Buying",
"name": "Supplier Quotation",

View File

@@ -59,7 +59,7 @@
{
"fieldname": "description",
"fieldtype": "Small Text",
"in_list_view": 1,
"in_list_view": 0,
"label": "Description",
"oldfieldname": "description",
"oldfieldtype": "Small Text",
@@ -413,7 +413,7 @@
],
"idx": 1,
"istable": 1,
"modified": "2015-05-27 02:47:15.853886",
"modified": "2015-06-02 14:19:33.922968",
"modified_by": "Administrator",
"module": "Buying",
"name": "Supplier Quotation Item",

View File

@@ -0,0 +1,17 @@
- Performance upgrade in Trial Balance, General Ledger, AR/AP, Balance Sheet and P&L Statement reports
- Add index on Account and GL Entry, Sales Invoice and Purchase Invoice table
- Don't create Time Logs against Production Order if Workstation is not specified in Operations
- Task should be mandatory in Time Log only when Project is mentioned but Production Order is not
- Supplier invoice no unique validation and supplier invoice date can not be after posting date
- Removed BOM No from mandatory from Stock Entry against Production Order
- Load tasks in project for printing purpose
- Added Customers Not Buying Since Long Time against Sales Invoice
- POS - search by Item Group
- Payment period based on invoice date: show party columns and filter based on party
- Barcode added to Purchase Receipt
- Fetch item name and desc on change of item code in Quality Inspection
- Show item name in item grid view based 'In List View' property
- Validate and update manufactured qty in Stock Entry
- Show only users with Expense Approver role in Expense Claim Approver field
- Over Production Allowance Percentage Setting added to Manufacturing Settings
- Activity Cost - Mandatory removed for Employee

View File

@@ -0,0 +1 @@
- Open notification of Sales Order and Purchase Order based on whether Invoice is created against them. For eg. If a Sales Order is not Invoiced, it will be considered as open. Previously it was considered open if Delivery Note was created against Sales Order.

View File

@@ -0,0 +1,8 @@
- Item variants is now manageable via dedicated tool **Manage Variants**. To learn about it, check https://manual.erpnext.com/contents/stock/item/item-variants
- Against account in General Ledger will show Party instead of Account (which is not useful)
- Print format for recurring documents can be set by the users
- Recurring documents won't be created for Stopped Sales / Purchase Orders.
- Lead status will be changed to 'Opportunity' when Lead converted to Opportunity
- Amount in Journal Entry list view
- Currency exchange rate is now automatically fetched from fixer.io, instead of jsonrates.com
- Item image is now available in Sales / Purchase Invoice

View File

@@ -103,6 +103,12 @@ def get_data():
"name": "Completed Production Orders",
"doctype": "Production Order"
},
{
"type": "report",
"is_query_report": True,
"name": "BOM Search",
"doctype": "BOM"
},
]
},
{

View File

@@ -237,6 +237,12 @@ def get_data():
"route": "query-report/Sales Person Target Variance Item Group-Wise",
"doctype": "Sales Person",
},
{
"type": "report",
"is_query_report": True,
"name": "BOM Search",
"doctype": "BOM"
},
{
"type": "report",
"is_query_report": True,

View File

@@ -38,7 +38,8 @@ class AccountsController(TransactionBase):
convert_to_recurring(self, self.get("posting_date") or self.get("transaction_date"))
def before_recurring(self):
self.fiscal_year = None
if self.meta.get_field("fiscal_year"):
self.fiscal_year = None
if self.meta.get_field("due_date"):
self.due_date = None
@@ -46,7 +47,7 @@ class AccountsController(TransactionBase):
for fieldname in ["posting_date", "transaction_date"]:
if not self.get(fieldname) and self.meta.get_field(fieldname):
self.set(fieldname, today())
if not self.fiscal_year:
if self.meta.get_field("fiscal_year") and not self.fiscal_year:
self.fiscal_year = get_fiscal_year(self.get(fieldname))[0]
break
@@ -334,7 +335,7 @@ class AccountsController(TransactionBase):
@frappe.whitelist()
def get_tax_rate(account_head):
return frappe.db.get_value("Account", account_head, "tax_rate")
@frappe.whitelist()
def get_default_taxes_and_charges(master_doctype):
default_tax = frappe.db.get_value(master_doctype, {"is_default": 1})

View File

@@ -194,7 +194,7 @@ def bom(doctype, txt, searchfield, start, page_len, filters):
and tabBOM.is_active=1
and tabBOM.%(key)s like "%(txt)s"
%(fcond)s %(mcond)s
limit %(start)s, %(page_len)s """ % {'key': searchfield, 'txt': "%%%s%%" % txt,
limit %(start)s, %(page_len)s """ % {'key': searchfield, 'txt': "%%%s%%" % frappe.db.escape(txt),
'fcond': get_filters_cond(doctype, filters, conditions),
'mcond':get_match_cond(doctype), 'start': start, 'page_len': page_len})
@@ -207,7 +207,7 @@ def get_project_name(doctype, txt, searchfield, start, page_len, filters):
where `tabProject`.status not in ("Completed", "Cancelled")
and %(cond)s `tabProject`.name like "%(txt)s" %(mcond)s
order by `tabProject`.name asc
limit %(start)s, %(page_len)s """ % {'cond': cond,'txt': "%%%s%%" % txt,
limit %(start)s, %(page_len)s """ % {'cond': cond,'txt': "%%%s%%" % frappe.db.escape(txt),
'mcond':get_match_cond(doctype),'start': start, 'page_len': page_len})
def get_delivery_notes_to_be_billed(doctype, txt, searchfield, start, page_len, filters):

View File

@@ -33,11 +33,13 @@ def manage_recurring_documents(doctype, next_date=None, commit=True):
next_date = next_date or nowdate()
date_field = date_field_map[doctype]
condition = " and ifnull(status, '') != 'Stopped'" if doctype in ("Sales Order", "Purchase Order") else ""
recurring_documents = frappe.db.sql("""select name, recurring_id
from `tab{}` where ifnull(is_recurring, 0)=1
and docstatus=1 and next_date='{}'
and next_date <= ifnull(end_date, '2199-12-31')""".format(doctype, next_date))
from `tab{0}` where ifnull(is_recurring, 0)=1
and docstatus=1 and next_date=%s
and next_date <= ifnull(end_date, '2199-12-31') {1}""".format(doctype, condition), next_date)
exception_list = []
for ref_document, recurring_id in recurring_documents:
@@ -124,7 +126,7 @@ def send_notification(new_rv):
frappe.sendmail(new_rv.notification_email_address,
subject= _("New {0}: #{1}").format(new_rv.doctype, new_rv.name),
message = _("Please find attached {0} #{1}").format(new_rv.doctype, new_rv.name),
attachments = [frappe.attach_print(new_rv.doctype, new_rv.name, file_name=new_rv.name)])
attachments = [frappe.attach_print(new_rv.doctype, new_rv.name, file_name=new_rv.name, print_format=new_rv.recurring_print_format)])
def notify_errors(doc, doctype, party, owner):
from frappe.utils.user import get_system_managers

View File

@@ -78,7 +78,7 @@ class StatusUpdater(Document):
self.status = s[0]
break
if self.status != _status:
if self.status != _status and self.status not in ("Submitted", "Cancelled"):
self.add_comment("Label", _(self.status))
if update:

View File

@@ -75,8 +75,7 @@ class Lead(SellingController):
return frappe.db.get_value("Customer", {"lead_name": self.name})
def has_opportunity(self):
return frappe.db.get_value("Opportunity", {"lead": self.name, "docstatus": 1,
"status": ["!=", "Lost"]})
return frappe.db.get_value("Opportunity", {"lead": self.name, "status": ["!=", "Lost"]})
@frappe.whitelist()
def make_customer(source_name, target_doc=None):

View File

@@ -85,7 +85,7 @@
{
"fieldname": "description",
"fieldtype": "Text",
"in_list_view": 1,
"in_list_view": 0,
"label": "Description",
"oldfieldname": "description",
"oldfieldtype": "Text",
@@ -134,7 +134,7 @@
],
"idx": 1,
"istable": 1,
"modified": "2015-05-14 14:55:18.325286",
"modified": "2015-06-02 14:18:16.622288",
"modified_by": "Administrator",
"module": "CRM",
"name": "Opportunity Item",

View File

@@ -5,7 +5,7 @@ app_publisher = "Frappe Technologies Pvt. Ltd. and Contributors"
app_description = "Open Source Enterprise Resource Planning for Small and Midsized Organizations"
app_icon = "icon-th"
app_color = "#e74c3c"
app_version = "5.0.14"
app_version = "5.1.0"
error_report_email = "support@erpnext.com"
@@ -38,16 +38,14 @@ website_route_rules = [
{"from_route": "/invoices", "to_route": "Sales Invoice"},
{"from_route": "/invoices/<path:name>", "to_route": "print", "defaults": {"doctype": "Sales Invoice"}},
{"from_route": "/shipments", "to_route": "Delivery Note"},
{"from_route": "/shipments/<path:name>", "to_route": "print", "defaults": {"doctype": "Delivery Note"}},
{"from_route": "/issues", "to_route": "Issue"},
{"from_route": "/issues/<path:name>", "to_route": "print", "defaults": {"doctype": "Issue"}},
{"from_route": "/addresses", "to_route": "Address"},
{"from_route": "/shipments/<path:name>", "to_route": "print", "defaults": {"doctype": "Delivery Note"}}
]
has_website_permission = {
"Sales Order": "erpnext.controllers.website_list_for_contact.has_website_permission",
"Sales Invoice": "erpnext.controllers.website_list_for_contact.has_website_permission",
"Delivery Note": "erpnext.controllers.website_list_for_contact.has_website_permission"
"Delivery Note": "erpnext.controllers.website_list_for_contact.has_website_permission",
"Issue": "erpnext.support.doctype.issue.issue.has_website_permission"
}
dump_report_map = "erpnext.startup.report_data_map.data_map"
@@ -80,8 +78,10 @@ doc_events = {
}
scheduler_events = {
"hourly": [
"erpnext.controllers.recurring_document.create_recurring_documents"
],
"daily": [
"erpnext.controllers.recurring_document.create_recurring_documents",
"erpnext.stock.reorder_item.reorder_item",
"erpnext.setup.doctype.email_digest.email_digest.send",
"erpnext.support.doctype.issue.issue.auto_close_tickets",

View File

@@ -63,7 +63,7 @@ cur_frm.cscript.onload = function(doc,cdt,cdn) {
cur_frm.set_query("exp_approver", function() {
return {
filters: [["UserRole", "role", "=", "Expense Approver"]]
query: "erpnext.hr.doctype.expense_claim.expense_claim.get_expense_approver"
};
});
}

View File

@@ -58,4 +58,13 @@ class ExpenseClaim(Document):
def validate_sanctioned_amount(self):
for d in self.get('expenses'):
if flt(d.sanctioned_amount) > flt(d.claim_amount):
frappe.throw(_("Sanctioned Amount cannot be greater than Claim Amount in Row {0}.").format(d.idx))
frappe.throw(_("Sanctioned Amount cannot be greater than Claim Amount in Row {0}.").format(d.idx))
@frappe.whitelist()
def get_expense_approver(doctype, txt, searchfield, start, page_len, filters):
return frappe.db.sql("""
select u.name, concat(u.first_name, ' ', u.last_name)
from tabUser u, tabUserRole r
where u.name = r.parent and r.role = 'Expense Approver' and u.name like %s
""", ("%" + txt + "%"))

View File

@@ -339,6 +339,7 @@ def add_block_dates(events, start, end, employee, company):
events.append({
"doctype": "Leave Block List Date",
"from_date": block_date.block_date,
"to_date": block_date.block_date,
"title": _("Leave Blocked") + ": " + block_date.reason,
"name": "_" + str(cnt),
})
@@ -355,6 +356,7 @@ def add_holidays(events, start, end, employee, company):
events.append({
"doctype": "Holiday",
"from_date": holiday.holiday_date,
"to_date": holiday.holiday_date,
"title": _("Holiday") + ": " + cstr(holiday.description),
"name": holiday.name
})

View File

@@ -24,4 +24,8 @@ cur_frm.cscript.to_date = function(doc, cdt, cdn) {
cur_frm.cscript.allocation_type = function (doc, cdt, cdn){
doc.no_of_days = '';
refresh_field('no_of_days');
}
}
frappe.ui.form.on("Leave Control Panel", "refresh", function(frm) {
frm.disable_save();
});

View File

@@ -94,11 +94,11 @@
}
],
"hide_heading": 0,
"hide_toolbar": 0,
"hide_toolbar": 1,
"icon": "icon-cog",
"idx": 1,
"issingle": 1,
"modified": "2015-02-05 05:11:40.791976",
"modified": "2015-06-05 11:38:19.994852",
"modified_by": "Administrator",
"module": "HR",
"name": "Leave Control Panel",
@@ -110,7 +110,7 @@
"read": 1,
"report": 0,
"role": "HR User",
"share": 1,
"share": 0,
"submit": 0,
"write": 1
}

View File

@@ -43,3 +43,8 @@ cur_frm.cscript.make_jv = function(doc, dt, dn) {
frappe.set_route("Form", doc.doctype, doc.name);
});
}
frappe.ui.form.on("Salary Manager", "refresh", function(frm) {
frm.disable_save();
});

View File

@@ -150,10 +150,11 @@
"permlevel": 0
}
],
"hide_toolbar": 1,
"icon": "icon-cog",
"idx": 1,
"issingle": 1,
"modified": "2015-02-25 07:21:04.778082",
"modified": "2015-06-05 11:33:00.152362",
"modified_by": "Administrator",
"module": "HR",
"name": "Salary Manager",

View File

@@ -4,7 +4,7 @@
from __future__ import unicode_literals
import frappe
from frappe.utils import cstr, flt
from frappe.utils import cstr, flt, getdate
from frappe.model.naming import make_autoname
from frappe import _
from frappe.model.mapper import get_mapped_doc
@@ -14,6 +14,13 @@ from erpnext.hr.utils import set_employee_name
class SalaryStructure(Document):
def autoname(self):
self.name = make_autoname(self.employee + '/.SST' + '/.#####')
def validate(self):
self.check_existing()
self.validate_amount()
self.validate_employee()
self.validate_joining_date()
set_employee_name(self)
def get_employee_details(self):
ret = {}
@@ -77,14 +84,11 @@ class SalaryStructure(Document):
old_employee = frappe.db.get_value("Salary Structure", self.name, "employee")
if old_employee and self.employee != old_employee:
frappe.throw(_("Employee can not be changed"))
def validate(self):
self.check_existing()
self.validate_amount()
self.validate_employee()
set_employee_name(self)
def validate_joining_date(self):
joining_date = getdate(frappe.db.get_value("Employee", self.employee, "date_of_joining"))
if getdate(self.from_date) < joining_date:
frappe.throw(_("From Date in Salary Structure cannot be lesser than Employee Joining Date."))
@frappe.whitelist()
def make_salary_slip(source_name, target_doc=None):

View File

@@ -12,6 +12,7 @@ erpnext.hr.AttendanceControlPanel = frappe.ui.form.Controller.extend({
},
refresh: function() {
this.frm.disable_save();
this.show_upload();
},

View File

@@ -1,4 +1,5 @@
{
"allow_copy": 1,
"creation": "2013-01-25 11:34:53",
"docstatus": 0,
"doctype": "DocType",
@@ -53,11 +54,13 @@
"permlevel": 0
}
],
"hide_heading": 0,
"hide_toolbar": 1,
"icon": "icon-upload-alt",
"idx": 1,
"issingle": 1,
"max_attachments": 1,
"modified": "2015-02-05 05:11:48.540845",
"modified": "2015-06-05 11:37:04.348120",
"modified_by": "Administrator",
"module": "HR",
"name": "Upload Attendance",
@@ -65,25 +68,25 @@
"permissions": [
{
"create": 1,
"email": 1,
"email": 0,
"permlevel": 0,
"print": 1,
"print": 0,
"read": 1,
"report": 0,
"role": "HR User",
"share": 1,
"share": 0,
"submit": 0,
"write": 1
},
{
"create": 1,
"email": 1,
"email": 0,
"permlevel": 0,
"print": 1,
"print": 0,
"read": 1,
"report": 0,
"role": "HR Manager",
"share": 1,
"share": 0,
"submit": 0,
"write": 1
}

View File

@@ -61,7 +61,7 @@ var get_bom_material_detail= function(doc, cdt, cdn) {
var d = locals[cdt][cdn];
if (d.item_code) {
return frappe.call({
doc: cur_frm.doc,
doc: doc,
method: "get_bom_material_detail",
args: {
'item_code': d.item_code,
@@ -234,5 +234,3 @@ frappe.ui.form.on("BOM", "with_operations", function(frm) {
cur_frm.cscript.image = function() {
refresh_field("image_view");
}

View File

@@ -12,7 +12,7 @@
"fieldname": "item",
"fieldtype": "Link",
"in_filter": 1,
"in_list_view": 0,
"in_list_view": 1,
"label": "Item",
"oldfieldname": "item",
"oldfieldtype": "Link",
@@ -54,7 +54,7 @@
"fieldname": "is_active",
"fieldtype": "Check",
"hidden": 0,
"in_list_view": 0,
"in_list_view": 1,
"label": "Is Active",
"no_copy": 1,
"oldfieldname": "is_active",
@@ -67,7 +67,7 @@
"default": "1",
"fieldname": "is_default",
"fieldtype": "Check",
"in_list_view": 0,
"in_list_view": 1,
"label": "Is Default",
"no_copy": 1,
"oldfieldname": "is_default",
@@ -279,7 +279,7 @@
"is_submittable": 1,
"issingle": 0,
"istable": 0,
"modified": "2015-03-03 14:22:44.725097",
"modified": "2015-06-26 02:02:30.705279",
"modified_by": "Administrator",
"module": "Manufacturing",
"name": "BOM",

View File

@@ -425,5 +425,5 @@ def validate_bom_no(item, bom_no):
if not getattr(frappe.flags, "in_test", False):
frappe.throw(_("BOM {0} must be submitted").format(bom_no))
if item and not (bom.item.lower() == item.lower() or \
bom.item.lower() == frappe.db.get_value("Item", item, "variant_of").lower()):
bom.item.lower() == cstr(frappe.db.get_value("Item", item, "variant_of")).lower()):
frappe.throw(_("BOM {0} does not belong to Item {1}").format(bom_no, item))

View File

@@ -55,6 +55,13 @@
"label": "Time Between Operations (in mins)",
"permlevel": 0,
"precision": ""
},
{
"fieldname": "over_production_allowance_percentage",
"fieldtype": "Percent",
"label": "Over Production Allowance Percentage",
"permlevel": 0,
"precision": ""
}
],
"hide_heading": 0,
@@ -65,7 +72,7 @@
"is_submittable": 0,
"issingle": 1,
"istable": 0,
"modified": "2015-04-21 07:57:40.260862",
"modified": "2015-06-15 05:52:22.986958",
"modified_by": "Administrator",
"module": "Manufacturing",
"name": "Manufacturing Settings",

View File

@@ -90,8 +90,9 @@ class ProductionOrder(Document):
(self.sales_order, self.production_item))[0][0]
# total qty in SO
so_qty = flt(so_item_qty) + flt(dnpi_qty)
if total_qty > so_qty:
allowance_percentage = flt(frappe.db.get_single_value("Manufacturing Settings", "over_production_allowance_percentage"))
if total_qty > so_qty + (allowance_percentage/100 * so_qty):
frappe.throw(_("Cannot produce more Item {0} than Sales Order quantity {1}").format(self.production_item,
so_qty), OverProductionError)
@@ -217,12 +218,14 @@ class ProductionOrder(Document):
for i, d in enumerate(self.operations):
self.set_operation_start_end_time(i, d)
if not d.workstation:
continue
time_log = make_time_log(self.name, d.operation, d.planned_start_time, d.planned_end_time,
flt(self.qty) - flt(d.completed_qty), self.project_name, d.workstation, operation_id=d.name)
if d.workstation:
# validate operating hours if workstation [not mandatory] is specified
self.check_operation_fits_in_working_hours(d)
# validate operating hours if workstation [not mandatory] is specified
self.check_operation_fits_in_working_hours(d)
original_start_time = time_log.from_time
while True:
@@ -309,10 +312,9 @@ class ProductionOrder(Document):
self.actual_end_date = None
def validate_delivery_date(self):
if self.docstatus==1:
if self.planned_end_date and self.expected_delivery_date \
and getdate(self.expected_delivery_date) < getdate(self.planned_end_date):
frappe.msgprint(_("Production might not be able to finish by the Expected Delivery Date."))
if self.planned_start_date and self.expected_delivery_date \
and getdate(self.expected_delivery_date) < getdate(self.planned_start_date):
frappe.throw(_("Expected Delivery Date must be greater than Planned Start Date."))
def delete_time_logs(self):
for time_log in frappe.get_all("Time Log", ["name"], {"production_order": self.name}):

View File

@@ -1,4 +1,5 @@
{
"allow_copy": 1,
"creation": "2013-01-21 12:03:47",
"default_print_format": "Standard",
"docstatus": 0,
@@ -154,11 +155,12 @@
"permlevel": 0
}
],
"hide_toolbar": 1,
"icon": "icon-calendar",
"idx": 1,
"in_create": 1,
"issingle": 1,
"modified": "2015-02-05 05:11:43.010625",
"modified": "2015-06-05 11:44:31.629114",
"modified_by": "Administrator",
"module": "Manufacturing",
"name": "Production Planning Tool",

View File

@@ -161,3 +161,13 @@ erpnext.patches.v5_0.set_footer_address
execute:frappe.db.set_value("Backup Manager", None, "send_backups_to_dropbox", 1 if frappe.db.get_value("Backup Manager", None, "upload_backups_to_dropbox") in ("Daily", "Weekly") else 0)
execute:frappe.db.sql_list("delete from `tabDocPerm` where parent='Issue' and modified_by='Administrator' and role='Guest'")
erpnext.patches.v5_0.update_item_and_description_again
erpnext.patches.v5_0.repost_gle_for_jv_with_multiple_party
erpnext.patches.v5_0.portal_fixes
erpnext.patches.v5_0.reset_values_in_tools
execute:frappe.delete_doc("Page", "users")
erpnext.patches.v5_0.update_material_transferred_for_manufacturing_again
erpnext.patches.v5_0.index_on_account_and_gl_entry
execute:frappe.db.sql("""delete from `tabProject Task`""")
erpnext.patches.v5_0.item_variants
erpnext.patches.v5_0.update_item_desc_in_invoice
erpnext.patches.v5_1.fix_against_account

View File

@@ -30,8 +30,8 @@ def create_receivable_payable_account():
account_id = account.name
frappe.db.set_value("Company", args["company"], ("default_receivable_account"
if args["account_type"]=="Receivable" else "default_payable_account"), account_id)
frappe.db.set_value("Company", args["company"], ("default_receivable_account"
if args["account_type"]=="Receivable" else "default_payable_account"), account_id)
receivable_payable_accounts.setdefault(args["company"], {}).setdefault(args["account_type"], account_id)

View File

@@ -0,0 +1,30 @@
from __future__ import unicode_literals
import frappe
def execute():
index_map = {
"Account": ["parent_account", "lft", "rgt"],
"GL Entry": ["posting_date", "account", 'party', "voucher_no"],
"Sales Invoice": ["posting_date", "debit_to", "customer"],
"Purchase Invoice": ["posting_date", "credit_to", "supplier"]
}
for dt, indexes in index_map.items():
existing_indexes = [(d.Key_name, d.Column_name) for d in frappe.db.sql("""show index from `tab{0}`
where Column_name != 'name'""".format(dt), as_dict=1)]
for old, column in existing_indexes:
if column in ("parent", "group_or_ledger", "is_group", "is_pl_account", "debit_or_credit",
"account_name", "company", "project_name", "voucher_date", "due_date", "bill_no",
"bill_date", "is_opening", "fiscal_year", "outstanding_amount"):
frappe.db.sql("alter table `tab{0}` drop index {1}".format(dt, old))
existing_indexes = [(d.Key_name, d.Column_name) for d in frappe.db.sql("""show index from `tab{0}`
where Column_name != 'name'""".format(dt), as_dict=1)]
existing_indexed_columns = list(set([x[1] for x in existing_indexes]))
for new in indexes:
if new not in existing_indexed_columns:
frappe.db.sql("alter table `tab{0}` add index ({1})".format(dt, new))

View File

@@ -0,0 +1,16 @@
import frappe
def execute():
frappe.reload_doctype("Item")
for dt in ["manage_variants", "manage_variants_item", "variant_attribute"]:
frappe.reload_doc("stock", "doctype", dt)
for d in frappe.get_list("Item", filters={"has_variants":1}):
manage_variant = frappe.new_doc("Manage Variants")
manage_variant.item_code = d.name
manage_variant.attributes = frappe.db.sql("select item_attribute as attribute, item_attribute_value as attribute_value \
from `tabItem Variant` where parent = %s", d.name, as_dict=1)
if manage_variant.attributes:
manage_variant.generate_combinations()
manage_variant.create_variants()
frappe.delete_doc("DocType", "Item Variant")

View File

@@ -0,0 +1,6 @@
import frappe
import erpnext.setup.install
def execute():
frappe.reload_doc("website", "doctype", "web_form_field", force=True)
erpnext.setup.install.add_web_forms()

View File

@@ -0,0 +1,26 @@
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe
def execute():
je_list = frappe.db.sql_list("""
select par.name from `tabJournal Entry` par
where par.docstatus=1 and par.creation > '2015-03-01'
and (select count(distinct child.party) from `tabJournal Entry Account` child
where par.name=child.parent and ifnull(child.party, '') != '') > 1
""")
for d in je_list:
# delete existing gle
frappe.db.sql("delete from `tabGL Entry` where voucher_type='Journal Entry' and voucher_no=%s", d)
# repost gl entries
je = frappe.get_doc("Journal Entry", d)
je.make_gl_entries()
if je_list:
print je_list

View File

@@ -0,0 +1,11 @@
# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe
def execute():
for dt in ["Payment Tool", "Bank Reconciliation", "Payment Reconciliation", "Leave Control Panel",
"Salary Manager", "Upload Attenadance", "Production Planning Tool", "BOM Replace Tool"]:
frappe.db.sql("delete from `tabSingles` where doctype=%s", dt)

View File

@@ -7,6 +7,6 @@ def execute():
account_settings = frappe.get_doc("Accounts Settings")
if not account_settings.frozen_accounts_modifier and account_settings.bde_auth_role:
frappe.db.set_value("Account Settings", None,
frappe.db.set_value("Accounts Settings", None,
"frozen_accounts_modifier", account_settings.bde_auth_role)

View File

@@ -0,0 +1,50 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
import frappe
from frappe.website.utils import find_first_image
from frappe.utils import cstr
import re
def execute():
item_details = frappe._dict()
for d in frappe.db.sql("select name, description, image from `tabItem`", as_dict=1):
description = cstr(d.description).strip()
item_details.setdefault(d.name, frappe._dict({
"description": description,
"image": d.image
}))
dt_list= ["Sales Invoice Item","Purchase Invoice Item"]
for dt in dt_list:
frappe.reload_doctype(dt)
records = frappe.db.sql("""select name, item_code, description from `tab{0}`
where description is not null """.format(dt), as_dict=1)
count = 1
for d in records:
if d.item_code and item_details.get(d.item_code) \
and cstr(d.description) == item_details.get(d.item_code).description:
desc = item_details.get(d.item_code).description
image = item_details.get(d.item_code).image
else:
desc, image = extract_image_and_description(cstr(d.description))
if not image:
image = item_details.get(d.item_code).image
frappe.db.sql("""update `tab{0}` set description = %s, image = %s
where name = %s """.format(dt), (desc, image, d.name))
count += 1
if count % 500 == 0:
frappe.db.commit()
def extract_image_and_description(data):
image_url = find_first_image(data)
desc = data
for tag in ("img", "table", "tr", "td"):
desc = re.sub("\</*{0}[^>]*\>".format(tag), "", desc)
return desc, image_url

View File

@@ -0,0 +1,18 @@
import frappe
def execute():
pro_order_qty_transferred = frappe._dict()
for se in frappe.db.sql("""select production_order, sum(fg_completed_qty) as transferred_qty
from `tabStock Entry`
where docstatus=1 and ifnull(production_order, '') != ''
and purpose = 'Material Transfer for Manufacture'
group by production_order""", as_dict=1):
pro_order_qty_transferred.setdefault(se.production_order, se.transferred_qty)
for d in frappe.get_all("Production Order", filters={"docstatus": 1}, fields=["name", "qty"]):
if d.name in pro_order_qty_transferred:
material_transferred_for_manufacturing = pro_order_qty_transferred.get(d.name) \
if pro_order_qty_transferred.get(d.name) <= d.qty else d.qty
frappe.db.sql("""update `tabProduction Order` set material_transferred_for_manufacturing=%s
where name=%s""", (material_transferred_for_manufacturing, d.name))

View File

View File

@@ -0,0 +1,37 @@
from __future__ import unicode_literals
import frappe
from erpnext.accounts.doctype.gl_entry.gl_entry import update_against_account
def execute():
from_date = "2015-05-01"
for doc in frappe.get_all("Journal Entry",
filters={"creation": (">", from_date), "docstatus": "1"}):
# update in gl_entry
update_against_account("Journal Entry", doc.name)
# update in jv
doc = frappe.get_doc("Journal Entry", doc.name)
doc.set_against_account()
doc.db_update()
for doc in frappe.get_all("Sales Invoice",
filters={"creation": (">", from_date), "docstatus": "1"},
fields=["name", "customer"]):
frappe.db.sql("""update `tabGL Entry` set against=%s
where voucher_type='Sales Invoice' and voucher_no=%s
and credit > 0 and ifnull(party, '')=''""",
(doc.customer, doc.name))
for doc in frappe.get_all("Purchase Invoice",
filters={"creation": (">", from_date), "docstatus": "1"},
fields=["name", "supplier"]):
frappe.db.sql("""update `tabGL Entry` set against=%s
where voucher_type='Purchase Invoice' and voucher_no=%s
and debit > 0 and ifnull(party, '')=''""",
(doc.supplier, doc.name))

View File

@@ -0,0 +1 @@
cur_frm.add_fetch('employee', 'employee_name', 'employee_name');

View File

@@ -2,47 +2,13 @@
"allow_copy": 0,
"allow_import": 1,
"allow_rename": 1,
"autoname": "Activity Cost - .#",
"autoname": "AC-.#####",
"creation": "2015-03-23 02:00:21.861546",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "Master",
"fields": [
{
"allow_on_submit": 0,
"fieldname": "employee",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Employee",
"no_copy": 0,
"options": "Employee",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0
},
{
"fieldname": "employee_name",
"fieldtype": "Read Only",
"label": "Employee Name",
"options": "employee.employee_name",
"permlevel": 0,
"precision": ""
},
{
"fieldname": "column_break_2",
"fieldtype": "Column Break",
"permlevel": 0,
"precision": ""
},
{
"allow_on_submit": 0,
"fieldname": "activity_type",
@@ -63,6 +29,41 @@
"search_index": 0,
"set_only_once": 0
},
{
"fieldname": "column_break_2",
"fieldtype": "Column Break",
"permlevel": 0,
"precision": ""
},
{
"allow_on_submit": 0,
"fieldname": "employee",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Employee",
"no_copy": 0,
"options": "Employee",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0
},
{
"fieldname": "employee_name",
"fieldtype": "Data",
"label": "Employee Name",
"options": "",
"permlevel": 0,
"precision": "",
"read_only": 1
},
{
"fieldname": "section_break_4",
"fieldtype": "Section Break",
@@ -135,7 +136,7 @@
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"modified": "2015-04-14 02:08:33.690406",
"modified": "2015-06-16 03:12:25.644839",
"modified_by": "Administrator",
"module": "Projects",
"name": "Activity Cost",

View File

@@ -15,10 +15,21 @@ class ActivityCost(Document):
self.check_unique()
def set_title(self):
self.title = _("{0} for {1}").format(self.employee_name, self.activity_type)
if self.employee:
if not self.employee_name:
self.employee_name = frappe.db.get_value("Employee", self.employee, "employee_name")
self.title = _("{0} for {1}").format(self.employee_name, self.activity_type)
else:
self.title = self.activity_type
def check_unique(self):
if frappe.db.sql("""select name from `tabActivity Cost` where employee_name= %s and activity_type= %s and name != %s""",
(self.employee_name, self.activity_type, self.name)):
frappe.throw(_("Activity Cost exists for Employee {0} against Activity Type - {1}")
.format(self.employee, self.activity_type), DuplicationError)
if self.employee:
if frappe.db.sql("""select name from `tabActivity Cost` where employee_name= %s and activity_type= %s and name != %s""",
(self.employee_name, self.activity_type, self.name)):
frappe.throw(_("Activity Cost exists for Employee {0} against Activity Type - {1}")
.format(self.employee, self.activity_type), DuplicationError)
else:
if frappe.db.sql("""select name from `tabActivity Cost` where ifnull(employee, '')='' and activity_type= %s and name != %s""",
(self.activity_type, self.name)):
frappe.throw(_("Default Activity Cost exists for Activity Type - {0}")
.format(self.activity_type), DuplicationError)

View File

@@ -163,6 +163,7 @@
"fieldtype": "Percent",
"in_list_view": 0,
"label": "% Tasks Completed",
"no_copy": 1,
"permlevel": 0,
"read_only": 1
},
@@ -356,7 +357,7 @@
"icon": "icon-puzzle-piece",
"idx": 1,
"max_attachments": 4,
"modified": "2015-04-27 07:37:44.239930",
"modified": "2015-06-12 09:00:54.080220",
"modified_by": "Administrator",
"module": "Projects",
"name": "Project",

View File

@@ -15,19 +15,27 @@ class Project(Document):
def onload(self):
"""Load project tasks for quick view"""
for task in frappe.get_all("Task", "*", {"project": self.name}, order_by="exp_start_date asc"):
self.append("tasks", {
"title": task.subject,
"status": task.status,
"start_date": task.exp_start_date,
"end_date": task.exp_end_date,
"description": task.description,
"task_id": task.name
})
if not self.get("tasks"):
for task in self.get_tasks():
self.append("tasks", {
"title": task.subject,
"status": task.status,
"start_date": task.exp_start_date,
"end_date": task.exp_end_date,
"description": task.description,
"task_id": task.name
})
def __setup__(self):
self.onload()
def get_tasks(self):
return frappe.get_all("Task", "*", {"project": self.name}, order_by="exp_start_date asc")
def validate(self):
self.validate_dates()
self.sync_tasks()
self.tasks = []
def validate_dates(self):
if self.expected_start_date and self.expected_end_date:
@@ -38,6 +46,8 @@ class Project(Document):
"""sync tasks and remove table"""
if self.flags.dont_sync_tasks: return
task_added_or_deleted = False
task_names = []
for t in self.tasks:
if t.task_id:
@@ -45,6 +55,7 @@ class Project(Document):
else:
task = frappe.new_doc("Task")
task.project = self.name
task_added_or_deleted = True
task.update({
"subject": t.title,
@@ -62,17 +73,22 @@ class Project(Document):
# delete
for t in frappe.get_all("Task", ["name"], {"project": self.name, "name": ("not in", task_names)}):
frappe.delete_doc("Task", t.name)
task_added_or_deleted = True
if task_added_or_deleted:
self.update_project()
self.tasks = []
def update_project(self):
self.update_percent_complete()
self.update_costing()
def update_percent_complete(self):
total = frappe.db.sql("""select count(*) from tabTask where project=%s""",
self.name)[0][0]
total = frappe.db.sql("""select count(*) from tabTask where project=%s""", self.name)[0][0]
if total:
completed = frappe.db.sql("""select count(*) from tabTask where
project=%s and status in ('Closed', 'Cancelled')""", self.name)[0][0]
frappe.db.set_value("Project", self.name, "percent_complete",
int(float(completed) / total * 100))
self.percent_complete = flt(completed) / total * 100
def update_costing(self):
total_cost = frappe.db.sql("""select sum(total_costing_amount) as costing_amount,

View File

@@ -5,3 +5,4 @@ from __future__ import unicode_literals
import frappe
test_records = frappe.get_test_records('Project')
test_ignore = ["Sales Order"]

View File

@@ -28,7 +28,11 @@ class Task(Document):
def validate(self):
self.validate_dates()
if self.status!=self.get_db_value("status") and self.status == "Closed":
from frappe.desk.form.assign_to import clear
clear(self.doctype, self.name)
def validate_dates(self):
if self.exp_start_date and self.exp_end_date and getdate(self.exp_start_date) > getdate(self.exp_end_date):
frappe.throw(_("'Expected Start Date' can not be greater than 'Expected End Date'"))
@@ -39,19 +43,12 @@ class Task(Document):
def on_update(self):
self.check_recursion()
self.reschedule_dependent_tasks()
self.update_percentage()
self.update_project()
def update_percentage(self):
"""update percent complete in project"""
if self.project and not self.flags.from_project:
project = frappe.get_doc("Project", self.project)
project.run_method("update_percent_complete")
def update_total_expense_claim(self):
self.total_expense_claim = frappe.db.sql("""select sum(total_sanctioned_amount) from `tabExpense Claim`
self.total_expense_claim = frappe.db.sql("""select sum(total_sanctioned_amount) from `tabExpense Claim`
where project = %s and task = %s and approval_status = "Approved" and docstatus=1""",(self.project, self.name))
def update_time_and_costing(self):
tl = frappe.db.sql("""select min(from_time) as start_date, max(to_time) as end_date,
sum(billing_amount) as total_billing_amount, sum(costing_amount) as total_costing_amount,
@@ -64,14 +61,14 @@ class Task(Document):
self.actual_time= tl.time
self.act_start_date= tl.start_date
self.act_end_date= tl.end_date
def update_project(self):
if self.project and frappe.db.exists("Project", self.project):
if self.project and not self.flags.from_project:
project = frappe.get_doc("Project", self.project)
project.flags.dont_sync_tasks = True
project.update_costing()
project.update_project()
project.save()
def check_recursion(self):
if self.flags.ignore_recursion_check: return
check_list = [['task', 'parent'], ['parent', 'task']]
@@ -88,7 +85,7 @@ class Task(Document):
task_list.append(b[0])
if count == 15:
break
def reschedule_dependent_tasks(self):
end_date = self.exp_end_date or self.act_end_date
if end_date:
@@ -137,7 +134,7 @@ def get_project(doctype, txt, searchfield, start, page_len, filters):
%(mcond)s
order by name
limit %(start)s, %(page_len)s """ % {'key': searchfield,
'txt': "%%%s%%" % txt, 'mcond':get_match_cond(doctype),
'txt': "%%%s%%" % frappe.db.escape(txt), 'mcond':get_match_cond(doctype),
'start': start, 'page_len': page_len})

View File

@@ -11,19 +11,19 @@ from erpnext.projects.doctype.task.task import CircularReferenceError
class TestTask(unittest.TestCase):
def test_circular_reference(self):
task1 = frappe.new_doc('Task')
task1.update({
"status": "Open",
"status": "Open",
"subject": "_Test Task 1",
"exp_start_date": "2015-1-1",
"exp_end_date": "2015-1-10"
})
task1.save()
task2 = frappe.new_doc('Task')
task2.update({
"status": "Open",
"status": "Open",
"subject": "_Test Task 2",
"exp_start_date": "2015-1-11",
"exp_end_date": "2015-1-15",
@@ -34,10 +34,10 @@ class TestTask(unittest.TestCase):
]
})
task2.save()
task3 = frappe.new_doc('Task')
task3.update({
"status": "Open",
"status": "Open",
"subject": "_Test Task 2",
"exp_start_date": "2015-1-11",
"exp_end_date": "2015-1-15",
@@ -53,13 +53,13 @@ class TestTask(unittest.TestCase):
"task": task3.name
})
self.assertRaises(CircularReferenceError, task1.save)
task1.set("depends_on", [])
task1.save()
task4 = frappe.new_doc('Task')
task4.update({
"status": "Open",
"status": "Open",
"subject": "_Test Task 1",
"exp_start_date": "2015-1-1",
"exp_end_date": "2015-1-15",
@@ -74,20 +74,20 @@ class TestTask(unittest.TestCase):
task3.append("depends_on", {
"task": task4.name
})
def test_reschedule_dependent_task(self):
task1 = frappe.new_doc('Task')
task1.update({
"status": "Open",
"status": "Open",
"subject": "_Test Task 1",
"exp_start_date": "2015-1-1",
"exp_end_date": "2015-1-10"
})
task1.save()
task2 = frappe.new_doc('Task')
task2.update({
"status": "Open",
"status": "Open",
"subject": "_Test Task 2",
"exp_start_date": "2015-1-11",
"exp_end_date": "2015-1-15",
@@ -98,10 +98,10 @@ class TestTask(unittest.TestCase):
]
})
task2.save()
task3 = frappe.new_doc('Task')
task3.update({
"status": "Open",
"status": "Open",
"subject": "_Test Task 3",
"exp_start_date": "2015-1-16",
"exp_end_date": "2015-1-18",
@@ -112,18 +112,18 @@ class TestTask(unittest.TestCase):
]
})
task3.save()
task1.update({
"exp_end_date": "2015-1-20"
})
task1.save()
self.assertEqual(frappe.db.get_value("Task", task2.name, "exp_start_date"), getdate('2015-1-21'))
self.assertEqual(frappe.db.get_value("Task", task2.name, "exp_end_date"), getdate('2015-1-25'))
self.assertEqual(frappe.db.get_value("Task", task3.name, "exp_start_date"), getdate('2015-1-26'))
self.assertEqual(frappe.db.get_value("Task", task3.name, "exp_end_date"), getdate('2015-1-28'))
time_log = frappe.new_doc('Time Log')
time_log.update({
"from_time": "2015-1-1",
@@ -131,18 +131,49 @@ class TestTask(unittest.TestCase):
"task": task1.name
})
time_log.submit()
self.assertEqual(frappe.db.get_value("Task", task2.name, "exp_start_date"), getdate('2015-1-21'))
self.assertEqual(frappe.db.get_value("Task", task2.name, "exp_end_date"), getdate('2015-1-25'))
self.assertEqual(frappe.db.get_value("Task", task3.name, "exp_start_date"), getdate('2015-1-26'))
self.assertEqual(frappe.db.get_value("Task", task3.name, "exp_end_date"), getdate('2015-1-28'))
time_log.cancel()
self.assertEqual(frappe.db.get_value("Task", task2.name, "exp_start_date"), getdate('2015-1-21'))
self.assertEqual(frappe.db.get_value("Task", task2.name, "exp_end_date"), getdate('2015-1-25'))
self.assertEqual(frappe.db.get_value("Task", task3.name, "exp_start_date"), getdate('2015-1-26'))
self.assertEqual(frappe.db.get_value("Task", task3.name, "exp_end_date"), getdate('2015-1-28'))
def test_close_assignment(self):
task = frappe.new_doc("Task")
task.subject = "Test Close Assignment"
task.insert()
def assign():
from frappe.desk.form import assign_to
assign_to.add({
"assign_to": "test@example.com",
"doctype": task.doctype,
"name": task.name,
"description": "Close this task"
})
def get_owner_and_status():
return frappe.db.get_value("ToDo", filters={"reference_type": task.doctype, "reference_name": task.name,
"description": "Close this task"}, fieldname=("owner", "status"), as_dict=True)
assign()
todo = get_owner_and_status()
self.assertEquals(todo.owner, "test@example.com")
self.assertEquals(todo.status, "Open")
# assignment should be
task.load_from_db()
task.status = "Closed"
task.save()
todo = get_owner_and_status()
self.assertEquals(todo.owner, "test@example.com")
self.assertEquals(todo.status, "Closed")

View File

@@ -128,7 +128,7 @@ class TimeLog(Document):
def update_production_order(self):
"""Updates `start_date`, `end_date`, `status` for operation in Production Order."""
if self.production_order and self.for_manufacturing:
if not self.operation_id:
frappe.throw(_("Operation ID not set"))
@@ -195,8 +195,6 @@ class TimeLog(Document):
if self.for_manufacturing:
if not self.production_order:
frappe.throw(_("Production Order is Mandatory"))
if not self.operation:
frappe.throw(_("Operation is Mandatory"))
if not self.completed_qty:
self.completed_qty = 0
@@ -210,22 +208,23 @@ class TimeLog(Document):
self.production_order = None
self.operation = None
self.quantity = None
def update_cost(self):
rate = get_activity_cost(self.employee, self.activity_type)
if rate:
self.costing_rate = rate.get('costing_rate')
self.billing_rate = rate.get('billing_rate')
self.billing_rate = rate.get('billing_rate')
self.costing_amount = self.costing_rate * self.hours
if self.billable:
self.billing_amount = self.billing_rate * self.hours
else:
self.billing_amount = 0
def validate_task(self):
if self.project and not self.task:
# if a time log is being created against a project without production order
if (self.project and not self.production_order) and not self.task:
frappe.throw(_("Task is Mandatory if Time Log is against a project"))
def update_task(self):
if self.task and frappe.db.exists("Task", self.task):
task = frappe.get_doc("Task", self.task)
@@ -268,9 +267,12 @@ def get_events(start, end, filters=None):
d.title += " for Project: " + d.project
return data
@frappe.whitelist()
def get_activity_cost(employee=None, activity_type=None):
rate = frappe.db.sql("""select costing_rate, billing_rate from `tabActivity Cost` where employee= %s
and activity_type= %s""", (employee, activity_type), as_dict=1)
if not rate:
rate = frappe.db.sql("""select costing_rate, billing_rate from `tabActivity Cost` where ifnull(employee, '')=''
and activity_type= %s""", (activity_type), as_dict=1)
return rate[0] if rate else {}

View File

@@ -37,6 +37,16 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
if(this.frm.fields_dict["items"]) {
this["items_remove"] = this.calculate_taxes_and_totals;
}
if(this.frm.fields_dict["recurring_print_format"]) {
this.frm.set_query("recurring_print_format", function(doc) {
return{
filters: [
['Print Format', 'doc_type', '=', cur_frm.doctype],
]
}
});
}
},
onload_post_render: function() {
@@ -105,6 +115,15 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
}
},
barcode: function(doc, cdt, cdn) {
var d = locals[cdt][cdn];
if(d.barcode=="" || d.barcode==null) {
// barcode cleared, remove item
d.item_code = "";
}
this.item_code(doc, cdt, cdn);
},
item_code: function(doc, cdt, cdn) {
var me = this;
var item = frappe.get_doc(cdt, cdn);
@@ -773,3 +792,5 @@ frappe.ui.form.on(cur_frm.doctype, "discount_amount", function(frm) {
cur_frm.cscript.set_dynamic_labels();
cur_frm.cscript.calculate_taxes_and_totals();
})

View File

@@ -81,7 +81,8 @@ erpnext.feature_setup.feature_dict = {
'Item': {'fields': ['barcode']},
'Delivery Note': {'items': ['barcode']},
'Sales Invoice': {'items': ['barcode']},
'Stock Entry': {'items': ['barcode']}
'Stock Entry': {'items': ['barcode']},
'Purchase Receipt': {'items': ['barcode']}
},
'fs_item_group_in_details': {
'Delivery Note': {'items':['item_group']},

View File

@@ -139,7 +139,7 @@ erpnext.StockAnalytics = erpnext.StockGridReport.extend({
if(sl.voucher_type=="Stock Reconciliation") {
var diff = (sl.qty_after_transaction * sl.valuation_rate) - item.closing_qty_value;
wh.fifo_stack.push([sl.qty_after_transaction, sl.valuation_rate, sl.posting_date]);
wh.fifo_stack = [[sl.qty_after_transaction, sl.valuation_rate, sl.posting_date]];
wh.balance_qty = sl.qty_after_transaction;
wh.balance_value = sl.valuation_rate * sl.qty_after_transaction;
} else {
@@ -167,7 +167,6 @@ erpnext.StockAnalytics = erpnext.StockGridReport.extend({
},
update_groups: function() {
var me = this;
$.each(this.data, function(i, item) {
// update groups
if(!item.is_group && me.apply_filter(item, "brand")) {

View File

@@ -488,7 +488,7 @@
{
"fieldname": "base_discount_amount",
"fieldtype": "Currency",
"label": "Discount Amount (Company Currency)",
"label": "Additional Discount Amount (Company Currency)",
"options": "Company:company:default_currency",
"permlevel": 0,
"precision": "",
@@ -858,7 +858,7 @@
"idx": 1,
"is_submittable": 1,
"max_attachments": 1,
"modified": "2015-05-27 02:48:00.388847",
"modified": "2015-06-15 15:37:39.199814",
"modified_by": "Administrator",
"module": "Selling",
"name": "Quotation",

View File

@@ -55,7 +55,7 @@
{
"fieldname": "description",
"fieldtype": "Small Text",
"in_list_view": 1,
"in_list_view": 0,
"label": "Description",
"oldfieldname": "description",
"oldfieldtype": "Small Text",
@@ -298,12 +298,13 @@
},
{
"fieldname": "prevdoc_doctype",
"fieldtype": "Data",
"fieldtype": "Link",
"hidden": 1,
"label": "Against Doctype",
"no_copy": 1,
"oldfieldname": "prevdoc_doctype",
"oldfieldtype": "Data",
"options": "DocType",
"permlevel": 0,
"print_hide": 1,
"print_width": "150px",
@@ -313,11 +314,12 @@
},
{
"fieldname": "prevdoc_docname",
"fieldtype": "Data",
"fieldtype": "Dynamic Link",
"label": "Against Docname",
"no_copy": 1,
"oldfieldname": "prevdoc_docname",
"oldfieldtype": "Data",
"options": "prevdoc_doctype",
"permlevel": 0,
"print_hide": 1,
"print_width": "150px",
@@ -390,7 +392,7 @@
],
"idx": 1,
"istable": 1,
"modified": "2015-05-27 02:47:15.474119",
"modified": "2015-06-02 14:18:00.266748",
"modified_by": "Administrator",
"module": "Selling",
"name": "Quotation Item",

View File

@@ -183,5 +183,3 @@ cur_frm.cscript.on_submit = function(doc, cdt, cdn) {
cur_frm.email_doc(frappe.boot.notification_settings.sales_order_message);
}
};
;

View File

@@ -493,7 +493,7 @@
{
"fieldname": "base_discount_amount",
"fieldtype": "Currency",
"label": "Discount Amount (Company Currency)",
"label": "Additional Discount Amount (Company Currency)",
"options": "Company:company:default_currency",
"permlevel": 0,
"precision": "",
@@ -1074,13 +1074,22 @@
"no_copy": 1,
"permlevel": 0,
"print_hide": 1
},
{
"depends_on": "eval:doc.is_recurring==1",
"fieldname": "recurring_print_format",
"fieldtype": "Link",
"label": "Recurring Print Format",
"options": "Print Format",
"permlevel": 0,
"precision": ""
}
],
"icon": "icon-file-text",
"idx": 1,
"is_submittable": 1,
"issingle": 0,
"modified": "2015-05-27 02:48:01.160307",
"modified": "2015-06-22 07:29:24.379272",
"modified_by": "Administrator",
"module": "Selling",
"name": "Sales Order",

View File

@@ -58,7 +58,7 @@
"fieldname": "description",
"fieldtype": "Small Text",
"in_filter": 1,
"in_list_view": 1,
"in_list_view": 0,
"label": "Description",
"oldfieldname": "description",
"oldfieldtype": "Small Text",
@@ -498,7 +498,7 @@
],
"idx": 1,
"istable": 1,
"modified": "2015-05-27 02:47:15.134435",
"modified": "2015-07-02 05:37:29.289574",
"modified_by": "Administrator",
"module": "Selling",
"name": "Sales Order Item",

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