merged with master (project cleanup)

This commit is contained in:
Rushabh Mehta 2012-08-08 14:28:24 +05:30
commit 0f0d8850d0
24 changed files with 192 additions and 1061 deletions

View File

@ -23,4 +23,7 @@
"public/js/complete_setup.js": [
"erpnext/startup/js/complete_setup.js",
],
"public/js/gantt_task.js": [
"erpnext/projects/gantt_task.js",
]
}

View File

@ -40,10 +40,9 @@
<li>Ace - code editor</li>
<li>Slick Grid - report grid</li>
<li>jQPlot - graphs</li>
<li><a href="http://taitems.github.com/jQuery.Gantt/">JQuery.Gantt</a> - Gantt Chart</li>
<li>JSON2 - JSON builder, parser</li>
<li>JSColor - color picker</li>
<li>sprintf - string formatting</li>
<li>historyjs - AJAX history</li>
</ul>
</ul>

View File

@ -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']
})

View File

@ -545,4 +545,8 @@ patch_list = [
'patch_module': 'patches.august_2012',
'patch_file': 'report_supplier_quotations',
},
{
'patch_module': 'patches.august_2012',
'patch_file': 'task_allocated_to_assigned',
}
]

View File

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

View File

@ -1,78 +0,0 @@
# DocType, Activity Type
[
# These values are common in all dictionaries
{
'creation': '2012-03-27 14:36:05',
'docstatus': 0,
'modified': '2012-03-27 14:36:05',
'modified_by': u'Administrator',
'owner': u'Administrator'
},
# These values are common for all DocType
{
'autoname': u'field:activity_type',
'colour': u'White:FFF',
'doctype': 'DocType',
'in_dialog': 1,
'module': u'Projects',
'name': '__common__',
'section_style': u'Simple',
'server_code_error': u' ',
'version': 12
},
# These values are common for all DocField
{
'doctype': u'DocField',
'fieldname': u'activity_type',
'fieldtype': u'Data',
'label': u'Activity Type',
'name': '__common__',
'parent': u'Activity Type',
'parentfield': u'fields',
'parenttype': u'DocType',
'permlevel': 0,
'reqd': 1
},
# These values are common for all DocPerm
{
'amend': 0,
'cancel': 0,
'create': 1,
'doctype': u'DocPerm',
'name': '__common__',
'parent': u'Activity Type',
'parentfield': u'permissions',
'parenttype': u'DocType',
'permlevel': 0,
'read': 1,
'submit': 0,
'write': 1
},
# DocType, Activity Type
{
'doctype': 'DocType',
'name': u'Activity Type'
},
# DocPerm
{
'doctype': u'DocPerm',
'role': u'System Manager'
},
# DocPerm
{
'doctype': u'DocPerm',
'role': u'Projects User'
},
# DocField
{
'doctype': u'DocField'
}
]

View File

