[MERGE] from trunk
authorChristophe Matthieu <chm@openerp.com>
Fri, 24 May 2013 10:05:33 +0000 (12:05 +0200)
committerChristophe Matthieu <chm@openerp.com>
Fri, 24 May 2013 10:05:33 +0000 (12:05 +0200)
bzr revid: chm@openerp.com-20130522145042-3ril2zvogqs55ako
bzr revid: chm@openerp.com-20130524100533-fc0c7l47hb8j4xib

1  2 
addons/crm/crm_case_section_view.xml
addons/crm/crm_lead.py
addons/crm/crm_lead_view.xml
addons/sale_crm/sale_crm.py
addons/sale_crm/sale_crm_view.xml

@@@ -43,8 -43,7 +43,7 @@@
              <field name="search_view_id" ref="crm.view_crm_case_opportunities_filter"/>
              <field name="context">{
                      'search_default_section_id': [active_id],
-                     'search_default_new': 1,
-                     'search_default_open': 1,
+                     'search_default_assigned_to_me': 1,
                      'default_section_id': active_id,
                      'stage_type': 'opportunity',
                      'default_type': 'opportunity',
                      <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_project oe_kanban_global_click oe_kanban_crm_salesteams">
 -                                <div class="oe_dropdown_toggle oe_dropdown_kanban" groups="base.group_user">
 +                            <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 class="oe_dropdown_toggle oe_dropdown_kanban" groups="base.group_sale_manager">
                                      <span class="oe_e">í</span>
                                      <ul class="oe_dropdown_menu">
                                          <li t-if="widget.view.is_action_enabled('edit')"><a type="edit">Sales Teams Settings</a></li>
                                      </ul>
                                  </div>
                                  <div class="oe_kanban_content">
 -                                    <h4><field name="name"/></h4>
 -                                    <div class="oe_kanban_alias" t-if="record.use_leads.raw_value and record.alias_id.value">
 -                                        <span class="oe_e">%%</span><small><field name="alias_id"/></small>
 +                                    <h4 class="oe_center"><field name="name"/></h4>
 +                                    <div class="oe_kanban_alias oe_center" t-if="record.use_leads.raw_value and record.alias_id.value">
 +                                        <small><span class="oe_e" style="float: none;">%%</span><t t-raw="record.alias_id.raw_value[1]"/></small>
                                      </div>
                                      <div class="oe_items_list">
 -                                        <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_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>
 -                                    </div>
 -                                    <div class="oe_avatars">
 -                                        <img t-if="record.user_id.raw_value" t-att-src="kanban_image('res.users', 'image_small', record.user_id.raw_value)" t-att-data-member_id="record.user_id.raw_value"/>
 -                                        <t t-foreach="record.member_ids.raw_value.slice(0,11)" t-as="member">
 -                                            <img t-att-src="kanban_image('res.users', 'image_small', member)" t-att-data-member_id="member"/>
 -                                        </t>
 +                                        <div class="oe_salesteams_leads" t-if="record.use_leads.raw_value">
 +                                            <a name="%(crm_case_form_view_salesteams_lead)d" type="action">Leads</a>
 +                                            <a name="%(action_report_crm_lead)d" type="action" class="oe_sparkline_bar_link"><field name="open_lead_per_duration" widget="sparkline_bar">Number of opening leads per duration.<br/>(last one is <t t-esc="record.target_duration_txt.value"/>).<br/>Click to see a detailed analysis of leads.</field></a>
 +                                        </div><div class="oe_salesteams_opportunities">
 +                                            <a name="%(crm_case_form_view_salesteams_opportunity)d" type="action">Opportunities</a>
 +                                            <a name="%(action_report_crm_opportunity)d" type="action"><field name="won_opportunity_per_duration" widget="sparkline_bar">Revenue of won opportunities per duration.<br/>(last one is <t t-esc="record.target_duration_txt.value"/>).<br/>Click to see a detailed analysis of opportunities.</field></a>
 +                                        </div>
                                      </div>
                                  </div>
                              </div>
              </field>
          </record>
  
 +        <!-- Case Sections Search view -->
 +
 +        <record id="crm_case_section_salesteams_search" model="ir.ui.view">
 +            <field name="name">Case Sections - Search</field>
 +            <field name="model">crm.case.section</field>
 +            <field name="arch" type="xml">
 +                <search string="Salesteams Search">
 +                    <field name="name"/>
 +                    <field name="parent_id"/>
 +                    <field name="user_id"/>
 +                    <field name="note"/>
 +                    <filter name="my" string="My" domain="['|', ('member_ids', '=', uid), ('user_id', '=', uid)]"/>
 +                    <group expand="0" string="Group By...">
 +                        <filter string="Parent Sales Teams" domain="[]" context="{'group_by':'parent_id'}"/>
 +                    </group>
 +                </search>
 +            </field>
 +        </record>
 +
          <!-- Case Sections Action -->
  
          <record id="crm_case_section_salesteams_act" model="ir.actions.act_window">
              <field name="res_model">crm.case.section</field>
              <field name="view_type">form</field>
              <field name="view_mode">kanban,tree,form</field>
 +            <field name="context">{'search_default_my': True}</field>
              <field name="view_id" ref="crm_case_section_salesteams_view_kanban"/>
              <field name="help" type="html">
                  <p class="oe_view_nocontent_create">
                  <form string="Sales Team" version="7.0">
                      <sheet>
                          <div class="oe_title">
 -                            <label for="name" class="oe_edit_only" string="Project Name"/>
 +                            <label for="name" class="oe_edit_only" string="Sales team"/>
                              <h1>
 -                                <field name="name" string="Project Name"/>
 +                                <field name="name" string="Sales team"/>
                              </h1>
                              <div name="group_alias"
                                      attrs="{'invisible': [('alias_domain', '=', False)]}">
                          <group>
                              <group>
                                  <field name="parent_id"/>
 -                                <field name="resource_calendar_id"/>
                                  <field name="active"/>
                              </group>
                              <group>
                                  <field name="user_id"/>
 -                                <field name="code"/>
 +                                <field name="change_responsible"/>
 +                            </group>
 +                            <group colspan="4" col="2">
 +                                <field name="target_duration" widget="radio"/>
                              </group>
                              <group colspan="4" attrs="{'invisible': [('use_leads', '=', False)]}">
                                  
                              </group>
                          </group>
                          <notebook colspan="4">
 -                            <page string="Sales Team">
 -                               <group>
 -                                    <field name="change_responsible"/>
 -                                </group>
 -                                <separator string="Team Members"/>
 +                            <page string="Team Members">
                                  <field name="member_ids" widget="many2many_kanban">
                                      <kanban quick_create="false" create="true">
                                          <field name="name"/>
diff --combined addons/crm/crm_lead.py
@@@ -23,8 -23,9 +23,9 @@@ from openerp.addons.base_status.base_st
  import crm
  from datetime import datetime
  from operator import itemgetter
- from openerp.osv import fields, osv
+ from openerp.osv import fields, osv, orm
  import time
+ from openerp import SUPERUSER_ID
  from openerp import tools
  from openerp.tools.translate import _
  from openerp.tools import html2plaintext
@@@ -366,8 -367,8 +367,8 @@@ class crm_lead(base_stage, format_addre
      def on_change_user(self, cr, uid, ids, user_id, context=None):
          """ When changing the user, also set a section_id or restrict section id
              to the ones user_id is member of. """
 -        section_id = False
 -        if user_id:
 +        section_id = self._get_default_section_id(cr, uid, context=context) or False
 +        if user_id and not section_id:
              section_ids = self.pool.get('crm.case.section').search(cr, uid, ['|', ('user_id', '=', user_id), ('member_ids', '=', user_id)], context=context)
              if section_ids:
                  section_id = section_ids[0]
      def message_get_reply_to(self, cr, uid, ids, context=None):
          """ Override to get the reply_to of the parent project. """
          return [lead.section_id.message_get_reply_to()[0] if lead.section_id else False
-                     for lead in self.browse(cr, uid, ids, context=context)]
+                     for lead in self.browse(cr, SUPERUSER_ID, ids, context=context)]
+     def _get_formview_action(self, cr, uid, id, context=None):
+         action = super(crm_lead, self)._get_formview_action(cr, uid, id, context=context)
+         obj = self.browse(cr, uid, id, context=context)
+         if obj.type == 'opportunity':
+             model, view_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'crm', 'crm_case_form_view_oppor')
+             action.update({
+                 'views': [(view_id, 'form')],
+                 })
+         return action
  
      def message_get_suggested_recipients(self, cr, uid, ids, context=None):
          recipients = super(crm_lead, self).message_get_suggested_recipients(cr, uid, ids, context=context)
