#
##############################################################################
+from datetime import date, datetime
+from dateutil import relativedelta
+
from openerp import tools
from openerp.osv import fields
from openerp.osv import osv
-from openerp.tools.translate import _
-from datetime import date
-from dateutil.relativedelta import relativedelta
MAX_LEVEL = 15
AVAILABLE_STATES = [
('5', 'Lowest'),
]
-DURATION_TXT = {
- "monthly": _("month"),
- "quarterly": _("quarter"),
- "semesterly": _("semester"),
- "annually": _("year")
-}
-
-MONTHS = {
- "monthly": 1,
- "quarterly": 3,
- "semesterly": 6,
- "annually": 12
-}
-
class crm_case_channel(osv.osv):
_name = "crm.case.channel"
_description = "Channels"
_inherit = "mail.thread"
_description = "Sales Teams"
_order = "complete_name"
+ # number of periods for lead/opportunities/... tracking in salesteam kanban dashboard/kanban view
+ _period_number = 5
def get_full_name(self, cr, uid, ids, field_name, arg, context=None):
return dict(self.name_get(cr, uid, ids, context=context))
- def _get_target_duration_txt(self, cr, uid, ids, field_name, arg, context=None):
- res = dict.fromkeys(ids, "")
- for section in self.browse(cr, uid, ids, context=context):
- res[section.id] = DURATION_TXT[section.target_duration]
- return res
-
- def _get_open_lead_per_duration(self, cr, uid, ids, field_name, arg, context=None):
- res = dict.fromkeys(ids, [])
- lead_obj = self.pool.get('crm.lead')
- first_day = date.today().replace(day=1)
-
- for section in self.browse(cr, uid, ids, context=context):
- dates = [first_day + relativedelta(months=-(MONTHS[section.target_duration]*(key+1)-1)) for key in range(0, 5)]
- nb_leads = []
- for when in range(0, 5):
- domain = [("section_id", "=", section.id), '|', ('type', '=', 'lead'), ('date_open', '!=', None), ('create_date', '>=', dates[when].strftime(tools.DEFAULT_SERVER_DATE_FORMAT))]
- if when:
- domain += [('create_date', '<', dates[when-1].strftime(tools.DEFAULT_SERVER_DATE_FORMAT))]
- nb_leads.append(lead_obj.search(cr, uid, domain, context=context, count=True))
- nb_leads.reverse()
- res[section.id] = nb_leads
- return res
-
- def _get_won_opportunity_per_duration(self, cr, uid, ids, field_name, arg, context=None):
- res = dict.fromkeys(ids, [])
+ def __get_bar_values(self, cr, uid, obj, domain, read_fields, value_field, groupby_field, context=None):
+ """ Generic method to generate data for bar chart values using SparklineBarWidget.
+ This method performs obj.read_group(cr, uid, domain, read_fields, groupby_field).
+
+ :param obj: the target model (i.e. crm_lead)
+ :param domain: the domain applied to the read_group
+ :param list read_fields: the list of fields to read in the read_group
+ :param str value_field: the field used to compute the value of the bar slice
+ :param str groupby_field: the fields used to group
+
+ :return list section_result: a list of dicts: [
+ { 'value': (int) bar_column_value,
+ 'tootip': (str) bar_column_tooltip,
+ }
+ ]
+ """
+ month_begin = date.today().replace(day=1)
+ section_result = [{
+ 'value': 0,
+ 'tooltip': (month_begin + relativedelta.relativedelta(months=-i)).strftime('%B'),
+ } for i in range(self._period_number - 1, -1, -1)]
+ group_obj = obj.read_group(cr, uid, domain, read_fields, groupby_field, context=context)
+ for group in group_obj:
+ group_begin_date = datetime.strptime(group['__domain'][0][2], tools.DEFAULT_SERVER_DATE_FORMAT)
+ month_delta = relativedelta.relativedelta(month_begin, group_begin_date)
+ section_result[self._period_number - (month_delta.months + 1)] = {'value': group.get(value_field, 0), 'tooltip': group_begin_date.strftime('%B')}
+ return section_result
+
+ def _get_opportunities_data(self, cr, uid, ids, field_name, arg, context=None):
+ """ Get opportunities-related data for salesteam kanban view
+ monthly_open_leads: number of open lead during the last months
+ monthly_planned_revenue: planned revenu of opportunities during the last months
+ """
obj = self.pool.get('crm.lead')
- first_day = date.today().replace(day=1)
-
- for section in self.browse(cr, uid, ids, context=context):
- dates = [first_day + relativedelta(months=-(MONTHS[section.target_duration]*(key+1)-1)) for key in range(0, 5)]
- rates = []
- for when in range(0, 5):
- domain = [("section_id", "=", section.id), ('state', '=', 'done'), ('type', '=', 'opportunity'), ('date_closed', '>=', dates[when].strftime(tools.DEFAULT_SERVER_DATE_FORMAT))]
- if when:
- domain += [('date_closed', '<', dates[when-1].strftime(tools.DEFAULT_SERVER_DATE_FORMAT))]
- group_obj = obj.read_group(cr, uid, domain, ['planned_revenue', 'section_id'], "section_id", context=context)
- rates.append(group_obj and group_obj[0]['planned_revenue'] or 0)
- rates.reverse()
- res[section.id] = rates
+ res = dict.fromkeys(ids, False)
+ month_begin = date.today().replace(day=1)
+ groupby_begin = (month_begin + relativedelta.relativedelta(months=-4)).strftime(tools.DEFAULT_SERVER_DATE_FORMAT)
+ for id in ids:
+ res[id] = dict()
+ lead_domain = [('type', '=', 'lead'), ('section_id', '=', id), ('create_date', '>=', groupby_begin)]
+ res[id]['monthly_open_leads'] = self.__get_bar_values(cr, uid, obj, lead_domain, ['create_date'], 'create_date_count', 'create_date', context=context)
+ opp_domain = [('type', '=', 'opportunity'), ('section_id', '=', id), ('create_date', '>=', groupby_begin)]
+ res[id]['monthly_planned_revenue'] = self.__get_bar_values(cr, uid, obj, opp_domain, ['planned_revenue', 'create_date'], 'planned_revenue', 'create_date', context=context)
return res
_columns = {
'use_leads': fields.boolean('Leads',
help="The first contact you get with a potential customer is a lead you qualify before converting it into a real business opportunity. Check this box to manage leads in this sales team."),
- 'target_duration': fields.selection([("monthly", "Monthly"), ("quarterly", "Quarterly"), ("semesterly", "Semesterly"), ("annually", "Annually")],
- string='Report Duration', required=True),
- 'target_duration_txt': fields.function(_get_target_duration_txt,
- string='Duration',
- type="string", readonly=True),
-
- 'open_lead_per_duration': fields.function(_get_open_lead_per_duration, string='Open Leads per duration', type="string", readonly=True),
- 'won_opportunity_per_duration': fields.function(_get_won_opportunity_per_duration, string='Revenue of opporunities whon per duration', type="string", readonly=True)
+ 'monthly_open_leads': fields.function(_get_opportunities_data,
+ type="string", readonly=True, multi='_get_opportunities_data',
+ string='Open Leads per Month'),
+ 'monthly_planned_revenue': fields.function(_get_opportunities_data,
+ type="string", readonly=True, multi='_get_opportunities_data',
+ string='Planned Revenue per Month')
}
def _get_stage_common(self, cr, uid, context):
'active': 1,
'stage_ids': _get_stage_common,
'use_leads': True,
- 'target_duration': "monthly",
}
_sql_constraints = [
return res
def create(self, cr, uid, vals, context=None):
- mail_alias = self.pool.get('mail.alias')
- if not vals.get('alias_id'):
- alias_name = vals.pop('alias_name', None) or vals.get('name') # prevent errors during copy()
- alias_id = mail_alias.create_unique_alias(cr, uid,
- {'alias_name': alias_name},
- model_name="crm.lead",
- context=context)
- vals['alias_id'] = alias_id
- res = super(crm_case_section, self).create(cr, uid, vals, context)
- mail_alias.write(cr, uid, [vals['alias_id']], {'alias_defaults': {'section_id': res, 'type': 'lead'}}, context)
- return res
+ if context is None:
+ context = {}
+ create_context = dict(context, alias_model_name='crm.lead', alias_parent_model_name=self._name)
+ section_id = super(crm_case_section, self).create(cr, uid, vals, context=create_context)
+ section = self.browse(cr, uid, section_id, context=context)
+ self.pool.get('mail.alias').write(cr, uid, [section.alias_id.id], {'alias_parent_thread_id': section_id, 'alias_defaults': {'section_id': section_id, 'type': 'lead'}}, context=context)
+ return section_id
def unlink(self, cr, uid, ids, context=None):
# Cascade-delete mail aliases as well, as they should not exist without the sales team.