diff options
| author | Thibault Delavallée <tde@openerp.com> | 2012-06-01 12:14:26 +0200 |
|---|---|---|
| committer | Thibault Delavallée <tde@openerp.com> | 2012-06-01 12:14:26 +0200 |
| commit | f9e6b60c9f48c48d7b0d2a9b67a3e2376e032fd2 (patch) | |
| tree | c602d1e223affb7b04a8c2cc0189fb4405441854 /addons/project | |
| parent | b98e0bdf14d4537f338fcee4fe2f14bdf76ac9ce (diff) | |
| parent | d988ca61568707ee4c9dca9288ff269dca9c77a6 (diff) | |
[MERGE] Merged branch holding state/stage cleaning for lead/opportunities, hr_recruitment, project_issue, tasks, crm_claim. Those models now use stage as the main status flow; the state is a related field to the stage, and is not important anymore. Updated views accordingly (buttons, statusbar on stage_id). Also updated view of crm_meeting, crm_helpdesk and crm_phonecall. Old crm_base and crm_case are nos distinct from crm, and are in a new addon called 'base_status'. This module defines most of the methods related to the logic; models inheriting from base_state or base_stage have few methods to override to implement a particular behavior (mainly stage_find for base_stage).
bzr revid: tde@openerp.com-20120601101426-28e6gnsywhkxeber
Diffstat (limited to 'addons/project')
| -rw-r--r-- | addons/project/__openerp__.py | 2 | ||||
| -rw-r--r-- | addons/project/board_project_view.xml | 27 | ||||
| -rw-r--r-- | addons/project/project.py | 317 | ||||
| -rw-r--r-- | addons/project/project_data.xml | 28 | ||||
| -rw-r--r-- | addons/project/project_demo.xml | 54 | ||||
| -rw-r--r-- | addons/project/project_view.xml | 93 | ||||
| -rw-r--r-- | addons/project/report/project_cumulative.xml | 3 | ||||
| -rw-r--r-- | addons/project/report/project_report.py | 4 | ||||
| -rw-r--r-- | addons/project/report/project_report_view.xml | 2 | ||||
| -rw-r--r-- | addons/project/test/task_process.yml | 6 |
10 files changed, 299 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 0b23196a67f..fa3e0c33f4d 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,49 +504,61 @@ 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" _log_create = True _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) @@ -562,11 +577,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: @@ -597,7 +611,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}} @@ -640,7 +653,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): @@ -670,10 +683,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" @@ -722,6 +740,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', @@ -729,7 +749,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" @@ -828,6 +848,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 = {} @@ -840,9 +895,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 @@ -863,12 +918,14 @@ class task(osv.osv): } return res - def do_close(self, cr, uid, ids, context={}): - """ - Close Task - """ + 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] + if not isinstance(ids, list): ids = [ids] for task in self.browse(cr, uid, ids, context=context): vals = {} project = task.project_id @@ -884,7 +941,6 @@ class task(osv.osv): 'ref_doc1': 'project.task,%d'% (task.id,), 'ref_doc2': 'project.project,%d'% (project.id,), }, context=context) - for parent_id in task.parent_ids: if parent_id.state in ('pending','draft'): reopen = True @@ -893,12 +949,12 @@ 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): @@ -916,12 +972,15 @@ class task(osv.osv): 'ref_doc1': 'project.task,%d' % task.id, 'ref_doc2': 'project.project,%d' % project.id, }, context=context) - - 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) @@ -937,27 +996,38 @@ class task(osv.osv): 'ref_doc1': 'project.task,%d' % task.id, 'ref_doc2': 'project.project,%d' % project.id, }, context=context) - self.write(cr, uid, [task.id], {'state': 'cancelled', 'remaining_hours':0.0}, context=context) - self.do_cancel_send_note(cr, uid, [task.id], context) + # cancel task + 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) @@ -966,7 +1036,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. @@ -1000,11 +1069,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): @@ -1033,36 +1097,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]}) - self.state_change_send_note(cr, uid, [task.id], context) - 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, { @@ -1070,7 +1104,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 @@ -1084,22 +1118,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.state_change_send_note(cr, uid, ids, context) return result def unlink(self, cr, uid, ids, context=None): @@ -1139,7 +1176,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): @@ -1156,28 +1197,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): @@ -1186,13 +1215,6 @@ class task(osv.osv): self.message_append_note(cr, uid, [task.id], body=msg, context=context) return True - def state_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" @@ -1231,7 +1253,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): @@ -1252,7 +1274,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) @@ -1313,7 +1334,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' @@ -1341,4 +1362,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 70cdac1efa0..d001af367c4 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" @@ -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/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")]) |