-         for lead in self.browse(cr, uid, ids, context=context):
-             if lead.partner_id:
-                 self._message_add_suggested_recipient(cr, uid, recipients, lead, partner=lead.partner_id, reason=_('Customer'))
-             elif lead.email_from:
-                 self._message_add_suggested_recipient(cr, uid, recipients, lead, email=lead.email_from, reason=_('Customer Email'))
+         try:
+             for lead in self.browse(cr, uid, ids, context=context):
+                 if lead.partner_id:
+                     self._message_add_suggested_recipient(cr, uid, recipients, lead, partner=lead.partner_id, reason=_('Customer'))
+                 elif lead.email_from:
+                     self._message_add_suggested_recipient(cr, uid, recipients, lead, email=lead.email_from, reason=_('Customer Email'))
+         except (osv.except_osv, orm.except_orm):  # no read access rights -> just ignore suggested recipients because this imply modifying followers
+             pass
          return recipients
  
      def message_new(self, cr, uid, msg, custom_values=None, context=None):
                              help="Leads that are assigned to me"/>
                      <filter string="Assigned to My Team(s)"
                              domain="[('section_id.member_ids', 'in', [uid])]" context="{'invisible_section': False}"
 -                            help="Leads that are assigned to any sales teams I am member of"/>
 +                            help="Leads that are assigned to any sales teams I am member of" groups="base.group_multi_salesteams"/>
                      <separator />
                      <filter string="Available for mass mailing"
                              name='not_opt_out' domain="[('opt_out', '=', False)]"
                      <separator />
                      <group expand="0" string="Group By...">
                          <filter string="Salesperson" domain="[]" context="{'group_by':'user_id'}"/>
 -                        <filter string="Team" domain="[]" context="{'group_by':'section_id'}"/>
 +                        <filter string="Team" domain="[]" context="{'group_by':'section_id'}" groups="base.group_multi_salesteams"/>
                          <filter string="Stage" domain="[]" context="{'group_by':'stage_id'}"/>
                          <filter string="Customer" help="Partner" domain="[]" context="{'group_by':'partner_id'}"/>
                          <filter string="Country" domain="[]" context="{'group_by':'country_id'}"/>
                      </group>
                      <group string="Display">
                          <filter string="Show Countries" context="{'invisible_country': False}" help="Show Countries"/>
 -                        <filter string="Show Sales Team" context="{'invisible_section': False}" domain="[]" help="Show Sales Team"/>
 +                        <filter string="Show Sales Team" context="{'invisible_section': False}" domain="[]" help="Show Sales Team" groups="base.group_multi_salesteams"/>
                      </group>
                  </search>
              </field>
                      <filter string="Lost" name="lost" domain="[('state','=','cancel')]"/>
                      <filter string="Unassigned" name="unassigned" domain="[('user_id','=', False)]" help="No salesperson"/>
                      <filter string="Unread Messages" name="message_unread" domain="[('message_unread','=',True)]" help="Unread messages"/>
