[CLEAN] crm, sale_crm: cleaned code for new fields. Fixed some bugs in calculation and monthly repartition. Updated form views. Improved use of sparkline widget, now having tootips.
bzr revid: tde@openerp.com-20130531153100-q1cmpx0kjb02cbtu
This commit is contained in:
parent
71df2e6f7d
commit
09e0cd8dc6
|
@ -19,12 +19,12 @@
|
||||||
#
|
#
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
|
from datetime import date, datetime
|
||||||
|
from dateutil import relativedelta
|
||||||
|
|
||||||
from openerp import tools
|
from openerp import tools
|
||||||
from openerp.osv import fields
|
from openerp.osv import fields
|
||||||
from openerp.osv import osv
|
from openerp.osv import osv
|
||||||
from openerp.tools.translate import _
|
|
||||||
from datetime import date, datetime
|
|
||||||
from dateutil.relativedelta import relativedelta
|
|
||||||
|
|
||||||
MAX_LEVEL = 15
|
MAX_LEVEL = 15
|
||||||
AVAILABLE_STATES = [
|
AVAILABLE_STATES = [
|
||||||
|
@ -105,34 +105,55 @@ class crm_case_section(osv.osv):
|
||||||
_inherit = "mail.thread"
|
_inherit = "mail.thread"
|
||||||
_description = "Sales Teams"
|
_description = "Sales Teams"
|
||||||
_order = "complete_name"
|
_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):
|
def get_full_name(self, cr, uid, ids, field_name, arg, context=None):
|
||||||
return dict(self.name_get(cr, uid, ids, context=context))
|
return dict(self.name_get(cr, uid, ids, context=context))
|
||||||
|
|
||||||
def _get_open_lead_per_duration(self, cr, uid, ids, field_name, arg, context=None):
|
def __get_bar_values(self, cr, uid, obj, domain, read_fields, value_field, groupby_field, context=None):
|
||||||
res = dict.fromkeys(ids, [])
|
""" Generic method to generate data for bar chart values using SparklineBarWidget.
|
||||||
obj = self.pool.get('crm.lead')
|
This method performs obj.read_group(cr, uid, domain, read_fields, groupby_field).
|
||||||
today = date.today().replace(day=1)
|
|
||||||
begin = (today + relativedelta(months=-5)).strftime(tools.DEFAULT_SERVER_DATE_FORMAT)
|
|
||||||
for section in self.browse(cr, uid, ids, context=context):
|
|
||||||
domain = [("section_id", "=", section.id), '|', ('type', '=', 'lead'), ('date_open', '!=', None), ('create_date', '>=', begin)]
|
|
||||||
group_obj = obj.read_group(cr, uid, domain, ["create_date"], "create_date", context=context)
|
|
||||||
group_list = [group['create_date_count'] for group in group_obj]
|
|
||||||
nb_month = group_obj and relativedelta(today, datetime.strptime(group_obj[-1]['__domain'][0][2], '%Y-%m-%d')).months or 0
|
|
||||||
res[section.id] = [0]*(5 - len(group_list) - nb_month) + group_list + [0]*nb_month
|
|
||||||
return res
|
|
||||||
|
|
||||||
def _get_won_opportunity_per_duration(self, cr, uid, ids, field_name, arg, context=None):
|
:param obj: the target model (i.e. crm_lead)
|
||||||
res = dict.fromkeys(ids, [])
|
: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')
|
obj = self.pool.get('crm.lead')
|
||||||
today = date.today().replace(day=1)
|
res = dict.fromkeys(ids, False)
|
||||||
begin = (today + relativedelta(months=-5)).strftime(tools.DEFAULT_SERVER_DATE_FORMAT)
|
month_begin = date.today().replace(day=1)
|
||||||
for section in self.browse(cr, uid, ids, context=context):
|
groupby_begin = (month_begin + relativedelta.relativedelta(months=-4)).strftime(tools.DEFAULT_SERVER_DATE_FORMAT)
|
||||||
domain = [("section_id", "=", section.id), '|', ('type', '=', 'opportunity'), ('date_open', '!=', None), ('create_date', '>=', begin)]
|
for id in ids:
|
||||||
group_obj = obj.read_group(cr, uid, domain, ['planned_revenue', "create_date"], "create_date", context=context)
|
res[id] = dict()
|
||||||
group_list = [group['planned_revenue'] for group in group_obj]
|
lead_domain = [('type', '=', 'lead'), ('section_id', '=', id), ('create_date', '>=', groupby_begin)]
|
||||||
nb_month = group_obj and relativedelta(today, datetime.strptime(group_obj[-1]['__domain'][0][2], '%Y-%m-%d')).months or 0
|
res[id]['monthly_open_leads'] = self.__get_bar_values(cr, uid, obj, lead_domain, ['create_date'], 'create_date_count', 'create_date', context=context)
|
||||||
res[section.id] = [0]*(5 - len(group_list) - nb_month) + group_list + [0]*nb_month
|
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
|
return res
|
||||||
|
|
||||||
_columns = {
|
_columns = {
|
||||||
|
@ -158,8 +179,12 @@ class crm_case_section(osv.osv):
|
||||||
'use_leads': fields.boolean('Leads',
|
'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."),
|
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."),
|
||||||
|
|
||||||
'open_lead_per_duration': fields.function(_get_open_lead_per_duration, string='Open Leads per duration', type="string", readonly=True),
|
'monthly_open_leads': fields.function(_get_opportunities_data,
|
||||||
'won_opportunity_per_duration': fields.function(_get_won_opportunity_per_duration, string='Revenue of opporunities whon per duration', type="string", readonly=True)
|
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):
|
def _get_stage_common(self, cr, uid, context):
|
||||||
|
|
|
@ -78,8 +78,8 @@
|
||||||
<field name="note"/>
|
<field name="note"/>
|
||||||
<field name="alias_id"/>
|
<field name="alias_id"/>
|
||||||
<field name="color"/>
|
<field name="color"/>
|
||||||
<field name="open_lead_per_duration"/>
|
<field name="monthly_open_leads"/>
|
||||||
<field name="won_opportunity_per_duration"/>
|
<field name="monthly_planned_revenue"/>
|
||||||
<templates>
|
<templates>
|
||||||
<t t-name="kanban-box">
|
<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 t-attf-class="oe_kanban_color_#{kanban_getcolor(record.color.raw_value)} oe_kanban_card oe_kanban_global_click oe_kanban_crm_salesteams">
|
||||||
|
@ -99,10 +99,11 @@
|
||||||
<div class="oe_items_list">
|
<div class="oe_items_list">
|
||||||
<div class="oe_salesteams_leads" t-if="record.use_leads.raw_value">
|
<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="%(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 month.<br/>Click to see a detailed analysis of leads.</field></a>
|
<a name="%(action_report_crm_lead)d" type="action" class="oe_sparkline_bar_link"><field name="monthly_open_leads" widget="sparkline_bar">Open Leads per Month<br/>Click to see a detailed analysis of leads.</field></a>
|
||||||
</div><div class="oe_salesteams_opportunities">
|
</div>
|
||||||
|
<div class="oe_salesteams_opportunities">
|
||||||
<a name="%(crm_case_form_view_salesteams_opportunity)d" type="action">Opportunities</a>
|
<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 month.<br/>Click to see a detailed analysis of opportunities.</field></a>
|
<a name="%(action_report_crm_opportunity)d" type="action"><field name="monthly_planned_revenue" widget="sparkline_bar">Planned Revenue per Month<br/>Click to see a detailed analysis of opportunities.</field></a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -182,15 +183,13 @@
|
||||||
</div>
|
</div>
|
||||||
<group>
|
<group>
|
||||||
<group>
|
<group>
|
||||||
<field name="parent_id"/>
|
<field name="user_id"/>
|
||||||
<field name="active"/>
|
<field name="code"/>
|
||||||
</group>
|
</group>
|
||||||
<group>
|
<group>
|
||||||
<field name="user_id"/>
|
<field name="parent_id"/>
|
||||||
<field name="change_responsible"/>
|
<field name="change_responsible"/>
|
||||||
</group>
|
<field name="active"/>
|
||||||
<group colspan="4" attrs="{'invisible': [('use_leads', '=', False)]}">
|
|
||||||
|
|
||||||
</group>
|
</group>
|
||||||
</group>
|
</group>
|
||||||
<notebook colspan="4">
|
<notebook colspan="4">
|
||||||
|
|
|
@ -15,7 +15,16 @@ openerp.crm = function(openerp) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var title = this.$node.html();
|
var title = this.$node.html();
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
self.$el.sparkline(self.field.value, {type: 'bar', barWidth: 5} );
|
var value = _.pluck(self.field.value, 'value');
|
||||||
|
var tooltips = _.pluck(self.field.value, 'tooltip');
|
||||||
|
self.$el.sparkline(value, {
|
||||||
|
type: 'bar',
|
||||||
|
barWidth: 5,
|
||||||
|
tooltipFormat: '{{offset:offset}} {{value}}',
|
||||||
|
tooltipValueLookups: {
|
||||||
|
'offset': tooltips
|
||||||
|
},
|
||||||
|
});
|
||||||
self.$el.tipsy({'delayIn': 0, 'html': true, 'title': function(){return title}, 'gravity': 'n'});
|
self.$el.tipsy({'delayIn': 0, 'html': true, 'title': function(){return title}, 'gravity': 'n'});
|
||||||
}, 0);
|
}, 0);
|
||||||
},
|
},
|
||||||
|
|
|
@ -19,9 +19,10 @@
|
||||||
#
|
#
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
from datetime import date, datetime
|
from datetime import date
|
||||||
|
from dateutil import relativedelta
|
||||||
|
|
||||||
from openerp import tools
|
from openerp import tools
|
||||||
from dateutil.relativedelta import relativedelta
|
|
||||||
from openerp.osv import osv, fields
|
from openerp.osv import osv, fields
|
||||||
|
|
||||||
|
|
||||||
|
@ -48,65 +49,51 @@ class sale_order(osv.osv):
|
||||||
class crm_case_section(osv.osv):
|
class crm_case_section(osv.osv):
|
||||||
_inherit = 'crm.case.section'
|
_inherit = 'crm.case.section'
|
||||||
|
|
||||||
def _get_created_quotation_per_duration(self, cr, uid, ids, field_name, arg, context=None):
|
def _get_sale_orders_data(self, cr, uid, ids, field_name, arg, context=None):
|
||||||
res = dict.fromkeys(ids, [])
|
|
||||||
obj = self.pool.get('sale.order')
|
obj = self.pool.get('sale.order')
|
||||||
today = date.today().replace(day=1)
|
res = dict.fromkeys(ids, False)
|
||||||
begin = (today + relativedelta(months=-5)).strftime(tools.DEFAULT_SERVER_DATE_FORMAT)
|
month_begin = date.today().replace(day=1)
|
||||||
for section in self.browse(cr, uid, ids, context=context):
|
groupby_begin = (month_begin + relativedelta.relativedelta(months=-4)).strftime(tools.DEFAULT_SERVER_DATE_FORMAT)
|
||||||
domain = [("section_id", "=", section.id), ('state', 'in', ['draft', 'sent']), ('date_order', '>=', begin)]
|
for id in ids:
|
||||||
group_obj = obj.read_group(cr, uid, domain, ['amount_total', "date_order"], "date_order", context=context)
|
res[id] = dict()
|
||||||
group_list = [group['amount_total'] for group in group_obj]
|
created_domain = [('section_id', '=', id), ('state', 'in', ['draft', 'sent']), ('date_order', '>=', groupby_begin)]
|
||||||
nb_month = group_obj and relativedelta(today, datetime.strptime(group_obj[-1]['__domain'][0][2], '%Y-%m-%d')).months or 0
|
res[id]['monthly_quoted'] = self.__get_bar_values(cr, uid, obj, created_domain, ['amount_total', 'date_order'], 'amount_total', 'date_order', context=context)
|
||||||
res[section.id] = [0]*(5 - len(group_list) - nb_month) + group_list + [0]*nb_month
|
validated_domain = [('section_id', '=', id), ('state', 'not in', ['draft', 'sent']), ('date_confirm', '>=', groupby_begin)]
|
||||||
|
res[id]['monthly_confirmed'] = self.__get_bar_values(cr, uid, obj, validated_domain, ['amount_total', 'date_confirm'], 'amount_total', 'date_confirm', context=context)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def _get_validate_saleorder_per_duration(self, cr, uid, ids, field_name, arg, context=None):
|
def _get_invoices_data(self, cr, uid, ids, field_name, arg, context=None):
|
||||||
res = dict.fromkeys(ids, [])
|
|
||||||
obj = self.pool.get('sale.order')
|
|
||||||
today = date.today().replace(day=1)
|
|
||||||
begin = (today + relativedelta(months=-5)).strftime(tools.DEFAULT_SERVER_DATE_FORMAT)
|
|
||||||
for section in self.browse(cr, uid, ids, context=context):
|
|
||||||
domain = [("section_id", "=", section.id), ('state', 'not in', ['draft', 'sent']), ('date_confirm', '>=', begin)]
|
|
||||||
group_obj = obj.read_group(cr, uid, domain, ['amount_total', "date_confirm"], "date_confirm", context=context)
|
|
||||||
group_list = [group['amount_total'] for group in group_obj]
|
|
||||||
nb_month = group_obj and relativedelta(today, datetime.strptime(group_obj[-1]['__domain'][0][2], '%Y-%m-%d')).months or 0
|
|
||||||
res[section.id] = [0]*(5 - len(group_list) - nb_month) + group_list + [0]*nb_month
|
|
||||||
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')
|
obj = self.pool.get('account.invoice.report')
|
||||||
today = date.today().replace(day=1)
|
res = dict.fromkeys(ids, False)
|
||||||
begin = (today + relativedelta(months=-5)).strftime(tools.DEFAULT_SERVER_DATE_FORMAT)
|
month_begin = date.today().replace(day=1)
|
||||||
for section in self.browse(cr, uid, ids, context=context):
|
groupby_begin = (month_begin + relativedelta.relativedelta(months=-4)).strftime(tools.DEFAULT_SERVER_DATE_FORMAT)
|
||||||
domain = [("section_id", "=", section.id), ('state', 'not in', ['draft', 'cancel']), ('date', '>=', begin)]
|
for id in ids:
|
||||||
group_obj = obj.read_group(cr, uid, domain, ['price_total', "date"], "date", context=context)
|
created_domain = [('section_id', '=', id), ('state', 'not in', ['draft', 'cancel']), ('date', '>=', groupby_begin)]
|
||||||
group_list = [group['price_total'] for group in group_obj]
|
res[id] = self.__get_bar_values(cr, uid, obj, created_domain, ['price_total', 'date'], 'price_total', 'date', context=context)
|
||||||
nb_month = group_obj and relativedelta(today, datetime.strptime(group_obj[-1]['__domain'][0][2], '%Y-%m-%d')).months or 0
|
|
||||||
res[section.id] = [0]*(5 - len(group_list) - nb_month) + group_list + [0]*nb_month
|
|
||||||
return res
|
return res
|
||||||
|
|
||||||
_columns = {
|
_columns = {
|
||||||
'quotation_ids': fields.one2many('sale.order', 'section_id',
|
'invoiced_forecast': fields.integer(string='Invoice Forecast',
|
||||||
string='Quotations', readonly=True,
|
help="Forecast of the invoice revenue for the current month. This is the amount the sales \n"
|
||||||
domain=[('state', 'in', ['draft', 'sent', 'cancel'])]),
|
"team should invoice this month. It is used to compute the progression ratio \n"
|
||||||
'sale_order_ids': fields.one2many('sale.order', 'section_id',
|
" of the current and forecast revenue on the kanban view."),
|
||||||
string='Sale Orders', readonly=True,
|
'invoiced_target': fields.integer(string='Invoice Target',
|
||||||
domain=[('state', 'not in', ['draft', 'sent', 'cancel'])]),
|
help="Target of invoice revenue for the current month. This is the amount the sales \n"
|
||||||
'invoice_ids': fields.one2many('account.invoice', 'section_id',
|
"team estimates to be able to invoice this month."),
|
||||||
string='Invoices', readonly=True,
|
'monthly_quoted': fields.function(_get_sale_orders_data,
|
||||||
domain=[('state', 'not in', ['draft', 'cancel'])]),
|
type='string', readonly=True, multi='_get_sale_orders_data',
|
||||||
|
string='Rate of created quotation per duration'),
|
||||||
'forecast': fields.integer(string='Total forecast'),
|
'monthly_confirmed': fields.function(_get_sale_orders_data,
|
||||||
'target_invoice': fields.integer(string='Invoicing Target'),
|
type='string', readonly=True, multi='_get_sale_orders_data',
|
||||||
'created_quotation_per_duration': fields.function(_get_created_quotation_per_duration, string='Rate of created quotation per duration', type="string", readonly=True),
|
string='Rate of validate sales orders per duration'),
|
||||||
'validate_saleorder_per_duration': fields.function(_get_validate_saleorder_per_duration, string='Rate of validate sales orders per duration', type="string", readonly=True),
|
'monthly_invoiced': fields.function(_get_invoices_data,
|
||||||
'sent_invoice_per_duration': fields.function(_get_sent_invoice_per_duration, string='Rate of sent invoices per duration', type="string", readonly=True),
|
type='string', readonly=True,
|
||||||
|
string='Rate of sent invoices per duration'),
|
||||||
}
|
}
|
||||||
|
|
||||||
def action_forecast(self, cr, uid, id, value, context=None):
|
def action_forecast(self, cr, uid, id, value, context=None):
|
||||||
return self.write(cr, uid, [id], {'forecast': value}, context=context)
|
return self.write(cr, uid, [id], {'invoiced_forecast': value}, context=context)
|
||||||
|
|
||||||
|
|
||||||
class res_users(osv.Model):
|
class res_users(osv.Model):
|
||||||
_inherit = 'res.users'
|
_inherit = 'res.users'
|
||||||
|
|
|
@ -217,10 +217,9 @@
|
||||||
<field name="inherit_id" ref="crm.crm_case_section_view_form"/>
|
<field name="inherit_id" ref="crm.crm_case_section_view_form"/>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<data>
|
<data>
|
||||||
<xpath expr="//group" position="inside">
|
<xpath expr="//field[@name='code']" position="after">
|
||||||
<group>
|
<field name="invoiced_target"/>
|
||||||
<field name="target_invoice"/>
|
<field name="invoiced_forecast"/>
|
||||||
</group>
|
|
||||||
</xpath>
|
</xpath>
|
||||||
</data>
|
</data>
|
||||||
</field>
|
</field>
|
||||||
|
@ -233,30 +232,46 @@
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<data>
|
<data>
|
||||||
<xpath expr="//field[@name='name']" position="after">
|
<xpath expr="//field[@name='name']" position="after">
|
||||||
<field name="created_quotation_per_duration"/>
|
<field name="monthly_quoted"/>
|
||||||
<field name="validate_saleorder_per_duration"/>
|
<field name="monthly_confirmed"/>
|
||||||
<field name="sent_invoice_per_duration"/>
|
<field name="monthly_invoiced"/>
|
||||||
|
<field name="invoiced_forecast"/>
|
||||||
<field name="forecast"/>
|
<field name="invoiced_target"/>
|
||||||
<field name="target_invoice"/>
|
|
||||||
</xpath>
|
</xpath>
|
||||||
<xpath expr="//div[@class='oe_salesteams_leads']" position="after"><div class="oe_salesteams_orders">
|
<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="%(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 month.<br/>Click the acces to Sales Analysis</field></a>
|
<a name="%(sale.action_order_report_all)d" type="action" class="oe_sparkline_bar_link">
|
||||||
</div></xpath>
|
<field name="monthly_confirmed" widget="sparkline_bar">
|
||||||
<xpath expr="//div[@class='oe_salesteams_opportunities']" position="after"><div class="oe_salesteams_invoices">
|
Revenue of confirmed sales orders per month.<br/>Click the acces to Sales Analysis
|
||||||
<a name="%(action_invoice_salesteams)d" type="action" groups="account.group_account_invoice">Invoices</a>
|
</field>
|
||||||
<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 month.<br/>Click to see a detailed analysis of invoices.</field></a>
|
</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 month.<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" 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'}">Invoiced</field>
|
|
||||||
<field name="forecast" widget="gage" style="width:160px; height: 120px;" options="{'max_field': 'target_invoice', 'action_change': 'action_forecast'}">Forecast</field>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="oe_center" style="color:#bbbbbb;" t-if="!record.target_invoice.raw_value">
|
</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="monthly_invoiced" widget="sparkline_bar">
|
||||||
|
Revenue of sent invoices per month.<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="monthly_quoted" widget="sparkline_bar">
|
||||||
|
Revenue of created quotation per month.<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" t-if="record.invoiced_target.raw_value">
|
||||||
|
<field name="monthly_invoiced" widget="gage" style="width:160px; height: 120px;" options="{'max_field': 'invoiced_target'}">Invoiced</field>
|
||||||
|
<field name="invoiced_forecast" widget="gage" style="width:160px; height: 120px;" options="{'max_field': 'invoiced_target', 'action_change': 'action_forecast'}">Forecast</field>
|
||||||
|
</div>
|
||||||
|
<div class="oe_center" style="color:#bbbbbb;" t-if="!record.invoiced_target.raw_value">
|
||||||
<br/>Define an invoicing target in the sales team settings to see the period's achievement and forecast at a glance.
|
<br/>Define an invoicing target in the sales team settings to see the period's achievement and forecast at a glance.
|
||||||
</div>
|
</div>
|
||||||
</xpath>
|
</xpath>
|
||||||
|
|
|
@ -11,7 +11,7 @@ openerp.sale_crm.GaugeWidget = openerp.web_kanban.AbstractField.extend({
|
||||||
var label = this.options.label_field ? parent.record[this.options.label_field].raw_value : "";
|
var label = this.options.label_field ? parent.record[this.options.label_field].raw_value : "";
|
||||||
var title = this.$node.html();
|
var title = this.$node.html();
|
||||||
var val = this.field.value;
|
var val = this.field.value;
|
||||||
var value = _.isArray(val) && val.length ? val[val.length-1] : val;
|
var value = _.isArray(val) && val.length ? val[val.length-1]['value'] : val;
|
||||||
var unique_id = _.uniqueId("JustGage");
|
var unique_id = _.uniqueId("JustGage");
|
||||||
|
|
||||||
this.$el.empty()
|
this.$el.empty()
|
||||||
|
|
Loading…
Reference in New Issue