[REF] project_task: first steps towards something using crm_case instead of re-implementing everything.
bzr revid: tde@openerp.com-20120525152238-3jc9l0m2jzicoy00
This commit is contained in:
parent
af2066a585
commit
5672b95b1f
|
@ -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,20 +19,15 @@
|
|||
#
|
||||
##############################################################################
|
||||
|
||||
from lxml import etree
|
||||
import time
|
||||
from crm import crm_case
|
||||
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')]
|
||||
_TASK_STATE = [('draft', 'New'),('open', 'In Progress'),('pending', 'Pending'), ('done', 'Done'), ('cancel', 'Cancelled')]
|
||||
|
||||
class project_task_type(osv.osv):
|
||||
_name = 'project.task.type'
|
||||
|
@ -42,10 +37,13 @@ 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."),
|
||||
'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 = {
|
||||
'state': 'draft',
|
||||
|
@ -53,7 +51,6 @@ class project_task_type(osv.osv):
|
|||
'fold': False,
|
||||
}
|
||||
_order = 'sequence'
|
||||
project_task_type()
|
||||
|
||||
class project(osv.osv):
|
||||
_name = "project.project"
|
||||
|
@ -214,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"
|
||||
|
@ -507,20 +504,19 @@ 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(crm_case, osv.osv):
|
||||
_name = "project.task"
|
||||
_description = "Task"
|
||||
_log_create = True
|
||||
_date_name = "date_start"
|
||||
_inherit = ['ir.needaction_mixin', 'mail.thread']
|
||||
|
||||
|
||||
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):
|
||||
|
@ -528,9 +524,10 @@ class task(osv.osv):
|
|||
return 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):
|
||||
stage_obj = self.pool.get('project.task.type')
|
||||
|
@ -543,7 +540,7 @@ class task(osv.osv):
|
|||
if project_id:
|
||||
domain = ['|', ('id','in',ids), ('project_ids','in',project_id)]
|
||||
else:
|
||||
domain = ['|', ('id','in',ids), ('project_default','=',1)]
|
||||
domain = ['|', ('id','in',ids), ('case_default','=',1)]
|
||||
stage_ids = stage_obj._search(cr, uid, 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
|
||||
|
@ -572,7 +569,6 @@ class task(osv.osv):
|
|||
'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:
|
||||
|
@ -603,7 +599,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}}
|
||||
|
@ -676,8 +671,8 @@ 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.related('type_id', 'state', type="selection", store=True,
|
||||
'stage_id': fields.many2one('project.task.type', 'Stage'),
|
||||
'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\'.\
|
||||
|
@ -838,6 +833,34 @@ 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:
|
||||
- type: stage type must be the same or 'both'
|
||||
- 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)
|
||||
domain = list(domain)
|
||||
if section_id:
|
||||
domain += ['|', ('section_ids', '=', section_id)]
|
||||
domain.append(('case_default', '=', True))
|
||||
for lead in cases:
|
||||
domain += ['|', ('type', '=', lead.type), ('type', '=', 'both')]
|
||||
lead_section_id = lead.section_id.id if lead.section_id else None
|
||||
if lead_section_id:
|
||||
domain += ['|', ('section_ids', '=', lead_section_id), ('case_default', '=', True)]
|
||||
stage_ids = self.pool.get('crm.case.stage').search(cr, uid, 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 = {}
|
||||
|
@ -850,15 +873,15 @@ 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
|
||||
task = self.browse(cr, uid, task_id, context=context)
|
||||
project = task.project_id
|
||||
res = self.do_close(cr, uid, [task_id], context=context)
|
||||
res = self.case_close(cr, uid, [task_id], context=context)
|
||||
if project.warn_manager or project.warn_customer:
|
||||
return {
|
||||
'name': _('Send Email after close task'),
|
||||
|
@ -873,12 +896,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
|
||||
|
@ -894,7 +919,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
|
||||
|
@ -903,12 +927,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, ids, context=context)
|
||||
return True
|
||||
|
||||
def do_reopen(self, cr, uid, ids, context=None):
|
||||
|
@ -931,7 +955,11 @@ class task(osv.osv):
|
|||
self.do_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(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)
|
||||
|
@ -947,27 +975,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], 'cancel', {'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(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)
|
||||
|
@ -976,7 +1015,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.
|
||||
|
@ -1010,11 +1048,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):
|
||||
|
@ -1173,25 +1206,8 @@ class task(osv.osv):
|
|||
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):
|
||||
|
|
Loading…
Reference in New Issue