-                     <filter string="Assigned to Me"
+                     <filter string="Mine" name="assigned_to_me"
                              domain="[('user_id','=',uid)]" context="{'invisible_section': False}"
                              help="Opportunities that are assigned to me"/>
                      <filter string="Assigned to My Team(s)"
                          <filter string="Creation" domain="[]" context="{'group_by':'create_date'}"/>
                      </group>
                      <group string="Display">
 -                        <filter string="Show Sales Team" context="{'invisible_section': False}" domain="[]" help="Show Sales Team"/>
 +                        <filter string="Show Sales Team" context="{'invisible_section': False}" domain="[]" help="Show Sales Team" groups="base.group_multi_salesteams"/>
                          <filter string="Show Countries" context="{'invisible_country': False}" help="Show Countries"/>
                      </group>
                  </search>
  #
  ##############################################################################
  
 -from datetime import datetime
 +from datetime import date
 +from openerp import tools
 +from dateutil.relativedelta import relativedelta
  from openerp.osv import osv, fields
  
 +MONTHS = {
 +    "monthly": 1,
 +    "semesterly": 3,
 +    "semiannually": 6,
 +    "annually": 12
 +}
  
  class sale_order(osv.osv):
      _inherit = 'sale.order'
              domain="['|',('section_id','=',section_id),('section_id','=',False), ('object_id.model', '=', 'crm.lead')]")
      }
  
 +    def _make_invoice(self, cr, uid, order, lines, context=None):
 +        if order.section_id:
 +            context = dict(context or {}, default_section_id= order.section_id.id)
 +        return super(sale_order, self)._make_invoice(cr, uid, order, lines, context=context)
 +
