From 13ec41abb27ce77e66c9c5d938de9d48ea1b3e44 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Thu, 10 Dec 2015 12:31:36 +0530 Subject: [PATCH] [enhancement] task status will be set to overdue when it crosses expected end date --- .../current/task_notification_change.md | 2 + erpnext/hooks.py | 3 +- erpnext/patches.txt | 1 + erpnext/patches/v6_12/__init__.py | 0 erpnext/patches/v6_12/set_overdue_tasks.py | 7 + erpnext/projects/doctype/task/task.js | 7 + erpnext/projects/doctype/task/task.json | 230 ++++++++++-------- erpnext/projects/doctype/task/task.py | 6 + erpnext/projects/doctype/task/task_list.js | 15 +- erpnext/projects/doctype/task/test_task.py | 17 +- erpnext/startup/notifications.py | 2 +- 11 files changed, 183 insertions(+), 107 deletions(-) create mode 100644 erpnext/change_log/current/task_notification_change.md create mode 100644 erpnext/patches/v6_12/__init__.py create mode 100644 erpnext/patches/v6_12/set_overdue_tasks.py diff --git a/erpnext/change_log/current/task_notification_change.md b/erpnext/change_log/current/task_notification_change.md new file mode 100644 index 0000000000..b6060f0aea --- /dev/null +++ b/erpnext/change_log/current/task_notification_change.md @@ -0,0 +1,2 @@ +- Task status will be automatically set to "Overdue" when it crosses expected end date. +- Task notification will only be for overdue tasks, not open tasks. diff --git a/erpnext/hooks.py b/erpnext/hooks.py index bed3a914c7..4d7eda5ab2 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -125,7 +125,8 @@ scheduler_events = { "erpnext.setup.doctype.email_digest.email_digest.send", "erpnext.support.doctype.issue.issue.auto_close_tickets", "erpnext.accounts.doctype.fiscal_year.fiscal_year.auto_create_fiscal_year", - "erpnext.hr.doctype.employee.employee.send_birthday_reminders" + "erpnext.hr.doctype.employee.employee.send_birthday_reminders", + "erpnext.projects.doctype.task.task.set_tasks_as_overdue" ] } diff --git a/erpnext/patches.txt b/erpnext/patches.txt index ac5e5ca5eb..612a44732a 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -239,3 +239,4 @@ erpnext.patches.v6_10.email_digest_default_quote erpnext.patches.v6_10.fix_billed_amount_in_drop_ship_po erpnext.patches.v6_10.fix_delivery_status_of_drop_ship_item #2015-12-08 erpnext.patches.v5_8.tax_rule #2015-12-08 +erpnext.patches.v6_12.set_overdue_tasks diff --git a/erpnext/patches/v6_12/__init__.py b/erpnext/patches/v6_12/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/patches/v6_12/set_overdue_tasks.py b/erpnext/patches/v6_12/set_overdue_tasks.py new file mode 100644 index 0000000000..39d601aa00 --- /dev/null +++ b/erpnext/patches/v6_12/set_overdue_tasks.py @@ -0,0 +1,7 @@ +import frappe + +def execute(): + frappe.reload_doctype("Task") + + from erpnext.projects.doctype.task.task import set_tasks_as_overdue + set_tasks_as_overdue() diff --git a/erpnext/projects/doctype/task/task.js b/erpnext/projects/doctype/task/task.js index 4e870fa59b..755147c79f 100644 --- a/erpnext/projects/doctype/task/task.js +++ b/erpnext/projects/doctype/task/task.js @@ -8,6 +8,13 @@ cur_frm.add_fetch("project", "company", "company"); frappe.ui.form.on("Task", { refresh: function(frm) { var doc = frm.doc; + if(doc.__islocal) { + if(!frm.doc.exp_end_date) { + frm.set_value("exp_end_date", frappe.datetime.add_days(new Date(), 7)); + } + } + + if(!doc.__islocal) { if(frappe.model.can_read("Time Log")) { frm.add_custom_button(__("Time Logs"), function() { diff --git a/erpnext/projects/doctype/task/task.json b/erpnext/projects/doctype/task/task.json index 1dd2a5c4e4..0e7f4fcd35 100644 --- a/erpnext/projects/doctype/task/task.json +++ b/erpnext/projects/doctype/task/task.json @@ -26,6 +26,7 @@ "oldfieldtype": "Data", "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 1, @@ -51,6 +52,7 @@ "options": "Project", "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -73,6 +75,7 @@ "oldfieldtype": "Column Break", "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "print_width": "50%", "read_only": 0, "report_hide": 0, @@ -84,7 +87,7 @@ }, { "allow_on_submit": 0, - "bold": 0, + "bold": 1, "collapsible": 0, "fieldname": "status", "fieldtype": "Select", @@ -97,9 +100,10 @@ "no_copy": 1, "oldfieldname": "status", "oldfieldtype": "Select", - "options": "Open\nWorking\nPending Review\nClosed\nCancelled", + "options": "Open\nWorking\nPending Review\nOverdue\nClosed\nCancelled", "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -125,6 +129,7 @@ "options": "Low\nMedium\nHigh\nUrgent", "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -132,102 +137,6 @@ "set_only_once": 0, "unique": 0 }, - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "section_break0", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "length": 0, - "no_copy": 0, - "oldfieldtype": "Section Break", - "options": "Simple", - "permlevel": 0, - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "description", - "fieldtype": "Text Editor", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Details", - "length": 0, - "no_copy": 0, - "oldfieldname": "description", - "oldfieldtype": "Text Editor", - "permlevel": 0, - "print_hide": 0, - "print_width": "300px", - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0, - "width": "300px" - }, - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "section_break", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Depends On", - "length": 0, - "no_copy": 0, - "oldfieldtype": "Section Break", - "permlevel": 0, - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "depends_on", - "fieldtype": "Table", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "depends_on", - "length": 0, - "no_copy": 0, - "options": "Task Depends On", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, { "allow_on_submit": 0, "bold": 0, @@ -243,6 +152,7 @@ "permlevel": 0, "precision": "", "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -267,6 +177,7 @@ "oldfieldtype": "Date", "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -293,6 +204,7 @@ "oldfieldtype": "Data", "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -315,6 +227,7 @@ "permlevel": 0, "precision": "", "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -324,7 +237,7 @@ }, { "allow_on_submit": 0, - "bold": 0, + "bold": 1, "collapsible": 0, "fieldname": "exp_end_date", "fieldtype": "Date", @@ -339,6 +252,7 @@ "oldfieldtype": "Date", "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -346,6 +260,106 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "section_break0", + "fieldtype": "Section Break", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "length": 0, + "no_copy": 0, + "oldfieldtype": "Section Break", + "options": "Simple", + "permlevel": 0, + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "description", + "fieldtype": "Text Editor", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Details", + "length": 0, + "no_copy": 0, + "oldfieldname": "description", + "oldfieldtype": "Text Editor", + "permlevel": 0, + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": "300px", + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0, + "width": "300px" + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "section_break", + "fieldtype": "Section Break", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Depends On", + "length": 0, + "no_copy": 0, + "oldfieldtype": "Section Break", + "permlevel": 0, + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "depends_on", + "fieldtype": "Table", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "depends_on", + "length": 0, + "no_copy": 0, + "options": "Task Depends On", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_on_submit": 0, "bold": 0, @@ -363,6 +377,7 @@ "oldfieldtype": "Column Break", "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "print_width": "50%", "read_only": 0, "report_hide": 0, @@ -389,6 +404,7 @@ "oldfieldtype": "Date", "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 1, "report_hide": 0, "reqd": 0, @@ -415,6 +431,7 @@ "permlevel": 0, "precision": "", "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 1, "report_hide": 0, "reqd": 0, @@ -437,6 +454,7 @@ "permlevel": 0, "precision": "", "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -461,6 +479,7 @@ "oldfieldtype": "Date", "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 1, "report_hide": 0, "reqd": 0, @@ -483,6 +502,7 @@ "permlevel": 0, "precision": "", "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -508,6 +528,7 @@ "options": "Company:company:default_currency", "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 1, "report_hide": 0, "reqd": 0, @@ -532,6 +553,7 @@ "permlevel": 0, "precision": "", "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 1, "report_hide": 0, "reqd": 0, @@ -554,6 +576,7 @@ "permlevel": 0, "precision": "", "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -577,6 +600,7 @@ "permlevel": 0, "precision": "", "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 1, "report_hide": 0, "reqd": 0, @@ -599,6 +623,7 @@ "no_copy": 0, "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -624,6 +649,7 @@ "oldfieldtype": "Date", "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -649,6 +675,7 @@ "oldfieldtype": "Date", "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -670,6 +697,7 @@ "no_copy": 0, "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -693,6 +721,7 @@ "options": "Company", "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -711,7 +740,8 @@ "issingle": 0, "istable": 0, "max_attachments": 5, - "modified": "2015-11-16 06:29:59.063379", + "menu_index": 0, + "modified": "2015-12-10 01:43:16.137084", "modified_by": "Administrator", "module": "Projects", "name": "Task", diff --git a/erpnext/projects/doctype/task/task.py b/erpnext/projects/doctype/task/task.py index cd0aabec94..15c98f4c40 100644 --- a/erpnext/projects/doctype/task/task.py +++ b/erpnext/projects/doctype/task/task.py @@ -144,3 +144,9 @@ def set_multiple_status(names, status): task = frappe.get_doc("Task", name) task.status = status task.save() + +def set_tasks_as_overdue(): + frappe.db.sql("""update tabTask set `status`='Overdue' + where exp_end_date is not null + and exp_end_date < CURDATE() + and `status` not in ('Closed', 'Cancelled')""") diff --git a/erpnext/projects/doctype/task/task_list.js b/erpnext/projects/doctype/task/task_list.js index 2a02fbb745..48a46555e5 100644 --- a/erpnext/projects/doctype/task/task_list.js +++ b/erpnext/projects/doctype/task/task_list.js @@ -1,10 +1,6 @@ frappe.listview_settings['Task'] = { add_fields: ["project", "status", "priority", "exp_end_date"], onload: function(listview) { - frappe.route_options = { - "status": "Open" - }; - var method = "erpnext.projects.doctype.task.task.set_multiple_status"; listview.page.add_menu_item(__("Set as Open"), function() { @@ -14,6 +10,17 @@ frappe.listview_settings['Task'] = { listview.page.add_menu_item(__("Set as Closed"), function() { listview.call_for_selected_items(method, {"status": "Closed"}); }); + }, + get_indicator: function(doc) { + var colors = { + "Open": "orange", + "Overdue": "red", + "Pending Review": "orange", + "Working": "orange", + "Closed": "green", + "Cancelled": "dark grey" + } + return [__(doc.status), colors[doc.status], "status,=," + doc.status]; } }; diff --git a/erpnext/projects/doctype/task/test_task.py b/erpnext/projects/doctype/task/test_task.py index fced0a45ed..7007269e4e 100644 --- a/erpnext/projects/doctype/task/test_task.py +++ b/erpnext/projects/doctype/task/test_task.py @@ -3,7 +3,7 @@ from __future__ import unicode_literals import frappe import unittest -from frappe.utils import getdate +from frappe.utils import getdate, nowdate, add_days # test_records = frappe.get_test_records('Task') @@ -177,3 +177,18 @@ class TestTask(unittest.TestCase): todo = get_owner_and_status() self.assertEquals(todo.owner, "test@example.com") self.assertEquals(todo.status, "Closed") + + def test_overdue(self): + task = frappe.get_doc({ + "doctype":"Task", + "subject": "Testing Overdue", + "status": "Open", + "exp_end_date": add_days(nowdate(), -1) + }) + + task.insert() + + from erpnext.projects.doctype.task.task import set_tasks_as_overdue + set_tasks_as_overdue() + + self.assertEquals(frappe.db.get_value("Task", task.name, "status"), "Overdue") diff --git a/erpnext/startup/notifications.py b/erpnext/startup/notifications.py index 4b5de233e5..3acf63c5f0 100644 --- a/erpnext/startup/notifications.py +++ b/erpnext/startup/notifications.py @@ -8,7 +8,7 @@ def get_notification_config(): { "Issue": {"status": "Open"}, "Warranty Claim": {"status": "Open"}, - "Task": {"status": "Open"}, + "Task": {"status": "Overdue"}, "Project": {"status": "Open"}, "Lead": {"status": "Open"}, "Contact": {"status": "Open"},