@ -14,42 +14,16 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//-------------------------- Onload ---------------------------
cur_frm.cscript.onload = function(doc, cdt, cdn) {
if(!doc.status) set_multiple(cdt,cdn,{status:'Draft'});
}
// show tasks
//------------------- Get Contact Person based on customer selected ---------------------------
cur_frm.fields_dict['contact_person'].get_query = function(doc, cdt, cdn) {
if(doc.customer)
return 'SELECT `tabContact`.contact_name FROM `tabContact` WHERE (`tabContact`.is_customer = 1 AND `tabContact`.customer_name = "'+ doc.customer+'") AND `tabContact`.docstatus != 2 AND `tabContact`.contact_name LIKE "%s" ORDER BY `tabContact`.contact_name ASC LIMIT 50';
else
msgprint("Please select Customer first")
}
//-------------------------------- get query select Territory ------------------------------------------
cur_frm.fields_dict['territory'].get_query = function(doc,cdt,cdn) {
return 'SELECT `tabTerritory`.`name`,`tabTerritory`.`parent_territory` FROM `tabTerritory` WHERE `tabTerritory`.`is_group` = "No" AND `tabTerritory`.`docstatus`!= 2 AND `tabTerritory`.%(key)s LIKE "%s" ORDER BY `tabTerritory`.`name` ASC LIMIT 50';
}
//------------------------ Customer and its primary contact Details ------------------------------------
cur_frm.cscript.customer = function(doc, cdt, cdn) {
if(doc.customer) get_server_fields('get_customer_details', '','', doc, cdt, cdn, 1);
}
//--------------------- Customer's Contact Person Details --------------------------------------------
cur_frm.cscript.contact_person = function(doc, cdt, cdn) {
if(doc.contact_person) {
get_server_fields('get_contact_details','','',doc, cdt, cdn, 1);
}
}
//--------- calculate gross profit --------------------------------
cur_frm.cscript.project_value = function(doc, cdt, cdn){
get_server_fields('get_gross_profit','','',doc, cdt, cdn, 1);
}
//--------- calculate gross profit --------------------------------
cur_frm.cscript.est_material_cost = function(doc, cdt, cdn){
get_server_fields('get_gross_profit','','',doc, cdt, cdn, 1);
}
cur_frm.cscript.refresh = function(doc) {
if(!doc.__islocal) {
// refresh gantt chart
wn.require('erpnext/projects/gantt_task.js');
if(!cur_frm.gantt_area)
cur_frm.gantt_area = $('<div>')
.appendTo(cur_frm.fields_dict.project_tasks.wrapper);
cur_frm.gantt_area.empty();
erpnext.show_task_gantt(cur_frm.gantt_area, cur_frm.docname);
}
}

View File

@ -3,9 +3,9 @@
# These values are common in all dictionaries
{
'creation': '2012-05-03 18:41:42',
'creation': '2012-08-08 13:25:19',
'docstatus': 0,
'modified': '2012-08-07 15:48:47',
'modified': '2012-08-08 13:55:01',
'modified_by': u'Administrator',
'owner': u'Administrator'
},
@ -225,6 +225,8 @@
# DocField
{
'colour': u'White:FFF',
'description': u'Milestones will be added as Events in the Calendar',
'doctype': u'DocField',
'fieldname': u'project_milestones',
'fieldtype': u'Table',
@ -237,6 +239,26 @@
'search_index': 0
},
# DocField
{
'colour': u'White:FFF',
'description': u'Tasks belonging to this Project.',
'doctype': u'DocField',
'fieldname': u'sb_tasks',
'fieldtype': u'Section Break',
'label': u'Tasks',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'project_tasks',
'fieldtype': u'HTML',
'label': u'Project Tasks',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
@ -282,7 +304,7 @@
'oldfieldname': u'project_value',
'oldfieldtype': u'Currency',
'permlevel': 0,
'reqd': 1,
'reqd': 0,
'search_index': 0,
'trigger': u'Client'
},
@ -322,7 +344,7 @@
'oldfieldname': u'gross_margin_value',
'oldfieldtype': u'Currency',
'permlevel': 0,
'reqd': 1,
'reqd': 0,
'search_index': 0
},
@ -336,7 +358,7 @@
'oldfieldname': u'per_gross_margin',
'oldfieldtype': u'Currency',
'permlevel': 0,
'reqd': 1,
'reqd': 0,
'search_index': 0
},

View File

@ -9,7 +9,7 @@ wn.doclistviews['Project'] = wn.views.ListView.extend({
'`tabProject`.priority',
'IFNULL(`tabProject`.project_value, 0) as project_value',
'IFNULL(`tabProject`.per_gross_margin, 0) as per_gross_margin',
'`tabProject`.completion_date',
'`tabProject`.creation',
]);
//this.stats = this.stats.concat(['company']);
},
@ -46,8 +46,8 @@ wn.doclistviews['Project'] = wn.views.ListView.extend({
},
css: {'text-align': 'right'},
},
{width: '12%', content:'completion_date', css: {
'text-align': 'right', 'color':'#777'
}},
{
width: '12%', content:'modified', css: {'text-align': 'right', 'color':'#777'}
},
]
});

View File

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

View File