+     def _prepare_invoice(self, cr, uid, order, lines, context=None):
+         invoice_vals = super(sale_order, self)._prepare_invoice(cr, uid, order, lines, context=context)
+         if order.section_id and order.section_id.id:
+             invoice_vals['section_id'] = order.section_id.id
+         return invoice_vals
  
  class crm_case_section(osv.osv):
      _inherit = 'crm.case.section'
  
 -    def _get_sum_month_invoice(self, cr, uid, ids, field_name, arg, context=None):
 -        res = dict.fromkeys(ids, 0)
 +    def _get_created_quotation_per_duration(self, cr, uid, ids, field_name, arg, context=None):
 +        res = dict.fromkeys(ids, [])
 +        obj = self.pool.get('sale.order')
 +        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)]
 +            rate_invoice = []
 +            for when in range(0, 5):
 +                domain = [("section_id", "=", section.id), ('state', 'in', ['draft', 'sent']), ('date_order', '>=', dates[when].strftime(tools.DEFAULT_SERVER_DATE_FORMAT))]
 +                if when:
 +                    domain += [('date_order', '<', dates[when-1].strftime(tools.DEFAULT_SERVER_DATE_FORMAT))]
 +                rate = 0
 +                order_ids = obj.search(cr, uid, domain, context=context)
 +                for order in obj.browse(cr, uid, order_ids, context=context):
 +                    rate += order.amount_total
 +                rate_invoice.append(rate)
 +            rate_invoice.reverse()
 +            res[section.id] = rate_invoice
 +        return res
 +
 +    def _get_validate_saleorder_per_duration(self, cr, uid, ids, field_name, arg, context=None):
 +        res = dict.fromkeys(ids, [])
 +        obj = self.pool.get('sale.order')
 +        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)]
 +            rate_invoice = []
 +            for when in range(0, 5):
 +                domain = [("section_id", "=", section.id), ('state', 'not in', ['draft', 'sent']), ('date_confirm', '>=', dates[when].strftime(tools.DEFAULT_SERVER_DATE_FORMAT))]
 +                if when:
 +                    domain += [('date_confirm', '<', dates[when-1].strftime(tools.DEFAULT_SERVER_DATE_FORMAT))]
 +                rate = 0
 +                order_ids = obj.search(cr, uid, domain, context=context)
 +                for order in obj.browse(cr, uid, order_ids, context=context):
 +                    rate += order.amount_total
 +                rate_invoice.append(rate)
 +            rate_invoice.reverse()
 +            res[section.id] = rate_invoice
 +        return res
 +
 +    def _get_sent_invoice_per_duration(self, cr, uid, ids, field_name, arg, context=None):
 +        res = dict.fromkeys(ids, [])
          obj = self.pool.get('account.invoice.report')
 -        when = datetime.today()
 -        for section_id in ids:
 -            invoice_ids = obj.search(cr, uid, [("section_id", "=", section_id), ('state', 'not in', ['draft', 'cancel']), ('year', '=', when.year), ('month', '=', when.month > 9 and when.month or "0%s" % when.month)], context=context)
 -            for invoice in obj.browse(cr, uid, invoice_ids, context=context):
 -                res[section_id] += invoice.price_total
 +        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)]
 +            rate_invoice = []
 +            for when in range(0, 5):
 +                domain = [("section_id", "=", section.id), ('state', 'not in', ['draft', 'cancel']), ('date', '>=', dates[when].strftime(tools.DEFAULT_SERVER_DATE_FORMAT))]
 +                if when:
 +                    domain += [('date', '<', dates[when-1].strftime(tools.DEFAULT_SERVER_DATE_FORMAT))]
 +                rate = 0
 +                invoice_ids = obj.search(cr, uid, domain, context=context)
 +                for invoice in obj.browse(cr, uid, invoice_ids, context=context):
 +                    rate += invoice.price_total
 +                rate_invoice.append(rate)
 +            rate_invoice.reverse()
 +            res[section.id] = rate_invoice
          return res
  
      _columns = {
          'invoice_ids': fields.one2many('account.invoice', 'section_id',
              string='Invoices', readonly=True,
              domain=[('state', 'not in', ['draft', 'cancel'])]),
 -        'sum_month_invoice': fields.function(_get_sum_month_invoice,
 -            string='Total invoiced this month',
 -            type='integer', readonly=True),
 +
 +        'forecast': fields.integer(string='Total forecast'),
 +        'target_invoice': fields.integer(string='Invoicing Target'),
 +        'created_quotation_per_duration': fields.function(_get_created_quotation_per_duration, string='Rate of created quotation per duration', type="string", readonly=True),
 +        'validate_saleorder_per_duration': fields.function(_get_validate_saleorder_per_duration, string='Rate of validate sales orders per duration', type="string", readonly=True),
 +        'sent_invoice_per_duration': fields.function(_get_sent_invoice_per_duration, string='Rate of sent invoices per duration', type="string", readonly=True),
      }
  
 +    def action_forecast(self, cr, uid, id, value, context=None):
 +        return self.write(cr, uid, [id], {'forecast': value}, context=context)
  
  class res_users(osv.Model):
      _inherit = 'res.users'
              </field>
          </record>
  
