summaryrefslogtreecommitdiff
path: root/addons/project
diff options
context:
space:
mode:
authorThibault Delavallée <tde@openerp.com>2012-06-01 13:36:25 +0200
committerThibault Delavallée <tde@openerp.com>2012-06-01 13:36:25 +0200
commitcd19f68eb9f145e9049949074e06196d540cf2c2 (patch)
tree6c050ac836af1e3226ce7b71726db7e40b32a126 /addons/project
parentc9ce120fcdda692dce255359654e9b393332197b (diff)
parentf9e6b60c9f48c48d7b0d2a9b67a3e2376e032fd2 (diff)
[MERGE] Merged with main addons.
bzr revid: tde@openerp.com-20120601113625-c9w0kmnw1dzvjswx
Diffstat (limited to 'addons/project')
-rw-r--r--addons/project/__openerp__.py2
-rw-r--r--addons/project/board_project_view.xml27
-rw-r--r--addons/project/project.py317
-rw-r--r--addons/project/project_data.xml28
-rw-r--r--addons/project/project_demo.xml54
-rw-r--r--addons/project/project_view.xml95
-rw-r--r--addons/project/report/project_cumulative.xml3
-rw-r--r--addons/project/report/project_report.py4
-rw-r--r--addons/project/report/project_report_view.xml2
-rw-r--r--addons/project/static/src/js/project.js10
-rw-r--r--addons/project/test/task_process.yml6
11 files changed, 311 insertions, 237 deletions
diff --git a/addons/project/__openerp__.py b/addons/project/__openerp__.py
index ef26425d3c9..2c53fc2a28a 100644
--- a/addons/project/__openerp__.py
+++ b/addons/project/__openerp__.py
@@ -28,7 +28,7 @@
"category": "Project Management",
"sequence": 8,
"images": ["images/gantt.png", "images/project_dashboard.jpeg","images/project_task_tree.jpeg","images/project_task.jpeg","images/project.jpeg","images/task_analysis.jpeg"],
- "depends": ["base_setup", "product", "analytic", "board", "mail", "resource","web_kanban"],
+ "depends": ["base_setup", "base_status", "product", "analytic", "board", "mail", "resource","web_kanban"],
"description": """
Project management module tracks multi-level projects, tasks, work done on tasks, eso.
======================================================================================
diff --git a/addons/project/board_project_view.xml b/addons/project/board_project_view.xml
index fa6816ebbf7..1f06ea6938c 100644
--- a/addons/project/board_project_view.xml
+++ b/addons/project/board_project_view.xml
@@ -17,11 +17,16 @@
<field name="planned_hours" widget="float_time"/>
<field name="effective_hours" widget="float_time"/>
<field name="progress" widget="progressbar"/>
- <field name="state" invisible="context.get('set_visible',False)"/>
- <button name="do_cancel" states="draft,open,pending" string="Cancel" type="object" icon="gtk-cancel" help="For cancelling the task"/>
- <button name="do_open" states="pending,draft,done,cancel" string="Start Task" type="object" icon="gtk-execute" help="For changing to open state" invisible="context.get('set_visible',False)"/>
- <button name="%(action_project_task_delegate)d" states="pending,open,draft" string="Delegate" type="action" icon="gtk-sort-descending" help="For changing to delegate state"/>
- <button name="action_close" states="draft,pending,open" string="Done" type="object" icon="terp-dialog-close" help="For changing to done state"/>
+ <field name="stage_id" invisible="context.get('set_visible',False)"/>
+ <field name="state" invisible="context.get('set_visible',False)" groups="base.group_no_one"/>
+ <button name="do_open" string="Start Task" type="object"
+ states="draft,pending" icon="gtk-go-forward" invisible="context.get('set_visible',False)"/>
+ <button name="action_close" string="Done" type="object"
+ states="draft,open,pending" icon="gtk-apply" invisible="context.get('set_visible',False)"/>
+ <button name="do_cancel" string="Cancel" type="object"
+ states="open,draft,pending" icon="gtk-cancel" invisible="context.get('set_visible',False)"/>
+ <button name="%(action_project_task_delegate)d" string="Delegate" type="action"
+ states="pending,open,draft" icon="gtk-sort-descending"/>
</tree>
</field>
</record>
@@ -39,10 +44,14 @@
<field name="date_deadline"/>
<field name="total_hours" widget="float_time"/>
<field name="progress" widget="progressbar"/>
- <field name="state" invisible="context.get('set_visible',False)"/>
- <button name="do_cancel" states="draft,open,pending" string="Cancel" type="object" icon="gtk-cancel" help="For cancelling the task"/>
- <button name="do_open" states="pending,draft,done,cancel" string="Start Task" type="object" icon="gtk-execute" help="For changing to open state" invisible="context.get('set_visible',False)"/>
- <button name="action_close" states="draft,pending,open" string="Done" type="object" icon="gtk-apply" help="For changing to done state"/>
+ <field name="stage_id" invisible="context.get('set_visible',False)"/>
+ <field name="state" invisible="context.get('set_visible',False)" groups="base.group_no_one"/>
+ <button name="do_open" string="Start Task" type="object"
+ states="draft,pending" icon="gtk-go-forward" invisible="context.get('set_visible',False)"/>
+ <button name="action_close" string="Done" type="object"
+ states="draft,open,pending" icon="gtk-apply" invisible="context.get('set_visible',False)"/>
+ <button name="do_cancel" string="Cancel" type="object"
+ states="open,draft,pending" icon="gtk-cancel" invisible="context.get('set_visible',False)"/>
</tree>
</field>
</record>
diff --git a/addons/project/project.py b/addons/project/project.py
index 804e14a15fe..e7af9f49b7d 100644
--- a/addons/project/project.py
+++ b/addons/project/project.py
@@ -2,7 +2,7 @@
##############################################################################
#
# OpenERP, Open Source Management Solution
-# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
+# Copyright (C) 2004-today OpenERP SA (<http://www.openerp.com>)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
@@ -19,18 +19,15 @@
#
##############################################################################
-from lxml import etree
-import time
+from base_status.base_stage import base_stage
from datetime import datetime, date
-
-from tools.translate import _
+from lxml import etree
from osv import fields, osv
from openerp.addons.resource.faces import task as Task
+import time
+from tools.translate import _
-# I think we can remove this in v6.1 since VMT's improvements in the framework ?
-#class project_project(osv.osv):
-# _name = 'project.project'
-#project_project()
+_TASK_STATE = [('draft', 'New'),('open', 'In Progress'),('pending', 'Pending'), ('done', 'Done'), ('cancelled', 'Cancelled')]
class project_task_type(osv.osv):
_name = 'project.task.type'
@@ -40,14 +37,20 @@ class project_task_type(osv.osv):
'name': fields.char('Stage Name', required=True, size=64, translate=True),
'description': fields.text('Description'),
'sequence': fields.integer('Sequence'),
- 'project_default': fields.boolean('Common to All Projects', help="If you check this field, this stage will be proposed by default on each new project. It will not assign this stage to existing projects."),
+ 'case_default': fields.boolean('Common to All Projects',
+ help="If you check this field, this stage will be proposed by default on each new project. It will not assign this stage to existing projects."),
'project_ids': fields.many2many('project.project', 'project_task_type_rel', 'type_id', 'project_id', 'Projects'),
+ 'state': fields.selection(_TASK_STATE, 'State', required=True,
+ help="The related state for the stage. The state of your document will automatically change regarding the selected stage. Example, a stage is related to the state 'Close', when your document reach this stage, it will be automatically closed."),
+ 'fold': fields.boolean('Hide in views if empty',
+ help="This stage is not visible, for example in status bar or kanban view, when there are no records in that stage to display."),
}
_defaults = {
- 'sequence': 1
+ 'sequence': 1,
+ 'state': 'draft',
+ 'fold': False,
}
_order = 'sequence'
-project_task_type()
class project(osv.osv):
_name = "project.project"
@@ -208,7 +211,7 @@ class project(osv.osv):
return True
def _get_type_common(self, cr, uid, context):
- ids = self.pool.get('project.task.type').search(cr, uid, [('project_default','=',1)], context=context)
+ ids = self.pool.get('project.task.type').search(cr, uid, [('case_default','=',1)], context=context)
return ids
_order = "sequence"
@@ -239,7 +242,7 @@ class project(osv.osv):
def set_done(self, cr, uid, ids, context=None):
task_obj = self.pool.get('project.task')
task_ids = task_obj.search(cr, uid, [('project_id', 'in', ids), ('state', 'not in', ('cancelled', 'done'))])
- task_obj.write(cr, uid, task_ids, {'state': 'done', 'date_end':time.strftime('%Y-%m-%d %H:%M:%S'), 'remaining_hours': 0.0})
+ task_obj.case_close(cr, uid, task_ids, context=context)
self.write(cr, uid, ids, {'state':'close'}, context=context)
self.set_close_send_note(cr, uid, ids, context=context)
return True
@@ -247,7 +250,7 @@ class project(osv.osv):
def set_cancel(self, cr, uid, ids, context=None):
task_obj = self.pool.get('project.task')
task_ids = task_obj.search(cr, uid, [('project_id', 'in', ids), ('state', '!=', 'done')])
- task_obj.write(cr, uid, task_ids, {'state': 'cancelled', 'date_end':time.strftime('%Y-%m-%d %H:%M:%S'), 'remaining_hours': 0.0})
+ task_obj.case_cancel(cr, uid, task_ids, context=context)
self.write(cr, uid, ids, {'state':'cancelled'}, context=context)
self.set_cancel_send_note(cr, uid, ids, context=context)
return True
@@ -501,48 +504,60 @@ def Project():
def set_close_send_note(self, cr, uid, ids, context=None):
message = _("Project has been <b>closed</b>.")
return self.message_append_note(cr, uid, ids, body=message, context=context)
-
-project()
-class task(osv.osv):
+
+class task(base_stage, osv.osv):
_name = "project.task"
_description = "Task"
_date_name = "date_start"
_inherit = ['ir.needaction_mixin', 'mail.thread']
+ def _get_default_project_id(self, cr, uid, context=None):
+ """ Gives default section by checking if present in the context """
+ return (self._resolve_project_id_from_context(cr, uid, context=context) or False)
+
+ def _get_default_stage_id(self, cr, uid, context=None):
+ """ Gives default stage_id """
+ project_id = self._get_default_project_id(cr, uid, context=context)
+ return self.stage_find(cr, uid, [], project_id, [('state', '=', 'draft')], context=context)
def _resolve_project_id_from_context(self, cr, uid, context=None):
- """Return ID of project based on the value of 'project_id'
- context key, or None if it cannot be resolved to a single project.
+ """ Returns ID of project based on the value of 'default_project_id'
+ context key, or None if it cannot be resolved to a single
+ project.
"""
if context is None: context = {}
if type(context.get('default_project_id')) in (int, long):
- project_id = context['default_project_id']
- return project_id
+ return context['default_project_id']
if isinstance(context.get('default_project_id'), basestring):
project_name = context['default_project_id']
- project_ids = self.pool.get('project.project').name_search(cr, uid, name=project_name)
+ project_ids = self.pool.get('project.project').name_search(cr, uid, name=project_name, context=context)
if len(project_ids) == 1:
return project_ids[0][0]
+ return None
- def _read_group_type_id(self, cr, uid, ids, domain, read_group_order=None, access_rights_uid=None, context=None):
+ def _read_group_stage_ids(self, cr, uid, ids, domain, read_group_order=None, access_rights_uid=None, context=None):
stage_obj = self.pool.get('project.task.type')
- project_id = self._resolve_project_id_from_context(cr, uid, context=context)
order = stage_obj._order
access_rights_uid = access_rights_uid or uid
- if read_group_order == 'type_id desc':
- # lame way to allow reverting search, should just work in the trivial case
+ # lame way to allow reverting search, should just work in the trivial case
+ if read_group_order == 'stage_id desc':
order = '%s desc' % order
+ # retrieve section_id from the context and write the domain
+ # - ('id', 'in', 'ids'): add columns that should be present
+ # - OR ('case_default', '=', True), ('fold', '=', False): add default columns that are not folded
+ # - OR ('project_ids', 'in', project_id), ('fold', '=', False) if project_id: add project columns that are not folded
+ search_domain = []
+ project_id = self._resolve_project_id_from_context(cr, uid, context=context)
if project_id:
- domain = ['|', ('id','in',ids), ('project_ids','in',project_id)]
- else:
- domain = ['|', ('id','in',ids), ('project_default','=',1)]
- stage_ids = stage_obj._search(cr, uid, domain, order=order, access_rights_uid=access_rights_uid, context=context)
+ search_domain += ['|', '&', ('project_ids', '=', project_id), ('fold', '=', False)]
+ search_domain += ['|', ('id', 'in', ids), '&', ('case_default', '=', True), ('fold', '=', False)]
+ stage_ids = stage_obj._search(cr, uid, search_domain, order=order, access_rights_uid=access_rights_uid, context=context)
result = stage_obj.name_get(cr, access_rights_uid, stage_ids, context=context)
# restore order of the search
result.sort(lambda x,y: cmp(stage_ids.index(x[0]), stage_ids.index(y[0])))
return result
-
+
def _read_group_user_id(self, cr, uid, ids, domain, read_group_order=None, access_rights_uid=None, context=None):
res_users = self.pool.get('res.users')
project_id = self._resolve_project_id_from_context(cr, uid, context=context)
@@ -561,11 +576,10 @@ class task(osv.osv):
return result
_group_by_full = {
- 'type_id': _read_group_type_id,
- 'user_id': _read_group_user_id
+ 'stage_id': _read_group_stage_ids,
+ 'user_id': _read_group_user_id,
}
-
def search(self, cr, user, args, offset=0, limit=None, order=None, context=None, count=False):
obj_project = self.pool.get('project.project')
for domain in args:
@@ -596,7 +610,6 @@ class task(osv.osv):
res[task.id]['progress'] = 100.0
return res
-
def onchange_remaining(self, cr, uid, ids, remaining=0.0, planned = 0.0):
if remaining and not planned:
return {'value':{'planned_hours': remaining}}
@@ -639,7 +652,7 @@ class task(osv.osv):
if not default.get('remaining_hours', False):
default['remaining_hours'] = float(self.read(cr, uid, id, ['planned_hours'])['planned_hours'])
default['active'] = True
- default['type_id'] = False
+ default['stage_id'] = False
if not default.get('name', False):
default['name'] = self.browse(cr, uid, id, context=context).name or ''
if not context.get('copy',False):
@@ -669,10 +682,15 @@ class task(osv.osv):
'description': fields.text('Description'),
'priority': fields.selection([('4','Very Low'), ('3','Low'), ('2','Medium'), ('1','Important'), ('0','Very important')], 'Priority', select=True),
'sequence': fields.integer('Sequence', select=True, help="Gives the sequence order when displaying a list of tasks."),
- 'type_id': fields.many2one('project.task.type', 'Stage'),
- 'state': fields.selection([('draft', 'New'),('cancelled', 'Cancelled'),('open', 'In Progress'),('pending', 'Pending'), ('done', 'Done')], 'Status', readonly=True, required=True,
- help='If the task is created the state is \'Draft\'.\n If the task is started, the state becomes \'In Progress\'.\n If review is needed the task is in \'Pending\' state.\
- \n If the task is over, the states is set to \'Done\'.'),
+ 'stage_id': fields.many2one('project.task.type', 'Stage',
+ domain="['|', ('project_ids', '=', project_id), ('case_default', '=', True)]"),
+ 'state': fields.related('stage_id', 'state', type="selection", store=True,
+ selection=_TASK_STATE, string="State", readonly=True,
+ help='The state is set to \'Draft\', when a case is created.\
+ If the case is in progress the state is set to \'Open\'.\
+ When the case is over, the state is set to \'Done\'.\
+ If the case needs to be reviewed then the state is \
+ set to \'Pending\'.'),
'kanban_state': fields.selection([('normal', 'Normal'),('blocked', 'Blocked'),('done', 'Ready To Pull')], 'Kanban State',
help="A task's kanban state indicates special situations affecting it:\n"
" * Normal is the default situation\n"
@@ -721,6 +739,8 @@ class task(osv.osv):
}
_defaults = {
+ 'stage_id': _get_default_stage_id,
+ 'project_id': _get_default_project_id,
'state': 'draft',
'kanban_state': 'normal',
'priority': '2',
@@ -728,7 +748,7 @@ class task(osv.osv):
'sequence': 10,
'active': True,
'user_id': lambda obj, cr, uid, context: uid,
- 'company_id': lambda self, cr, uid, c: self.pool.get('res.company')._company_default_get(cr, uid, 'project.task', context=c)
+ 'company_id': lambda self, cr, uid, c: self.pool.get('res.company')._company_default_get(cr, uid, 'project.task', context=c),
}
_order = "priority, sequence, date_start, name, id"
@@ -827,6 +847,41 @@ class task(osv.osv):
res['fields'][f]['string'] = res['fields'][f]['string'].replace('Hours',tm)
return res
+ # ****************************************
+ # Case management
+ # ****************************************
+
+ def stage_find(self, cr, uid, cases, section_id, domain=[], order='sequence', context=None):
+ """ Override of the base.stage method
+ Parameter of the stage search taken from the lead:
+ - section_id: if set, stages must belong to this section or
+ be a default stage; if not set, stages must be default
+ stages
+ """
+ if isinstance(cases, (int, long)):
+ cases = self.browse(cr, uid, cases, context=context)
+ # collect all section_ids
+ section_ids = []
+ if section_id:
+ section_ids.append(section_id)
+ for task in cases:
+ if task.project_id:
+ section_ids.append(task.project_id.id)
+ # OR all section_ids and OR with case_default
+ search_domain = []
+ if section_ids:
+ search_domain += [('|')] * len(section_ids)
+ for section_id in section_ids:
+ search_domain.append(('project_ids', '=', section_id))
+ search_domain.append(('case_default', '=', True))
+ # AND with the domain in parameter
+ search_domain += list(domain)
+ # perform search, return the first found
+ stage_ids = self.pool.get('project.task.type').search(cr, uid, search_domain, order=order, context=context)
+ if stage_ids:
+ return stage_ids[0]
+ return False
+
def _check_child_task(self, cr, uid, ids, context=None):
if context == None:
context = {}
@@ -839,9 +894,9 @@ class task(osv.osv):
return True
def action_close(self, cr, uid, ids, context=None):
- # This action open wizard to send email to partner or project manager after close task.
- if context == None:
- context = {}
+ """ This action closes the task, then opens the wizard to send an
+ email to the partner or the project manager.
+ """
task_id = len(ids) and ids[0] or False
self._check_child_task(cr, uid, ids, context=context)
if not task_id: return False
@@ -862,12 +917,14 @@ class task(osv.osv):
}
return res
- def do_close(self, cr, uid, ids, context={}):
- """
- Close Task
- """
-
- if not isinstance(ids,list): ids = [ids]
+ def do_close(self, cr, uid, ids, context=None):
+ """ Compatibility when changing to case_close. """
+ return self.case_close(cr, uid, ids, context=context)
+
+ def case_close(self, cr, uid, ids, context=None):
+ """ Closes Task """
+ request = self.pool.get('res.request')
+ if not isinstance(ids, list): ids = [ids]
for task in self.browse(cr, uid, ids, context=context):
vals = {}
project = task.project_id
@@ -879,47 +936,61 @@ class task(osv.osv):
reopen = False
if reopen:
self.do_reopen(cr, uid, [parent_id.id], context=context)
- vals.update({'state': 'done'})
- vals.update({'remaining_hours': 0.0})
+ # close task
+ vals['remaining_hours'] = 0.0
if not task.date_end:
- vals.update({ 'date_end':time.strftime('%Y-%m-%d %H:%M:%S')})
- self.write(cr, uid, [task.id],vals, context=context)
- self.do_close_send_note(cr, uid, [task.id], context)
+ vals['date_end'] = fields.datetime.now()
+ self.case_set(cr, uid, [task.id], 'done', vals, context=context)
+ self.case_close_send_note(cr, uid, [task.id], context=context)
return True
def do_reopen(self, cr, uid, ids, context=None):
-
for task in self.browse(cr, uid, ids, context=context):
project = task.project_id
- self.write(cr, uid, [task.id], {'state': 'open'}, context=context)
- self.do_open_send_note(cr, uid, [task.id], context)
+ self.case_set(cr, uid, [task.id], 'open', {}, context=context)
+ self.case_open_send_note(cr, uid, [task.id], context)
return True
- def do_cancel(self, cr, uid, ids, context={}):
+ def do_cancel(self, cr, uid, ids, context=None):
+ """ Compatibility when changing to case_cancel. """
+ return self.case_cancel(cr, uid, ids, context=context)
+
+ def case_cancel(self, cr, uid, ids, context=None):
+ request = self.pool.get('res.request')
tasks = self.browse(cr, uid, ids, context=context)
self._check_child_task(cr, uid, ids, context=context)
for task in tasks:
- self.write(cr, uid, [task.id], {'state': 'cancelled', 'remaining_hours':0.0}, context=context)
- self.do_cancel_send_note(cr, uid, [task.id], context)
+ self.case_set(cr, uid, [task.id], 'cancelled', {'remaining_hours': 0.0}, context=context)
+ self.case_cancel_send_note(cr, uid, [task.id], context=context)
return True
- def do_open(self, cr, uid, ids, context={}):
+ def do_open(self, cr, uid, ids, context=None):
+ """ Compatibility when changing to case_open. """
+ return self.case_open(cr, uid, ids, context=context)
+
+ def case_open(self, cr, uid, ids, context=None):
if not isinstance(ids,list): ids = [ids]
- tasks= self.browse(cr, uid, ids, context=context)
- for t in tasks:
- data = {'state': 'open'}
- if not t.date_start:
- data['date_start'] = time.strftime('%Y-%m-%d %H:%M:%S')
- self.write(cr, uid, [t.id], data, context=context)
- self.do_open_send_note(cr, uid, [t.id], context)
+ self.case_set(cr, uid, ids, 'open', {'date_start': fields.datetime.now()}, context=context)
+ self.case_open_send_note(cr, uid, ids, context)
return True
- def do_draft(self, cr, uid, ids, context={}):
- self.write(cr, uid, ids, {'state': 'draft'}, context=context)
- self.do_draft_send_note(cr, uid, ids, context)
+ def do_draft(self, cr, uid, ids, context=None):
+ """ Compatibility when changing to case_draft. """
+ return self.case_draft(cr, uid, ids, context=context)
+
+ def case_draft(self, cr, uid, ids, context=None):
+ self.case_set(cr, uid, ids, 'draft', {}, context=context)
+ self.case_draft_send_note(cr, uid, ids, context=context)
return True
-
+ def do_pending(self, cr, uid, ids, context=None):
+ """ Compatibility when changing to case_pending. """
+ return self.case_pending(cr, uid, ids, context=context)
+
+ def case_pending(self, cr, uid, ids, context=None):
+ self.case_set(cr, uid, ids, 'pending', {}, context=context)
+ return self.case_pending_send_note(cr, uid, ids, context=context)
+
def _delegate_task_attachments(self, cr, uid, task_id, delegated_task_id, context=None):
attachment = self.pool.get('ir.attachment')
attachment_ids = attachment.search(cr, uid, [('res_model', '=', self._name), ('res_id', '=', task_id)], context=context)
@@ -928,7 +999,6 @@ class task(osv.osv):
new_attachment_ids.append(attachment.copy(cr, uid, attachment_id, default={'res_id': delegated_task_id}, context=context))
return new_attachment_ids
-
def do_delegate(self, cr, uid, ids, delegate_data={}, context=None):
"""
Delegate Task to another users.
@@ -962,11 +1032,6 @@ class task(osv.osv):
delegated_tasks[task.id] = delegated_task_id
return delegated_tasks
- def do_pending(self, cr, uid, ids, context={}):
- self.write(cr, uid, ids, {'state': 'pending'}, context=context)
- self.do_pending_send_note(cr, uid, ids, context)
- return True
-
def set_remaining_time(self, cr, uid, ids, remaining_time=1.0, context=None):
for task in self.browse(cr, uid, ids, context=context):
if (task.state=='draft') or (task.planned_hours==0.0):
@@ -995,35 +1060,6 @@ class task(osv.osv):
def set_kanban_state_done(self, cr, uid, ids, context=None):
self.write(cr, uid, ids, {'kanban_state': 'done'}, context=context)
- def _change_type(self, cr, uid, ids, next, context=None):
- """
- go to the next stage
- if next is False, go to previous stage
- """
- for task in self.browse(cr, uid, ids):
- if task.project_id.type_ids:
- typeid = task.type_id.id
- types_seq={}
- for type in task.project_id.type_ids :
- types_seq[type.id] = type.sequence
- if next:
- types = sorted(types_seq.items(), lambda x, y: cmp(x[1], y[1]))
- else:
- types = sorted(types_seq.items(), lambda x, y: cmp(y[1], x[1]))
- sorted_types = [x[0] for x in types]
- if not typeid:
- self.write(cr, uid, task.id, {'type_id': sorted_types[0]})
- elif typeid and typeid in sorted_types and sorted_types.index(typeid) != len(sorted_types)-1:
- index = sorted_types.index(typeid)
- self.write(cr, uid, task.id, {'type_id': sorted_types[index+1]})
- return True
-
- def next_type(self, cr, uid, ids, context=None):
- return self._change_type(cr, uid, ids, True, context=context)
-
- def prev_type(self, cr, uid, ids, context=None):
- return self._change_type(cr, uid, ids, False, context=context)
-
def _store_history(self, cr, uid, ids, context=None):
for task in self.browse(cr, uid, ids, context=context):
self.pool.get('project.task.history').create(cr, uid, {
@@ -1031,7 +1067,7 @@ class task(osv.osv):
'remaining_hours': task.remaining_hours,
'planned_hours': task.planned_hours,
'kanban_state': task.kanban_state,
- 'type_id': task.type_id.id,
+ 'type_id': task.stage_id.id,
'state': task.state,
'user_id': task.user_id.id
@@ -1045,22 +1081,25 @@ class task(osv.osv):
return task_id
# Overridden to reset the kanban_state to normal whenever
- # the stage (type_id) of the task changes.
+ # the stage (stage_id) of the task changes.
def write(self, cr, uid, ids, vals, context=None):
if isinstance(ids, (int, long)):
ids = [ids]
- if vals and not 'kanban_state' in vals and 'type_id' in vals:
- new_stage = vals.get('type_id')
+ if vals and not 'kanban_state' in vals and 'stage_id' in vals:
+ new_stage = vals.get('stage_id')
vals_reset_kstate = dict(vals, kanban_state='normal')
for t in self.browse(cr, uid, ids, context=context):
- write_vals = vals_reset_kstate if t.type_id != new_stage else vals
+ #TO FIX:Kanban view doesn't raise warning
+ #stages = [stage.id for stage in t.project_id.type_ids]
+ #if new_stage not in stages:
+ #raise osv.except_osv(_('Warning !'), _('Stage is not defined in the project.'))
+ write_vals = vals_reset_kstate if t.stage_id != new_stage else vals
super(task,self).write(cr, uid, [t.id], write_vals, context=context)
result = True
else:
result = super(task,self).write(cr, uid, ids, vals, context=context)
- if ('type_id' in vals) or ('remaining_hours' in vals) or ('user_id' in vals) or ('state' in vals) or ('kanban_state' in vals):
+ if ('stage_id' in vals) or ('remaining_hours' in vals) or ('user_id' in vals) or ('state' in vals) or ('kanban_state' in vals):
self._store_history(cr, uid, ids, context=context)
- self.stage_change_send_note(cr, uid, ids, context)
return result
def unlink(self, cr, uid, ids, context=None):
@@ -1100,7 +1139,11 @@ class task(osv.osv):
# ---------------------------------------------------
# OpenChatter methods and notifications
# ---------------------------------------------------
-
+
+ def case_get_note_msg_prefix(self, cr, uid, id, context=None):
+ """ Override of default prefix for notifications. """
+ return 'Task'
+
def get_needaction_user_ids(self, cr, uid, ids, context=None):
result = dict.fromkeys(ids, [])
for obj in self.browse(cr, uid, ids, context=context):
@@ -1117,28 +1160,16 @@ class task(osv.osv):
sub_ids.append(obj.manager_id.id)
return self.pool.get('res.users').read(cr, uid, sub_ids, context=context)
+ def stage_set_send_note(self, cr, uid, ids, stage_id, context=None):
+ """ Override of the (void) default notification method. """
+ stage_name = self.pool.get('project.task.type').name_get(cr, uid, [stage_id], context=context)[0][1]
+ return self.message_append_note(cr, uid, ids, body= _("Stage changed to <b>%s</b>.") % (stage_name), context=context)
+
def create_send_note(self, cr, uid, ids, context=None):
return self.message_append_note(cr, uid, ids, body=_("Task has been <b>created</b>."), context=context)
- def do_pending_send_note(self, cr, uid, ids, context=None):
- if not isinstance(ids,list): ids = [ids]
- msg = _('Task is now <b>pending</b>.')
- return self.message_append_note(cr, uid, ids, body=msg, context=context)
-
- def do_open_send_note(self, cr, uid, ids, context=None):
- msg = _('Task has been <b>opened</b>.')
- return self.message_append_note(cr, uid, ids, body=msg, context=context)
-
- def do_cancel_send_note(self, cr, uid, ids, context=None):
- msg = _('Task has been <b>canceled</b>.')
- return self.message_append_note(cr, uid, ids, body=msg, context=context)
-
- def do_close_send_note(self, cr, uid, ids, context=None):
- msg = _('Task has been <b>closed</b>.')
- return self.message_append_note(cr, uid, ids, body=msg, context=context)
-
- def do_draft_send_note(self, cr, uid, ids, context=None):
- msg = _('Task has been <b>renewed</b>.')
+ def case_draft_send_note(self, cr, uid, ids, context=None):
+ msg = _('Task has been set as <b>draft</b>.')
return self.message_append_note(cr, uid, ids, body=msg, context=context)
def do_delegation_send_note(self, cr, uid, ids, context=None):
@@ -1147,13 +1178,6 @@ class task(osv.osv):
self.message_append_note(cr, uid, [task.id], body=msg, context=context)
return True
- def stage_change_send_note(self, cr, uid, ids, context=None):
- for task in self.browse(cr, uid, ids, context=context):
- msg = _('Stage changed to <b>%s</b>') % (task.type_id.name)
- self.message_append_note(cr, uid, [task.id], body=msg, context=context)
- return True
-
-task()
class project_work(osv.osv):
_name = "project.task.work"
@@ -1192,7 +1216,7 @@ class project_work(osv.osv):
for work in self.browse(cr, uid, ids):
cr.execute('update project_task set remaining_hours=remaining_hours + %s where id=%s', (work.hours, work.task_id.id))
return super(project_work,self).unlink(cr, uid, ids,*args, **kwargs)
-project_work()
+
class account_analytic_account(osv.osv):
@@ -1213,7 +1237,6 @@ class account_analytic_account(osv.osv):
raise osv.except_osv(_('Warning !'), _('Please delete the project linked with this account first.'))
return super(account_analytic_account, self).unlink(cr, uid, ids, *args, **kwargs)
-account_analytic_account()
#
# Tasks History, used for cumulative flow charts (Lean/Agile)
@@ -1274,7 +1297,7 @@ class project_task_history(osv.osv):
_defaults = {
'date': fields.date.context_today,
}
-project_task_history()
+
class project_task_history_cumulative(osv.osv):
_name = 'project.task.history.cumulative'
@@ -1302,4 +1325,4 @@ class project_task_history_cumulative(osv.osv):
) as history
)
""")
-project_task_history_cumulative()
+
diff --git a/addons/project/project_data.xml b/addons/project/project_data.xml
index b7b59911fa4..4c95373d91f 100644
--- a/addons/project/project_data.xml
+++ b/addons/project/project_data.xml
@@ -24,22 +24,40 @@
<record id="project_tt_specification" model="project.task.type">
<field name="sequence">1</field>
<field name="name">Design</field>
- <field name="project_default" eval="1"/>
+ <field name="state">draft</field>
+ <field name="case_default" eval="True"/>
</record>
<record id="project_tt_development" model="project.task.type">
<field name="sequence">2</field>
<field name="name">Development</field>
- <field name="project_default" eval="1"/>
+ <field name="state">open</field>
+ <field name="case_default" eval="True"/>
</record>
<record id="project_tt_testing" model="project.task.type">
<field name="sequence">3</field>
<field name="name">Testing</field>
- <field name="project_default" eval="1"/>
+ <field name="state">open</field>
+ <field name="case_default" eval="True"/>
</record>
- <record id="project_tt_merge" model="project.task.type">
+ <record id="project_tt_pending" model="project.task.type">
<field name="sequence">4</field>
+ <field name="name">Pending</field>
+ <field name="state">pending</field>
+ <field name="case_default" eval="True"/>
+ <field name="fold" eval="True"/>
+ </record>
+ <record id="project_tt_merge" model="project.task.type">
+ <field name="sequence">5</field>
<field name="name">Deployment</field>
- <field name="project_default" eval="1"/>
+ <field name="state">done</field>
+ <field name="case_default" eval="True"/>
+ </record>
+ <record id="project_tt_cancel" model="project.task.type">
+ <field name="sequence">6</field>
+ <field name="name">Cancelled</field>
+ <field name="state">cancelled</field>
+ <field name="case_default" eval="True"/>
+ <field name="fold" eval="True"/>
</record>
</data>
</openerp>
diff --git a/addons/project/project_demo.xml b/addons/project/project_demo.xml
index 2f8c9e9638a..f685f14c85b 100644
--- a/addons/project/project_demo.xml
+++ b/addons/project/project_demo.xml
@@ -77,7 +77,7 @@
<field name="priority">2</field>
<field name="project_id" ref="project.project_integrate_openerp"/>
<field name="name">Prepare Requirements Document</field>
- <field name="type_id" ref="project_tt_specification"/>
+ <field name="stage_id" ref="project_tt_specification"/>
<field name="color">3</field>
</record>
@@ -88,7 +88,7 @@
<field name="priority">2</field>
<field name="project_id" ref="project.project_integrate_openerp"/>
<field name="name">Make SRS</field>
- <field name="type_id" ref="project_tt_specification"/>
+ <field name="stage_id" ref="project_tt_specification"/>
</record>
<record id="project_task_3" model="project.task">
@@ -99,7 +99,7 @@
<field name="project_id" ref="project.project_integrate_openerp"/>
<field name="name">Design Use Cases</field>
<field name="date_deadline" eval="time.strftime('%Y-%m-24')"/>
- <field name="type_id" ref="project_tt_specification"/>
+ <field name="stage_id" ref="project_tt_specification"/>
</record>
<record id="project_task_4" model="project.task">
@@ -112,7 +112,7 @@
<field name="description">Use the account_budget module</field>
<field name="date_deadline" eval="time.strftime('%Y-%m-19')"/>
<field name="color">3</field>
- <field name="type_id" ref="project_tt_specification"/>
+ <field name="stage_id" ref="project_tt_specification"/>
</record>
<record id="project_task_5" model="project.task">
@@ -125,7 +125,7 @@
<field name="kanban_state">done</field>
<field name="priority">0</field>
<field name="date_deadline" eval="time.strftime('%Y-%m-%d')"/>
- <field name="type_id" ref="project_tt_specification"/>
+ <field name="stage_id" ref="project_tt_specification"/>
</record>
<record id="project_task_6" model="project.task">
@@ -135,7 +135,7 @@
<field name="priority">2</field>
<field name="project_id" ref="project.project_integrate_openerp"/>
<field name="name">Risk Management Planning</field>
- <field name="type_id" ref="project_tt_specification"/>
+ <field name="stage_id" ref="project_tt_specification"/>
</record>
<record id="project_task_7" model="project.task">
@@ -145,7 +145,7 @@
<field name="priority">2</field>
<field name="project_id" ref="project.project_integrate_openerp"/>
<field name="name">Create Project Schedules</field>
- <field name="type_id" ref="project_tt_specification"/>
+ <field name="stage_id" ref="project_tt_specification"/>
</record>
<record id="project_task_8" model="project.task">
@@ -156,7 +156,7 @@
<field name="project_id" ref="project.project_integrate_openerp"/>
<field name="name">Dataflow Design</field>
<field name="priority">0</field>
- <field name="type_id" ref="project_tt_specification"/>
+ <field name="stage_id" ref="project_tt_specification"/>
</record>
<record id="project_task_9" model="project.task">
@@ -166,7 +166,7 @@
<field name="priority">2</field>
<field name="project_id" ref="project.project_integrate_openerp"/>
<field name="name">User Interface Design</field>
- <field name="type_id" ref="project_tt_specification"/>
+ <field name="stage_id" ref="project_tt_specification"/>
</record>
<record id="project_task_10" model="project.task">
@@ -177,7 +177,7 @@
<field name="project_id" ref="project.project_integrate_openerp"/>
<field name="name">Develop Module in Sale Management</field>
<field name="kanban_state">blocked</field>
- <field name="type_id" ref="project_tt_development"/>
+ <field name="stage_id" ref="project_tt_development"/>
</record>
<record id="project_task_11" model="project.task">
@@ -187,7 +187,7 @@
<field name="priority">2</field>
<field name="project_id" ref="project.project_integrate_openerp"/>
<field name="name">Develop module in Warehouse</field>
- <field name="type_id" ref="project_tt_merge"/>
+ <field name="stage_id" ref="project_tt_merge"/>
</record>
<function model="project.task" name="do_close" eval="[ref('project_task_11')], {'install_mode': True}"/>
@@ -199,7 +199,7 @@
<field name="priority">2</field>
<field name="project_id" ref="project.project_integrate_openerp"/>
<field name="name">Integrate Modules</field>
- <field name="type_id" ref="project_tt_development"/>
+ <field name="stage_id" ref="project_tt_development"/>
</record>
<function model="project.task" name="do_close" eval="[ref('project_task_12')], {'install_mode': True}"/>
@@ -211,7 +211,7 @@
<field name="priority">2</field>
<field name="project_id" ref="project.project_integrate_openerp"/>
<field name="name">Unit Testing</field>
- <field name="type_id" ref="project_tt_development"/>
+ <field name="stage_id" ref="project_tt_development"/>
</record>
<function model="project.task" name="do_pending" eval="[ref('project_task_13')], {'install_mode': True}"/>
@@ -223,8 +223,7 @@
<field name="priority">2</field>
<field name="project_id" ref="project.project_integrate_openerp"/>
<field name="name">Regression Test</field>
- <field name="type_id" ref="project_tt_development"/>
- <field name="state">pending</field>
+ <field name="stage_id" ref="project_tt_development"/>
</record>
<record id="project_task_15" model="project.task">
@@ -234,7 +233,7 @@
<field name="priority">2</field>
<field name="project_id" ref="project.project_integrate_openerp"/>
<field name="name">Documentation</field>
- <field name="type_id" ref="project_tt_specification"/>
+ <field name="stage_id" ref="project_tt_specification"/>
<field name="date_start">2011-02-06</field>
</record>
@@ -247,7 +246,7 @@
<field name="project_id" ref="project.project_integrate_openerp"/>
<field name="name">Performance Tuning</field>
<field name="description">Test on Runbot</field>
- <field name="type_id" ref="project_tt_specification"/>
+ <field name="stage_id" ref="project_tt_specification"/>
</record>
<function model="project.task" name="do_open" eval="[ref('project_task_16')], {'install_mode': True}"/>
@@ -258,7 +257,7 @@
<field name="priority">2</field>
<field name="project_id" ref="project.project_integrate_openerp"/>
<field name="name">Deploy and Review on Customer System</field>
- <field name="type_id" ref="project_tt_specification"/>
+ <field name="stage_id" ref="project_tt_specification"/>
</record>
<function model="project.task" name="do_open" eval="[ref('project_task_17')], {'install_mode': True}"/>
@@ -269,7 +268,7 @@
<field name="priority">2</field>
<field name="project_id" ref="project.project_integrate_openerp"/>
<field name="name">Training and Presentation</field>
- <field name="type_id" ref="project_tt_specification"/>
+ <field name="stage_id" ref="project_tt_specification"/>
</record>
<!--
@@ -322,7 +321,7 @@
<record id="project_task_116" model="project.task">
<field name="planned_hours">38.0</field>
<field name="remaining_hours">38.0</field>
- <field name="type_id" ref="project_tt_development"/>
+ <field name="stage_id" ref="project_tt_development"/>
<field name="user_id" eval="False"/>
<field name="project_id" ref="project_project_22"/>
<field name="description">BoM, After sales returns, interventions. Traceability.</field>
@@ -334,7 +333,7 @@
<field name="planned_hours">16.0</field>
<field name="remaining_hours">16.0</field>
<field name="user_id" eval="False"/>
- <field name="type_id" ref="project_tt_development"/>
+ <field name="stage_id" ref="project_tt_development"/>
<field name="project_id" ref="project_project_23"/>
<field name="name">Data importation + Doc</field>
</record>
@@ -344,7 +343,7 @@
<field name="planned_hours">16.0</field>
<field name="remaining_hours">16.0</field>
<field name="user_id" eval="False"/>
- <field name="type_id" ref="project_tt_development"/>
+ <field name="stage_id" ref="project_tt_development"/>
<field name="project_id" ref="project_project_23"/>
<field name="name">Modifications asked by the customer.</field>
</record>
@@ -353,7 +352,7 @@
<record id="project_task_184" model="project.task">
<field name="planned_hours">16.0</field>
<field name="remaining_hours">16.0</field>
- <field name="type_id" ref="project_tt_testing"/>
+ <field name="stage_id" ref="project_tt_testing"/>
<field name="user_id" eval="False"/>
<field name="priority">0</field>
<field name="project_id" ref="project_project_21"/>
@@ -364,7 +363,7 @@
<field name="sequence">15</field>
<field name="planned_hours">8.0</field>
<field name="remaining_hours">8.0</field>
- <field name="type_id" ref="project_tt_testing"/>
+ <field name="stage_id" ref="project_tt_testing"/>
<field name="user_id" eval="False"/>
<field name="project_id" ref="project_project_21"/>
<field name="name">Internal testing + Software Install</field>
@@ -374,7 +373,7 @@
<field name="sequence">17</field>
<field name="planned_hours">16.0</field>
<field name="remaining_hours">16.0</field>
- <field name="type_id" ref="project_tt_development"/>
+ <field name="stage_id" ref="project_tt_development"/>
<field name="user_id" eval="False"/>
<field name="priority">2</field>
<field name="project_id" ref="project_project_21"/>
@@ -389,7 +388,7 @@
<field name="user_id" eval="False"/>
<field name="project_id" ref="project_project_23"/>
<field name="name">Parameters</field>
- <field name="type_id" ref="project_tt_specification"/>
+ <field name="stage_id" ref="project_tt_specification"/>
</record>
<function model="project.task" name="do_open" eval="[ref('project_task_189')], {'install_mode': True}"/>
@@ -398,10 +397,9 @@
<field name="planned_hours">32.0</field>
<field name="remaining_hours">32.0</field>
<field name="user_id" eval="False"/>
- <field name="state">open</field>
<field name="project_id" ref="project_project_21"/>
<field name="name">Start of the doc redaction + MRP</field>
- <field name="type_id" ref="project_tt_testing"/>
+ <field name="stage_id" ref="project_tt_testing"/>
</record>
<!-- Schedule tasks to assign users and dates -->
diff --git a/addons/project/project_view.xml b/addons/project/project_view.xml
index e84bb8dcd25..17e1445f141 100644
--- a/addons/project/project_view.xml
+++ b/addons/project/project_view.xml
@@ -161,7 +161,7 @@
</tree>
</field>
</record>
-
+
<act_window
context="{'search_default_project_id': [active_id], 'default_project_id': active_id}"
id="act_project_project_2_project_task_all"
@@ -196,7 +196,7 @@
<li><ul class="oe_kanban_colorpicker" data-field="color"/></li>
</ul>
<div class="oe_kanban_content">
- <a type="edit"><h3 class="oe_kanban_ellipsis"><field name="name"/></h3></a>
+ <h3 class="oe_kanban_ellipsis"><field name="name"/></h3>
<div class="oe_kanban_project_list">
<a t-if="record.use_tasks.raw_value"
@@ -305,15 +305,26 @@
<field name="arch" type="xml">
<form string="Project" layout="manual">
<div class="oe_form_topbar">
- <button name="action_close" states="pending,open" string="Done" type="object"/>
- <button name="do_open" states="pending,draft" string="Start Task" type="object"/>
- <button name="%(action_project_task_reevaluate)d" states="done,cancelled" string="Reactivate" type="action" context="{'button_reactivate':True}" />
- <button name="do_pending" states="open" string="Pending" type="object"/>
- <button name="do_draft" states="open" string="Draft" type="object"/>
- <button name="%(action_project_task_delegate)d" states="pending,open,draft" string="Delegate" type="action"/>
- <button name="do_cancel" states="draft,open,pending" string="Cancel" type="object"/>
+ <button name="do_open" string="Start Task" type="object"
+ states="draft,pending"/>
+ <button name="%(action_project_task_reevaluate)d" string="Reactivate" type="action"
+ states="done,cancelled" context="{'button_reactivate':True}"/>
+ <button name="do_pending" string="Pending" type="object"
+ states="open"/>
+ <button name="action_close" string="Done" type="object"
+ states="draft,open,pending"/>
+ <button name="do_draft" string="Draft" type="object"
+ states="cancel,done"/>
+ <button name="%(action_project_task_delegate)d" string="Delegate" type="action"
+ states="pending,open,draft"/>
+ <button name="do_cancel" string="Cancel" type="object"
+ states="draft,open,pending" />
+ <button name="stage_previous" string="Previous Stage" type="object"
+ states="open,pending" icon="gtk-go-back" attrs="{'invisible': [('stage_id','=', False)]}"/>
+ <button name="stage_next" string="Next Stage" type="object"
+ states="open,pending" icon="gtk-go-forward" attrs="{'invisible': [('stage_id','=', False)]}"/>
<div class="oe_right">
- <field name="state" nolabel="1" widget="statusbar" statusbar_visible="draft,open,done" statusbar_colors='{"pending":"blue"}' select="1"/>
+ <field name="stage_id" nolabel="1" widget="statusbar"/>
</div>
<div class="oe_clear"/>
</div>
@@ -362,7 +373,8 @@
<tree string="Delegated tasks">
<field name="name"/>
<field name="user_id"/>
- <field name="state"/>
+ <field name="stage_id"/>
+ <field name="state" groups="base.group_no_one"/>
<field name="effective_hours" widget="float_time"/>
<field name="progress" widget="progressbar"/>
<field name="remaining_hours" widget="float_time"/>
@@ -376,16 +388,13 @@
<separator string="Planning" colspan="2"/>
<field name="priority"/>
<field name="sequence"/>
+ <field name="state" groups="base.group_no_one"/>
</group>
<separator string="Miscellaneous" colspan="4"/>
<field name="partner_id" />
<field name="company_id" select="1" groups="base.group_multi_company" widget="selection"/>
- <group col="4" colspan="2">
- <field name="type_id" widget="selection" readonly="1"/>
- <button name="prev_type" string="Previous" type="object" icon="gtk-go-back" help="Change to Previous Stage"/>
- <button name="next_type" string="Next" type="object" icon="gtk-go-forward" help="Change to Next Stage"/>
- </group>
+ <field name="state" groups="base.group_no_one"/>
<separator colspan="4" string="Notes"/>
<field colspan="4" name="notes" nolabel="1"/>
</page>
@@ -397,22 +406,22 @@
</form>
</field>
</record>
-
+
<!-- Project Task Kanban View -->
<record model="ir.ui.view" id="view_task_kanban">
<field name="name">project.task.kanban</field>
<field name="model">project.task</field>
<field name="type">kanban</field>
<field name="arch" type="xml">
- <kanban default_group_by="type_id" >
+ <kanban default_group_by="stage_id" >
<field name="color"/>
<field name="priority"/>
- <field name="type_id"/>
+ <field name="stage_id"/>
<field name="user_id"/>
<field name="user_email"/>
<field name="description"/>
<field name="sequence"/>
- <field name="state"/>
+ <field name="state" groups="base.group_no_one"/>
<field name="kanban_state"/>
<field name="remaining_hours" sum="Remaining Time" groups="project.group_time_work_estimation_tasks"/>
<field name="date_deadline"/>
@@ -508,20 +517,21 @@
<field name="effective_hours" widget="float_time" sum="Spent Hours" invisible="1"/>
<field name="remaining_hours" widget="float_time" sum="Remaining Hours" on_change="onchange_remaining(remaining_hours,planned_hours)" invisible="context.get('set_visible',False)" groups="project.group_time_work_estimation_tasks"/>
<field name="date_deadline" invisible="context.get('deadline_visible',True)"/>
- <field name="type_id" invisible="context.get('set_visible',False)"/>
- <button name="next_type" invisible="context.get('set_visible',False)"
- states="draft,open,pending"
- string="Change Stage"
- type="object"
- icon="gtk-go-forward"
- help="Change Type"/>
+ <button name="do_open" string="Start Task" type="object"
+ states="draft,pending" icon="gtk-go-forward"/>
+ <button name="action_close" string="Done" type="object"
+ states="draft,open,pending" icon="gtk-apply"/>
+ <button name="%(action_project_task_delegate)d" string="Delegate" type="action"
+ states="pending,open,draft" icon="terp-personal"/>
+ <field name="stage_id" invisible="context.get('set_visible',False)"/>
+ <button name="stage_previous" string="Previous Stage" type="object"
+ states="open,pending" icon="gtk-go-back" attrs="{'invisible': [('stage_id','=', False)]}"/>
+ <button name="stage_next" string="Next Stage" type="object"
+ states="open,pending" icon="gtk-go-forward" attrs="{'invisible': [('stage_id','=', False)]}"/>
+ <field name="state" invisible="context.get('set_visible',False)" groups="base.group_no_one"/>
<field name="date_start" invisible="1" groups="base.group_no_one"/>
<field name="date_end" invisible="1" groups="base.group_no_one"/>
<field name="progress" widget="progressbar" invisible="context.get('set_visible',False)"/>
- <field name="state" invisible="context.get('set_visible',False)"/>
- <button name="do_open" states="pending,draft,done,cancelled" string="Start Task" type="object" icon="gtk-media-play" help="For changing to open state" invisible="context.get('set_visible',False)"/>
- <button name="%(action_project_task_delegate)d" states="pending,open,draft" string="Delegate" type="action" icon="terp-personal" help="For changing to delegate state"/>
- <button name="action_close" states="draft,pending,open" string="Done" type="object" icon="terp-dialog-close" help="For changing to done state"/>
</tree>
</field>
</record>
@@ -589,7 +599,7 @@
<separator orientation="vertical"/>
<filter string="Project" name="group_project_id" icon="terp-folder-violet" domain="[]" context="{'group_by':'project_id'}"/>
<separator orientation="vertical"/>
- <filter string="Stage" name="group_stage_id" icon="terp-stage" domain="[]" context="{'group_by':'type_id'}"/>
+ <filter string="Stage" name="group_stage_id" icon="terp-stage" domain="[]" context="{'group_by':'stage_id'}"/>
<filter string="Status" name="group_state" icon="terp-stock_effects-object-colorize" domain="[]" context="{'group_by':'state'}"/>
<separator orientation="vertical"/>
<filter string="Deadline" icon="terp-gnome-cpu-frequency-applet+" domain="[]" context="{'group_by':'date_deadline'}"/>
@@ -660,7 +670,7 @@
<field name="arch" type="xml">
<search string="Tasks Stages">
<group>
- <filter icon="terp-check" string="Common" name="common" domain="[('project_default', '=', 1)]" help="Stages common to all projects"/>
+ <filter icon="terp-check" string="Common" name="common" domain="[('case_default', '=', 1)]" help="Stages common to all projects"/>
<separator orientation="vertical"/>
<field name="name"/>
</group>
@@ -674,10 +684,14 @@
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Task Stage">
- <group colspan="4" col="6">
- <field name="name"/>
- <field name="project_default"/>
- <field name="sequence"/>
+ <group colspan="2" col="2">
+ <field name="name"/>
+ <field name="state"/>
+ </group>
+ <group colspan="2" col="4">
+ <field name="case_default"/>
+ <field name="sequence"/>
+ <field name="fold"/>
</group>
<separator string="Description" colspan="4"/>
<field colspan="4" name="description" nolabel="1"/>
@@ -693,6 +707,7 @@
<tree string="Task Stage">
<field name="sequence"/>
<field name="name"/>
+ <field name="state"/>
</tree>
</field>
</record>
@@ -707,10 +722,10 @@
<menuitem id="menu_tasks_config" name="GTD" parent="project.menu_definitions" sequence="1"/>
- <menuitem id="menu_project_config_project" name="Stages" parent="menu_definitions" sequence="1"/>
+ <menuitem id="menu_project_config_project" name="Stages" parent="project.menu_definitions" sequence="1"/>
- <menuitem action="open_task_type_form" id="menu_task_types_view" parent="menu_project_config_project" sequence="2" groups="base.group_no_one"/>
- <menuitem action="open_view_project_all" id="menu_projects" name="Projects" parent="menu_project_management" sequence="1"/>
+ <menuitem action="open_task_type_form" name="Task Stages" id="menu_task_types_view" parent="menu_project_config_project" sequence="2"/>
+ <menuitem action="open_view_project_all" id="menu_projects" name="Projects" parent="menu_project_management" sequence="1" groups="base.group_no_one"/>
<act_window context="{'search_default_user_id': [active_id], 'default_user_id': active_id}" id="act_res_users_2_project_project" name="User's projects" res_model="project.project" src_model="res.users" view_mode="tree,form" view_type="form"/>
diff --git a/addons/project/report/project_cumulative.xml b/addons/project/report/project_cumulative.xml
index 89667992f0a..3c04d36feb6 100644
--- a/addons/project/report/project_cumulative.xml
+++ b/addons/project/report/project_cumulative.xml
@@ -15,7 +15,8 @@
<field name="user_id"/>
<field name="remaining_hours"/>
<field name="kanban_state"/>
- <field name="state"/>
+ <field name="stage_id"/>
+ <field name="state" groups="base.group_no_one"/>
</tree>
</field>
</record>
diff --git a/addons/project/report/project_report.py b/addons/project/report/project_report.py
index 1012ca9d518..58f7739e96d 100644
--- a/addons/project/report/project_report.py
+++ b/addons/project/report/project_report.py
@@ -82,7 +82,7 @@ class report_project_task_user(osv.osv):
t.name as name,
t.company_id,
t.partner_id,
- t.type_id,
+ t.stage_id,
remaining_hours as remaining_hours,
total_hours as total_hours,
t.delay_hours as hours_delay,
@@ -114,7 +114,7 @@ class report_project_task_user(osv.osv):
name,
t.company_id,
t.partner_id,
- t.type_id
+ t.stage_id
""")
diff --git a/addons/project/report/project_report_view.xml b/addons/project/report/project_report_view.xml
index 3bdec47fcb9..240176f7941 100644
--- a/addons/project/report/project_report_view.xml
+++ b/addons/project/report/project_report_view.xml
@@ -214,7 +214,7 @@
<tree string="Task By Days" >
<field name="day"/>
<field name="total_task"/>
- <field name="state"/>
+ <field name="state" groups="base.group_no_one"/>
</tree>
</field>
</record>
diff --git a/addons/project/static/src/js/project.js b/addons/project/static/src/js/project.js
index 297aa7184b9..510fcbb99e7 100644
--- a/addons/project/static/src/js/project.js
+++ b/addons/project/static/src/js/project.js
@@ -23,4 +23,14 @@ openerp.project = function(openerp) {
}
}
});
+
+ openerp.web_kanban.KanbanRecord.include({
+ on_card_clicked: function() {
+ if (this.view.dataset.model === 'project.project') {
+ this.$('.oe_kanban_project_list a').first().click();
+ } else {
+ this._super.apply(this, arguments);
+ }
+ }
+ });
};
diff --git a/addons/project/test/task_process.yml b/addons/project/test/task_process.yml
index c4d17f783f6..ad4bbe53bb3 100644
--- a/addons/project/test/task_process.yml
+++ b/addons/project/test/task_process.yml
@@ -40,7 +40,7 @@
I change the stage of task to next stage.
-
!python {model: project.task}: |
- self.next_type(cr, uid, [ref("project_task_1")])
+ self.stage_next(cr, uid, [ref("project_task_1")])
-
!record {model: project.task.reevaluate, id: reevaluate_id}:
remaining_hours : 120
@@ -68,9 +68,9 @@
I change the stage of task to previous stage.
-
!python {model: project.task}: |
- self.prev_type(cr, uid, [ref("project_task_1")])
+ self.stage_previous(cr, uid, [ref("project_task_1")])
-
I cancel Task.
-
!python {model: project.task}: |
- self.do_cancel(cr, uid, [ref("project_task_2")]) \ No newline at end of file
+ self.do_cancel(cr, uid, [ref("project_task_2")])