[IMP] crm: salesteams sparkline for lead and opportunity
authorChristophe Matthieu <chm@openerp.com>
Wed, 17 Apr 2013 13:17:59 +0000 (15:17 +0200)
committerChristophe Matthieu <chm@openerp.com>
Wed, 17 Apr 2013 13:17:59 +0000 (15:17 +0200)
bzr revid: chm@openerp.com-20130417131759-ysnbosoikd16kwlo

addons/crm/crm.py
addons/crm/crm_case_section_view.xml
addons/crm/static/src/js/crm_case_section.js
addons/sale_crm/sale_crm_view.xml

index 8c57374..d6cea46 100644 (file)
 #
 ##############################################################################
 
-import base64
-import time
-from lxml import etree
 from openerp.osv import fields
 from openerp.osv import osv
-from openerp import tools
 from openerp.tools.translate import _
+from datetime import date
+from dateutil.relativedelta import relativedelta
 
 MAX_LEVEL = 15
 AVAILABLE_STATES = [
@@ -44,13 +42,22 @@ AVAILABLE_PRIORITIES = [
     ('5', 'Lowest'),
 ]
 
-duration_txt = {
+DURATION_TXT = {
     "monthly": _("this month"),
     "semesterly": _("this semester"),
     "semiannually": _("this semi"),
     "annually": _("this year")
 }
 
+MONTHS = {
+    "monthly": 1,
+    "semesterly": 3,
+    "semiannually": 6,
+    "annually": 12
+}
+
+_strftime = '%Y-%m-%d %H:%M:%S'
+
 class crm_case_channel(osv.osv):
     _name = "crm.case.channel"
     _description = "Channels"
@@ -120,7 +127,45 @@ class crm_case_section(osv.osv):
     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]
+            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 = [('type', '!=', 'opportunity'), ("section_id", "=", section.id), ('create_date', '>=', dates[when].strftime(_strftime))]
+                if when:
+                    domain += [('create_date', '<', dates[when-1].strftime(_strftime))]
+                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, [])
+        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 = [('type', '=', 'opportunity'), ("section_id", "=", section.id), ('state', '!=', 'cancel'), ('date_closed', '>=', dates[when].strftime(_strftime))]
+                if when:
+                    domain += [('date_closed', '<', dates[when-1].strftime(_strftime))]
+                rate = 0
+                opportunity_ids = lead_obj.search(cr, uid, domain, context=context)
+                for opportunity in lead_obj.browse(cr, uid, opportunity_ids, context=context):
+                    rate += opportunity.planned_revenue
+                nb_leads.append(rate)
+            nb_leads.reverse()
+            res[section.id] = nb_leads
         return res
 
     _columns = {
@@ -142,20 +187,19 @@ class crm_case_section(osv.osv):
         'alias_id': fields.many2one('mail.alias', 'Alias', ondelete="cascade", required=True,
                                     help="The email address associated with this team. New emails received will automatically "
                                          "create new leads assigned to the team."),
-        'open_lead_ids': fields.one2many('crm.lead', 'section_id',
-            string='Open Leads', readonly=True,
-            domain=['&', ('type', '!=', 'opportunity'), ('state', 'not in', ['done', 'cancel'])]),
-        'open_opportunity_ids': fields.one2many('crm.lead', 'section_id',
-            string='Open Opportunities', readonly=True,
-            domain=['&', '|', ('type', '=', 'opportunity'), ('type', '=', 'both'), ('state', 'not in', ['done', 'cancel'])]),
         'color': fields.integer('Color Index'),
         'use_leads': fields.boolean('Leads',
             help="This enables the management of leads in the sales team. Otherwise the sales team manages only opportunities."),
+
         'target_duration': fields.selection([("monthly", "Monthly"), ("semesterly", "Semesterly"), ("semiannually", "Semiannually"), ("annually", "Annually")],
             string='Report duration view', 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='Rate of opporunities whon per duration', type="string", readonly=True)
+        
     }
 
     def _get_stage_common(self, cr, uid, context):
index 44f45f2..c32ce4e 100644 (file)
@@ -79,9 +79,9 @@
                     <field name="note"/>
                     <field name="alias_id"/>
                     <field name="color"/>
-                    <field name="open_lead_ids"/>
-                    <field name="open_opportunity_ids"/>
                     <field name="target_duration_txt"/>
+                    <field name="open_lead_per_duration"/>
+                    <field name="won_opportunity_per_duration"/>
                     <templates>
                         <t t-name="kanban-box">
                             <div t-attf-class="oe_kanban_color_#{kanban_getcolor(record.color.raw_value)} oe_kanban_card oe_kanban_global_click oe_kanban_crm_salesteams">
                                     </div>
                                     <div class="oe_items_list">
                                         <div>