@ -1,99 +0,0 @@
// ERPNext - web based ERP (http://erpnext.com)
// Copyright (C) 2012 Web Notes Technologies Pvt Ltd
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
cur_frm.cscript.onload = function(doc, dt, dn) {
// created?
if(cur_frm.mylist) {
cur_frm.mylist.run();
return;
} else {
// create a new listing
var lst = new Listing('Activities Updates');
lst.colwidths = ['5%','30%','40%','25%'];
// define options
var opts = {};
opts.head_main_style = {};
opts.cell_style = { padding:'3px 2px', borderRight : '0px', borderBottom : '1px solid #AAA', verticalAlign: 'top'}
opts.head_style = { padding:'3px 2px', borderBottom : '1px solid #AAA'}
opts.alt_cell_style = {};
opts.hide_print = 1;
opts.no_border = 1;
opts.hide_export = 1;
opts.hide_print = 1;
opts.hide_rec_label = 1;
lst.opts = opts;
// query
lst.get_query = function() {
var doc = cur_frm.doc;
this.query = "select owner,creation,`update`, hours from `tabProject Activity Update` where parent = '"+doc.name+"'";
this.query_max = "select count(*) from `tabProject Activity Update` where parent = '"+doc.name+"'";
}
lst.show_cell = function(cell,ri,ci,d){
// owner and date
if (ci==0){
var d1 = $a(cell,'div');
var img = $a(cell,'img','',{width:'40px'});
img.src = wn.user_info(d[ri][0]).image;
var d2 = $a(cell,'div');
d2.innerHTML = d[ri][0] + ' on: ' + date.str_to_user(d[ri][1]);
}
// update
if(ci==1) {
cell.innerHTML = replace_newlines(d[ri][2]);
}
// Hours
if (ci==2) {
cell.innerHTML = d[ri][3] + ' hrs';
}
}
lst.make(cur_frm.fields_dict['updates_html'].wrapper);
cur_frm.mylist = lst;
lst.run();
}
}
cur_frm.cscript.refresh = function(doc, dt, dn) {
// show activities only after project is saved
var fl = ['new_update','add','hours','updates_html'];
if(doc.__islocal) {
hide_field(fl);}
else {
unhide_field(fl); }
}
cur_frm.cscript.add = function(doc, dt, dn) {
var callback = function(r,rt) {
// refresh listing
cur_frm.mylist.run();
}
$c_obj(make_doclist(doc.doctype, doc.name),'add_update','',callback);
}

View File

@ -1,49 +0,0 @@
# ERPNext - web based ERP (http://erpnext.com)
# Copyright (C) 2012 Web Notes Technologies Pvt Ltd
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Please edit this list and import only required elements
from __future__ import unicode_literals
import webnotes
from webnotes.utils import add_days, add_months, add_years, cint, cstr, date_diff, default_fields, flt, fmt_money, formatdate, generate_hash, getTraceback, get_defaults, get_first_day, get_last_day, getdate, has_common, month_name, now, nowdate, replace_newlines, sendmail, set_default, str_esc_quote, user_format, validate_email_add
from webnotes.model import db_exists
from webnotes.model.doc import Document, addchild, getchildren, make_autoname
from webnotes.model.doclist import getlist, copy_doclist
from webnotes.model.code import get_obj, get_server_obj, run_server_obj, updatedb, check_syntax
from webnotes import session, form, is_testing, msgprint, errprint
set = webnotes.conn.set
sql = webnotes.conn.sql
get_value = webnotes.conn.get_value
in_transaction = webnotes.conn.in_transaction
convert_to_lists = webnotes.conn.convert_to_lists
# -----------------------------------------------------------------------------------------
class DocType:
def __init__(self,d,dl):
self.doc, self.doclist = d, dl
def add_update(self):
d = Document('Project Activity Update')
d.parent = self.doc.name
d.update = self.doc.new_update
d.hours = self.doc.hours
d.save(1)
self.doc.new_update = ''
self.doc.hours = ''

View File

