diff --git a/erpnext/patches/august_2012/task_allocated_to_assigned.py b/erpnext/patches/august_2012/task_allocated_to_assigned.py new file mode 100644 index 00000000000..957820648fe --- /dev/null +++ b/erpnext/patches/august_2012/task_allocated_to_assigned.py @@ -0,0 +1,14 @@ +import webnotes + +def execute(): + from webnotes.widgets.form.assign_to import add + for t in webnotes.conn.sql("""select * from tabTask + where ifnull(allocated_to, '')!=''""", as_dict=1): + add({ + 'doctype': "Task", + 'name': t['name'], + 'assign_to': t['allocated_to'], + 'assigned_by': t['owner'], + 'description': t['subject'], + 'date': t['creation'] + }) \ No newline at end of file diff --git a/erpnext/patches/patch_list.py b/erpnext/patches/patch_list.py index 83da5c3fa3e..689e4e3c34e 100644 --- a/erpnext/patches/patch_list.py +++ b/erpnext/patches/patch_list.py @@ -521,4 +521,8 @@ patch_list = [ 'patch_module': 'patches.august_2012', 'patch_file': 'report_supplier_quotations', }, + { + 'patch_module': 'patches.august_2012', + 'patch_file': 'task_allocated_to_assigned', + } ] \ No newline at end of file diff --git a/erpnext/projects/doctype/task/task.js b/erpnext/projects/doctype/task/task.js index af4864bc444..d1317aeb65d 100644 --- a/erpnext/projects/doctype/task/task.js +++ b/erpnext/projects/doctype/task/task.js @@ -14,49 +14,9 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -cur_frm.cscript.onload = function(doc,cdt,cdn){ - if(!doc.senders_name) { - doc.senders_name = user_fullname; - doc.senders_email = user; - refresh_many(['senders_name', 'senders_email']); - } - - if(doc.__islocal) { - doc.status = 'Open'; - doc.opening_date = get_today(); - refresh_many(['status', 'opening_date']); - } - else{ - if(!doc.opening_date){ - doc.opening_date = dateutil.str_to_user(only_date(doc.creation)); - refresh_field('opening_date'); - } - } - - //hide unhide field depends on status - if(doc.status == 'Open') doc.review_date = doc.closing_date = ''; - else if(doc.status == 'Pending Review') doc.closing_date = ''; - refresh_many(['closing_date','review_date']); - - if(doc.project) cur_frm.cscript.project(doc, cdt, cdn); -} - -cur_frm.cscript.refresh = function(doc,cdt,cdn) { - cur_frm.clear_custom_buttons(); - if(doc.status == 'Pending Review' && (doc.senders_name == user_fullname || doc.senders_email == user)) { - cur_frm.add_custom_button('Declare Completed', cur_frm.cscript.declare_completed); - cur_frm.add_custom_button('Reopen Task', cur_frm.cscript['Reopen Task']); - } - if(doc.status == 'Open' && !doc.__islocal) { - cur_frm.add_custom_button('Cancel Task', cur_frm.cscript['Cancel Task']); - if(doc.allocated_to == user) cur_frm.add_custom_button('Get Approval', cur_frm.cscript['Get Approval']); - } -} - cur_frm.fields_dict['project'].get_query = function(doc,cdt,cdn){ var cond=''; - if(doc.customer) cond = 'ifnull(`tabProject`.customer, "") = "'+doc.customer+'" AND'; - + if(doc.customer) cond = 'ifnull(`tabProject`.customer, "") = "'+doc.customer+'" AND'; return repl('SELECT distinct `tabProject`.`name` FROM `tabProject` WHERE %(cond)s `tabProject`.`name` LIKE "%s" ORDER BY `tabProject`.`name` ASC LIMIT 50', {cond:cond}); } @@ -68,7 +28,6 @@ cur_frm.cscript.project = function(doc, cdt, cdn){ cur_frm.fields_dict['customer'].get_query = function(doc,cdt,cdn){ var cond=''; if(doc.project) cond = 'ifnull(`tabProject`.customer, "") = `tabCustomer`.name AND ifnull(`tabProject`.name, "") = "'+doc.project+'" AND'; - return repl('SELECT distinct `tabCustomer`.`name` FROM `tabCustomer`, `tabProject` WHERE %(cond)s `tabCustomer`.`name` LIKE "%s" ORDER BY `tabCustomer`.`name` ASC LIMIT 50', {cond:cond}); } @@ -77,46 +36,4 @@ cur_frm.cscript.customer = function(doc, cdt, cdn){ else doc.customer_name =''; } -cur_frm.cscript.allocated_to = function(doc,cdt,cdn){ - get_server_fields('get_allocated_to_name','','',doc,cdt,cdn,1); -} -cur_frm.cscript['Get Approval'] = function(){ - $c_obj(make_doclist(cur_frm.doc.doctype, cur_frm.doc.name), 'set_for_review', '',function(r, rt) { - if(r.message == 'true'){ - doc.status = 'Pending Review'; //for refresh - refresh_many(['review_date','status']); - cur_frm.cscript.refresh(cur_frm.doc, cur_frm.doc.doctype, cur_frm.doc.name); - } - }); -} - -cur_frm.cscript['Reopen Task'] = function(){ - $c_obj(make_doclist(cur_frm.doc.doctype, cur_frm.doc.name), 'reopen_task', '',function(r, rt) { - if(r.message == 'true'){ - doc.status = 'Open'; //for refresh - refresh_many(['status']); - cur_frm.cscript.refresh(cur_frm.doc, cur_frm.doc.doctype, cur_frm.doc.name); - } - }); -} - -cur_frm.cscript['Cancel Task'] = function(){ - $c_obj(make_doclist(cur_frm.doc.doctype, cur_frm.doc.name), 'cancel_task', '',function(r, rt) { - if(r.message == 'true'){ - doc.status = 'Cancelled'; //for refresh - refresh_many(['status']); - cur_frm.cscript.refresh(cur_frm.doc, cur_frm.doc.doctype, cur_frm.doc.name); - } - }); -} - -cur_frm.cscript.declare_completed = function(){ - $c_obj(make_doclist(cur_frm.doc.doctype, cur_frm.doc.name),'declare_completed', '',function(r, rt) { - if(r.message == 'true'){ - doc.status = 'Closed'; //for refresh - refresh_many(['review_date', 'closing_date', 'status']); - cur_frm.cscript.refresh(cur_frm.doc, cur_frm.doc.doctype, cur_frm.doc.name); - } - }); -} diff --git a/erpnext/projects/doctype/task/task.py b/erpnext/projects/doctype/task/task.py index 7f023ca41fd..cbfbbbef8ca 100644 --- a/erpnext/projects/doctype/task/task.py +++ b/erpnext/projects/doctype/task/task.py @@ -26,8 +26,6 @@ from webnotes.model.code import get_obj, get_server_obj, run_server_obj, updated from webnotes import session, form, is_testing, msgprint, errprint sql = webnotes.conn.sql -set = webnotes.conn.set -get_value = webnotes.conn.get_value # ----------------------------------------------------------------------------------------- @@ -48,15 +46,6 @@ class DocType: if cust: ret = {'customer_name': cust and cust[0][0] or ''} return ret - - def get_allocated_to_name(self): - as_em = sql("select first_name, last_name from `tabProfile` where name=%s",str(self.doc.allocated_to)) - ret = { 'allocated_to_name' : as_em and (cstr(as_em[0][0]) + ' ' + cstr(as_em[0][1])) or ''} - return ret - - # validate - #-------------------------------------------- - def validate(self): if self.doc.exp_start_date and self.doc.exp_end_date and getdate(self.doc.exp_start_date) > getdate(self.doc.exp_end_date): @@ -67,159 +56,3 @@ class DocType: msgprint("'Actual Start Date' can not be greater than 'Actual End Date'") raise Exception - # on update - #-------------------------------------------- - - def on_update(self): - if self.doc.status =='Open' and self.doc.allocated_to: - if self.doc.task_email_notify: - self.send_notification() - if self.doc.exp_start_date: - sql("delete from tabEvent where ref_type='Task' and ref_name=%s", self.doc.name) - self.add_calendar_event() - else: - msgprint("Tip: Add an expected start date to create a calendar event.") - - - def validate_for_pending_review(self): - if not self.doc.allocated_to: - msgprint("Please enter Allocated To.") - raise Exception - self.validate_with_timesheet_dates() - - #Sent Notification - def send_notification(self): - i = { - 'name' : self.doc.name, - 'senders_name': self.doc.senders_name, - 'opening_date': self.doc.opening_date, - 'exp_start_date': self.doc.exp_start_date, - 'exp_end_date' : self.doc.exp_end_date, - 'subject' : self.doc.subject, - 'project': self.doc.project, - 'review_date': self.doc.review_date, - 'description': self.doc.description - } - - task_label = '[Task Updated] ' - if self.doc.creation==self.doc.modified: - task_label = '[New Task] ' - - msg2="""

%(name)s

-

This is a Notification for the task %(name)s that has been assigned / updated to you - by %(senders_name)s on %(opening_date)s

-

Subject: %(subject)s

-

Project: %(project)s

-

Review Date: %(review_date)s

-

Expected Start Date: %(exp_start_date)s

-

Expected End Date: %(exp_end_date)s

-

Details: %(description)s

-

(This notification is autogenerated)

""" % i - sendmail(self.doc.allocated_to, msg=msg2,subject= task_label + self.doc.subject) - - #validate before closing task - def validate_for_closed(self): - self.check_non_submitted_timesheets() - self.get_actual_total_hrs() - - def check_non_submitted_timesheets(self): - chk = sql("select t1.name from `tabTimesheet` t1, `tabTimesheet Detail` t2 where t2.parent=t1.name and t2.task_id=%s and t1.status='Draft'", self.doc.name) - if chk: - chk_lst = [x[0] for x in chk] - msgprint("Please submit timesheet(s) : "+','.join(chk_lst)+" before declaring this task as completed. As details of this task present in timesheet(s)") - raise Exception - - #calculate actual total hours taken to complete task from timesheets - def get_actual_total_hrs(self): - import datetime - import time - chk = sql("select t2.act_total_hrs from `tabTimesheet` t1, `tabTimesheet Detail` t2 where t2.parent = t1.name and t2.task_id = %s and t1.status = 'Submitted' and ifnull(t2.act_total_hrs, '')!='' order by t1.timesheet_date asc", self.doc.name) - if chk: - chk_lst = [x[0] for x in chk] - actual_total = total =0 - - for m in chk_lst: - m1, m2=[], 0 - m1 = m.split(":") - m2 = (datetime.timedelta(minutes=cint(m1[1]), hours=cint(m1[0]))).seconds - total = total + m2 - - actual_total = time.strftime("%H:%M", time.gmtime(total)) - set(self.doc, 'act_total_hrs', actual_total) - - # validate and fetch actual start and end date - def validate_with_timesheet_dates(self): - chk = sql("select t1.name, t1.timesheet_date from `tabTimesheet` t1, `tabTimesheet Detail` t2 where t2.parent = t1.name and t2.task_id = %s and t1.status = 'Submitted' order by t1.timesheet_date asc", self.doc.name, as_dict=1) - if chk: - if self.doc.act_start_date: - if chk[0]['timesheet_date'] > getdate(self.doc.act_start_date) or chk[0]['timesheet_date'] < getdate(self.doc.act_start_date): - msgprint("Actual start date of this task is "+cstr(chk[0]['timesheet_date'])+" as per timesheet "+cstr(chk[0]['name'])) - raise Exception - else: - self.doc.act_start_date = chk[0]['timesheet_date'] - - if self.doc.act_end_date: - if chk[len(chk)-1]['timesheet_date'] < getdate(self.doc.act_end_date) or chk[len(chk)-1]['timesheet_date'] > getdate(self.doc.act_end_date): - msgprint("Actual end date of this task is "+cstr(chk[len(chk)-1]['timesheet_date'])+" as per timesheet "+cstr(chk[len(chk)-1]['name'])) - raise Exception - else: - self.doc.act_end_date = chk[len(chk)-1]['timesheet_date'] - - def set_for_review(self): - self.check_non_submitted_timesheets() - self.validate_for_pending_review() - self.get_actual_total_hrs() - self.doc.review_date = nowdate() - self.doc.status = 'Pending Review' - self.doc.save() - return cstr('true') - - def reopen_task(self): - self.doc.status = 'Open' - self.doc.save() - return cstr('true') - - def declare_completed(self): - if self.doc.status == 'Open': - self.validate_for_pending_review() - self.doc.review_date = nowdate() - else: - self.validate_with_timesheet_dates() - self.validate_for_closed() - - self.doc.closing_date = nowdate() - self.doc.status = 'Closed' - self.doc.docstatus = 1 - self.doc.save() - - self.remove_event_from_calender() - return cstr('true') - - def remove_event_from_calender(self): - sql("delete from tabEvent where ref_type='Task' and ref_name=%s", self.doc.name) - - def cancel_task(self): - chk = sql("select distinct t1.name from `tabTimesheet` t1, `tabTimesheet Detail` t2 where t2.parent = t1.name and t2.task_id = %s and t1.status!='Cancelled'", self.doc.name) - if chk: - chk_lst = [x[0] for x in chk] - msgprint("Timesheet(s) "+','.join(chk_lst)+" created against this task. Thus can not be cancelled") - raise Exception - else: - self.doc.status = 'Cancelled' - self.doc.docstatus = 2 - self.remove_event_from_calender() - self.doc.save() - return cstr('true') - - - def add_calendar_event(self): - """ Add calendar event for task in calendar of Allocated person""" - event = Document('Event') - event.owner = self.doc.allocated_to - event.description = self.doc.subject - event.event_date = self.doc.exp_start_date and self.doc.exp_start_date or '' - event.event_hour = self.doc.event_hour and self.doc.event_hour or '10:00' - event.event_type = 'Private' - event.ref_type = 'Task' - event.ref_name = self.doc.name - event.save(1) diff --git a/erpnext/projects/doctype/task/task.txt b/erpnext/projects/doctype/task/task.txt index eedb651f38a..9c9f07debec 100644 --- a/erpnext/projects/doctype/task/task.txt +++ b/erpnext/projects/doctype/task/task.txt @@ -3,9 +3,9 @@ # These values are common in all dictionaries { - 'creation': '2012-04-02 16:02:06', + 'creation': '2012-06-04 14:05:07', 'docstatus': 0, - 'modified': '2012-06-04 12:33:35', + 'modified': '2012-08-08 12:53:33', 'modified_by': u'Administrator', 'owner': u'Administrator' }, @@ -14,7 +14,7 @@ { '_last_update': u'1324880734', 'allow_trash': 1, - 'autoname': u'TIC/.####', + 'autoname': u'TASK.#####', 'colour': u'White:FFF', 'default_print_format': u'Standard', 'doctype': 'DocType', @@ -54,44 +54,6 @@ 'name': u'Task' }, - # DocPerm - { - 'amend': 1, - 'cancel': 1, - 'create': 1, - 'doctype': u'DocPerm', - 'permlevel': 0, - 'role': u'All', - 'submit': 0, - 'write': 1 - }, - - # DocPerm - { - 'doctype': u'DocPerm', - 'permlevel': 1, - 'role': u'All', - 'write': 0 - }, - - # DocPerm - { - 'amend': 1, - 'cancel': 1, - 'create': 1, - 'doctype': u'DocPerm', - 'permlevel': 0, - 'role': u'Projects User', - 'write': 1 - }, - - # DocPerm - { - 'doctype': u'DocPerm', - 'permlevel': 1, - 'role': u'Projects User' - }, - # DocField { 'doctype': u'DocField', @@ -117,29 +79,6 @@ 'reqd': 1 }, - # DocField - { - 'colour': u'White:FFF', - 'doctype': u'DocField', - 'fieldname': u'allocated_to', - 'fieldtype': u'Link', - 'label': u'Allocated To', - 'oldfieldname': u'allocated_to', - 'oldfieldtype': u'Link', - 'options': u'Profile', - 'permlevel': 0, - 'trigger': u'Client' - }, - - # DocField - { - 'doctype': u'DocField', - 'fieldname': u'task_email_notify', - 'fieldtype': u'Check', - 'label': u'Send Mail Notification', - 'permlevel': 0 - }, - # DocField { 'doctype': u'DocField', @@ -192,6 +131,7 @@ # DocField { + 'colour': u'White:FFF', 'doctype': u'DocField', 'fieldname': u'status', 'fieldtype': u'Select', @@ -199,8 +139,8 @@ 'no_copy': 1, 'oldfieldname': u'status', 'oldfieldtype': u'Select', - 'options': u'Open\nPending Review\nClosed\nCancelled', - 'permlevel': 1, + 'options': u'Open\nWorking\nPending Review\nClosed\nCancelled', + 'permlevel': 0, 'trigger': u'Client' }, @@ -219,18 +159,6 @@ 'search_index': 1 }, - # DocField - { - 'doctype': u'DocField', - 'fieldname': u'allocated_to_name', - 'fieldtype': u'Data', - 'hidden': 1, - 'label': u'Allocated To Name', - 'oldfieldname': u'allocated_to_name', - 'oldfieldtype': u'Data', - 'permlevel': 0 - }, - # DocField { 'doctype': u'DocField', @@ -302,32 +230,6 @@ 'permlevel': 1 }, - # DocField - { - 'doctype': u'DocField', - 'fieldname': u'senders_name', - 'fieldtype': u'Data', - 'in_filter': 1, - 'label': u'Raised By', - 'oldfieldname': u'senders_name', - 'oldfieldtype': u'Data', - 'permlevel': 0, - 'reqd': 1, - 'search_index': 1 - }, - - # DocField - { - 'doctype': u'DocField', - 'fieldname': u'senders_email', - 'fieldtype': u'Data', - 'label': u'Email', - 'oldfieldname': u'senders_email', - 'oldfieldtype': u'Data', - 'permlevel': 0, - 'reqd': 0 - }, - # DocField { 'doctype': u'DocField', @@ -534,5 +436,42 @@ 'permlevel': 1, 'print_hide': 1, 'report_hide': 1 + }, + + # DocPerm + { + 'amend': 1, + 'cancel': 1, + 'create': 1, + 'doctype': u'DocPerm', + 'permlevel': 0, + 'role': u'All', + 'write': 1 + }, + + # DocPerm + { + 'doctype': u'DocPerm', + 'permlevel': 1, + 'role': u'All', + 'write': 0 + }, + + # DocPerm + { + 'amend': 1, + 'cancel': 1, + 'create': 1, + 'doctype': u'DocPerm', + 'permlevel': 0, + 'role': u'Projects User', + 'write': 1 + }, + + # DocPerm + { + 'doctype': u'DocPerm', + 'permlevel': 1, + 'role': u'Projects User' } ] \ No newline at end of file diff --git a/erpnext/projects/page/projects/projects.js b/erpnext/projects/page/projects/projects.js index 7dc93586779..f9af826911d 100644 --- a/erpnext/projects/page/projects/projects.js +++ b/erpnext/projects/page/projects/projects.js @@ -14,14 +14,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -pscript.queries_bg_dict = { - 'Urgent':'RED', - 'High':'ORANGE', - 'Low':'BLUE', - 'Closed':'GREEN', - 'Pending Review':'YELLOW' -} - pscript.onload_Projects = function(wrapper) { wn.ui.make_app_page({parent:wrapper, title:'Gantt Chart: All Tasks', single_column:true}); @@ -46,7 +38,15 @@ pscript.onload_Projects = function(wrapper) { label: v.subject, desc: v.description || v.subject, from: '/Date("'+v.exp_start_date+'")/', - to: '/Date("'+v.exp_end_date+'")/' + to: '/Date("'+v.exp_end_date+'")/', + customClass: { + 'Open':'ganttRed', + 'Pending Review':'ganttOrange', + 'Working':'', + 'Completed':'ganttGreen', + 'Cancelled':'ganttGray' + }[v.status], + dataObj: v }] }) }) @@ -59,10 +59,10 @@ pscript.onload_Projects = function(wrapper) { minScale: "weeks", maxScale: "months", onItemClick: function(data) { - alert("Item clicked - show some details"); + wn.set_route('Form', 'Task', data.name); }, onAddClick: function(dt, rowId) { - //alert("Empty space clicked - add an item!"); + } }); diff --git a/erpnext/projects/page/projects/projects.py b/erpnext/projects/page/projects/projects.py index 8f170def251..4774194cfc7 100644 --- a/erpnext/projects/page/projects/projects.py +++ b/erpnext/projects/page/projects/projects.py @@ -19,7 +19,7 @@ import webnotes @webnotes.whitelist() def get_tasks(): return webnotes.conn.sql("""select name, project, subject, exp_start_date, exp_end_date, - description from tabTask where + description, status from tabTask where project is not null and exp_start_date is not null and exp_end_date is not null""", as_dict=True) \ No newline at end of file