mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-24 07:29:22 +00:00
Converting Task to a Tree structure (#11117)
* added support for tree view * nestedset added to handle tree based structure * treeview ui added * removed is_group dependency * added validation while editing a group-task * codacy fix * BOM like filter added * Added ui-test for treeview-task
This commit is contained in:
@@ -15,6 +15,7 @@ def get_data():
|
|||||||
{
|
{
|
||||||
"type": "doctype",
|
"type": "doctype",
|
||||||
"name": "Task",
|
"name": "Task",
|
||||||
|
"route": "Tree/Task",
|
||||||
"description": _("Project activity / task."),
|
"description": _("Project activity / task."),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -19,38 +19,47 @@ frappe.ui.form.on("Task", {
|
|||||||
},
|
},
|
||||||
|
|
||||||
refresh: function(frm) {
|
refresh: function(frm) {
|
||||||
var doc = frm.doc;
|
frm.fields_dict['parent_task'].get_query = function() {
|
||||||
if(doc.__islocal) {
|
return {
|
||||||
if(!frm.doc.exp_end_date) {
|
filters: {
|
||||||
frm.set_value("exp_end_date", frappe.datetime.add_days(new Date(), 7));
|
"is_group": 1,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(!frm.is_group){
|
||||||
if(!doc.__islocal) {
|
var doc = frm.doc;
|
||||||
if(frappe.model.can_read("Timesheet")) {
|
if(doc.__islocal) {
|
||||||
frm.add_custom_button(__("Timesheet"), function() {
|
if(!frm.doc.exp_end_date) {
|
||||||
frappe.route_options = {"project": doc.project, "task": doc.name}
|
frm.set_value("exp_end_date", frappe.datetime.add_days(new Date(), 7));
|
||||||
frappe.set_route("List", "Timesheet");
|
}
|
||||||
}, __("View"), true);
|
|
||||||
}
|
|
||||||
if(frappe.model.can_read("Expense Claim")) {
|
|
||||||
frm.add_custom_button(__("Expense Claims"), function() {
|
|
||||||
frappe.route_options = {"project": doc.project, "task": doc.name}
|
|
||||||
frappe.set_route("List", "Expense Claim");
|
|
||||||
}, __("View"), true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(frm.perm[0].write) {
|
if(!doc.__islocal) {
|
||||||
if(frm.doc.status!=="Closed" && frm.doc.status!=="Cancelled") {
|
if(frappe.model.can_read("Timesheet")) {
|
||||||
frm.add_custom_button(__("Close"), function() {
|
frm.add_custom_button(__("Timesheet"), function() {
|
||||||
frm.set_value("status", "Closed");
|
frappe.route_options = {"project": doc.project, "task": doc.name}
|
||||||
frm.save();
|
frappe.set_route("List", "Timesheet");
|
||||||
});
|
}, __("View"), true);
|
||||||
} else {
|
}
|
||||||
frm.add_custom_button(__("Reopen"), function() {
|
if(frappe.model.can_read("Expense Claim")) {
|
||||||
frm.set_value("status", "Open");
|
frm.add_custom_button(__("Expense Claims"), function() {
|
||||||
frm.save();
|
frappe.route_options = {"project": doc.project, "task": doc.name}
|
||||||
});
|
frappe.set_route("List", "Expense Claim");
|
||||||
|
}, __("View"), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(frm.perm[0].write) {
|
||||||
|
if(frm.doc.status!=="Closed" && frm.doc.status!=="Cancelled") {
|
||||||
|
frm.add_custom_button(__("Close"), function() {
|
||||||
|
frm.set_value("status", "Closed");
|
||||||
|
frm.save();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
frm.add_custom_button(__("Reopen"), function() {
|
||||||
|
frm.set_value("status", "Open");
|
||||||
|
frm.save();
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -71,6 +80,21 @@ frappe.ui.form.on("Task", {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
is_group: function(frm) {
|
||||||
|
frappe.call({
|
||||||
|
method:"erpnext.projects.doctype.task.task.check_if_child_exists",
|
||||||
|
args: {
|
||||||
|
name: frm.doc.name
|
||||||
|
},
|
||||||
|
callback: function(r){
|
||||||
|
if(r.message){
|
||||||
|
frappe.msgprint(__('Cannot convert it to non-group. Child Tasks exist.'));
|
||||||
|
frm.reload_doc();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
validate: function(frm) {
|
validate: function(frm) {
|
||||||
frm.doc.project && frappe.model.remove_from_locals("Project",
|
frm.doc.project && frappe.model.remove_from_locals("Project",
|
||||||
frm.doc.project);
|
frm.doc.project);
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"allow_guest_to_view": 0,
|
"allow_guest_to_view": 0,
|
||||||
"allow_import": 1,
|
"allow_import": 1,
|
||||||
"allow_rename": 1,
|
"allow_rename": 1,
|
||||||
"autoname": "TASK.#####",
|
"autoname": "field:subject",
|
||||||
"beta": 0,
|
"beta": 0,
|
||||||
"creation": "2013-01-29 19:25:50",
|
"creation": "2013-01-29 19:25:50",
|
||||||
"custom": 0,
|
"custom": 0,
|
||||||
@@ -30,9 +30,8 @@
|
|||||||
"label": "Subject",
|
"label": "Subject",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"oldfieldname": "subject",
|
|
||||||
"oldfieldtype": "Data",
|
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
@@ -75,6 +74,37 @@
|
|||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 1,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"default": "0",
|
||||||
|
"fieldname": "is_group",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 1,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Is Group",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
@@ -173,9 +203,42 @@
|
|||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 1,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"fieldname": "parent_task",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 1,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Parent Task",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"options": "Task",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 1,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"collapsible_depends_on": "",
|
||||||
|
"columns": 0,
|
||||||
|
"depends_on": "",
|
||||||
"fieldname": "section_break_10",
|
"fieldname": "section_break_10",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@@ -205,6 +268,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"depends_on": "",
|
||||||
"fieldname": "exp_start_date",
|
"fieldname": "exp_start_date",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@@ -237,6 +301,7 @@
|
|||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"default": "0",
|
"default": "0",
|
||||||
|
"depends_on": "",
|
||||||
"description": "",
|
"description": "",
|
||||||
"fieldname": "expected_time",
|
"fieldname": "expected_time",
|
||||||
"fieldtype": "Float",
|
"fieldtype": "Float",
|
||||||
@@ -269,6 +334,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"depends_on": "",
|
||||||
"fieldname": "task_weight",
|
"fieldname": "task_weight",
|
||||||
"fieldtype": "Float",
|
"fieldtype": "Float",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@@ -328,6 +394,7 @@
|
|||||||
"bold": 1,
|
"bold": 1,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"depends_on": "",
|
||||||
"fieldname": "exp_end_date",
|
"fieldname": "exp_end_date",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@@ -359,6 +426,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"depends_on": "",
|
||||||
"fieldname": "progress",
|
"fieldname": "progress",
|
||||||
"fieldtype": "Percent",
|
"fieldtype": "Percent",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@@ -389,6 +457,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"depends_on": "",
|
||||||
"fieldname": "is_milestone",
|
"fieldname": "is_milestone",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@@ -418,7 +487,9 @@
|
|||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
|
"collapsible_depends_on": "",
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"depends_on": "",
|
||||||
"fieldname": "section_break0",
|
"fieldname": "section_break0",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@@ -449,6 +520,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"depends_on": "",
|
||||||
"fieldname": "description",
|
"fieldname": "description",
|
||||||
"fieldtype": "Text Editor",
|
"fieldtype": "Text Editor",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@@ -481,7 +553,9 @@
|
|||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
|
"collapsible_depends_on": "",
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"depends_on": "",
|
||||||
"fieldname": "section_break",
|
"fieldname": "section_break",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@@ -512,6 +586,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"depends_on": "",
|
||||||
"fieldname": "depends_on",
|
"fieldname": "depends_on",
|
||||||
"fieldtype": "Table",
|
"fieldtype": "Table",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@@ -543,6 +618,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"depends_on": "",
|
||||||
"fieldname": "depends_on_tasks",
|
"fieldname": "depends_on_tasks",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"hidden": 1,
|
"hidden": 1,
|
||||||
@@ -572,7 +648,9 @@
|
|||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
|
"collapsible_depends_on": "",
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"depends_on": "",
|
||||||
"description": "",
|
"description": "",
|
||||||
"fieldname": "actual",
|
"fieldname": "actual",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
@@ -606,6 +684,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"depends_on": "",
|
||||||
"fieldname": "act_start_date",
|
"fieldname": "act_start_date",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@@ -638,6 +717,7 @@
|
|||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"default": "",
|
"default": "",
|
||||||
|
"depends_on": "",
|
||||||
"description": "",
|
"description": "",
|
||||||
"fieldname": "actual_time",
|
"fieldname": "actual_time",
|
||||||
"fieldtype": "Float",
|
"fieldtype": "Float",
|
||||||
@@ -699,6 +779,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"depends_on": "",
|
||||||
"fieldname": "act_end_date",
|
"fieldname": "act_end_date",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@@ -730,6 +811,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"depends_on": "",
|
||||||
"fieldname": "section_break_17",
|
"fieldname": "section_break_17",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@@ -759,6 +841,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"depends_on": "",
|
||||||
"fieldname": "total_costing_amount",
|
"fieldname": "total_costing_amount",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@@ -791,6 +874,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"depends_on": "",
|
||||||
"fieldname": "total_expense_claim",
|
"fieldname": "total_expense_claim",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@@ -851,6 +935,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"depends_on": "",
|
||||||
"fieldname": "total_billing_amount",
|
"fieldname": "total_billing_amount",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@@ -1025,6 +1110,96 @@
|
|||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "lft",
|
||||||
|
"fieldtype": "Int",
|
||||||
|
"hidden": 1,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "lft",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "rgt",
|
||||||
|
"fieldtype": "Int",
|
||||||
|
"hidden": 1,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "rgt",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "old_parent",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"hidden": 1,
|
||||||
|
"ignore_user_permissions": 1,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Old Parent",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"has_web_view": 0,
|
"has_web_view": 0,
|
||||||
@@ -1039,7 +1214,7 @@
|
|||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 5,
|
"max_attachments": 5,
|
||||||
"menu_index": 0,
|
"menu_index": 0,
|
||||||
"modified": "2017-05-23 11:28:28.161600",
|
"modified": "2017-10-06 03:57:37.901446",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Projects",
|
"module": "Projects",
|
||||||
"name": "Task",
|
"name": "Task",
|
||||||
|
|||||||
@@ -5,13 +5,14 @@ from __future__ import unicode_literals
|
|||||||
import frappe, json
|
import frappe, json
|
||||||
|
|
||||||
from frappe.utils import getdate, date_diff, add_days, cstr
|
from frappe.utils import getdate, date_diff, add_days, cstr
|
||||||
from frappe import _
|
from frappe import _, throw
|
||||||
|
from frappe.utils.nestedset import NestedSet, rebuild_tree
|
||||||
from frappe.model.document import Document
|
|
||||||
|
|
||||||
class CircularReferenceError(frappe.ValidationError): pass
|
class CircularReferenceError(frappe.ValidationError): pass
|
||||||
|
|
||||||
class Task(Document):
|
class Task(NestedSet):
|
||||||
|
nsm_parent_field = 'parent_task'
|
||||||
|
|
||||||
def get_feed(self):
|
def get_feed(self):
|
||||||
return '{0}: {1}'.format(_(self.status), self.subject)
|
return '{0}: {1}'.format(_(self.status), self.subject)
|
||||||
|
|
||||||
@@ -59,11 +60,16 @@ class Task(Document):
|
|||||||
depends_on_tasks += d.task + ","
|
depends_on_tasks += d.task + ","
|
||||||
self.depends_on_tasks = depends_on_tasks
|
self.depends_on_tasks = depends_on_tasks
|
||||||
|
|
||||||
|
def update_nsm_model(self):
|
||||||
|
frappe.utils.nestedset.update_nsm(self)
|
||||||
|
|
||||||
def on_update(self):
|
def on_update(self):
|
||||||
|
self.update_nsm_model()
|
||||||
self.check_recursion()
|
self.check_recursion()
|
||||||
self.reschedule_dependent_tasks()
|
self.reschedule_dependent_tasks()
|
||||||
self.update_project()
|
self.update_project()
|
||||||
self.unassign_todo()
|
self.unassign_todo()
|
||||||
|
rebuild_tree("Task", "parent_task")
|
||||||
|
|
||||||
def unassign_todo(self):
|
def unassign_todo(self):
|
||||||
if self.status == "Closed" or self.status == "Cancelled":
|
if self.status == "Closed" or self.status == "Cancelled":
|
||||||
@@ -128,6 +134,17 @@ class Task(Document):
|
|||||||
if project_user:
|
if project_user:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def on_trash(self):
|
||||||
|
if check_if_child_exists(self.name):
|
||||||
|
throw(_("Child Task exists for this Task. You can not delete this Task."))
|
||||||
|
|
||||||
|
self.update_nsm_model()
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def check_if_child_exists(name):
|
||||||
|
return frappe.db.sql("""select name from `tabTask`
|
||||||
|
where parent_task = %s""", name)
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_events(start, end, filters=None):
|
def get_events(start, end, filters=None):
|
||||||
"""Returns events for Gantt / Calendar view rendering.
|
"""Returns events for Gantt / Calendar view rendering.
|
||||||
@@ -177,4 +194,48 @@ def set_tasks_as_overdue():
|
|||||||
and exp_end_date < CURDATE()
|
and exp_end_date < CURDATE()
|
||||||
and `status` not in ('Closed', 'Cancelled')""")
|
and `status` not in ('Closed', 'Cancelled')""")
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def get_children():
|
||||||
|
doctype = frappe.local.form_dict.get('doctype')
|
||||||
|
|
||||||
|
parent_field = 'parent_' + doctype.lower().replace(' ', '_')
|
||||||
|
parent = frappe.form_dict.get("parent") or ""
|
||||||
|
|
||||||
|
if parent == "task":
|
||||||
|
parent = ""
|
||||||
|
|
||||||
|
tasks = frappe.db.sql("""select name as value,
|
||||||
|
is_group as expandable
|
||||||
|
from `tab{doctype}`
|
||||||
|
where docstatus < 2
|
||||||
|
and ifnull(`{parent_field}`,'') = %s
|
||||||
|
order by name""".format(doctype=frappe.db.escape(doctype),
|
||||||
|
parent_field=frappe.db.escape(parent_field)), (parent), as_dict=1)
|
||||||
|
|
||||||
|
# return tasks
|
||||||
|
return tasks
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def add_node():
|
||||||
|
from frappe.desk.treeview import make_tree_args
|
||||||
|
args = frappe.form_dict
|
||||||
|
args.update({
|
||||||
|
"name_field": "subject"
|
||||||
|
})
|
||||||
|
args = make_tree_args(**args)
|
||||||
|
|
||||||
|
if args.parent_task == 'task':
|
||||||
|
args.parent_task = None
|
||||||
|
|
||||||
|
frappe.get_doc(args).insert()
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def add_multiple_tasks(data, parent):
|
||||||
|
data = json.loads(data)['tasks']
|
||||||
|
tasks = data.split('\n')
|
||||||
|
new_doc = {'doctype': 'Task', 'parent_task': parent}
|
||||||
|
|
||||||
|
for d in tasks:
|
||||||
|
new_doc['subject'] = d
|
||||||
|
new_task = frappe.get_doc(new_doc)
|
||||||
|
new_task.insert()
|
||||||
|
|||||||
59
erpnext/projects/doctype/task/task_tree.js
Normal file
59
erpnext/projects/doctype/task/task_tree.js
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
frappe.provide("frappe.treeview_settings");
|
||||||
|
|
||||||
|
frappe.treeview_settings['Task'] = {
|
||||||
|
get_tree_nodes: "erpnext.projects.doctype.task.task.get_children",
|
||||||
|
add_tree_node: "erpnext.projects.doctype.task.task.add_node",
|
||||||
|
filters: [
|
||||||
|
{
|
||||||
|
fieldname: "task",
|
||||||
|
fieldtype:"Link",
|
||||||
|
options: "Task",
|
||||||
|
label: __("Task"),
|
||||||
|
get_query: function(){
|
||||||
|
return {
|
||||||
|
filters: [["Task", 'is_group', '=', 1]]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
title: "Task",
|
||||||
|
breadcrumb: "Projects",
|
||||||
|
get_tree_root: false,
|
||||||
|
root_label: "task",
|
||||||
|
ignore_fields:["parent_task"],
|
||||||
|
get_label: function(node) {
|
||||||
|
return node.data.value;
|
||||||
|
},
|
||||||
|
onload: function(me){
|
||||||
|
me.make_tree();
|
||||||
|
me.set_root = true;
|
||||||
|
},
|
||||||
|
toolbar: [
|
||||||
|
{
|
||||||
|
label:__("Add Multiple"),
|
||||||
|
condition: function(node) {
|
||||||
|
return node.expandable;
|
||||||
|
},
|
||||||
|
click: function(node) {
|
||||||
|
var d = new frappe.ui.Dialog({
|
||||||
|
'fields': [
|
||||||
|
{'fieldname': 'tasks', 'label': 'Tasks', 'fieldtype': 'Text'},
|
||||||
|
],
|
||||||
|
primary_action: function(){
|
||||||
|
d.hide();
|
||||||
|
return frappe.call({
|
||||||
|
method: "erpnext.projects.doctype.task.task.add_multiple_tasks",
|
||||||
|
args: {
|
||||||
|
data: d.get_values(),
|
||||||
|
parent: node.data.value
|
||||||
|
},
|
||||||
|
callback: function() { }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
d.show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
extend_toolbar: true
|
||||||
|
};
|
||||||
99
erpnext/projects/doctype/task/tests/test_task_tree.js
Normal file
99
erpnext/projects/doctype/task/tests/test_task_tree.js
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
/* eslint-disable */
|
||||||
|
// rename this file from _test_[name] to test_[name] to activate
|
||||||
|
// and remove above this line
|
||||||
|
|
||||||
|
QUnit.test("test: Task Tree", function (assert) {
|
||||||
|
let done = assert.async();
|
||||||
|
|
||||||
|
// number of asserts
|
||||||
|
assert.expect(5);
|
||||||
|
|
||||||
|
frappe.run_serially([
|
||||||
|
// insert a new Task
|
||||||
|
() => frappe.set_route('Tree', 'Task'),
|
||||||
|
() => frappe.timeout(0.5),
|
||||||
|
|
||||||
|
// Checking adding child without selecting any Node
|
||||||
|
() => frappe.tests.click_button('New'),
|
||||||
|
() => frappe.timeout(0.5),
|
||||||
|
() => {assert.equal($(`.msgprint`).text(), "Select a group node first.", "Error message success");},
|
||||||
|
() => frappe.tests.click_button('Close'),
|
||||||
|
() => frappe.timeout(0.5),
|
||||||
|
|
||||||
|
// Creating child nodes
|
||||||
|
() => frappe.tests.click_link('task'),
|
||||||
|
() => frappe.map_group.make('Test-1'),
|
||||||
|
() => frappe.map_group.make('Test-2'),
|
||||||
|
() => frappe.map_group.make('Test-3', 1),
|
||||||
|
() => frappe.timeout(1),
|
||||||
|
() => frappe.tests.click_link('Test-3'),
|
||||||
|
() => frappe.map_group.make('Test-4', 0),
|
||||||
|
|
||||||
|
// Checking Edit button
|
||||||
|
() => frappe.timeout(0.5),
|
||||||
|
() => frappe.tests.click_link('Test-1'),
|
||||||
|
() => frappe.tests.click_button('Edit'),
|
||||||
|
() => frappe.timeout(0.5),
|
||||||
|
() => {assert.deepEqual(frappe.get_route(), ["Form", "Task", "Test-1"], "Edit route checks");},
|
||||||
|
|
||||||
|
// Deleting child Node
|
||||||
|
() => frappe.set_route('Tree', 'Task'),
|
||||||
|
() => frappe.timeout(0.5),
|
||||||
|
() => frappe.tests.click_link('Test-1'),
|
||||||
|
() => frappe.tests.click_button('Delete'),
|
||||||
|
() => frappe.timeout(0.5),
|
||||||
|
() => frappe.tests.click_button('Yes'),
|
||||||
|
|
||||||
|
// Deleting Group Node that has child nodes in it
|
||||||
|
() => frappe.timeout(0.5),
|
||||||
|
() => frappe.tests.click_link('Test-3'),
|
||||||
|
() => frappe.tests.click_button('Delete'),
|
||||||
|
() => frappe.timeout(0.5),
|
||||||
|
() => frappe.tests.click_button('Yes'),
|
||||||
|
() => frappe.timeout(1),
|
||||||
|
() => {assert.equal(cur_dialog.title, 'Message', 'Error thrown correctly');},
|
||||||
|
() => frappe.tests.click_button('Close'),
|
||||||
|
|
||||||
|
// Renaming Child node
|
||||||
|
() => frappe.timeout(0.5),
|
||||||
|
() => frappe.tests.click_link('Test-2'),
|
||||||
|
() => frappe.tests.click_button('Rename'),
|
||||||
|
() => frappe.timeout(1),
|
||||||
|
() => cur_dialog.set_value('new_name', 'Test-5'),
|
||||||
|
() => frappe.timeout(1.5),
|
||||||
|
() => cur_dialog.get_primary_btn().click(),
|
||||||
|
() => frappe.timeout(1),
|
||||||
|
() => {assert.equal($(`a:contains("Test-5"):visible`).length, 1, 'Rename successfull');},
|
||||||
|
|
||||||
|
// Add multiple child tasks
|
||||||
|
() => frappe.tests.click_link('Test-3'),
|
||||||
|
() => frappe.timeout(0.5),
|
||||||
|
() => frappe.click_button('Add Multiple'),
|
||||||
|
() => frappe.timeout(1),
|
||||||
|
() => cur_dialog.set_value('tasks', 'Test-6\nTest-7'),
|
||||||
|
() => frappe.timeout(0.5),
|
||||||
|
() => frappe.click_button('Submit'),
|
||||||
|
() => frappe.timeout(2),
|
||||||
|
() => frappe.click_button('Expand All'),
|
||||||
|
() => frappe.timeout(1),
|
||||||
|
() => {
|
||||||
|
let count = $(`a:contains("Test-6"):visible`).length + $(`a:contains("Test-7"):visible`).length;
|
||||||
|
assert.equal(count, 2, "Multiple Tasks added successfully");
|
||||||
|
},
|
||||||
|
|
||||||
|
() => done()
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
frappe.map_group = {
|
||||||
|
make:function(subject, is_group = 0){
|
||||||
|
return frappe.run_serially([
|
||||||
|
() => frappe.click_button('Add Child'),
|
||||||
|
() => frappe.timeout(1),
|
||||||
|
() => cur_dialog.set_value('is_group', is_group),
|
||||||
|
() => cur_dialog.set_value('subject', subject),
|
||||||
|
() => frappe.click_button('Create New'),
|
||||||
|
() => frappe.timeout(1.5)
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -133,3 +133,4 @@ erpnext/restaurant/doctype/restaurant/test_restaurant.js
|
|||||||
erpnext/restaurant/doctype/restaurant_table/test_restaurant_table.js
|
erpnext/restaurant/doctype/restaurant_table/test_restaurant_table.js
|
||||||
erpnext/restaurant/doctype/restaurant_menu/test_restaurant_menu.js
|
erpnext/restaurant/doctype/restaurant_menu/test_restaurant_menu.js
|
||||||
erpnext/restaurant/doctype/restaurant_order_entry/restaurant_order_entry.js
|
erpnext/restaurant/doctype/restaurant_order_entry/restaurant_order_entry.js
|
||||||
|
erpnext/projects/doctype/task/tests/test_task_tree.js
|
||||||
|
|||||||
Reference in New Issue
Block a user