diff --git a/addons/crm/board_crm_view.xml b/addons/crm/board_crm_view.xml
index 6bbd450ca38..8bbbece18cb 100644
--- a/addons/crm/board_crm_view.xml
+++ b/addons/crm/board_crm_view.xml
@@ -20,10 +20,7 @@
graph,tree,form
- ['|',
- '!', '&', ('probability', '=', 100), ('stage_id.on_change', '=', 1),
- '!', '&', ('probability', '=', 0), ('stage_id.sequence', '!=', 1),
- ('type', '=', 'opportunity')]
+ ['&', ('stage_id.fold', '=', False), ('type', '=', 'opportunity')]{'search_default_Stage':1}
@@ -48,7 +45,7 @@
graph,tree,form
- ['!', '&', ('probability', '=', 0), ('stage_id.sequence', '!=', 1)]
+ ['|', ('stage_id.fold', '=', False), ('stage_id.probability', '=', 100)]{'search_default_user': 1, 'search_default_Stage': 1}
diff --git a/addons/crm/crm.py b/addons/crm/crm.py
index 6c2db63b0be..b09dc8faa2b 100644
--- a/addons/crm/crm.py
+++ b/addons/crm/crm.py
@@ -68,8 +68,9 @@ class crm_case_stage(osv.osv):
help="Link between stages and sales teams. When set, this limitate the current stage to the selected sales teams."),
'case_default': fields.boolean('Default to New Sales Team',
help="If you check this field, this stage will be proposed by default on each sales team. It will not assign this stage to existing teams."),
- 'fold': fields.boolean('Fold by Default',
- help="This stage is not visible, for example in status bar or kanban view, when there are no records in that stage to display."),
+ 'fold': fields.boolean('Folded in Kanban View',
+ help='This stage is folded in the kanban view when'
+ 'there are no records in that stage to display.'),
'type': fields.selection([('lead', 'Lead'),
('opportunity', 'Opportunity'),
('both', 'Both')],
diff --git a/addons/crm/crm_lead.py b/addons/crm/crm_lead.py
index 046d4419809..5f52980c8b0 100644
--- a/addons/crm/crm_lead.py
+++ b/addons/crm/crm_lead.py
@@ -71,10 +71,11 @@ class crm_lead(format_address, osv.osv):
_track = {
'stage_id': {
- 'crm.mt_lead_create': lambda self, cr, uid, obj, ctx=None: obj.probability == 0 and obj.stage_id and obj.stage_id.sequence == 1,
- 'crm.mt_lead_stage': lambda self, cr, uid, obj, ctx=None: (obj.stage_id and obj.stage_id.sequence != 1) and obj.probability < 100,
- 'crm.mt_lead_won': lambda self, cr, uid, obj, ctx=None: obj.probability == 100 and obj.stage_id and obj.stage_id.on_change,
- 'crm.mt_lead_lost': lambda self, cr, uid, obj, ctx=None: obj.probability == 0 and obj.stage_id and obj.stage_id.sequence != 1,
+ # this is only an heuristics; depending on your particular stage configuration it may not match all 'new' stages
+ 'crm.mt_lead_create': lambda self, cr, uid, obj, ctx=None: obj.probability == 0 and obj.stage_id and obj.stage_id.sequence <= 1,
+ 'crm.mt_lead_stage': lambda self, cr, uid, obj, ctx=None: (obj.stage_id and obj.stage_id.sequence > 1) and obj.probability < 100,
+ 'crm.mt_lead_won': lambda self, cr, uid, obj, ctx=None: obj.probability == 100 and obj.stage_id and obj.stage_id.fold,
+ 'crm.mt_lead_lost': lambda self, cr, uid, obj, ctx=None: obj.probability == 0 and obj.stage_id and obj.stage_id.fold and obj.stage_id.sequence > 1,
},
}
@@ -92,7 +93,7 @@ class crm_lead(format_address, osv.osv):
def _get_default_stage_id(self, cr, uid, context=None):
""" Gives default stage_id """
section_id = self._get_default_section_id(cr, uid, context=context)
- return self.stage_find(cr, uid, [], section_id, [('sequence', '=', '1')], context=context)
+ return self.stage_find(cr, uid, [], section_id, [('fold', '=', False)], context=context)
def _resolve_section_id_from_context(self, cr, uid, context=None):
""" Returns ID of section based on the value of 'section_id'
@@ -381,15 +382,17 @@ class crm_lead(format_address, osv.osv):
# AND with the domain in parameter
search_domain += list(domain)
# perform search, return the first found
- stage_ids = self.pool.get('crm.case.stage').search(cr, uid, search_domain, order=order, context=context)
+ stage_ids = self.pool.get('crm.case.stage').search(cr, uid, search_domain, order=order, limit=1, context=context)
if stage_ids:
return stage_ids[0]
return False
def case_mark_lost(self, cr, uid, ids, context=None):
- """ Mark the case as lost: state=cancel and probability=0 """
+ """ Mark the case as lost: state=cancel and probability=0
+ :deprecated: this method will be removed in OpenERP v8.
+ """
for lead in self.browse(cr, uid, ids):
- stage_id = self.stage_find(cr, uid, [lead], lead.section_id.id or False, [('probability', '=', 0.0), ('on_change', '=', True), ('sequence', '>', 1)], context=context)
+ stage_id = self.stage_find(cr, uid, [lead], lead.section_id.id or False, [('probability', '=', 0.0), ('fold', '=', True), ('sequence', '>', 1)], context=context)
if stage_id:
return self.write(cr, uid, [lead.id], {'stage_id': stage_id}, context=context)
else:
@@ -399,9 +402,11 @@ class crm_lead(format_address, osv.osv):
'Create a specific stage or edit an existing one by editing columns of your opportunity pipe.'))
def case_mark_won(self, cr, uid, ids, context=None):
- """ Mark the case as won: state=done and probability=100 """
+ """ Mark the case as won: state=done and probability=100
+ :deprecated: this method will be removed in OpenERP v8.
+ """
for lead in self.browse(cr, uid, ids):
- stage_id = self.stage_find(cr, uid, [lead], lead.section_id.id or False, [('probability', '=', 100.0), ('on_change', '=', True), ('sequence', '>', 1)], context=context)
+ stage_id = self.stage_find(cr, uid, [lead], lead.section_id.id or False, [('probability', '=', 100.0), ('fold', '=', True)], context=context)
if stage_id:
return self.write(cr, uid, [lead.id], {'stage_id': stage_id}, context=context)
else:
@@ -616,7 +621,7 @@ class crm_lead(format_address, osv.osv):
# An Opportunity always has higher confidence level than a lead, unless its stage probability is 0.0
for opportunity in opportunities:
sequence = -1
- if opportunity.stage_id and (opportunity.stage_id.probability != 0 or opportunity.stage_id.sequence == 1):
+ if opportunity.stage_id and not opportunity.stage_id.fold:
sequence = opportunity.stage_id.sequence
sequenced_opps.append(((int(sequence != -1 and opportunity.type == 'opportunity'), sequence, -opportunity.id), opportunity))
@@ -677,7 +682,7 @@ class crm_lead(format_address, osv.osv):
'phone': customer and customer.phone or lead.phone,
}
if not lead.stage_id or lead.stage_id.type=='lead':
- val['stage_id'] = self.stage_find(cr, uid, [lead], section_id, [('sequence', '=', '1'), ('type', 'in', ('opportunity','both'))], context=context)
+ val['stage_id'] = self.stage_find(cr, uid, [lead], section_id, [('type', 'in', ('opportunity', 'both'))], context=context)
return val
def convert_opportunity(self, cr, uid, ids, partner_id, user_ids=False, section_id=False, context=None):
@@ -687,7 +692,7 @@ class crm_lead(format_address, osv.osv):
customer = partner.browse(cr, uid, partner_id, context=context)
for lead in self.browse(cr, uid, ids, context=context):
# TDE: was if lead.state in ('done', 'cancel'):
- if (lead.probability == '100') or (lead.probability == '0' and lead.stage_id.sequence != '1'):
+ if lead.probability == 100 or (lead.probability == 0 and lead.stage_id.fold):
continue
vals = self._convert_opportunity_data(cr, uid, lead, customer, section_id, context=context)
self.write(cr, uid, [lead.id], vals, context=context)
diff --git a/addons/crm/crm_lead_data.xml b/addons/crm/crm_lead_data.xml
index 3c299fef704..1cd3d51be90 100644
--- a/addons/crm/crm_lead_data.xml
+++ b/addons/crm/crm_lead_data.xml
@@ -44,6 +44,7 @@
Won1
+ 1100170
diff --git a/addons/crm/crm_lead_view.xml b/addons/crm/crm_lead_view.xml
index c0eefcc8d4c..5a3a0aa34fe 100644
--- a/addons/crm/crm_lead_view.xml
+++ b/addons/crm/crm_lead_view.xml
@@ -341,7 +341,7 @@
domain="[('section_id.member_ids', 'in', [uid])]" context="{'invisible_section': False}"
help="Leads that are assigned to any sales teams I am member of"/>
+ domain="[('probability', '=', '0'), ('stage_id.fold', '=', True)]"/>
diff --git a/addons/hr_recruitment/report/hr_recruitment_report.py b/addons/hr_recruitment/report/hr_recruitment_report.py
index 0292875a2c7..908b701d928 100644
--- a/addons/hr_recruitment/report/hr_recruitment_report.py
+++ b/addons/hr_recruitment/report/hr_recruitment_report.py
@@ -90,7 +90,7 @@ class hr_recruitment_report(osv.Model):
(sum(salary_proposed)/count(*)) as salary_prop_avg,
sum(salary_expected) as salary_exp,
(sum(salary_expected)/count(*)) as salary_exp_avg,
- extract('epoch' from (s.date_closed-s.create_date))/(3600*24) as delay_close,
+ extract('epoch' from (s.write_date-s.create_date))/(3600*24) as delay_close,
count(*) as nbr
from hr_applicant s
group by
@@ -101,6 +101,7 @@ class hr_recruitment_report(osv.Model):
date_trunc('day',s.date_closed),
s.date_open,
s.create_date,
+ s.write_date,
s.date_closed,
s.date_last_stage_update,
s.partner_id,
diff --git a/addons/project/project.py b/addons/project/project.py
index d153a849dc7..9173318366e 100644
--- a/addons/project/project.py
+++ b/addons/project/project.py
@@ -41,14 +41,13 @@ class project_task_type(osv.osv):
'case_default': fields.boolean('Default for New 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'),
- 'fold': fields.boolean('Folded by Default',
- help="This stage is not visible, for example in status bar or kanban view, when there are no records in that stage to display."),
+ 'fold': fields.boolean('Folded in Kanban View',
+ help='This stage is folded in the kanban view when'
+ 'there are no records in that stage to display.'),
}
_defaults = {
'sequence': 1,
- 'fold': False,
- 'case_default': False,
'project_ids': lambda self, cr, uid, ctx=None: self.pool['project.task']._get_default_project_id(cr, uid, context=ctx),
}
_order = 'sequence'
@@ -189,6 +188,8 @@ class project(osv.osv):
return res
def _task_count(self, cr, uid, ids, field_name, arg, context=None):
+ """ :deprecated: this method will be removed with OpenERP v8. Use task_ids
+ fields instead. """
if context is None:
context = {}
res = dict.fromkeys(ids, 0)
@@ -263,7 +264,10 @@ class project(osv.osv):
}),
'resource_calendar_id': fields.many2one('resource.calendar', 'Working Time', help="Timetable working hours to adjust the gantt diagram report", states={'close':[('readonly',True)]} ),
'type_ids': fields.many2many('project.task.type', 'project_task_type_rel', 'project_id', 'type_id', 'Tasks Stages', states={'close':[('readonly',True)], 'cancelled':[('readonly',True)]}),
- 'task_count': fields.function(_task_count, type='integer', string="Open Tasks"),
+ 'task_count': fields.function(_task_count, type='integer', string="Open Tasks",
+ deprecated="This field will be removed in OpenERP v8. Use task_ids one2many field instead."),
+ 'task_ids': fields.one2many('project.task', 'project_id',
+ domain=[('stage_id.fold', '=', False)]),
'color': fields.integer('Color Index'),
'alias_id': fields.many2one('mail.alias', 'Alias', ondelete="restrict", required=True,
help="Internal email associated with this project. Incoming emails are automatically synchronized"
@@ -555,8 +559,9 @@ class task(osv.osv):
_mail_post_access = 'read'
_track = {
'stage_id': {
- 'project.mt_task_new': lambda self, cr, uid, obj, ctx=None: obj.stage_id and obj.stage_id.sequence == 1,
- 'project.mt_task_stage': lambda self, cr, uid, obj, ctx=None: obj.stage_id.sequence != 1,
+ # this is only an heuristics; depending on your particular stage configuration it may not match all 'new' stages
+ 'project.mt_task_new': lambda self, cr, uid, obj, ctx=None: obj.stage_id and obj.stage_id.sequence <= 1,
+ 'project.mt_task_stage': lambda self, cr, uid, obj, ctx=None: obj.stage_id.sequence > 1,
},
'user_id': {
'project.mt_task_assigned': lambda self, cr, uid, obj, ctx=None: obj.user_id and obj.user_id.id,
@@ -581,7 +586,7 @@ class task(osv.osv):
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, [('sequence', '=', '1')], context=context)
+ return self.stage_find(cr, uid, [], project_id, [('fold', '=', False)], context=context)
def _resolve_project_id_from_context(self, cr, uid, context=None):
""" Returns ID of project based on the value of 'default_project_id'
@@ -804,7 +809,7 @@ class task(osv.osv):
_defaults = {
'stage_id': _get_default_stage_id,
'project_id': _get_default_project_id,
- 'date_last_stage_update': lambda *a: fields.datetime.now(),
+ 'date_last_stage_update': fields.datetime.now,
'kanban_state': 'normal',
'priority': '2',
'progress': 0,
@@ -993,7 +998,7 @@ class task(osv.osv):
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.stage_id and task.stage_id.sequence == 1) or (task.planned_hours == 0.0):
+ if (task.stage_id and task.stage_id.sequence <= 1) or (task.planned_hours == 0.0):
self.write(cr, uid, [task.id], {'planned_hours': remaining_time}, context=context)
self.write(cr, uid, ids, {'remaining_hours': remaining_time}, context=context)
return True
diff --git a/addons/project/project_data.xml b/addons/project/project_data.xml
index 0f48dfe9a2b..1f49451a377 100644
--- a/addons/project/project_data.xml
+++ b/addons/project/project_data.xml
@@ -63,12 +63,14 @@
Done
+ 30Cancelled
+
diff --git a/addons/project/project_view.xml b/addons/project/project_view.xml
index 4d025d15cb4..d5e6a216149 100644
--- a/addons/project/project_view.xml
+++ b/addons/project/project_view.xml
@@ -19,7 +19,7 @@
-
+
@@ -240,6 +240,7 @@
+
@@ -259,9 +260,10 @@
%%