@ -1,167 +0,0 @@
# DocType, Project Activity
[
# These values are common in all dictionaries
{
'creation': '2012-03-27 14:36:06',
'docstatus': 0,
'modified': '2012-03-27 14:36:06',
'modified_by': u'Administrator',
'owner': u'Administrator'
},
# These values are common for all DocType
{
'autoname': u'Activity.######',
'colour': u'White:FFF',
'doctype': 'DocType',
'module': u'Projects',
'name': '__common__',
'section_style': u'Simple',
'server_code_error': u' ',
'version': 15
},
# These values are common for all DocField
{
'doctype': u'DocField',
'name': '__common__',
'parent': u'Project Activity',
'parentfield': u'fields',
'parenttype': u'DocType',
'permlevel': 0
},
# These values are common for all DocPerm
{
'create': 1,
'doctype': u'DocPerm',
'name': '__common__',
'parent': u'Project Activity',
'parentfield': u'permissions',
'parenttype': u'DocType',
'permlevel': 0,
'read': 1,
'role': u'All',
'write': 1
},
# DocType, Project Activity
{
'doctype': 'DocType',
'name': u'Project Activity'
},
# DocPerm
{
'doctype': u'DocPerm'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'project',
'fieldtype': u'Link',
'label': u'Project',
'oldfieldname': u'project',
'oldfieldtype': u'Link',
'options': u'Project'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'activity_name',
'fieldtype': u'Data',
'label': u'Activity Name',
'oldfieldname': u'activity_name',
'oldfieldtype': u'Data',
'print_hide': 1,
'reqd': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'percent_complete',
'fieldtype': u'Select',
'label': u'Percent Complete',
'oldfieldname': u'percent_complete',
'oldfieldtype': u'Select',
'options': u'0\n5\n10\n15\n20\n25\n30\n35\n40\n45\n50\n55\n60\n65\n70\n75\n80\n85\n90\n95\n100',
'reqd': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'last_update',
'fieldtype': u'Date',
'hidden': 1,
'label': u'Last Update',
'oldfieldname': u'last_update',
'oldfieldtype': u'Date',
'print_hide': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'last_update_by',
'fieldtype': u'Data',
'hidden': 1,
'label': u'Last Update By',
'oldfieldname': u'last_update_by',
'oldfieldtype': u'Data',
'print_hide': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'updates',
'fieldtype': u'Section Break',
'label': u'Updates',
'oldfieldtype': u'Section Break'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'updates_html',
'fieldtype': u'HTML',
'label': u'Updates HTML',
'oldfieldtype': u'HTML'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'new_update',
'fieldtype': u'Text',
'label': u'New Update',
'oldfieldname': u'new_update',
'oldfieldtype': u'Text'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'hours',
'fieldtype': u'Float',
'label': u'Hours',
'oldfieldname': u'hours',
'oldfieldtype': u'Float'
},
# DocField
{
'colour': u'White:FFF',
'doctype': u'DocField',
'fieldname': u'add',
'fieldtype': u'Button',
'label': u'Add',
'oldfieldtype': u'Button',
'trigger': u'Client'
}
]

View File

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

View File

@ -1,61 +0,0 @@
# DocType, Project Activity Update
[
# These values are common in all dictionaries
{
'creation': '2012-03-27 14:36:06',
'docstatus': 0,
'modified': '2012-03-27 14:36:06',
'modified_by': u'Administrator',
'owner': u'Administrator'
},
# These values are common for all DocType
{
'colour': u'White:FFF',
'doctype': 'DocType',
'istable': 1,
'module': u'Projects',
'name': '__common__',
'section_style': u'Simple',
'version': 1
},
# These values are common for all DocField
{
'doctype': u'DocField',
'name': '__common__',
'parent': u'Project Activity Update',
'parentfield': u'fields',
'parenttype': u'DocType',
'permlevel': 0
},
# DocType, Project Activity Update
{
'doctype': 'DocType',
'name': u'Project Activity Update'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'update',
'fieldtype': u'Text',
'label': u'Update',
'oldfieldname': u'update',
'oldfieldtype': u'Text'
},
# DocField
{
'colour': u'White:FFF',
'description': u'e.g. 0.5, 2.5 etc',
'doctype': u'DocField',
'fieldname': u'hours',
'fieldtype': u'Float',
'label': u'Hours',
'oldfieldname': u'hours',
'oldfieldtype': u'Float'
}
]