+         <!-- add needaction_menu_ref to reload quotation needaction when opportunity needaction is reloaded -->
+         <record model="ir.actions.act_window" id="crm.crm_case_category_act_oppor11">
+             <field name="context">{'stage_type': 'opportunity', 'default_type': 'opportunity', 'default_user_id': uid, 'needaction_menu_ref': 'sale.menu_sale_quotations'}</field>
+         </record>
          <record model="ir.ui.view" id="sale_view_inherit123">
              <field name="name">sale.order.inherit</field>
              <field name="model">sale.order</field>
@@@ -38,7 -43,7 +43,7 @@@
                      <filter string="My Sales Team(s)"
                          icon="terp-personal+"
                          domain="[('section_id.user_id','=',uid)]"
 -                        help="My Sales Team(s)"/>
 +                        help="My Sales Team(s)"  groups="base.group_multi_salesteams"/>
                  </xpath>
                  <xpath expr="//field[@name='user_id']" position="after">
                      <field name="section_id" string="Sales Team" groups="base.group_multi_salesteams"/>
@@@ -70,7 -75,7 +75,7 @@@
                      <field name="section_id"/>
                  </xpath>
                  <xpath expr="//group/filter[@string='Due Date']" position="after">
 -                    <filter string="Sales Team" domain="[]" context="{'group_by':'section_id'}"/>
 +                    <filter string="Sales Team" domain="[]" context="{'group_by':'section_id'}" groups="base.group_multi_salesteams"/>
                  </xpath>
              </field>
          </record>
              <field name="context">{
                      'search_default_section_id': [active_id],
                      'default_section_id': active_id,
 -                    'search_default_my_sale_orders_filter': 1,
                  }
              </field>
              <field name="help" type="html">
              <field name="view_mode">tree,form,calendar,graph</field>
              <field name="context">{
                      'search_default_section_id': [active_id],
 -                    'default_section_id': active_id, 'show_address': 1,
 -                    'search_default_my_sale_orders_filter': 1
 +                    'default_section_id': active_id,
 +                    'show_address': 1,
                  }
              </field>
              <field name="domain">[('state','in',('draft','sent','cancel'))]</field>
                  ('type', '=', 'out_invoice')]</field>
              <field name="context">{
                      'search_default_section_id': [active_id],
 -                    'default_section_id': active_id},
 +                    'default_section_id': active_id,
                      'default_type':'out_invoice',
                      'type':'out_invoice',
                      'journal_type': 'sale',
              <field name="act_window_id" ref="sale_crm.action_invoice_salesteams"/>
          </record>
  
 +        <record id="crm_case_section_salesteams_view_form" model="ir.ui.view">
 +            <field name="name">crm.case.section.form</field>
 +            <field name="model">crm.case.section</field>
 +            <field name="inherit_id" ref="crm.crm_case_section_view_form"/>
 +            <field name="arch" type="xml">
 +            <data>
 +                <field name="target_duration" position="before">
 +                    <field name="target_invoice"/>
 +                </field>
 +            </data>
 +            </field>
 +        </record>
 +
          <record id="crm_case_section_salesteams_view_kanban" model="ir.ui.view">
              <field name="name">crm.case.section.kanban</field>
              <field name="model">crm.case.section</field>
              <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">
 -                    <field name="quotation_ids"/>
 -                    <field name="sale_order_ids"/>
 -                    <field name="invoice_ids"/>
 -                </xpath>
 -                <xpath expr="//div[@class='oe_items_list']" position="inside">
 -                    <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_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_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>
 +                <xpath expr="//field[@name='name']" position="after">
 +                    <field name="created_quotation_per_duration"/>
 +                    <field name="validate_saleorder_per_duration"/>
 +                    <field name="sent_invoice_per_duration"/>
 +
 +                    <field name="forecast"/>
 +                    <field name="target_invoice"/>
                  </xpath>
 +                <xpath expr="//div[@class='oe_salesteams_leads']" position="after"><div class="oe_salesteams_orders">
 +                        <a name="%(action_orders_salesteams)d" type="action">Sales Orders</a>
 +                        <a name="%(sale.action_order_report_all)d" type="action" class="oe_sparkline_bar_link"><field name="validate_saleorder_per_duration" widget="sparkline_bar">Revenue of confirmed sales orders per <t t-esc="record.target_duration_txt.value"/>).<br/>Click the acces to Sales Analysis</field></a>
 +                    </div></xpath>
 +                <xpath expr="//div[@class='oe_salesteams_opportunities']" position="after"><div class="oe_salesteams_invoices">
 +                        <a name="%(action_invoice_salesteams)d" type="action" groups="account.group_account_invoice">Invoices</a>
 +                        <a name="%(account.action_account_invoice_report_all)d" type="action" class="oe_sparkline_bar_link"><field name="sent_invoice_per_duration" widget="sparkline_bar">Revenue of sent invoices per <t t-esc="record.target_duration_txt.value"/>.<br/>Click to see a detailed analysis of invoices.</field></a>
 +                    </div><div class="oe_salesteams_quotations">
 +                        <a name="%(action_quotations_salesteams)d" type="action" class="oe_sparkline_bar_link">Quotations</a>
 +                        <a name="%(sale.action_order_report_all)d" type="action" class="oe_sparkline_bar_link"><field name="created_quotation_per_duration" widget="sparkline_bar">Revenue of created quotation per <t t-esc="record.target_duration_txt.value"/>.<br/>Click to see a detailed analysis of sales.</field></a>
 +                    </div></xpath>
                  <xpath expr="//div[@class='oe_items_list']" position="after">
 -                    <div class="oe_center">
 -                        <div class="oe_sum"><field name="sum_month_invoice"/></div>
 -                        <div class="oe_subsum">Invoiced this month</div>
 +                    <div class="oe_center" t-if="record.target_invoice.raw_value">
 +                        <field name="sent_invoice_per_duration" widget="gage" style="width:160px; height: 120px;" options="{'max_field': 'target_invoice', 'label_field': 'target_duration_txt'}">Invoiced</field>
 +                        <field name="forecast" widget="gage" style="width:160px; height: 120px;" options="{'max_field': 'target_invoice', 'label_field': 'target_duration_txt', 'action_change': 'action_forecast'}">Forecast</field>
 +                    </div>
 +                    <div class="oe_center" style="color:#bbbbbb;" t-if="!record.target_invoice.raw_value">
 +                        <br/>Define an invoicing target in the sales team settings to see the period's achievement and forecast at a glance.
                      </div>
                  </xpath>
              </data>