-                                            <a t-if="record.use_leads.raw_value" name="%(crm_case_form_view_salesteams_lead)d" type="action"><t t-raw="record.open_lead_ids.raw_value.length"/><t t-if="record.open_lead_ids.raw_value.length &gt;= 2">Leads</t><t t-if="record.open_lead_ids.raw_value.length &lt; 2">Lead</t></a>
-                                            <a name="%(crm_case_form_view_salesteams_lead)d" type="action" class="oe_sparkline_bar"><t t-raw="[6,4,7,2]"/></a>
+                                            <a t-if="record.use_leads.raw_value" name="%(crm_case_form_view_salesteams_lead)d" type="action">Leads</a>
+                                            <a name="%(crm_case_form_view_salesteams_lead)d" type="action" class="oe_sparkline_bar" title="Number of opening leads per duration.\n(last item is the most recent)"><t t-raw="record.open_lead_per_duration.raw_value"/></a>
                                         </div>
                                         <div>
-                                            <a name="%(crm_case_form_view_salesteams_opportunity)d" type="action"><t t-raw="record.open_opportunity_ids.raw_value.length"/><t t-if="record.open_opportunity_ids.raw_value.length &gt;= 2">Opportunities</t><t t-if="record.open_opportunity_ids.raw_value.length &lt; 2">Opportunity</t></a>
-                                            <a name="%(crm_case_form_view_salesteams_opportunity)d" type="action" class="oe_sparkline_bar"><t t-raw="[6,4,7,2]"/></a>
+                                            <a name="%(crm_case_form_view_salesteams_opportunity)d" type="action">Opportunities</a>
+                                            <a name="%(crm_case_form_view_salesteams_opportunity)d" type="action" class="oe_sparkline_bar" title="Rate of won opportunities per duration.\n(last item is the most recent)"><t t-raw="record.won_opportunity_per_duration.raw_value"/></a>
                                         </div>
                                     </div>
                                 </div>
index 4e69bf8..a228d09 100644 (file)
@@ -61,7 +61,7 @@ openerp.crm = function(openerp) {
                             });
                         }
                     });
-                    setTimeout(function () {self.$(".oe_sparkline_bar").sparkline('html', {type: 'bar', barWidth: 5, zeroColor: '#ff0000'} );}, 0);
+                    setTimeout(function () {self.$(".oe_sparkline_bar").sparkline('html', {type: 'bar', barWidth: 5} );}, 0);
                 });
             }
         },
index 7cabe1c..f3453dd 100644 (file)
             <field name="inherit_id" ref="crm.crm_case_section_salesteams_view_kanban"/>
             <field name="arch" type="xml">
             <data>
-                <xpath expr="//field[@name='open_opportunity_ids']" position="after">
+                <xpath expr="//field[@name='name']" position="after">
                     <field name="quotation_ids"/>
                     <field name="sale_order_ids"/>
                     <field name="invoice_ids"/>
                 <xpath expr="//div[@class='oe_items_list']" position="inside">
                     <div>
                         <a name="%(action_quotations_salesteams)d" type="action"><t t-raw="record.quotation_ids.raw_value.length"/><t t-if="record.quotation_ids.raw_value.length &gt;= 2">Quotations</t><t t-if="record.quotation_ids.raw_value.length &lt; 2">Quotation</t></a>
-                        <a name="%(action_quotations_salesteams)d" type="action" class="oe_sparkline_bar"><t t-raw="[6,4,7,2]"/></a>
+                        <a name="%(action_quotations_salesteams)d" type="action" class="oe_sparkline_bar"><t t-raw="[6,4,7,2,1]"/></a>
                     </div>
                     <div>
                         <a name="%(action_orders_salesteams)d" type="action"><t t-raw="record.sale_order_ids.raw_value.length"/><t t-if="record.sale_order_ids.raw_value.length &gt;= 2">Sales Orders</t><t t-if="record.sale_order_ids.raw_value.length &lt; 2">Sales Order</t>
                         </a>
-                        <a name="%(action_orders_salesteams)d" type="action" class="oe_sparkline_bar"><t t-raw="[6,4,7,2]"/></a>
+                        <a name="%(action_orders_salesteams)d" type="action" class="oe_sparkline_bar"><t t-raw="[6,4,7,4,2]"/></a>
                     </div>
                     <div>
                         <a name="%(action_invoice_salesteams)d" type="action" groups="account.group_account_invoice"><t t-raw="record.invoice_ids.raw_value.length"/><t t-if="record.invoice_ids.raw_value.length &gt;= 2">Invoices</t><t t-if="record.invoice_ids.raw_value.length &lt; 2">Invoice</t></a>
-                        <a name="%(action_invoice_salesteams)d" type="action" class="oe_sparkline_bar"><t t-raw="[6,4,7,2]"/></a>
+                        <a name="%(action_invoice_salesteams)d" type="action" class="oe_sparkline_bar"><t t-raw="[6,4,7,2,6]"/></a>
                     </div>
                 </xpath>
                 <xpath expr="//div[@class='oe_items_list']" position="after">