View File

@ -1,30 +0,0 @@
# DocType, Project Control
[
# These values are common in all dictionaries
{
'creation': '2012-03-27 14:36:06',
'docstatus': 0,
'modified': '2012-03-27 14:36:06',
'modified_by': u'Administrator',
'owner': u'harshada@webnotestech.com'
},
# These values are common for all DocType
{
'colour': u'White:FFF',
'doctype': 'DocType',
'issingle': 1,
'module': u'Projects',
'name': '__common__',
'section_style': u'Simple',
'server_code_error': u' ',
'version': 30
},
# DocType, Project Control
{
'doctype': 'DocType',
'name': u'Project Control'
}
]

View File

@ -14,49 +14,9 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
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);
}
});
}

View File

@ -27,8 +27,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
# -----------------------------------------------------------------------------------------
@ -49,15 +47,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):
@ -68,159 +57,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="""<h2>%(name)s</h2>
<p>This is a Notification for the task %(name)s that has been assigned / updated to you
by %(senders_name)s on %(opening_date)s</p>
<p><b>Subject:</b> %(subject)s </p>
<p><b>Project:</b> %(project)s</p>
<p><b>Review Date:</b> %(review_date)s</p>
<p><b>Expected Start Date:</b> %(exp_start_date)s</p>
<p><b>Expected End Date:</b> %(exp_end_date)s</p>
<p><b>Details:</b> %(description)s</p>
<p>(This notification is autogenerated)</p>""" % 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)

View File

@ -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 14:01:34',
'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',
@ -35,7 +35,8 @@
'name': '__common__',
'parent': u'Task',
'parentfield': u'fields',
'parenttype': u'DocType'
'parenttype': u'DocType',
'permlevel': 0
},
# These values are common for all DocPerm
@ -62,7 +63,6 @@
'doctype': u'DocPerm',
'permlevel': 0,
'role': u'All',
'submit': 0,
'write': 1
},
@ -99,7 +99,6 @@
'fieldtype': u'Section Break',
'label': u'Task Details',
'oldfieldtype': u'Section Break',
'permlevel': 0,
'search_index': 0,
'width': u'50%'
},
@ -113,33 +112,9 @@
'label': u'Subject',
'oldfieldname': u'subject',
'oldfieldtype': u'Data',
'permlevel': 0,
'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',
@ -148,7 +123,6 @@
'label': u'Expected Start Date',
'oldfieldname': u'exp_start_date',
'oldfieldtype': u'Date',
'permlevel': 0,
'reqd': 0
},
@ -161,7 +135,6 @@
'label': u'Expected End Date',
'oldfieldname': u'exp_end_date',
'oldfieldtype': u'Date',
'permlevel': 0,
'reqd': 0,
'search_index': 1
},
@ -172,7 +145,6 @@
'fieldname': u'column_break0',
'fieldtype': u'Column Break',
'oldfieldtype': u'Column Break',
'permlevel': 0,
'width': u'50%'
},
@ -186,12 +158,12 @@
'oldfieldname': u'project',
'oldfieldtype': u'Link',
'options': u'Project',
'permlevel': 0,
'trigger': u'Client'
},
# DocField
{
'colour': u'White:FFF',
'doctype': u'DocField',
'fieldname': u'status',
'fieldtype': u'Select',
@ -199,8 +171,7 @@
'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',
'trigger': u'Client'
},
@ -214,31 +185,17 @@
'oldfieldname': u'priority',
'oldfieldtype': u'Select',
'options': u'Low\nMedium\nHigh\nUrgent',
'permlevel': 0,
'reqd': 0,
'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',
'fieldname': u'section_break0',
'fieldtype': u'Section Break',
'oldfieldtype': u'Section Break',
'options': u'Simple',
'permlevel': 0
'options': u'Simple'
},
# DocField
@ -249,123 +206,17 @@
'label': u'Details',
'oldfieldname': u'description',
'oldfieldtype': u'Text Editor',
'permlevel': 0,
'reqd': 0,
'width': u'300px'
},
# DocField
{
'colour': u'White:FFF',
'description': u'If linked to a Customer',
'doctype': u'DocField',
'fieldname': u'customer_details',
'fieldtype': u'Section Break',
'label': u'Customer Details',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'external_or_internal',
'fieldtype': u'Select',
'label': u'External or Internal',
'oldfieldname': u'external_or_internal',
'oldfieldtype': u'Select',
'options': u'External\nInternal',
'permlevel': 0
},
# DocField
{
'colour': u'White:FFF',
'doctype': u'DocField',
'fieldname': u'customer',
'fieldtype': u'Link',
'label': u'Customer',
'oldfieldname': u'customer',
'oldfieldtype': u'Link',
'options': u'Customer',
'permlevel': 0,
'trigger': u'Client'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'customer_name',
'fieldtype': u'Data',
'label': u'Customer Name',
'oldfieldname': u'customer_name',
'oldfieldtype': u'Data',
'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',
'fieldname': u'column_break25',
'fieldtype': u'Column Break',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'senders_contact_no',
'fieldtype': u'Data',
'label': u'Senders Contact No',
'oldfieldname': u'senders_contact_no',
'oldfieldtype': u'Data',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'senders_company',
'fieldtype': u'Data',
'label': u'Senders Company',
'oldfieldname': u'senders_company',
'oldfieldtype': u'Data',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'time_and_budget',
'fieldtype': u'Section Break',
'label': u'Time and Budget',
'oldfieldtype': u'Section Break',
'permlevel': 0
'oldfieldtype': u'Section Break'
},
# DocField
@ -375,7 +226,6 @@
'fieldtype': u'Column Break',
'label': u'Expected',
'oldfieldtype': u'Column Break',
'permlevel': 0,
'width': u'50%'
},
@ -387,7 +237,6 @@
'label': u'Total Hours (Expected)',
'oldfieldname': u'exp_total_hrs',
'oldfieldtype': u'Data',
'permlevel': 0,
'reqd': 0
},
@ -398,8 +247,7 @@
'fieldtype': u'Currency',
'label': u'Allocated Budget',
'oldfieldname': u'allocated_budget',
'oldfieldtype': u'Currency',
'permlevel': 0
'oldfieldtype': u'Currency'
},
# DocField
@ -409,7 +257,6 @@
'fieldtype': u'Column Break',
'label': u'Actual',
'oldfieldtype': u'Column Break',
'permlevel': 0,
'width': u'50%'
},
@ -420,8 +267,7 @@
'fieldtype': u'Date',
'label': u'Actual Start Date',
'oldfieldname': u'act_start_date',
'oldfieldtype': u'Date',
'permlevel': 0
'oldfieldtype': u'Date'
},
# DocField
@ -431,8 +277,7 @@
'fieldtype': u'Date',
'label': u'Actual End Date',
'oldfieldname': u'act_end_date',
'oldfieldtype': u'Date',
'permlevel': 0
'oldfieldtype': u'Date'
},
# DocField
@ -442,8 +287,7 @@
'fieldtype': u'Data',
'label': u'Total Hours (Actual)',
'oldfieldname': u'act_total_hrs',
'oldfieldtype': u'Data',
'permlevel': 0
'oldfieldtype': u'Data'
},
# DocField
@ -453,8 +297,7 @@
'fieldtype': u'Currency',
'label': u'Actual Budget',
'oldfieldname': u'actual_budget',
'oldfieldtype': u'Currency',
'permlevel': 0
'oldfieldtype': u'Currency'
},
# DocField
@ -462,20 +305,7 @@
'doctype': u'DocField',
'fieldname': u'more_details',
'fieldtype': u'Section Break',
'label': u'More Details',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'opening_date',
'fieldtype': u'Date',
'label': u'Creation Date',
'oldfieldname': u'opening_date',
'oldfieldtype': u'Date',
'permlevel': 0,
'reqd': 1
'label': u'More Details'
},
# DocField
@ -488,8 +318,7 @@
'hidden': 1,
'label': u'Review Date',
'oldfieldname': u'review_date',
'oldfieldtype': u'Date',
'permlevel': 0
'oldfieldtype': u'Date'
},
# DocField
@ -502,37 +331,6 @@
'hidden': 1,
'label': u'Closing Date',
'oldfieldname': u'closing_date',
'oldfieldtype': u'Date',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'amended_from',
'fieldtype': u'Data',
'hidden': 1,
'label': u'Amended From',
'no_copy': 1,
'oldfieldname': u'amended_from',
'oldfieldtype': u'Data',
'permlevel': 1,
'print_hide': 1,
'report_hide': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'amendment_date',
'fieldtype': u'Date',
'hidden': 1,
'label': u'Amendment Date',
'no_copy': 1,
'oldfieldname': u'amendment_date',
'oldfieldtype': u'Date',
'permlevel': 1,
'print_hide': 1,
'report_hide': 1
'oldfieldtype': u'Date'
}
]

View File

@ -0,0 +1,88 @@
// ERPNext - web based ERP (http://erpnext.com)
// Copyright (C) 2012 Web Notes Technologies Pvt Ltd
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// gantt chart for project tasks
wn.require('js/lib/jQuery.Gantt/css/style.css');
wn.require('js/lib/jQuery.Gantt/js/jquery.fn.gantt.min.js');
erpnext.show_task_gantt = function(parent, project) {
$(parent).css('min-height', '300px').html('<div class="help-box">Loading...</div>')
var get_source = function(r) {
var source = [];
// projects
$.each(r.message, function(i,v) {
source.push({
name: v.project,
desc: v.subject,
values: [{
label: v.subject,
desc: v.description || v.subject,
from: '/Date("'+v.exp_start_date+'")/',
to: '/Date("'+v.exp_end_date+'")/',
customClass: {
'Open':'ganttRed',
'Pending Review':'ganttOrange',
'Working':'',
'Completed':'ganttGreen',
'Cancelled':'ganttGray'
}[v.status],
dataObj: v
}]
})
});
return source
}
wn.call({
method: 'projects.page.projects.projects.get_tasks',
args: {
project: project || ''
},
callback: function(r) {
$(parent).empty();
if(!r.message.length) {
$(parent).html('<div class="help-box">No Tasks Yet.</div>');
} else {
var gantt_area = $('<div class="gantt">').appendTo(parent);
gantt_area.gantt({
source: get_source(r),
navigate: project ? "button" : "scroll",
scale: "weeks",
minScale: "weeks",
maxScale: "months",
onItemClick: function(data) {
wn.set_route('Form', 'Task', data.name);
},
onAddClick: function(dt, rowId) {
newdoc('Task');
}
});
}
$('<button class="btn"><i class="icon icon-plus"></i>\
Create a new Task</button>').click(function() {
wn.model.with_doctype('Task', function() {
var new_name = LocalDB.create('Task');
if(project)
locals.Task[new_name].project = project;
wn.set_route('Form', 'Task', new_name);
});
}).appendTo(parent);
}
})
}

View File

@ -14,58 +14,11 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
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});
$(wrapper).find('.layout-main').html('<div class="help-box">Loading...</div>')
wn.require('js/lib/jQuery.Gantt/css/style.css');
wn.require('js/lib/jQuery.Gantt/js/jquery.fn.gantt.min.js');
wn.call({
method: 'projects.page.projects.projects.get_tasks',
callback: function(r) {
$(wrapper).find('.layout-main').empty();
var source = [];
// projects
$.each(r.message, function(i,v) {
source.push({
name: v.project,
desc: v.subject,
values: [{
label: v.subject,
desc: v.description || v.subject,
from: '/Date("'+v.exp_start_date+'")/',
to: '/Date("'+v.exp_end_date+'")/'
}]
})
})
var gantt_area = $('<div class="gantt">').appendTo($(wrapper).find('.layout-main'));
gantt_area.gantt({
source: source,
navigate: "scroll",
scale: "weeks",
minScale: "weeks",
maxScale: "months",
onItemClick: function(data) {
alert("Item clicked - show some details");
},
onAddClick: function(dt, rowId) {
//alert("Empty space clicked - add an item!");
}
});
}
})
if(!erpnext.show_task_gantt)
wn.require('js/gantt_task.js');
var gantt_area = $('<div>').appendTo($(wrapper).find('.layout-main'));
erpnext.show_task_gantt(gantt_area);
}

View File

@ -18,8 +18,11 @@ import webnotes
@webnotes.whitelist()
def get_tasks():
cond = ''
if webnotes.form_dict.get('project'):
cond = ' and project="%s"' % webnotes.form_dict.get('project')
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)
and exp_end_date is not null %s""" % cond, as_dict=True)

View File

@ -1107,7 +1107,7 @@ Layout.prototype.show=function(){$ds(this.wrapper);}
Layout.prototype.hide=function(){$dh(this.wrapper);}
Layout.prototype.close_borders=function(){if(this.with_border){this.myrows[this.myrows.length-1].wrapper.style.borderBottom='1px solid #000';}}
function LayoutRow(layout,parent){this.layout=layout;this.wrapper=$a(parent,'div','form-layout-row');this.main_head=$a(this.wrapper,'div');this.main_body=$a(this.wrapper,'div');if(layout.with_border){this.wrapper.style.border='1px solid #000';this.wrapper.style.borderBottom='0px';}
this.header=$a(this.main_body,'div','',{padding:(layout.with_border?'0px 8px':'0px')});this.body=$a(this.main_body,'div');this.table=$a(this.body,'table','',{width:'100%',borderCollapse:'collapse'});this.row=this.table.insertRow(0);this.mycells=[];}
this.header=$a(this.main_body,'div','',{padding:(layout.with_border?'0px 8px':'0px')});this.body=$a(this.main_body,'div');this.table=$a(this.body,'table','',{width:'100%',borderCollapse:'collapse',tableLayout:'fixed'});this.row=this.table.insertRow(0);this.mycells=[];}
LayoutRow.prototype.hide=function(){$dh(this.wrapper);}
LayoutRow.prototype.show=function(){$ds(this.wrapper);}
LayoutRow.prototype.addCell=function(wid){var lc=new LayoutCell(this.layout,this,wid);this.mycells[this.mycells.length]=lc;return lc;}

10
public/js/gantt_task.js Normal file
View File

@ -0,0 +1,10 @@
/*
* erpnext/projects/gantt_task.js
*/
wn.require('js/lib/jQuery.Gantt/css/style.css');wn.require('js/lib/jQuery.Gantt/js/jquery.fn.gantt.min.js');erpnext.show_task_gantt=function(parent,project){$(parent).css('min-height','300px').html('<div class="help-box">Loading...</div>')
var get_source=function(r){var source=[];$.each(r.message,function(i,v){source.push({name:v.project,desc:v.subject,values:[{label:v.subject,desc:v.description||v.subject,from:'/Date("'+v.exp_start_date+'")/',to:'/Date("'+v.exp_end_date+'")/',customClass:{'Open':'ganttRed','Pending Review':'ganttOrange','Working':'','Completed':'ganttGreen','Cancelled':'ganttGray'}[v.status],dataObj:v}]})});return source}
wn.call({method:'projects.page.projects.projects.get_tasks',args:{project:project||''},callback:function(r){$(parent).empty();if(!r.message.length){$(parent).html('<div class="help-box">No Tasks Yet.</div>');}else{var gantt_area=$('<div class="gantt">').appendTo(parent);gantt_area.gantt({source:get_source(r),navigate:project?"button":"scroll",scale:"weeks",minScale:"weeks",maxScale:"months",onItemClick:function(data){wn.set_route('Form','Task',data.name);},onAddClick:function(dt,rowId){newdoc('Task');}});}
$('<button class="btn"><i class="icon icon-plus"></i>\
Create a new Task</button>').click(function(){wn.model.with_doctype('Task',function(){var new_name=LocalDB.create('Task');if(project)
locals.Task[new_name].project=project;wn.set_route('Form','Task',new_name);});}).appendTo(parent);}})}