[IMP][ADD] crm: add the concept of activities, allowing
to define custom light workflows on opportunities. Activities are linked to mail.message.subtype through inheritance. This means that the follow mechanism works for activities. When an activity is done, a message with the matching subtype is posted on the opportunity. Activities are internal by default. They are only visible by employees. A shortcut in the 'log a note' chatter option allows to post a note linked to an activity (subtype).
This commit is contained in:
committed by
Thibault Delavallée
parent
03592e1c73
commit
ff2b14d4c3
@@ -4,8 +4,8 @@
|
||||
import crm
|
||||
import crm_lead
|
||||
import sales_team
|
||||
import models
|
||||
import calendar_event
|
||||
import crm_phonecall
|
||||
import report
|
||||
import wizard
|
||||
import res_partner
|
||||
|
||||
@@ -7,12 +7,12 @@
|
||||
'version': '1.0',
|
||||
'category': 'Customer Relationship Management',
|
||||
'sequence': 2,
|
||||
'summary': 'Leads, Opportunities, Phone Calls',
|
||||
'summary': 'Leads, Opportunities, Activities',
|
||||
'description': """
|
||||
The generic OpenERP Customer Relationship Management
|
||||
====================================================
|
||||
|
||||
This application enables a group of people to intelligently and efficiently manage leads, opportunities, meetings and phone calls.
|
||||
This application enables a group of people to intelligently and efficiently manage leads, opportunities, meetings and activities.
|
||||
|
||||
It manages key tasks such as communication, identification, prioritization, assignment, resolution and notification.
|
||||
|
||||
@@ -44,33 +44,27 @@ Dashboard for CRM will include:
|
||||
'web_planner',
|
||||
],
|
||||
'data': [
|
||||
'data/crm_action_data.xml',
|
||||
'crm_data.xml',
|
||||
'crm_lead_data.xml',
|
||||
'crm_phonecall_data.xml',
|
||||
'crm_tip_data.xml',
|
||||
|
||||
'security/crm_security.xml',
|
||||
'security/ir.model.access.csv',
|
||||
|
||||
'wizard/crm_lead_to_opportunity_view.xml',
|
||||
|
||||
'wizard/crm_phonecall_to_phonecall_view.xml',
|
||||
|
||||
'wizard/crm_merge_opportunities_view.xml',
|
||||
|
||||
'crm_view.xml',
|
||||
|
||||
'crm_phonecall_view.xml',
|
||||
'crm_phonecall_menu.xml',
|
||||
|
||||
'crm_lead_view.xml',
|
||||
'crm_lead_menu.xml',
|
||||
'views/crm_action_views.xml',
|
||||
|
||||
'calendar_event_menu.xml',
|
||||
|
||||
'report/crm_lead_report_view.xml',
|
||||
'report/crm_activity_report_view.xml',
|
||||
'report/crm_opportunity_report_view.xml',
|
||||
'report/crm_phonecall_report_view.xml',
|
||||
|
||||
'res_partner_view.xml',
|
||||
|
||||
@@ -85,7 +79,7 @@ Dashboard for CRM will include:
|
||||
'demo': [
|
||||
'crm_demo.xml',
|
||||
'crm_lead_demo.xml',
|
||||
'crm_phonecall_demo.xml',
|
||||
'data/crm_action_demo.xml',
|
||||
'crm_action_rule_demo.xml',
|
||||
],
|
||||
'test': [
|
||||
@@ -95,7 +89,6 @@ Dashboard for CRM will include:
|
||||
'test/lead2opportunity_assign_salesmen.yml',
|
||||
'test/crm_lead_merge.yml',
|
||||
'test/crm_lead_cancel.yml',
|
||||
'test/phonecalls.yml',
|
||||
'test/crm_lead_onchange.yml',
|
||||
'test/crm_lead_copy.yml',
|
||||
'test/crm_lead_unlink.yml',
|
||||
|
||||
@@ -10,7 +10,6 @@ class calendar_event(osv.Model):
|
||||
""" Model for Calendar Event """
|
||||
_inherit = 'calendar.event'
|
||||
_columns = {
|
||||
'phonecall_id': fields.many2one('crm.phonecall', 'Phonecall'),
|
||||
'opportunity_id': fields.many2one('crm.lead', 'Opportunity', domain="[('type', '=', 'opportunity')]"),
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
<field name="message_type">notification</field>
|
||||
<field name="subtype_id" ref="mail.mt_comment"/>
|
||||
<field name="subject">CRM application installed!</field>
|
||||
<field name="body"><![CDATA[<p>From the top Sales menu you can track leads and opportunities, get accurate forecast on your sales pipeline, plan meetings and phonecalls, get realtime statistics and efficiently organize the communication with your prospects.</p>
|
||||
<field name="body"><![CDATA[<p>From the top Sales menu you can track leads and opportunities, get accurate forecast on your sales pipeline, plan meetings, get realtime statistics and efficiently organize the communication with your prospects.</p>
|
||||
<p>To manage quotations and sale orders, install the "Sales Management" application.</p>]]></field>
|
||||
</record>
|
||||
|
||||
|
||||
+78
-77
@@ -1,10 +1,11 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import crm
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timedelta
|
||||
import logging
|
||||
from operator import itemgetter
|
||||
|
||||
import crm
|
||||
import openerp
|
||||
from openerp import SUPERUSER_ID
|
||||
from openerp import tools, api
|
||||
@@ -14,6 +15,7 @@ from openerp.tools.translate import _
|
||||
from openerp.tools import email_re, email_split
|
||||
from openerp.exceptions import UserError, AccessError
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
CRM_LEAD_FIELDS_TO_MERGE = ['name',
|
||||
'partner_id',
|
||||
@@ -155,14 +157,6 @@ class crm_lead(format_address, osv.osv):
|
||||
for opp_id in ids
|
||||
}
|
||||
|
||||
def _calls_count(self, cr, uid, ids, field_name, args, context=None):
|
||||
res = dict.fromkeys(ids, 0)
|
||||
phonecall_data = self.pool['crm.phonecall'].read_group(
|
||||
cr, uid, [('opportunity_id', 'in', ids)], ['opportunity_id'], ['opportunity_id'], context=context)
|
||||
for data in phonecall_data:
|
||||
res[data['opportunity_id'][0]] = data['opportunity_id_count']
|
||||
return res
|
||||
|
||||
_columns = {
|
||||
'partner_id': fields.many2one('res.partner', 'Partner', ondelete='set null', track_visibility='onchange',
|
||||
select=True, help="Linked partner (optional). Usually created when converting the lead."),
|
||||
@@ -211,8 +205,14 @@ class crm_lead(format_address, osv.osv):
|
||||
'ref2': fields.reference('Reference 2', selection=openerp.addons.base.res.res_request.referencable_models),
|
||||
'phone': fields.char("Phone", size=64),
|
||||
'date_deadline': fields.date('Expected Closing', help="Estimate of the date on which the opportunity will be won."),
|
||||
# CRM Actions
|
||||
'next_activity_id': fields.many2one("crm.activity", "Next Activity", select=True),
|
||||
'next_activity_1': fields.related("next_activity_id", "activity_1_id", "name", type="char", string="Next Activity 1"),
|
||||
'next_activity_2': fields.related("next_activity_id", "activity_2_id", "name", type="char", string="Next Activity 2"),
|
||||
'next_activity_3': fields.related("next_activity_id", "activity_3_id", "name", type="char", string="Next Activity 3"),
|
||||
'date_action': fields.date('Next Action Date', select=True),
|
||||
'title_action': fields.char('Next Action'),
|
||||
'title_action': fields.char('Next Action Summary'),
|
||||
|
||||
'color': fields.integer('Color Index'),
|
||||
'partner_address_name': fields.related('partner_id', 'name', type='char', string='Partner Contact Name', readonly=True),
|
||||
'partner_address_email': fields.related('partner_id', 'email', type='char', string='Partner Contact Email', readonly=True),
|
||||
@@ -236,7 +236,6 @@ class crm_lead(format_address, osv.osv):
|
||||
'planned_cost': fields.float('Planned Costs'),
|
||||
'meeting_count': fields.function(_meeting_count, string='# Meetings', type='integer'),
|
||||
'lost_reason': fields.many2one('crm.lost.reason', 'Lost Reason', select=True, track_visibility='onchange'),
|
||||
'calls_count': fields.function(_calls_count, string='# Phonecalls', type='integer'),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
@@ -381,6 +380,73 @@ class crm_lead(format_address, osv.osv):
|
||||
self.write(cr, uid, lead_ids, {'stage_id': stage_id}, context=context)
|
||||
return True
|
||||
|
||||
def log_next_activity_1(self, cr, uid, ids, context=None):
|
||||
return self.log_next_activity_done(cr, uid, ids, next_activity_name='activity_1_id', context=context)
|
||||
|
||||
def log_next_activity_2(self, cr, uid, ids, context=None):
|
||||
return self.log_next_activity_done(cr, uid, ids, next_activity_name='activity_2_id', context=context)
|
||||
|
||||
def log_next_activity_3(self, cr, uid, ids, context=None):
|
||||
return self.log_next_activity_done(cr, uid, ids, next_activity_name='activity_3_id', context=context)
|
||||
|
||||
def log_next_activity_done(self, cr, uid, ids, context=None, next_activity_name=False):
|
||||
to_clear_ids = []
|
||||
for lead in self.browse(cr, uid, ids, context=context):
|
||||
if not lead.next_activity_id:
|
||||
continue
|
||||
body_html = """<div><b>${object.next_activity_id.name}</b></div>
|
||||
%if object.title_action:
|
||||
<div>${object.title_action}</div>
|
||||
%endif"""
|
||||
body_html = self.pool['mail.template'].render_template(cr, uid, body_html, 'crm.lead', lead.id, context=context)
|
||||
msg_id = lead.message_post(body_html, subtype_id=lead.next_activity_id.subtype_id.id)
|
||||
# update subtype after posting NOT SURE
|
||||
|
||||
next_activity = next_activity_name and getattr(lead.next_activity_id, next_activity_name, False) or False
|
||||
if next_activity:
|
||||
date_action = False
|
||||
if next_activity.days:
|
||||
date_action = (datetime.now() + timedelta(days=next_activity.days)).strftime(tools.DEFAULT_SERVER_DATETIME_FORMAT),
|
||||
lead.write({
|
||||
'next_activity_id': next_activity.id,
|
||||
'date_action': date_action,
|
||||
'title_action': next_activity.description,
|
||||
})
|
||||
else:
|
||||
to_clear_ids.append(lead.id)
|
||||
|
||||
if to_clear_ids:
|
||||
self.cancel_next_activity(cr, uid, to_clear_ids, context=context)
|
||||
return True
|
||||
|
||||
def cancel_next_activity(self, cr, uid, ids, context=None):
|
||||
return self.write(cr, uid, ids, {
|
||||
'next_activity_id': False,
|
||||
'date_action': False,
|
||||
'title_action': False,
|
||||
}, context=context)
|
||||
|
||||
def onchange_next_activity_id(self, cr, uid, ids, next_activity_id, context=None):
|
||||
if not next_activity_id:
|
||||
return {'value': {
|
||||
'next_action1': False,
|
||||
'next_action2': False,
|
||||
'next_action3': False,
|
||||
'title_action': False,
|
||||
'date_action': False,
|
||||
}}
|
||||
activity = self.pool['crm.activity'].browse(cr, uid, next_activity_id, context=context)
|
||||
date_action = False
|
||||
if activity.days:
|
||||
date_action = (datetime.now() + timedelta(days=activity.days)).strftime(tools.DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
return {'value': {
|
||||
'next_activity_1': activity.activity_1_id and activity.activity_1_id.name or False,
|
||||
'next_activity_2': activity.activity_2_id and activity.activity_2_id.name or False,
|
||||
'next_activity_3': activity.activity_3_id and activity.activity_3_id.name or False,
|
||||
'title_action': activity.description,
|
||||
'date_action': date_action,
|
||||
}}
|
||||
|
||||
def _merge_get_result_type(self, cr, uid, opps, context=None):
|
||||
"""
|
||||
Define the type of the result of the merge. If at least one of the
|
||||
@@ -534,13 +600,6 @@ class crm_lead(format_address, osv.osv):
|
||||
attachment.write(values)
|
||||
return True
|
||||
|
||||
def _merge_opportunity_phonecalls(self, cr, uid, opportunity_id, opportunities, context=None):
|
||||
phonecall_obj = self.pool['crm.phonecall']
|
||||
for opportunity in opportunities:
|
||||
for phonecall_id in phonecall_obj.search(cr, uid, [('opportunity_id', '=', opportunity.id)], context=context):
|
||||
phonecall_obj.write(cr, uid, phonecall_id, {'opportunity_id': opportunity_id}, context=context)
|
||||
return True
|
||||
|
||||
def get_duplicated_leads(self, cr, uid, ids, partner_id, include_lost=False, context=None):
|
||||
"""
|
||||
Search for opportunities that have the same partner and that arent done or cancelled
|
||||
@@ -571,7 +630,6 @@ class crm_lead(format_address, osv.osv):
|
||||
self._merge_notify(cr, uid, highest, opportunities, context=context)
|
||||
self._merge_opportunity_history(cr, uid, highest, opportunities, context=context)
|
||||
self._merge_opportunity_attachments(cr, uid, highest, opportunities, context=context)
|
||||
self._merge_opportunity_phonecalls(cr, uid, highest, opportunities, context=context)
|
||||
|
||||
def merge_opportunity(self, cr, uid, ids, user_id=False, team_id=False, context=None):
|
||||
"""
|
||||
@@ -647,7 +705,6 @@ class crm_lead(format_address, osv.osv):
|
||||
'name': lead.name,
|
||||
'partner_id': customer and customer.id or False,
|
||||
'type': 'opportunity',
|
||||
'date_action': fields.datetime.now(),
|
||||
'date_open': fields.datetime.now(),
|
||||
'email_from': customer and customer.email or lead.email_from,
|
||||
'phone': customer and customer.phone or lead.phone,
|
||||
@@ -726,7 +783,6 @@ class crm_lead(format_address, osv.osv):
|
||||
:param int partner_id: partner to assign if any
|
||||
:return dict: dictionary organized as followed: {lead_id: partner_assigned_id}
|
||||
"""
|
||||
#TODO this is a duplication of the handle_partner_assignation method of crm_phonecall
|
||||
partner_ids = {}
|
||||
for lead in self.browse(cr, uid, ids, context=context):
|
||||
# If the action is set to 'create' and no partner_id is set, create a new one
|
||||
@@ -767,45 +823,6 @@ class crm_lead(format_address, osv.osv):
|
||||
self.write(cr, uid, [lead_id], value, context=context)
|
||||
return True
|
||||
|
||||
def schedule_phonecall(self, cr, uid, ids, schedule_time, call_summary, desc, phone, contact_name, user_id=False, team_id=False, categ_id=False, action='schedule', context=None):
|
||||
"""
|
||||
:param string action: ('schedule','Schedule a call'), ('log','Log a call')
|
||||
"""
|
||||
phonecall = self.pool.get('crm.phonecall')
|
||||
model_data = self.pool.get('ir.model.data')
|
||||
phonecall_dict = {}
|
||||
if not categ_id:
|
||||
try:
|
||||
res_id = model_data._get_id(cr, uid, 'crm', 'categ_phone2')
|
||||
categ_id = model_data.browse(cr, uid, res_id, context=context).res_id
|
||||
except ValueError:
|
||||
pass
|
||||
for lead in self.browse(cr, uid, ids, context=context):
|
||||
if not team_id:
|
||||
team_id = lead.team_id and lead.team_id.id or False
|
||||
if not user_id:
|
||||
user_id = lead.user_id and lead.user_id.id or False
|
||||
vals = {
|
||||
'name': call_summary,
|
||||
'opportunity_id': lead.id,
|
||||
'user_id': user_id or False,
|
||||
'categ_id': categ_id or False,
|
||||
'description': desc or '',
|
||||
'date': schedule_time,
|
||||
'team_id': team_id or False,
|
||||
'partner_id': lead.partner_id and lead.partner_id.id or False,
|
||||
'partner_phone': phone or lead.phone or (lead.partner_id and lead.partner_id.phone or False),
|
||||
'partner_mobile': lead.partner_id and lead.partner_id.mobile or False,
|
||||
'priority': lead.priority,
|
||||
}
|
||||
new_id = phonecall.create(cr, uid, vals, context=context)
|
||||
phonecall.write(cr, uid, [new_id], {'state': 'open'}, context=context)
|
||||
if action == 'log':
|
||||
phonecall.write(cr, uid, [new_id], {'state': 'done'}, context=context)
|
||||
phonecall_dict[lead.id] = new_id
|
||||
self.schedule_phonecall_send_note(cr, uid, [lead.id], new_id, action, context=context)
|
||||
return phonecall_dict
|
||||
|
||||
def redirect_opportunity_view(self, cr, uid, opportunity_id, context=None):
|
||||
models_data = self.pool.get('ir.model.data')
|
||||
|
||||
@@ -1006,22 +1023,6 @@ class crm_lead(format_address, osv.osv):
|
||||
|
||||
return super(crm_lead, self).message_update(cr, uid, ids, msg, update_vals=update_vals, context=context)
|
||||
|
||||
# ----------------------------------------
|
||||
# OpenChatter methods and notifications
|
||||
# ----------------------------------------
|
||||
|
||||
def schedule_phonecall_send_note(self, cr, uid, ids, phonecall_id, action, context=None):
|
||||
phonecall = self.pool.get('crm.phonecall').browse(cr, uid, [phonecall_id], context=context)[0]
|
||||
if action == 'log':
|
||||
message = _('Logged a call for %(date)s. %(description)s')
|
||||
else:
|
||||
message = _('Scheduled a call for %(date)s. %(description)s')
|
||||
phonecall_date = datetime.strptime(phonecall.date, tools.DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
phonecall_usertime = fields.datetime.context_timestamp(cr, uid, phonecall_date, context=context).strftime(tools.DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
html_time = "<time datetime='%s+00:00'>%s</time>" % (phonecall.date, phonecall_usertime)
|
||||
message = message % dict(date=html_time, description=phonecall.description)
|
||||
return self.message_post(cr, uid, ids, body=message, context=context)
|
||||
|
||||
def log_meeting(self, cr, uid, ids, meeting_subject, meeting_date, duration, context=None):
|
||||
if not duration:
|
||||
duration = _('unknown')
|
||||
|
||||
@@ -319,6 +319,7 @@ Andrew</field>
|
||||
<field name="tag_ids" eval="[(6, 0, [categ_oppor1])]"/>
|
||||
<field name="priority">1</field>
|
||||
<field eval="time.strftime('%Y-%m-25')" name="date_deadline"/>
|
||||
<field name="next_activity_id" ref="crm_activity_data_meeting"/>
|
||||
<field eval="time.strftime('%Y-%m-12')" name="date_action"/>
|
||||
<field name="title_action">Meeting for pricing information.</field>
|
||||
<field name="team_id" ref="sales_team.team_sales_department"/>
|
||||
@@ -345,6 +346,7 @@ Andrew</field>
|
||||
<field name="tag_ids" eval="[(6, 0, [categ_oppor2])]"/>
|
||||
<field name="priority">2</field>
|
||||
<field eval="time.strftime('%Y-%m-23')" name="date_deadline"/>
|
||||
<field name="next_activity_id" ref="crm_activity_data_email"/>
|
||||
<field eval="time.strftime('%Y-%m-10')" name="date_action"/>
|
||||
<field name="title_action">Send Catalogue by Email</field>
|
||||
<field name="team_id" ref="sales_team.team_sales_department"/>
|
||||
@@ -368,6 +370,7 @@ Andrew</field>
|
||||
<field name="tag_ids" eval="[(6, 0, [categ_oppor1])]"/>
|
||||
<field name="priority">1</field>
|
||||
<field eval="time.strftime('%Y-%m-12')" name="date_deadline"/>
|
||||
<field name="next_activity_id" ref="crm_activity_data_call"/>
|
||||
<field eval="time.strftime('%Y-%m-10')" name="date_action"/>
|
||||
<field name="title_action">Call to ask system requirement</field>
|
||||
<field name="team_id" ref="sales_team.team_sales_department"/>
|
||||
@@ -396,6 +399,7 @@ Andrew</field>
|
||||
<field name="tag_ids" eval="[(6, 0, [categ_oppor5])]"/>
|
||||
<field name="priority">2</field>
|
||||
<field eval="time.strftime('%Y-%m-28')" name="date_deadline"/>
|
||||
<field name="next_activity_id" ref="crm_activity_data_meeting"/>
|
||||
<field eval="time.strftime('%Y-%m-1')" name="date_action"/>
|
||||
<field name="title_action">Convert to quote</field>
|
||||
<field name="team_id" ref="sales_team.crm_team_1"/>
|
||||
@@ -421,6 +425,7 @@ Andrew</field>
|
||||
<field name="tag_ids" eval="[(6, 0, [categ_oppor3,categ_oppor4])]"/>
|
||||
<field name="priority">1</field>
|
||||
<field eval="time.strftime('%Y-%m-8')" name="date_deadline"/>
|
||||
<field name="next_activity_id" ref="crm_activity_data_email"/>
|
||||
<field eval="time.strftime('%Y-%m-3')" name="date_action"/>
|
||||
<field name="title_action">Send price list regarding our interventions</field>
|
||||
<field name="team_id" ref="sales_team.crm_team_1"/>
|
||||
@@ -450,6 +455,7 @@ Andrew</field>
|
||||
<field name="tag_ids" eval="[(6, 0, [categ_oppor4,categ_oppor6])]"/>
|
||||
<field name="priority">1</field>
|
||||
<field eval="time.strftime('%Y-%m-13')" name="date_deadline"/>
|
||||
<field name="next_activity_id" ref="crm_activity_data_call"/>
|
||||
<field eval="time.strftime('%Y-%m-4')" name="date_action"/>
|
||||
<field name="title_action">Call to define real needs about training</field>
|
||||
<field name="team_id" ref="sales_team.crm_team_1"/>
|
||||
@@ -478,6 +484,7 @@ Andrew</field>
|
||||
<field name="tag_ids" eval="[(6, 0, [categ_oppor1])]"/>
|
||||
<field name="priority">1</field>
|
||||
<field eval="time.strftime('%Y-%m-10')" name="date_deadline"/>
|
||||
<field name="next_activity_id" ref="crm_activity_data_call"/>
|
||||
<field eval="time.strftime('%Y-%m-5')" name="date_action"/>
|
||||
<field name="title_action">Ask for the good receprion of the proposition</field>
|
||||
<field name="team_id" ref="sales_team.crm_team_1"/>
|
||||
@@ -498,6 +505,7 @@ Andrew</field>
|
||||
<field name="partner_id" ref="base.res_partner_5"/>
|
||||
<field name="tag_ids" eval="[(6, 0, [categ_oppor4,categ_oppor8])]"/>
|
||||
<field name="priority">2</field>
|
||||
<field name="next_activity_id" ref="crm_activity_data_call"/>
|
||||
<field name="team_id" ref="sales_team.crm_team_1"/>
|
||||
<field name="user_id" ref="base.user_demo"/>
|
||||
<field name="stage_id" ref="crm.stage_lead4"/>
|
||||
@@ -512,6 +520,7 @@ Andrew</field>
|
||||
<field name="partner_id" ref="base.res_partner_7"/>
|
||||
<field name="tag_ids" eval="[(6, 0, [categ_oppor7])]"/>
|
||||
<field name="priority">2</field>
|
||||
<field name="next_activity_id" ref="crm_activity_data_meeting"/>
|
||||
<field name="team_id" ref="sales_team.crm_team_2"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="stage_id" ref="crm.stage_lead4"/>
|
||||
@@ -531,6 +540,7 @@ Andrew</field>
|
||||
<field name="partner_id" ref="base.res_partner_17"/>
|
||||
<field name="tag_ids" eval="[(6, 0, [categ_oppor3])]"/>
|
||||
<field name="priority">1</field>
|
||||
<field name="next_activity_id" ref="crm_activity_data_email"/>
|
||||
<field name="team_id" ref="sales_team.crm_team_2"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="stage_id" ref="crm.stage_lead5"/>
|
||||
@@ -547,6 +557,7 @@ Andrew</field>
|
||||
<field name="partner_id" ref="base.res_partner_18"/>
|
||||
<field name="tag_ids" eval="[(6, 0, [categ_oppor3])]"/>
|
||||
<field name="priority">0</field>
|
||||
<field name="next_activity_id" ref="crm_activity_data_email"/>
|
||||
<field name="team_id" ref="sales_team.team_sales_department"/>
|
||||
<field name="user_id" ref="base.user_demo"/>
|
||||
<field name="stage_id" ref="crm.stage_lead5"/>
|
||||
@@ -567,6 +578,7 @@ Andrew</field>
|
||||
<field name="tag_ids" eval="[(6, 0, [categ_oppor7])]"/>
|
||||
<field name="priority">0</field>
|
||||
<field eval="time.strftime('%Y-%m-6')" name="date_deadline"/>
|
||||
<field name="next_activity_id" ref="crm_activity_data_email"/>
|
||||
<field name="team_id" ref="sales_team.team_sales_department"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="stage_id" ref="crm.stage_lead5"/>
|
||||
@@ -591,6 +603,7 @@ Andrew</field>
|
||||
<field name="zip">B7313</field>
|
||||
<field name="tag_ids" eval="[(6, 0, [categ_oppor4])]"/>
|
||||
<field name="priority">2</field>
|
||||
<field name="next_activity_id" ref="crm_activity_data_call"/>
|
||||
<field name="title_action">Conf call with technical service</field>
|
||||
<field name="team_id" ref="sales_team.crm_team_1"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
@@ -614,6 +627,7 @@ Andrew</field>
|
||||
<field name="tag_ids" eval="[(6, 0, [categ_oppor2])]"/>
|
||||
<field name="priority">2</field>
|
||||
<field eval="time.strftime('%Y-%m-23')" name="date_deadline"/>
|
||||
<field name="next_activity_id" ref="crm_activity_data_email"/>
|
||||
<field eval="time.strftime('%Y-%m-10')" name="date_action"/>
|
||||
<field name="title_action">Send Catalogue by Email</field>
|
||||
<field name="team_id" ref="sales_team.crm_team_2"/>
|
||||
@@ -640,6 +654,7 @@ Andrew</field>
|
||||
<field name="tag_ids" eval="[(6, 0, [categ_oppor2])]"/>
|
||||
<field name="priority">2</field>
|
||||
<field eval="time.strftime('%Y-%m-23')" name="date_deadline"/>
|
||||
<field name="next_activity_id" ref="crm_activity_data_email"/>
|
||||
<field eval="time.strftime('%Y-%m-10')" name="date_action"/>
|
||||
<field name="title_action">Send Catalogue by Email</field>
|
||||
<field name="team_id" ref="sales_team.crm_team_1"/>
|
||||
@@ -703,7 +718,7 @@ Andrew</field>
|
||||
<field name="model">crm.lead</field>
|
||||
<field name="res_id" ref="crm_case_15"/>
|
||||
<field name="body"><![CDATA[<p>Hello</p>
|
||||
<p>After our phonecall and discussion with our technical experts, here is the offer of YourCompany. We believe it will meet every requirement you had in mind. Please feel free to contact me for any detail or technical detail that is not clear enough for you.</p>
|
||||
<p>After our discussion with our technical experts, here is the offer of YourCompany. We believe it will meet every requirement you had in mind. Please feel free to contact me for any detail or technical detail that is not clear enough for you.</p>
|
||||
<p>Notice that as agreed on phone, we offer you a <b>10% discount on the hardware</b>!</p>
|
||||
<p>Best regards,</p>]]></field>
|
||||
<field name="message_type">email</field>
|
||||
|
||||
@@ -88,15 +88,6 @@
|
||||
<!--
|
||||
LEADS
|
||||
-->
|
||||
<act_window
|
||||
id="act_crm_opportunity_crm_phonecall_new"
|
||||
name="Phone calls"
|
||||
groups="base.group_sale_salesman"
|
||||
res_model="crm.phonecall"
|
||||
view_mode="tree,calendar,form"
|
||||
context="{'default_duration': 1.0 ,'default_opportunity_id': active_id}"
|
||||
view_type="form"/>
|
||||
|
||||
<act_window
|
||||
id="act_crm_opportunity_calendar_event_new"
|
||||
name="Meetings"
|
||||
@@ -121,13 +112,7 @@
|
||||
on_change="onchange_stage_id(stage_id)"/>
|
||||
</header>
|
||||
<sheet>
|
||||
<div class="oe_button_box" name="button_box">
|
||||
<button class="oe_stat_button" type="action"
|
||||
context="{'default_opportunity_id': active_id, 'search_default_opportunity_id': active_id, 'default_partner_id': partner_id, 'default_duration': 1.0}"
|
||||
name="%(crm.crm_phonecall_category_phone_incoming0)d" icon="fa-phone">
|
||||
<field string="Calls" name="calls_count" widget="statinfo"/>
|
||||
</button>
|
||||
</div>
|
||||
<div class="oe_button_box" name="button_box"/>
|
||||
<div class="oe_title">
|
||||
<label for="name" class="oe_edit_only"/>
|
||||
<h1><field name="name" placeholder="Describe the lead..."/></h1>
|
||||
@@ -309,7 +294,6 @@
|
||||
<t t-if="widget.editable"><li><a type="edit">Edit Opportunity</a></li></t>
|
||||
<t t-if="widget.deletable"><li><a type="delete">Delete</a></li></t>
|
||||
<li><a name="%(mail.action_email_compose_message_wizard)d" type="action" >Send Email</a></li>
|
||||
<li><a type="action" name="%(crm.crm_phonecall_category_phone_incoming0)d">Calls</a></li>
|
||||
<li><a name="action_schedule_meeting" type="object">Schedule Meeting</a></li>
|
||||
<li><ul class="oe_kanban_colorpicker" data-field="color"/></li>
|
||||
</ul>
|
||||
@@ -402,11 +386,6 @@
|
||||
</header>
|
||||
<sheet>
|
||||
<div class="oe_button_box" name="button_box">
|
||||
<button class="oe_stat_button" type="action"
|
||||
name="%(crm.crm_phonecall_category_phone_incoming0)d" icon="fa-phone"
|
||||
context="{'default_opportunity_id': active_id, 'search_default_opportunity_id': active_id, 'default_partner_id': partner_id, 'default_duration': 1.0}">
|
||||
<field string="Calls" name="calls_count" widget="statinfo"/>
|
||||
</button>
|
||||
<button class="oe_stat_button" type="object"
|
||||
context="{'partner_id': partner_id}"
|
||||
name="action_schedule_meeting" icon="fa-calendar">
|
||||
@@ -439,11 +418,34 @@
|
||||
</group>
|
||||
|
||||
<group>
|
||||
<label for="title_action"/>
|
||||
<div class="o_row">
|
||||
<field name="date_action" nolabel="1"/>
|
||||
<span attrs="{'invisible': ['|', ('date_action', '=', False), ('title_action', '=', False)]}" class="oe_read_only"> - </span>
|
||||
<field name="title_action" nolabel="1" placeholder="e.g. Call for proposal"/>
|
||||
<label for="next_activity_id"/>
|
||||
<div>
|
||||
<field name="next_activity_id"
|
||||
class="oe_inline" options="{'no_create': True, 'no_open': True}"
|
||||
domain="['|',('team_id','=',False),('team_id','=',team_id)]"
|
||||
on_change="onchange_next_activity_id(next_activity_id)"/>
|
||||
<span class="oe_form_field oe_read_only oe_inline"
|
||||
attrs="{'invisible': ['|', ('next_activity_id', '=', False), ('date_action', '=', False)]}"> on </span>
|
||||
<field name="date_action" nolabel="1" attrs="{'invisible': [('next_activity_id', '=', False)]}"/>
|
||||
<field name="title_action" nolabel="1" placeholder="e.g. Discuss proposal"
|
||||
attrs="{'invisible': [('next_activity_id', '=', False)]}"/>
|
||||
<div attrs="{'invisible': [('next_activity_id', '=', False)]}">
|
||||
<button name="log_next_activity_done" string="Done" type="object" class="oe_link"/>
|
||||
<button name="log_next_activity_1" type="object" class="oe_link" attrs="{'invisible': [('next_activity_1','=',False)]}">
|
||||
<span> | </span>
|
||||
<field name="next_activity_1" class="oe_inline" readonly="1"/>
|
||||
</button>
|
||||
<button name="log_next_activity_2" type="object" class="oe_link" attrs="{'invisible': [('next_activity_2','=',False)]}">
|
||||
<span> | </span>
|
||||
<field name="next_activity_2" class="oe_inline" readonly="1"/>
|
||||
</button>
|
||||
<button name="log_next_activity_3" type="object" class="oe_link" attrs="{'invisible': [('next_activity_3','=',False)]}">
|
||||
<span> | </span>
|
||||
<field name="next_activity_3" class="oe_inline" readonly="1"/>
|
||||
</button>
|
||||
<span> | </span>
|
||||
<button name="cancel_next_activity" string="Cancel" type="object" class="oe_link"/>
|
||||
</div>
|
||||
</div>
|
||||
<field name="date_deadline"/>
|
||||
<field name="priority" widget="priority"/>
|
||||
|
||||
@@ -1,292 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import crm
|
||||
from datetime import datetime
|
||||
from openerp.osv import fields, osv
|
||||
from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT
|
||||
from openerp.tools.translate import _
|
||||
from openerp.exceptions import UserError
|
||||
|
||||
class crm_phonecall(osv.osv):
|
||||
""" Model for CRM phonecalls """
|
||||
_name = "crm.phonecall"
|
||||
_description = "Phonecall"
|
||||
_order = "id desc"
|
||||
_inherit = ['mail.thread']
|
||||
|
||||
_columns = {
|
||||
'date_action_last': fields.datetime('Last Action', readonly=1),
|
||||
'date_action_next': fields.datetime('Next Action', readonly=1),
|
||||
'create_date': fields.datetime('Creation Date' , readonly=True),
|
||||
'team_id': fields.many2one('crm.team', 'Sales Team', oldname='section_id',\
|
||||
select=True, help='Sales team to which Case belongs to.'),
|
||||
'user_id': fields.many2one('res.users', 'Responsible'),
|
||||
'partner_id': fields.many2one('res.partner', 'Contact'),
|
||||
'company_id': fields.many2one('res.company', 'Company'),
|
||||
'description': fields.text('Description'),
|
||||
'state': fields.selection(
|
||||
[('open', 'Confirmed'),
|
||||
('cancel', 'Cancelled'),
|
||||
('pending', 'Pending'),
|
||||
('done', 'Held')
|
||||
], string='Status', readonly=True, track_visibility='onchange',
|
||||
help='The status is set to Confirmed, when a case is created.\n'
|
||||
'When the call is over, the status is set to Held.\n'
|
||||
'If the callis not applicable anymore, the status can be set to Cancelled.'),
|
||||
'email_from': fields.char('Email', size=128, help="These people will receive email."),
|
||||
'date_open': fields.datetime('Opened', readonly=True),
|
||||
# phonecall fields
|
||||
'name': fields.char('Call Summary', required=True),
|
||||
'active': fields.boolean('Active', required=False),
|
||||
'duration': fields.float('Duration', help='Duration in minutes and seconds.'),
|
||||
'categ_id': fields.many2one('crm.phonecall.category', 'Category'),
|
||||
'partner_phone': fields.char('Phone'),
|
||||
'partner_mobile': fields.char('Mobile'),
|
||||
'priority': fields.selection([('0','Low'), ('1','Normal'), ('2','High')], 'Priority'),
|
||||
'date_closed': fields.datetime('Closed', readonly=True),
|
||||
'date': fields.datetime('Date'),
|
||||
'opportunity_id': fields.many2one ('crm.lead', 'Lead/Opportunity'),
|
||||
}
|
||||
|
||||
def _get_default_state(self, cr, uid, context=None):
|
||||
if context and context.get('default_state'):
|
||||
return context.get('default_state')
|
||||
return 'open'
|
||||
|
||||
_defaults = {
|
||||
'date': fields.datetime.now,
|
||||
'priority': '1',
|
||||
'state': _get_default_state,
|
||||
'user_id': lambda self, cr, uid, ctx: uid,
|
||||
'team_id': lambda s, cr, uid, c: s.pool['crm.team']._get_default_team_id(cr, uid, context=c),
|
||||
'active': 1
|
||||
}
|
||||
|
||||
def on_change_partner_id(self, cr, uid, ids, partner_id, context=None):
|
||||
values = {}
|
||||
if partner_id:
|
||||
partner = self.pool.get('res.partner').browse(cr, uid, partner_id, context=context)
|
||||
values = {
|
||||
'partner_phone': partner.phone,
|
||||
'partner_mobile': partner.mobile,
|
||||
}
|
||||
return {'value': values}
|
||||
|
||||
def write(self, cr, uid, ids, values, context=None):
|
||||
""" Override to add case management: open/close dates """
|
||||
if values.get('state'):
|
||||
if values.get('state') == 'done':
|
||||
values['date_closed'] = fields.datetime.now()
|
||||
self.compute_duration(cr, uid, ids, context=context)
|
||||
elif values.get('state') == 'open':
|
||||
values['date_open'] = fields.datetime.now()
|
||||
values['duration'] = 0.0
|
||||
return super(crm_phonecall, self).write(cr, uid, ids, values, context=context)
|
||||
|
||||
def compute_duration(self, cr, uid, ids, context=None):
|
||||
for phonecall in self.browse(cr, uid, ids, context=context):
|
||||
if phonecall.duration <= 0:
|
||||
duration = datetime.now() - datetime.strptime(phonecall.date, DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
values = {'duration': duration.seconds/float(60)}
|
||||
self.write(cr, uid, [phonecall.id], values, context=context)
|
||||
return True
|
||||
|
||||
def schedule_another_phonecall(self, cr, uid, ids, schedule_time, call_summary, \
|
||||
user_id=False, team_id=False, categ_id=False, action='schedule', context=None):
|
||||
"""
|
||||
action :('schedule','Schedule a call'), ('log','Log a call')
|
||||
"""
|
||||
model_data = self.pool.get('ir.model.data')
|
||||
phonecall_dict = {}
|
||||
if not categ_id:
|
||||
try:
|
||||
res_id = model_data._get_id(cr, uid, 'crm', 'categ_phone2')
|
||||
categ_id = model_data.browse(cr, uid, res_id, context=context).res_id
|
||||
except ValueError:
|
||||
pass
|
||||
for call in self.browse(cr, uid, ids, context=context):
|
||||
if not team_id:
|
||||
team_id = call.team_id and call.team_id.id or False
|
||||
if not user_id:
|
||||
user_id = call.user_id and call.user_id.id or False
|
||||
if not schedule_time:
|
||||
schedule_time = call.date
|
||||
vals = {
|
||||
'name' : call_summary,
|
||||
'user_id' : user_id or False,
|
||||
'categ_id' : categ_id or False,
|
||||
'description' : call.description or False,
|
||||
'date' : schedule_time,
|
||||
'team_id' : team_id or False,
|
||||
'partner_id': call.partner_id and call.partner_id.id or False,
|
||||
'partner_phone' : call.partner_phone,
|
||||
'partner_mobile' : call.partner_mobile,
|
||||
'priority': call.priority,
|
||||
'opportunity_id': call.opportunity_id and call.opportunity_id.id or False,
|
||||
}
|
||||
new_id = self.create(cr, uid, vals, context=context)
|
||||
if action == 'log':
|
||||
self.write(cr, uid, [new_id], {'state': 'done'}, context=context)
|
||||
phonecall_dict[call.id] = new_id
|
||||
return phonecall_dict
|
||||
|
||||
def _call_create_partner(self, cr, uid, phonecall, context=None):
|
||||
partner = self.pool.get('res.partner')
|
||||
partner_id = partner.create(cr, uid, {
|
||||
'name': phonecall.name,
|
||||
'user_id': phonecall.user_id.id,
|
||||
'comment': phonecall.description,
|
||||
'address': []
|
||||
})
|
||||
return partner_id
|
||||
|
||||
def on_change_opportunity(self, cr, uid, ids, opportunity_id, context=None):
|
||||
values = {}
|
||||
if opportunity_id:
|
||||
opportunity = self.pool.get('crm.lead').browse(cr, uid, opportunity_id, context=context)
|
||||
values = {
|
||||
'team_id' : opportunity.team_id and opportunity.team_id.id or False,
|
||||
'partner_phone' : opportunity.phone,
|
||||
'partner_mobile' : opportunity.mobile,
|
||||
'partner_id' : opportunity.partner_id and opportunity.partner_id.id or False,
|
||||
}
|
||||
return {'value' : values}
|
||||
|
||||
def _call_set_partner(self, cr, uid, ids, partner_id, context=None):
|
||||
write_res = self.write(cr, uid, ids, {'partner_id' : partner_id}, context=context)
|
||||
self._call_set_partner_send_note(cr, uid, ids, context)
|
||||
return write_res
|
||||
|
||||
def _call_create_partner_address(self, cr, uid, phonecall, partner_id, context=None):
|
||||
address = self.pool.get('res.partner')
|
||||
return address.create(cr, uid, {
|
||||
'parent_id': partner_id,
|
||||
'name': phonecall.name,
|
||||
'phone': phonecall.partner_phone,
|
||||
})
|
||||
|
||||
def handle_partner_assignation(self, cr, uid, ids, action='create', partner_id=False, context=None):
|
||||
"""
|
||||
Handle partner assignation during a lead conversion.
|
||||
if action is 'create', create new partner with contact and assign lead to new partner_id.
|
||||
otherwise assign lead to specified partner_id
|
||||
|
||||
:param list ids: phonecalls ids to process
|
||||
:param string action: what has to be done regarding partners (create it, assign an existing one, or nothing)
|
||||
:param int partner_id: partner to assign if any
|
||||
:return dict: dictionary organized as followed: {lead_id: partner_assigned_id}
|
||||
"""
|
||||
#TODO this is a duplication of the handle_partner_assignation method of crm_lead
|
||||
partner_ids = {}
|
||||
# If a partner_id is given, force this partner for all elements
|
||||
force_partner_id = partner_id
|
||||
for call in self.browse(cr, uid, ids, context=context):
|
||||
# If the action is set to 'create' and no partner_id is set, create a new one
|
||||
if action == 'create':
|
||||
partner_id = force_partner_id or self._call_create_partner(cr, uid, call, context=context)
|
||||
self._call_create_partner_address(cr, uid, call, partner_id, context=context)
|
||||
self._call_set_partner(cr, uid, [call.id], partner_id, context=context)
|
||||
partner_ids[call.id] = partner_id
|
||||
return partner_ids
|
||||
|
||||
|
||||
def redirect_phonecall_view(self, cr, uid, phonecall_id, context=None):
|
||||
model_data = self.pool.get('ir.model.data')
|
||||
# Select the view
|
||||
tree_view = model_data.get_object_reference(cr, uid, 'crm', 'crm_case_phone_tree_view')
|
||||
form_view = model_data.get_object_reference(cr, uid, 'crm', 'crm_case_phone_form_view')
|
||||
search_view = model_data.get_object_reference(cr, uid, 'crm', 'view_crm_case_phonecalls_filter')
|
||||
value = {
|
||||
'name': _('Phone Call'),
|
||||
'view_type': 'form',
|
||||
'view_mode': 'tree,form',
|
||||
'res_model': 'crm.phonecall',
|
||||
'res_id' : int(phonecall_id),
|
||||
'views': [(form_view and form_view[1] or False, 'form'), (tree_view and tree_view[1] or False, 'tree'), (False, 'calendar')],
|
||||
'type': 'ir.actions.act_window',
|
||||
'search_view_id': search_view and search_view[1] or False,
|
||||
}
|
||||
return value
|
||||
|
||||
def convert_opportunity(self, cr, uid, ids, opportunity_summary=False, partner_id=False, planned_revenue=0.0, probability=0.0, context=None):
|
||||
partner = self.pool.get('res.partner')
|
||||
opportunity = self.pool.get('crm.lead')
|
||||
opportunity_dict = {}
|
||||
default_contact = False
|
||||
for call in self.browse(cr, uid, ids, context=context):
|
||||
if not partner_id:
|
||||
partner_id = call.partner_id and call.partner_id.id or False
|
||||
if partner_id:
|
||||
address_id = partner.address_get(cr, uid, [partner_id])['default']
|
||||
if address_id:
|
||||
default_contact = partner.browse(cr, uid, address_id, context=context)
|
||||
opportunity_id = opportunity.create(cr, uid, {
|
||||
'name': opportunity_summary or call.name,
|
||||
'planned_revenue': planned_revenue,
|
||||
'probability': probability,
|
||||
'partner_id': partner_id or False,
|
||||
'mobile': default_contact and default_contact.mobile,
|
||||
'team_id': call.team_id and call.team_id.id or False,
|
||||
'description': call.description or False,
|
||||
'priority': call.priority,
|
||||
'type': 'opportunity',
|
||||
'phone': call.partner_phone or False,
|
||||
'email_from': default_contact and default_contact.email,
|
||||
})
|
||||
vals = {
|
||||
'partner_id': partner_id,
|
||||
'opportunity_id': opportunity_id,
|
||||
'state': 'done',
|
||||
}
|
||||
self.write(cr, uid, [call.id], vals, context=context)
|
||||
opportunity_dict[call.id] = opportunity_id
|
||||
return opportunity_dict
|
||||
|
||||
def action_make_meeting(self, cr, uid, ids, context=None):
|
||||
"""
|
||||
Open meeting's calendar view to schedule a meeting on current phonecall.
|
||||
:return dict: dictionary value for created meeting view
|
||||
"""
|
||||
partner_ids = []
|
||||
phonecall = self.browse(cr, uid, ids[0], context)
|
||||
if phonecall.partner_id and phonecall.partner_id.email:
|
||||
partner_ids.append(phonecall.partner_id.id)
|
||||
res = self.pool.get('ir.actions.act_window').for_xml_id(cr, uid, 'calendar', 'action_calendar_event', context)
|
||||
res['context'] = {
|
||||
'default_phonecall_id': phonecall.id,
|
||||
'default_partner_ids': partner_ids,
|
||||
'default_user_id': uid,
|
||||
'default_email_from': phonecall.email_from,
|
||||
'default_name': phonecall.name,
|
||||
'default_opportunity_id': phonecall.opportunity_id.id,
|
||||
}
|
||||
return res
|
||||
|
||||
def action_button_convert2opportunity(self, cr, uid, ids, context=None):
|
||||
"""
|
||||
Convert a phonecall into an opp and then redirect to the opp view.
|
||||
|
||||
:param list ids: list of calls ids to convert (typically contains a single id)
|
||||
:return dict: containing view information
|
||||
"""
|
||||
if len(ids) != 1:
|
||||
raise UserError(_('It\'s only possible to convert one phonecall at a time.'))
|
||||
|
||||
opportunity_dict = self.convert_opportunity(cr, uid, ids, context=context)
|
||||
return self.pool.get('crm.lead').redirect_opportunity_view(cr, uid, opportunity_dict[ids[0]], context)
|
||||
|
||||
# ----------------------------------------
|
||||
# OpenChatter
|
||||
# ----------------------------------------
|
||||
|
||||
def _call_set_partner_send_note(self, cr, uid, ids, context=None):
|
||||
return self.message_post(cr, uid, ids, body=_("Partner has been <b>created</b>."), context=context)
|
||||
|
||||
class crm_phonecall_category(osv.Model):
|
||||
_name = "crm.phonecall.category"
|
||||
_description = "Category of phonecall"
|
||||
_columns = {
|
||||
'name': fields.char('Name', required=True, translate=True),
|
||||
'team_id': fields.many2one('crm.team', 'Sales Team'),
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<openerp>
|
||||
<data noupdate="1">
|
||||
<!--
|
||||
Phonecall Categories
|
||||
-->
|
||||
<record model="crm.phonecall.category" id="categ_phone1">
|
||||
<field name="name">Inbound</field>
|
||||
<field name="team_id" ref="sales_team.team_sales_department"/>
|
||||
</record>
|
||||
<record model="crm.phonecall.category" id="categ_phone2">
|
||||
<field name="name">Outbound</field>
|
||||
<field name="team_id" ref="sales_team.team_sales_department"/>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -1,84 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<openerp>
|
||||
<data noupdate="1">
|
||||
|
||||
<!-- Demo Cases -->
|
||||
<record id="crm_phonecall_1" model="crm.phonecall">
|
||||
<field eval="time.strftime('%Y-%m-04 10:45:36')" name="date"/>
|
||||
<field name="partner_id" ref="base.res_partner_11"/>
|
||||
<field eval="'1'" name="priority"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="name">Left the message</field>
|
||||
<field name="state">done</field>
|
||||
<field name="partner_phone">+34 934 340 230</field>
|
||||
<field name="team_id" ref="sales_team.team_sales_department"/>
|
||||
<field eval="1" name="active"/>
|
||||
<field name="categ_id" ref="crm.categ_phone1"/>
|
||||
<field eval="2.3" name="duration"/>
|
||||
</record>
|
||||
<record id="crm_phonecall_2" model="crm.phonecall">
|
||||
<field eval="time.strftime('%Y-%m-11 11:19:25')" name="date"/>
|
||||
<field name="partner_id" ref="base.res_partner_7"/>
|
||||
<field eval="'0'" name="priority"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="name">Need more information on the proposed deal</field>
|
||||
<field name="state">done</field>
|
||||
<field name="partner_phone">+44 121 690 4596</field>
|
||||
<field name="team_id" ref="sales_team.crm_team_1"/>
|
||||
<field eval="1" name="active"/>
|
||||
<field name="categ_id" ref="crm.categ_phone1"/>
|
||||
<field eval="1.5" name="duration"/>
|
||||
</record>
|
||||
<record id="crm_phonecall_3" model="crm.phonecall">
|
||||
<field eval="time.strftime('%Y-%m-15 17:44:12')" name="date"/>
|
||||
<field name="partner_id" ref="base.res_partner_10"/>
|
||||
<field eval="'2'" name="priority"/>
|
||||
<field name="user_id" ref="base.user_demo"/>
|
||||
<field name="name">Ask for convenient time of meeting</field>
|
||||
<field name="state">open</field>
|
||||
<field name="partner_phone">+1 786 525 0724</field>
|
||||
<field name="team_id" ref="sales_team.crm_team_2"/>
|
||||
<field eval="1" name="active"/>
|
||||
<field name="categ_id" ref="crm.categ_phone2"/>
|
||||
<field eval="5.0" name="duration"/>
|
||||
</record>
|
||||
<record id="crm_phonecall_4" model="crm.phonecall">
|
||||
<field eval="time.strftime('%Y-%m-21 14:10:23')" name="date"/>
|
||||
<field eval="'1'" name="priority"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="name">Wanted information about pricing of laptops</field>
|
||||
<field name="state">done</field>
|
||||
<field name="partner_phone">(077) 582-4035</field>
|
||||
<field name="partner_mobile">(077) 341-3591</field>
|
||||
<field name="team_id" ref="sales_team.crm_team_2"/>
|
||||
<field eval="1" name="active"/>
|
||||
<field name="categ_id" ref="crm.categ_phone1"/>
|
||||
<field eval="5.45" name="duration"/>
|
||||
</record>
|
||||
<record id="crm_phonecall_5" model="crm.phonecall">
|
||||
<field eval="time.strftime('%Y-%m-28 16:20:43')" name="date"/>
|
||||
<field name="partner_id" ref="base.res_partner_5"/>
|
||||
<field eval="'1'" name="priority"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="name">More information on the proposed deal</field>
|
||||
<field name="state">pending</field>
|
||||
<field name="partner_phone">+1 312 349 2324</field>
|
||||
<field name="team_id" ref="sales_team.crm_team_1"/>
|
||||
<field eval="1" name="active"/>
|
||||
<field name="categ_id" ref="crm.categ_phone1"/>
|
||||
<field eval="2.08" name="duration"/>
|
||||
</record>
|
||||
<record id="crm_phonecall_6" model="crm.phonecall">
|
||||
<field eval="'1'" name="priority"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="name">Proposal for discount offer</field>
|
||||
<field name="state">open</field>
|
||||
<field name="partner_phone">+34 230 953 485</field>
|
||||
<field name="team_id" ref="sales_team.crm_team_2"/>
|
||||
<field eval="time.strftime('%Y-%m-28 14:15:30')" name="date"/>
|
||||
<field name="categ_id" ref="crm.categ_phone2"/>
|
||||
<field eval="8.56" name="duration"/>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -1,97 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
|
||||
<!-- TO CONFIRM: This is fine -->
|
||||
<!-- act_window
|
||||
id="act_crm_phonecall_calendar_event_new"
|
||||
name="Meetings"
|
||||
res_model="calendar.event"
|
||||
src_model="crm.phonecall"
|
||||
view_mode="tree,form,calendar"
|
||||
context="{'default_duration': 4.0, 'default_phonecall_id': active_id}"
|
||||
domain="[('phonecall_id', '=', active_id)]"
|
||||
view_type="form"/-->
|
||||
|
||||
<!-- PHONE CALLS (menu) -->
|
||||
|
||||
<record model="ir.actions.act_window" id="crm_phonecall_category_phone0">
|
||||
<field name="name">Phone Calls</field>
|
||||
<field name="res_model">crm.phonecall</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,calendar</field>
|
||||
<field name="view_id" ref="crm_case_phone_tree_view"/>
|
||||
<field name="context">{"search_default_user_id":uid}</field>
|
||||
<field name="search_view_id" ref="crm.view_crm_case_phonecalls_filter"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.actions.act_window.view" id="action_crm_tag_tree_phone0">
|
||||
<field name="sequence" eval="1"/>
|
||||
<field name="view_mode">tree</field>
|
||||
<field name="view_id" ref="crm_case_phone_tree_view"/>
|
||||
<field name="act_window_id" ref="crm_phonecall_category_phone0"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.actions.act_window.view" id="action_crm_tag_calendar_phone0">
|
||||
<field name="sequence" eval="2"/>
|
||||
<field name="view_mode">calendar</field>
|
||||
<field name="view_id" ref="crm_case_phone_calendar_view"/>
|
||||
<field name="act_window_id" ref="crm_phonecall_category_phone0"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.actions.act_window.view" id="action_crm_tag_form_phone0">
|
||||
<field name="sequence" eval="3"/>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="crm_case_phone_form_view"/>
|
||||
<field name="act_window_id" ref="crm_phonecall_category_phone0"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.actions.act_window" id="crm_phonecall_category_phone_incoming0">
|
||||
<field name="name">Logged Calls</field>
|
||||
<field name="res_model">crm.phonecall</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,calendar</field>
|
||||
<field name="view_id" ref="crm_case_inbound_phone_tree_view"/>
|
||||
<field name="search_view_id" ref="crm.view_crm_case_phonecalls_filter"/>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click to log the summary of a phone call.
|
||||
</p><p>
|
||||
Odoo allows you to log inbound calls on the fly to track the
|
||||
history of the communication with a customer or to inform another
|
||||
team member.
|
||||
</p><p>
|
||||
In order to follow up on the call, you can trigger a request for
|
||||
another call, a meeting or an opportunity.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.actions.act_window.view" id="action_crm_tag_tree_phone_incoming0">
|
||||
<field name="sequence" eval="1"/>
|
||||
<field name="view_mode">tree</field>
|
||||
<field name="view_id" ref="crm_case_inbound_phone_tree_view"/>
|
||||
<field name="act_window_id" ref="crm_phonecall_category_phone_incoming0"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.actions.act_window.view" id="action_crm_tag_calendar_phone_incoming0">
|
||||
<field name="sequence" eval="2"/>
|
||||
<field name="view_mode">calendar</field>
|
||||
<field name="view_id" ref="crm_case_phone_calendar_view"/>
|
||||
<field name="act_window_id" ref="crm_phonecall_category_phone_incoming0"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.actions.act_window.view" id="action_crm_tag_form_phone_incoming0">
|
||||
<field name="sequence" eval="3"/>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="crm_case_phone_form_view"/>
|
||||
<field name="act_window_id" ref="crm_phonecall_category_phone_incoming0"/>
|
||||
</record>
|
||||
|
||||
<menuitem name="Calls" id="menu_crm_case_phone" sequence="4"
|
||||
parent="base.menu_sales"
|
||||
action="crm_phonecall_category_phone_incoming0" />
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -1,232 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
|
||||
<!-- Phonecall Categories -->
|
||||
|
||||
<record id="crm_phonecall_category_form" model="ir.ui.view">
|
||||
<field name="name">crm.phonecall.category.form</field>
|
||||
<field name="model">crm.phonecall.category</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Phonecall Categories">
|
||||
<group>
|
||||
<field name="name"/>
|
||||
<field name="team_id" groups="base.group_multi_salesteams"/>
|
||||
</group>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="crm_phonecall_category_tree" model="ir.ui.view">
|
||||
<field name="name">crm.phonecall.category.tree</field>
|
||||
<field name="model">crm.phonecall.category</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Phonecall Categories">
|
||||
<field name="name"/>
|
||||
<field name="team_id" groups="base.group_multi_salesteams"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="crm_phonecall_category_action" model="ir.actions.act_window">
|
||||
<field name="name">Phonecall Categories</field>
|
||||
<field name="res_model">crm.phonecall.category</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_id" ref="crm_phonecall_category_tree"/>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click to add a new category.
|
||||
</p><p>
|
||||
Create specific phone call categories to better define the type of
|
||||
calls tracked in the system.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<menuitem action="crm_phonecall_category_action" name="Categories"
|
||||
id="menu_crm_case_phonecall-act" parent="menu_crm_config_phonecall" groups="base.group_no_one"/>
|
||||
|
||||
<!-- Phonecalls Tree View -->
|
||||
<record model="ir.ui.view" id="crm_case_phone_tree_view">
|
||||
<field name="name">CRM - Phone Calls Tree</field>
|
||||
<field name="model">crm.phonecall</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree decoration-muted="state in ('cancel','done')" decoration-info="state in ('pending',)" string="Phone Calls">
|
||||
<field name="date"/>
|
||||
<field name="name"/>
|
||||
<field name="partner_id"/>
|
||||
<button string="Meeting"
|
||||
states="open,pending"
|
||||
name="action_make_meeting"
|
||||
icon="fa-share"
|
||||
type="object"/>
|
||||
<button string="Create an Opportunity"
|
||||
type="object"
|
||||
name="action_button_convert2opportunity"
|
||||
states="open,pending"
|
||||
icon="fa-check-square-o"
|
||||
attrs="{'invisible':[('opportunity_id','!=',False)]}"/>
|
||||
<field name="partner_phone"/>
|
||||
<field name="user_id"/>
|
||||
<field name="categ_id" invisible="1"/>
|
||||
<field name="create_date" invisible="1"/>
|
||||
<field name="opportunity_id" invisible="1"/>
|
||||
<field name="state"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Phonecalls Form View -->
|
||||
<record model="ir.ui.view" id="crm_case_phone_form_view">
|
||||
<field name="name">CRM - Phone Call Form</field>
|
||||
<field name="model">crm.phonecall</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Phone Call">
|
||||
<header>
|
||||
<field name="state" nolabel="1" widget="statusbar" clickable="True"/>
|
||||
</header>
|
||||
<sheet string="Phone Call">
|
||||
<div class="oe_button_box" name="button_box">
|
||||
<button class="oe_stat_button" type="object" name="action_button_convert2opportunity"
|
||||
icon="fa-star" attrs="{'invisible':[ '|', ('opportunity_id','!=',False), ('state', 'not in', ('open', 'done'))]}"
|
||||
help="Convert To Opportunity">
|
||||
<div class="o_form_field o_stat_info">
|
||||
<span class="o_stat_text">Convert To</span>
|
||||
<span class="o_stat_text">Opportunity</span>
|
||||
</div>
|
||||
</button>
|
||||
|
||||
<button class="oe_stat_button" type="action"
|
||||
name="%(phonecall_to_phonecall_act)d" icon="fa-phone">
|
||||
<div class="o_form_field o_stat_info">
|
||||
<span class="o_stat_text">Schedule</span>
|
||||
<span class="o_stat_text">Other Call</span>
|
||||
</div>
|
||||
</button>
|
||||
<button class="oe_stat_button" name="action_make_meeting" type="object" icon="fa-calendar fa-fw">
|
||||
<div class="o_form_field o_stat_info">
|
||||
<span class="o_stat_text">Schedule</span>
|
||||
<span class="o_stat_text">A Meeting</span>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<div class="oe_title">
|
||||
<div class="oe_edit_only">
|
||||
<label for="name"/>
|
||||
</div>
|
||||
<h1><field name="name" required="1"/></h1>
|
||||
<div class="oe_edit_only">
|
||||
<label for="partner_phone" string="Phone"/>
|
||||
</div>
|
||||
<h2><field name="partner_phone"/></h2>
|
||||
</div>
|
||||
|
||||
<group col="4">
|
||||
<field name="date"/>
|
||||
<field name="user_id" context="{'default_groups_ref': ['base.group_user', 'base.group_partner_manager', 'base.group_sale_salesman_all_leads']}"/>
|
||||
<label for="duration"/>
|
||||
<div>
|
||||
<field name="duration" widget="float_time" class="oe_inline" style="vertical-align:baseline"/> <b> min(s)</b>
|
||||
</div>
|
||||
<field name="team_id" colspan="1" widget="selection"
|
||||
groups="base.group_multi_salesteams"/>
|
||||
<field name="partner_id" on_change="on_change_partner_id(partner_id)"/>
|
||||
<field name="categ_id" widget="selection"/>
|
||||
<field name="partner_mobile"/>
|
||||
<field name="priority" widget="priority"/>
|
||||
<field name="opportunity_id" on_change="on_change_opportunity(opportunity_id)" context="{'opportunity_id': opportunity_id}"/>
|
||||
</group>
|
||||
<field name="description" placeholder="Description..."/>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!--Logged Phonecalls Tree View -->
|
||||
<record model="ir.ui.view" id="crm_case_inbound_phone_tree_view">
|
||||
<field name="name">CRM - Logged Phone Calls Tree</field>
|
||||
<field name="model">crm.phonecall</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Phone Calls" editable="top">
|
||||
<field name="date"/>
|
||||
<field name="name"/>
|
||||
<field name="partner_id"
|
||||
on_change="on_change_partner_id(partner_id)"/>
|
||||
<field name="partner_phone"
|
||||
invisible="1"/>
|
||||
<field name="partner_mobile"
|
||||
invisible="1"/>
|
||||
<field name="user_id" context="{'default_groups_ref': ['base.group_user', 'base.group_partner_manager', 'base.group_sale_salesman_all_leads']}"/>
|
||||
<field name="categ_id" widget="selection"
|
||||
invisible="1"/>
|
||||
<field name="state" invisible="1"/>
|
||||
<field name="create_date" invisible="1"/>
|
||||
<field name="opportunity_id" invisible="1" on_change="on_change_opportunity(opportunity_id)"/>
|
||||
<button string="Schedule Other Call"
|
||||
icon="fa-phone"
|
||||
name="%(phonecall_to_phonecall_act)d"
|
||||
type="action"/>
|
||||
<button string="Meeting"
|
||||
icon="fa-share"
|
||||
name="action_make_meeting" type="object"/>
|
||||
<button string="Create an Opportunity"
|
||||
name="action_button_convert2opportunity"
|
||||
states="open,pending"
|
||||
icon="fa-check-square-o"
|
||||
type="object" attrs="{'invisible':[('opportunity_id','!=',False)]}"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Phonecalls Calendar View -->
|
||||
<record model="ir.ui.view" id="crm_case_phone_calendar_view">
|
||||
<field name="name">CRM - Phone Calls Calendar</field>
|
||||
<field name="model">crm.phonecall</field>
|
||||
<field name="priority" eval="2"/>
|
||||
<field name="arch" type="xml">
|
||||
<calendar string="Phone Calls" date_start="date" color="user_id" date_delay="duration">
|
||||
<field name="name"/>
|
||||
<field name="partner_id"/>
|
||||
</calendar>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Phonecalls Search View -->
|
||||
<record id="view_crm_case_phonecalls_filter" model="ir.ui.view">
|
||||
<field name="name">CRM - Phone Calls Search</field>
|
||||
<field name="model">crm.phonecall</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search Phonecalls">
|
||||
<field name="name" string="Phonecalls"/>
|
||||
<field name="date"/>
|
||||
<field name="state"/>
|
||||
<filter string="My Phonecalls" domain="[('user_id', '=', uid)]"/>
|
||||
<filter string="My Team" domain="[('team_id.user_id', '=', uid)]"/>
|
||||
<filter string="Unassigned" domain="[('user_id','=',False)]"/>
|
||||
<separator/>
|
||||
<filter string="To Do" name="current" domain="[('state','in',('open','pending'))]"/>
|
||||
<separator/>
|
||||
<filter string="New Mail" name="message_unread" domain="[('message_unread','=',True)]"/>
|
||||
<separator/>
|
||||
<field name="partner_id" operator="child_of"/>
|
||||
<field name="user_id"/>
|
||||
<field name="opportunity_id"/>
|
||||
<field name="team_id" string="Sales Team"
|
||||
groups="base.group_multi_salesteams"/>
|
||||
<group expand="0" string="Group By">
|
||||
<filter string="Partner" domain="[]" context="{'group_by':'partner_id'}"/>
|
||||
<filter string="Responsible" domain="[]" context="{'group_by':'user_id'}"/>
|
||||
<filter string="Creation" help="Creation Date" domain="[]" context="{'group_by':'create_date'}"/>
|
||||
<filter string="Month" domain="[]" context="{'group_by':'date'}" help="Calls Date by Month"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -22,9 +22,6 @@
|
||||
<menuitem id="base.menu_sale_config_sales" name="Sales"
|
||||
parent="base.menu_sale_config" sequence="0" groups="base.group_sale_manager"/>
|
||||
|
||||
<menuitem id="menu_crm_config_phonecall" name="Phone Calls"
|
||||
parent="base.menu_sale_config" sequence="45" groups="base.group_sale_salesman"/>
|
||||
|
||||
<!-- CRM.LOST.REASON VIEWS -->
|
||||
<record id="crm_lost_reason_view_form" model="ir.ui.view">
|
||||
<field name="name">crm.lost.reason.form</field>
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data noupdate="0">
|
||||
|
||||
<record id="crm_activity_data_email" model="crm.activity">
|
||||
<field name="name">Email</field>
|
||||
</record>
|
||||
<record id="crm_activity_data_call" model="crm.activity">
|
||||
<field name="name">Call</field>
|
||||
<field name="activity_1_id" ref="crm_activity_data_email"/>
|
||||
</record>
|
||||
<record id="crm_activity_data_meeting" model="crm.activity">
|
||||
<field name="name">Task</field>
|
||||
<field name="days">3</field>
|
||||
<field name="activity_1_id" ref="crm_activity_data_call"/>
|
||||
<field name="activity_2_id" ref="crm_activity_data_email"/>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</odoo>
|
||||
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data noupdate="1">
|
||||
|
||||
<record id="crm_activity_demo_followup_quote" model="crm.activity">
|
||||
<field name="name">Follow-up Quote</field>
|
||||
</record>
|
||||
<record id="crm_activity_demo_make_quote" model="crm.activity">
|
||||
<field name="name">Make Quote</field>
|
||||
<field name="description">Send a quotation</field>
|
||||
<field name="activity_1_id" ref="crm_activity_demo_followup_quote"/>
|
||||
</record>
|
||||
|
||||
<record id="crm_activity_demo_call_demo" model="crm.activity">
|
||||
<field name="name">Call for Demo</field>
|
||||
<field name="days">15</field>
|
||||
<field name="description">Call for a demo</field>
|
||||
<field name="activity_1_id" ref="crm_activity_demo_make_quote"/>
|
||||
</record>
|
||||
|
||||
<record id="crm_activity_data_call" model="crm.activity">
|
||||
<field name="activity_2_id" ref="crm_activity_demo_call_demo"/>
|
||||
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</odoo>
|
||||
@@ -8,11 +8,10 @@ Changelog
|
||||
|
||||
- Stage/state update
|
||||
|
||||
- ``crm.phonecall``: removed inheritance towards ``base_state``.
|
||||
- ``crm.lead``: removed ``state`` field. Added ``date_last_stage_update`` field
|
||||
holding last stage_id modification. Updated reports.
|
||||
- ``crm.case.stage``: removed ``state`` field.
|
||||
|
||||
- ``crm``, ``crm_claim``: removed inheritance from ``base_stage`` class. Missing
|
||||
methods have been added into ``crm`` and ``crm_claim``. Also removed inheritance
|
||||
in ``crm_helpdesk`` because it uses states, not stages.
|
||||
in ``crm_helpdesk`` because it uses states, not stages.
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import crm_activity
|
||||
@@ -0,0 +1,47 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from openerp import api, fields, models
|
||||
|
||||
|
||||
class CrmActivity(models.Model):
|
||||
''' CrmActivity is a model introduced in Odoo v9 that models activities
|
||||
performed in CRM, like phonecalls, sending emails, making demonstrations,
|
||||
... Users are able to configure their custom activities.
|
||||
|
||||
Each activity has up to three next activities. This allows to model light
|
||||
custom workflows. This way sales manager can configure their crm workflow
|
||||
that salepersons will use in their daily job.
|
||||
|
||||
CrmActivity inherits from mail.message.subtype. This allows users to follow
|
||||
some activities through subtypes. Each activity will generate messages with
|
||||
the matching subtypes, allowing reporting and statistics computation based
|
||||
on mail.message.subtype model. '''
|
||||
|
||||
_name = 'crm.activity'
|
||||
_description = 'CRM Activity'
|
||||
_inherits = {'mail.message.subtype': 'subtype_id'}
|
||||
_rec_name = 'name'
|
||||
_order = "sequence"
|
||||
|
||||
days = fields.Integer('Number of days', default=0,
|
||||
help='Number of days before doing fulfilling the action, allowing to plan the action date.')
|
||||
sequence = fields.Integer('Sequence', default=0)
|
||||
team_id = fields.Many2one('crm.team', string='Sales Team')
|
||||
subtype_id = fields.Many2one('mail.message.subtype', string='Message Subtype', required=True, ondelete='cascade')
|
||||
activity_1_id = fields.Many2one('crm.activity', string="Next Activity 1")
|
||||
activity_2_id = fields.Many2one('crm.activity', string="Next Activity 2")
|
||||
activity_3_id = fields.Many2one('crm.activity', string="Next Activity 3")
|
||||
|
||||
@api.model
|
||||
def create(self, values):
|
||||
''' Override to set the res_model of inherited subtype to crm.lead.
|
||||
This cannot be achieved using a default on res_model field because
|
||||
of the inherits. Indeed a new field would be created. However the
|
||||
field on the subtype would still exist. Being void, the subtype
|
||||
will be present for every model in Odoo. That's quite an issue. '''
|
||||
if not values.get('res_model') and 'default_res_model' not in self._context:
|
||||
values['res_model'] = 'crm.lead'
|
||||
if 'internal' not in values and 'default_internal' not in self._context:
|
||||
values['internal'] = True
|
||||
return super(CrmActivity, self).create(values)
|
||||
@@ -2,5 +2,5 @@
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import crm_lead_report
|
||||
import crm_activity_report
|
||||
import crm_opportunity_report
|
||||
import crm_phonecall_report
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from openerp import fields, models
|
||||
from openerp import tools
|
||||
|
||||
|
||||
class crm_activity_report(models.Model):
|
||||
""" CRM Lead Analysis """
|
||||
_name = "crm.activity.report"
|
||||
_auto = False
|
||||
_description = "CRM Activity Analysis"
|
||||
_rec_name = 'id'
|
||||
|
||||
date = fields.Datetime('Date', readonly=True)
|
||||
author_id = fields.Many2one('res.partner', 'Author', readonly=True)
|
||||
user_id = fields.Many2one('res.users', 'Responsible', readonly=True)
|
||||
team_id = fields.Many2one('crm.team', 'Sales Team', readonly=True)
|
||||
subtype_id = fields.Many2one('mail.message.subtype', 'Action', readonly=True)
|
||||
country_id = fields.Many2one('res.country', 'Country', readonly=True)
|
||||
company_id = fields.Many2one('res.company', 'Company', readonly=True)
|
||||
stage_id = fields.Many2one('crm.stage', 'Stage', readonly=True)
|
||||
partner_id = fields.Many2one('res.partner', 'Partner/Customer', readonly=True)
|
||||
lead_type = fields.Char(
|
||||
string='Type',
|
||||
selection=[('lead', 'Lead'), ('opportunity', 'Opportunity')],
|
||||
help="Type is used to separate Leads and Opportunities")
|
||||
|
||||
def init(self, cr):
|
||||
tools.drop_view_if_exists(cr, 'crm_activity_report')
|
||||
cr.execute("""
|
||||
CREATE OR REPLACE VIEW crm_activity_report AS (
|
||||
select
|
||||
m.id,
|
||||
m.subtype_id,
|
||||
m.author_id,
|
||||
m.date,
|
||||
l.user_id,
|
||||
l.team_id,
|
||||
l.country_id,
|
||||
l.company_id,
|
||||
l.stage_id,
|
||||
l.partner_id,
|
||||
l.type as lead_type
|
||||
from
|
||||
"mail_message" m
|
||||
left join
|
||||
"crm_lead" l
|
||||
on
|
||||
(m.res_id = l.id)
|
||||
WHERE
|
||||
(m.model = 'crm.lead')
|
||||
)""")
|
||||
@@ -0,0 +1,67 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<record id="crm_activity_report_view_graph" model="ir.ui.view">
|
||||
<field name="name">crm.activity.report.graph</field>
|
||||
<field name="model">crm.activity.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<graph string="Activities Analysis" type="pivot" stacked="True">
|
||||
<field name="subtype_id" type="col"/>
|
||||
<field name="date" interval="month" type="row"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="crm_activity_report_view_pivot" model="ir.ui.view">
|
||||
<field name="name">crm.activity.report.pivot</field>
|
||||
<field name="model">crm.activity.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<pivot string="Activities Analysis" disable_linking="True">
|
||||
<field name="subtype_id" type="col"/>
|
||||
<field name="date" interval="month" type="row"/>
|
||||
</pivot>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="crm_activity_report_view_search" model="ir.ui.view">
|
||||
<field name="name">crm.activity.report.search</field>
|
||||
<field name="model">crm.activity.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Activities Analysis">
|
||||
<filter name="lead" string="Leads" domain="[('lead_type','=', 'lead')]" help="Show only lead"/>
|
||||
<filter name="opportunity" string="Opportunities" domain="[('lead_type','=','opportunity')]" help="Show only opportunity"/>
|
||||
<separator/>
|
||||
<filter string="Won" name="won"
|
||||
domain="['&', ('stage_id.probability', '=', 100), ('stage_id.on_change', '=', 1)]"/>
|
||||
<filter string="Lost" name="lost"
|
||||
domain="['&', ('stage_id.probability', '=', 0), ('stage_id.sequence', '!=', 1)]"/>
|
||||
<field name="team_id" context="{'invisible_team': False}"
|
||||
groups="base.group_multi_salesteams"/>
|
||||
<field name="author_id" string="Salesperson"/>
|
||||
<group expand="1" string="Group By">
|
||||
<filter string="Salesperson" context="{'group_by':'author_id'}" />
|
||||
<filter string="Sales Team" context="{'group_by':'team_id'}" groups="base.group_multi_salesteams"/>
|
||||
<filter string="Country" context="{'group_by':'country_id'}" />
|
||||
<filter string="Company" context="{'group_by':'company_id'}" groups="base.group_multi_company"/>
|
||||
<filter string="Stage" context="{'group_by':'stage_id'}"/>
|
||||
<filter string="Month" context="{'group_by':'date:month'}" name="month"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="crm_activity_report_action" model="ir.actions.act_window">
|
||||
<field name="name">Activities Analysis</field>
|
||||
<field name="res_model">crm.activity.report</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">pivot,graph</field>
|
||||
<field name="context">{}</field>
|
||||
<field name="domain">[]</field>
|
||||
</record>
|
||||
<menuitem name="Activities" id="crm_activity_report_menu"
|
||||
groups="base.group_sale_manager"
|
||||
parent="base.menu_sale_report" action="crm_activity_report_action" sequence="6"/>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -29,6 +29,7 @@ class crm_opportunity_report(osv.Model):
|
||||
|
||||
'user_id':fields.many2one('res.users', 'User', readonly=True),
|
||||
'team_id':fields.many2one('crm.team', 'Sales Team', oldname='section_id', readonly=True),
|
||||
'nbr_activities': fields.integer('# of Activities', readonly=True),
|
||||
'country_id':fields.many2one('res.country', 'Country', readonly=True),
|
||||
'company_id': fields.many2one('res.company', 'Company', readonly=True),
|
||||
'probability': fields.float('Probability',digits=(16,2),readonly=True, group_operator="avg"),
|
||||
@@ -51,9 +52,9 @@ class crm_opportunity_report(osv.Model):
|
||||
cr.execute("""
|
||||
CREATE OR REPLACE VIEW crm_opportunity_report AS (
|
||||
SELECT
|
||||
id,
|
||||
c.id,
|
||||
c.date_deadline,
|
||||
count(id) as nbr_cases,
|
||||
count(c.id) as nbr_cases,
|
||||
|
||||
c.date_open as opening_date,
|
||||
c.date_closed as date_closed,
|
||||
@@ -67,6 +68,7 @@ class crm_opportunity_report(osv.Model):
|
||||
c.company_id,
|
||||
c.priority,
|
||||
c.team_id,
|
||||
activity.nbr_activities,
|
||||
c.campaign_id,
|
||||
c.source_id,
|
||||
c.medium_id,
|
||||
@@ -81,7 +83,14 @@ class crm_opportunity_report(osv.Model):
|
||||
c.lost_reason,
|
||||
c.date_conversion as date_conversion
|
||||
FROM
|
||||
crm_lead c
|
||||
"crm_lead" c
|
||||
LEFT JOIN (
|
||||
SELECT m.res_id, COUNT(*) nbr_activities
|
||||
FROM "mail_message" m
|
||||
WHERE m.model = 'crm.lead'
|
||||
GROUP BY m.res_id ) activity
|
||||
ON
|
||||
(activity.res_id = c.id)
|
||||
WHERE c.active = 'true'
|
||||
GROUP BY c.id
|
||||
GROUP BY c.id, activity.nbr_activities
|
||||
)""")
|
||||
|
||||
@@ -63,6 +63,12 @@
|
||||
<field name="user_id" eval="False"/>
|
||||
<field name="context">{'group_by': ['create_date:month', 'country_id']}</field>
|
||||
</record>
|
||||
<record id="ir_filters_crm_opportunity_report_next_action" model="ir.filters">
|
||||
<field name="name">Team Activities</field>
|
||||
<field name="model_id">crm.opportunity.report</field>
|
||||
<field name="user_id" eval="False"/>
|
||||
<field name="context">{'group_by': ['team_id'], 'measures': ['nbr_activities']}</field>
|
||||
</record>
|
||||
|
||||
<!-- Opportunities by user and team Search View -->
|
||||
<record id="view_report_crm_opportunity_filter" model="ir.ui.view">
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from openerp import tools
|
||||
from openerp.addons.crm import crm
|
||||
from openerp.osv import fields, osv
|
||||
|
||||
AVAILABLE_STATES = [
|
||||
('draft', 'Draft'),
|
||||
('open', 'Todo'),
|
||||
('cancel', 'Cancelled'),
|
||||
('done', 'Held'),
|
||||
('pending', 'Pending')
|
||||
]
|
||||
|
||||
|
||||
class crm_phonecall_report(osv.osv):
|
||||
""" Phone calls by user and team """
|
||||
|
||||
_name = "crm.phonecall.report"
|
||||
_description = "Phone calls by user and team"
|
||||
_auto = False
|
||||
|
||||
_columns = {
|
||||
'user_id':fields.many2one('res.users', 'User', readonly=True),
|
||||
'team_id':fields.many2one('crm.team', 'Sales Team', oldname='section_id', readonly=True),
|
||||
'priority': fields.selection([('0','Low'), ('1','Normal'), ('2','High')], 'Priority'),
|
||||
'nbr': fields.integer('# of Cases', readonly=True), # TDE FIXME master: rename into nbr_cases
|
||||
'state': fields.selection(AVAILABLE_STATES, 'Status', readonly=True),
|
||||
'create_date': fields.datetime('Create Date', readonly=True, select=True),
|
||||
'delay_close': fields.float('Delay to close', digits=(16,2),readonly=True, group_operator="avg",help="Number of Days to close the case"),
|
||||
'duration': fields.float('Duration', digits=(16,2),readonly=True, group_operator="avg"),
|
||||
'delay_open': fields.float('Delay to open',digits=(16,2),readonly=True, group_operator="avg",help="Number of Days to open the case"),
|
||||
'categ_id': fields.many2one('crm.phonecall.category', 'Category'),
|
||||
'partner_id': fields.many2one('res.partner', 'Partner' , readonly=True),
|
||||
'company_id': fields.many2one('res.company', 'Company', readonly=True),
|
||||
'opening_date': fields.datetime('Opening Date', readonly=True, select=True),
|
||||
'date_closed': fields.datetime('Close Date', readonly=True, select=True),
|
||||
}
|
||||
|
||||
def init(self, cr):
|
||||
|
||||
""" Phone Calls By User And Team
|
||||
@param cr: the current row, from the database cursor,
|
||||
"""
|
||||
tools.drop_view_if_exists(cr, 'crm_phonecall_report')
|
||||
cr.execute("""
|
||||
create or replace view crm_phonecall_report as (
|
||||
select
|
||||
id,
|
||||
c.date_open as opening_date,
|
||||
c.date_closed as date_closed,
|
||||
c.state,
|
||||
c.user_id,
|
||||
c.team_id,
|
||||
c.categ_id,
|
||||
c.partner_id,
|
||||
c.duration,
|
||||
c.company_id,
|
||||
c.priority,
|
||||
1 as nbr,
|
||||
c.create_date as create_date,
|
||||
extract('epoch' from (c.date_closed-c.create_date))/(3600*24) as delay_close,
|
||||
extract('epoch' from (c.date_open-c.create_date))/(3600*24) as delay_open
|
||||
from
|
||||
crm_phonecall c
|
||||
)""")
|
||||
@@ -1,126 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<!-- Phone calls by user and team Pivot View -->
|
||||
|
||||
<record id="view_report_crm_phonecall_pivot" model="ir.ui.view">
|
||||
<field name="name">crm.phonecall.report.pivot</field>
|
||||
<field name="model">crm.phonecall.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<pivot string="Phone calls" disable_linking="True">
|
||||
<field name="team_id" type="row"/>
|
||||
<field name="create_date" interval="month" type="col"/>
|
||||
<field name="nbr" type="measure"/>
|
||||
<field name="duration" type="measure"/>
|
||||
</pivot>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Phone calls by user and team Graph View -->
|
||||
<record id="view_report_crm_phonecall_graph" model="ir.ui.view">
|
||||
<field name="name">crm.phonecall.report.graph</field>
|
||||
<field name="model">crm.phonecall.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<graph string="Phone calls">
|
||||
<field name="create_date" interval="month"/>
|
||||
<field name="team_id"/>
|
||||
<field name="nbr" type="measure"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Custom reports (aka filters) -->
|
||||
<record id="filter_crm_phonecall_sales_team" model="ir.filters">
|
||||
<field name="name">By Sales Team</field>
|
||||
<field name="model_id">crm.phonecall.report</field>
|
||||
<field name="domain">[('state','=','done')]</field>
|
||||
<field name="user_id" eval="False"/>
|
||||
<field name="context">{'group_by': ['team_id'], 'col_group_by': ['categ_id'], 'measures': ['nbr', 'duration']}</field>
|
||||
</record>
|
||||
<record id="filter_crm_phonecall_delay_to_close" model="ir.filters">
|
||||
<field name="name">Delay To Close</field>
|
||||
<field name="model_id">crm.phonecall.report</field>
|
||||
<field name="domain">[('state','=','done')]</field>
|
||||
<field name="user_id" eval="False"/>
|
||||
<field name="context">{'group_by': ['team_id'], 'col_group_by': ['categ_id'], 'measures': ['delay_close']}</field>
|
||||
</record>
|
||||
<record id="filter_crm_phonecall_phone_call_to_do" model="ir.filters">
|
||||
<field name="name">Phone Calls To Do</field>
|
||||
<field name="model_id">crm.phonecall.report</field>
|
||||
<field name="domain">[('state','in',('draft','open'))]</field>
|
||||
<field name="user_id" eval="False"/>
|
||||
<field name="context">{'group_by': ['team_id'], 'measures': ['nbr']}</field>
|
||||
</record>
|
||||
|
||||
|
||||
<!-- Phone calls by user and team Search View -->
|
||||
|
||||
<record id="view_report_crm_phonecall_filter" model="ir.ui.view">
|
||||
<field name="name">crm.phonecall.report.select</field>
|
||||
<field name="model">crm.phonecall.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search">
|
||||
<filter string="Held" name="held" domain="[('state','=','done')]"
|
||||
help="Phone calls which are in closed state"/>
|
||||
<filter string="Not Held" domain="[('state','=','pending')]"
|
||||
help="Phone calls which are in pending state"/>
|
||||
<separator/>
|
||||
<filter string="My Sales Team(s)" context="{'invisible_team': False}" domain="[('team_id.user_id','=',uid)]"
|
||||
help="Phone calls that are assigned to one of the sale teams I manage" groups="base.group_multi_salesteams"/>
|
||||
<separator/>
|
||||
<field name="team_id" string="Sales Team" context="{'invisible_team': False}"
|
||||
groups="base.group_multi_salesteams"/>
|
||||
<field name="user_id" string="Salesperson"/>
|
||||
<group expand="0" string="Extended Filters...">
|
||||
<field name="partner_id" filter_domain="[('partner_id','child_of',self)]"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
<field name="opening_date"/>
|
||||
<field name="date_closed"/>
|
||||
</group>
|
||||
<group expand="1" string="Group By">
|
||||
<filter string="Salesperson" name="Salesperson" context="{'group_by':'user_id'}" />
|
||||
<filter string="Sales Team" context="{'group_by':'team_id'}" groups="base.group_multi_salesteams"/>
|
||||
<filter string="Customer" context="{'group_by':'partner_id'}" />
|
||||
<filter string="Status" context="{'group_by':'state'}" />
|
||||
<separator/>
|
||||
<filter string="Creation Month" context="{'group_by':'create_date:month'}" help="Month of call"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Phone calls by user and team Action -->
|
||||
|
||||
<record id="action_report_crm_phonecall" model="ir.actions.act_window">
|
||||
<field name="name">Phone Calls Analysis</field>
|
||||
<field name="res_model">crm.phonecall.report</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">pivot,graph</field>
|
||||
<field name="context">{}</field>
|
||||
<field name="search_view_id" ref="view_report_crm_phonecall_filter"/>
|
||||
<field name="view_id"></field> <!-- force empty -->
|
||||
<field name="help">From this report, you can analyse the performance of your sales team, based on their phone calls. You can group or filter the information according to several criteria and drill down the information, by adding more groups in the report.</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.actions.act_window.view" id="action_report_crm_phonecall_graph">
|
||||
<field name="sequence" eval="2"/>
|
||||
<field name="view_mode">graph</field>
|
||||
<field name="view_id" ref="view_report_crm_phonecall_graph"/>
|
||||
<field name="act_window_id" ref="action_report_crm_phonecall"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.actions.act_window.view" id="action_report_crm_phonecall_pivot">
|
||||
<field name="sequence" eval="1"/>
|
||||
<field name="view_mode">pivot</field>
|
||||
<field name="view_id" ref="view_report_crm_phonecall_pivot"/>
|
||||
<field name="act_window_id" ref="action_report_crm_phonecall"/>
|
||||
</record>
|
||||
|
||||
<menuitem name="Phone Calls"
|
||||
groups="base.group_sale_salesman"
|
||||
action="action_report_crm_phonecall"
|
||||
id="menu_report_crm_phonecalls_tree" parent="base.menu_sale_report" sequence="15"/>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -20,10 +20,7 @@ class crm_configuration(osv.TransientModel):
|
||||
help='Allows you to communicate with Customer, process Customer query, and provide better help and support.\n'
|
||||
'-This installs the module crm_helpdesk.'),
|
||||
'alias_prefix': fields.char('Default Alias Name for Leads'),
|
||||
'alias_domain' : fields.char('Alias Domain'),
|
||||
'group_scheduled_calls': fields.boolean("Schedule calls to manage call center",
|
||||
implied_group='crm.group_scheduled_calls',
|
||||
help="""This adds the menu 'Scheduled Calls' under 'Sales / Phone Calls'""")
|
||||
'alias_domain' : fields.char('Alias Domain')
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
|
||||
@@ -9,15 +9,6 @@
|
||||
<data>
|
||||
<div name="config_sale" position="inside">
|
||||
<separator string="Sale Services"/>
|
||||
<group>
|
||||
<label for="id" string="Pre-Sale Services"/>
|
||||
<div>
|
||||
<div>
|
||||
<field name="group_scheduled_calls" class="oe_inline"/>
|
||||
<label for="group_scheduled_calls"/>
|
||||
</div>
|
||||
</div>
|
||||
</group>
|
||||
<group>
|
||||
<label for="id" string="After-Sale Services"/>
|
||||
<div>
|
||||
|
||||
@@ -7,7 +7,7 @@ class res_partner(osv.osv):
|
||||
""" Inherits partner and adds CRM information in the partner form """
|
||||
_inherit = 'res.partner'
|
||||
|
||||
def _opportunity_meeting_phonecall_count(self, cr, uid, ids, field_name, arg, context=None):
|
||||
def _opportunity_meeting_count(self, cr, uid, ids, field_name, arg, context=None):
|
||||
res = dict(map(lambda x: (x,{'opportunity_count': 0, 'meeting_count': 0}), ids))
|
||||
# the user may not have access rights for opportunities or meetings
|
||||
try:
|
||||
@@ -23,8 +23,6 @@ class res_partner(osv.osv):
|
||||
}
|
||||
except:
|
||||
pass
|
||||
for partner in self.browse(cr, uid, ids, context):
|
||||
res[partner.id]['phonecall_count'] = len(partner.phonecall_ids)
|
||||
return res
|
||||
|
||||
_columns = {
|
||||
@@ -33,11 +31,8 @@ class res_partner(osv.osv):
|
||||
'Opportunities', domain=[('type', '=', 'opportunity')]),
|
||||
'meeting_ids': fields.many2many('calendar.event', 'calendar_event_res_partner_rel','res_partner_id', 'calendar_event_id',
|
||||
'Meetings'),
|
||||
'phonecall_ids': fields.one2many('crm.phonecall', 'partner_id',\
|
||||
'Phonecalls'),
|
||||
'opportunity_count': fields.function(_opportunity_meeting_phonecall_count, string="Opportunity", type='integer', multi='opp_meet'),
|
||||
'meeting_count': fields.function(_opportunity_meeting_phonecall_count, string="# Meetings", type='integer', multi='opp_meet'),
|
||||
'phonecall_count': fields.function(_opportunity_meeting_phonecall_count, string="Phonecalls", type="integer", multi='opp_meet'),
|
||||
'opportunity_count': fields.function(_opportunity_meeting_count, string="Opportunity", type='integer', multi='opp_meet'),
|
||||
'meeting_count': fields.function(_opportunity_meeting_count, string="# Meetings", type='integer', multi='opp_meet'),
|
||||
}
|
||||
|
||||
def redirect_partner_form(self, cr, uid, partner_id, context=None):
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
Use opportunities to keep track of your sales pipeline, follow
|
||||
up potential sales and better forecast your future revenues.
|
||||
</p><p>
|
||||
You will be able to plan meetings and phone calls from
|
||||
You will be able to plan meetings and log activities from
|
||||
opportunities, convert them into quotations, attach related
|
||||
documents, track all discussions, and much more.
|
||||
</p>
|
||||
@@ -99,12 +99,6 @@
|
||||
context="{'partner_id': active_id}">
|
||||
<field string="Meetings" name="meeting_count" widget="statinfo"/>
|
||||
</button>
|
||||
<button class="oe_stat_button" type="action"
|
||||
name="%(crm.crm_phonecall_category_phone_incoming0)d"
|
||||
icon="fa-phone"
|
||||
context="{'search_default_partner_id': active_id, 'default_duration': 1.0}">
|
||||
<field string="Calls" name="phonecall_count" widget="statinfo"/>
|
||||
</button>
|
||||
</div>
|
||||
</data>
|
||||
</field>
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
Odoo helps you keep track of your sales pipeline to follow
|
||||
up potential sales and better forecast your future revenues.
|
||||
</p><p>
|
||||
You will be able to plan meetings and phone calls from
|
||||
You will be able to plan meetings and log activities from
|
||||
opportunities, convert them into quotations, attach related
|
||||
documents, track all discussions, and much more.
|
||||
</p>
|
||||
|
||||
@@ -29,11 +29,6 @@
|
||||
<field name="category_id" ref="base.module_category_hidden"/>
|
||||
</record>
|
||||
|
||||
<record id="group_scheduled_calls" model="res.groups">
|
||||
<field name="name">Show Scheduled Calls Menu</field>
|
||||
<field name="category_id" ref="base.module_category_hidden"/>
|
||||
</record>
|
||||
|
||||
<record model="res.users" id="base.user_root">
|
||||
<field eval="[(4,ref('base.group_partner_manager'))]" name="groups_id"/>
|
||||
</record>
|
||||
@@ -70,19 +65,6 @@
|
||||
<field name="domain_force">['|',('user_id','=',user.id),('show_as','=','busy')]</field>
|
||||
</record>
|
||||
|
||||
<record id="crm_rule_personal_phonecall" model="ir.rule">
|
||||
<field name="name">Personal Phone Calls</field>
|
||||
<field ref="model_crm_phonecall" name="model_id"/>
|
||||
<field name="domain_force">['|',('user_id','=',user.id),('user_id','=',False)]</field>
|
||||
<field name="groups" eval="[(4, ref('base.group_sale_salesman'))]"/>
|
||||
</record>
|
||||
<record id="crm_rule_all_phones" model="ir.rule">
|
||||
<field name="name">All Phones</field>
|
||||
<field ref="model_crm_phonecall" name="model_id"/>
|
||||
<field name="domain_force">[(1,'=',1)]</field>
|
||||
<field name="groups" eval="[(4, ref('base.group_sale_salesman_all_leads'))]"/>
|
||||
</record>
|
||||
|
||||
<record id="crm_rule_personal_lead_report" model="ir.rule">
|
||||
<field name="name">Personal Leads Analysis</field>
|
||||
<field ref="model_crm_lead_report" name="model_id"/>
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_crm_lead_manager,crm.lead.manager,model_crm_lead,base.group_sale_manager,1,1,1,1
|
||||
access_crm_phonecall_manager,crm.phonecall.manager,model_crm_phonecall,base.group_sale_manager,1,1,1,1
|
||||
access_crm_lead,crm.lead,model_crm_lead,base.group_sale_salesman,1,1,1,0
|
||||
access_crm_phonecall,crm.phonecall,model_crm_phonecall,base.group_sale_salesman,1,1,1,0
|
||||
access_crm_stage,crm.stage,model_crm_stage,,1,0,0,0
|
||||
access_crm_stage_manager,crm.stage,model_crm_stage,base.group_sale_manager,1,1,1,1
|
||||
access_crm_phonecall_report_user,crm.phonecall.report.user,model_crm_phonecall_report,base.group_sale_salesman,1,0,0,0
|
||||
access_crm_phonecall_report_manager,crm.phonecall.report,model_crm_phonecall_report,base.group_sale_manager,1,1,1,1
|
||||
access_crm_opportunity_report_user,crm.opportunity.report,model_crm_opportunity_report,base.group_sale_salesman,1,0,0,0
|
||||
access_crm_opportunity_report_manager,crm.opportunity.report,model_crm_opportunity_report,base.group_sale_manager,1,1,1,1
|
||||
access_res_partner_manager,res.partner.crm.manager,base.model_res_partner,base.group_sale_manager,1,0,0,0
|
||||
@@ -18,13 +14,13 @@ access_base_action_rule_manager,base.action.rule manager,base_action_rule.model_
|
||||
access_crm_lead_report_user,crm.lead.report user,model_crm_lead_report,base.group_sale_salesman,1,1,1,1
|
||||
access_res_partner_bank_type_crm_user,res.partner.bank.type.crm.user,base.model_res_partner_bank_type,base.group_sale_salesman,1,0,0,0
|
||||
access_crm_lead_partner_manager,crm.lead.partner.manager,model_crm_lead,base.group_partner_manager,1,0,0,0
|
||||
access_crm_phonecall_partner_manager,crm.phonecall.partner.manager,model_crm_phonecall,base.group_partner_manager,1,1,1,1
|
||||
access_crm_lead_tag,crm_lead_tag,model_crm_lead_tag,base.group_user,1,0,0,0
|
||||
access_crm_lead_tag_salesman,crm_lead_tag salesman,model_crm_lead_tag,base.group_sale_salesman,1,1,1,0
|
||||
access_crm_lead_tag_manager,crm_lead_tag manager,model_crm_lead_tag,base.group_sale_manager,1,1,1,1
|
||||
access_crm_phonecall_category,crm_phonecall_category,model_crm_phonecall_category,base.group_user,1,0,0,0
|
||||
access_crm_phonecall_category_salesman,crm_phonecall_category salesman,model_crm_phonecall_category,base.group_sale_salesman,1,1,1,0
|
||||
access_crm_phonecall_category_manager,crm_phonecall_category manager,model_crm_phonecall_category,base.group_sale_manager,1,1,1,1
|
||||
access_crm_lost_reason_manager,crm.lost.reason.manager,model_crm_lost_reason,base.group_sale_manager,1,1,1,1
|
||||
access_crm_lost_reason_salesman,crm.lost.reason.salesman,model_crm_lost_reason,base.group_sale_salesman,1,1,1,0
|
||||
access_crm_lost_reason_user,crm.lost.reason.user,model_crm_lost_reason,base.group_user,1,0,0,0
|
||||
access_crm_activity_user,crm.activity.user,model_crm_activity,base.group_user,1,1,1,0
|
||||
access_crm_activity_manager,crm.activity.manager,model_crm_activity,base.group_sale_manager,1,1,1,1
|
||||
access_crm_activity_salesman,crm.activity.salesman,model_crm_activity,base.group_sale_salesman,1,1,1,0
|
||||
access_crm_activity_report_user,crm.activity.report.user,model_crm_activity_report,base.group_user,1,0,0,0
|
||||
|
||||
|
@@ -14,7 +14,7 @@
|
||||
</div>
|
||||
<div class="oe_span6">
|
||||
<p class="oe_mt32">
|
||||
Manage your sales funnel with no effort. Attract leads, follow-up on phone calls and meetings. Analyse the quality of your leads to make informed decisions and save time by integrating emails directly into the application.
|
||||
Manage your sales funnel with no effort. Attract leads, follow-up on activities and meetings. Analyse the quality of your leads to make informed decisions and save time by integrating emails directly into the application.
|
||||
</p>
|
||||
<div class="oe_centeralign oe_websiteonly">
|
||||
<a href="http://www.openerp.com/start?app=crm" class="oe_button oe_big oe_tacky">Start your <span class="oe_emph">free</span> trial</a>
|
||||
@@ -69,7 +69,7 @@ Find duplicates, merge leads and assign them to the right salesperson in one ope
|
||||
</div>
|
||||
<div class="oe_span6">
|
||||
<p class="oe_mt32">
|
||||
Get your opportunities organized to stay focused on the best deals. Manage all your customer interactions from the opportunity like emails, phone calls, internal notes, meetings and quotations.
|
||||
Get your opportunities organized to stay focused on the best deals. Manage all your customer interactions from the opportunity like emails, internal notes, meetings and quotations.
|
||||
</p><p>
|
||||
Follow opportunities that interest you to get notified upon specific events: deal won or lost, stage changed, new customer demand, etc.
|
||||
</p>
|
||||
@@ -105,7 +105,7 @@ Route, sort and filter incoming emails automatically. Odoo CRM handles incoming
|
||||
</div>
|
||||
<div class="oe_span6">
|
||||
<p class="oe_mt32">
|
||||
Schedule your meetings and phone calls using the integrated calendar. You can see your agenda and your colleagues' in one view. As a manager, it's easy to see what your team is busy with.
|
||||
Schedule your meetings using the integrated calendar. You can see your agenda and your colleagues' in one view. As a manager, it's easy to see what your team is busy with.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -17,9 +17,3 @@
|
||||
type: opportunity
|
||||
stage_id: crm.stage_lead1
|
||||
opt_out: True
|
||||
-
|
||||
Sales manager create a phonecall record to call a partner onchange method.
|
||||
-
|
||||
!record {model: crm.phonecall, id: crm_phonecall_5}:
|
||||
name: 'Bad time'
|
||||
partner_id: base.res_partner_5
|
||||
@@ -28,15 +28,6 @@
|
||||
assert lead.type == 'opportunity', 'Lead is not converted to opportunity!'
|
||||
assert lead.partner_id.id == ref("base.res_partner_2"), 'Partner mismatch!'
|
||||
assert lead.stage_id.id == ref("stage_lead1"), 'Stage of opportunity is incorrect!'
|
||||
-
|
||||
Now I begin communication and schedule a phone call with the customer.
|
||||
-
|
||||
!python {model: crm.phonecall2phonecall}: |
|
||||
import time
|
||||
context.update({'active_model': 'crm.lead', 'active_ids': [ref('crm_case_3')],'active_id': ref('crm_case_3')})
|
||||
call_id = self.create(cr, uid, {'date': time.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
'name': "Bonjour M. Jean, Comment allez-vous? J'ai bien reçu votre demande, pourrions-nous en parler quelques minutes?"}, context=context)
|
||||
self.action_schedule(cr, uid, [call_id], context=context)
|
||||
-
|
||||
Now I schedule meeting with customer.
|
||||
-
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
-
|
||||
Salesman check the phone calls data so test with the access rights of salesman.
|
||||
-
|
||||
!context
|
||||
uid: 'crm_res_users_salesman'
|
||||
-
|
||||
I schedule a phone call with a customer.
|
||||
-
|
||||
!python {model: crm.phonecall2phonecall}: |
|
||||
context.update({'active_model': 'crm.phonecall', 'active_ids': [ref("crm.crm_phonecall_6")], 'active_id': ref("crm.crm_phonecall_6")})
|
||||
res_id = self.create(cr, uid, {'name': "Proposition de réduction"}, context=context)
|
||||
self.action_schedule(cr, uid, [res_id], context=context)
|
||||
-
|
||||
I schedule a meeting based on this phone call.
|
||||
-
|
||||
!python {model: crm.phonecall}: |
|
||||
self.action_make_meeting(cr, uid, [ref("crm.crm_phonecall_6")])
|
||||
@@ -0,0 +1,67 @@
|
||||
<?xml version="1.0"?>
|
||||
<odoo>
|
||||
|
||||
<record id="crm_activity_view_search" model="ir.ui.view">
|
||||
<field name="name">crm.activity.view.search</field>
|
||||
<field name="model">crm.activity</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Action Search">
|
||||
<field name="name"/>
|
||||
<field name="team_id"/>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="crm_activity_view_form" model="ir.ui.view">
|
||||
<field name="name">crm.activity.view.form</field>
|
||||
<field name="model">crm.activity</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Activities">
|
||||
<label for="name" class="oe_edit_only"/>
|
||||
<h1>
|
||||
<field name="name"/>
|
||||
</h1>
|
||||
<group>
|
||||
<group>
|
||||
<field name="team_id" groups="base.group_multi_salesteams"/>
|
||||
<field name="description"/>
|
||||
<field name="days"/>
|
||||
</group><group>
|
||||
<field name="activity_1_id"/>
|
||||
<field name="activity_2_id"/>
|
||||
<field name="activity_3_id"/>
|
||||
</group>
|
||||
</group>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="crm_activity_view_tree" model="ir.ui.view">
|
||||
<field name="name">crm.activity.view.tree</field>
|
||||
<field name="model">crm.activity</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Activities">
|
||||
<field name="sequence" widget="handle"/>
|
||||
<field name="name"/>
|
||||
<field name="days"/>
|
||||
<field name="team_id" groups="base.group_multi_salesteams"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="crm_activity_action" model="ir.actions.act_window">
|
||||
<field name="name">Activities</field>
|
||||
<field name="res_model">crm.activity</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click to create a new activity.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<menuitem id="crm_activity_menu" action="crm_activity_action"
|
||||
name="Activities" parent="base.menu_crm_config_lead"/>
|
||||
|
||||
</odoo>
|
||||
@@ -2,6 +2,5 @@
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import crm_partner_binding
|
||||
import crm_phonecall_to_phonecall
|
||||
import crm_lead_to_opportunity
|
||||
import crm_merge_opportunities
|
||||
|
||||
@@ -36,11 +36,9 @@ class crm_partner_binding(osv.osv_memory):
|
||||
partner_id = False
|
||||
partner_obj = self.pool.get('res.partner')
|
||||
|
||||
# The active model has to be a lead or a phonecall
|
||||
# The active model has to be a lead
|
||||
if (context.get('active_model') == 'crm.lead') and context.get('active_id'):
|
||||
active_model = self.pool.get('crm.lead').browse(cr, uid, context.get('active_id'), context=context)
|
||||
elif (context.get('active_model') == 'crm.phonecall') and context.get('active_id'):
|
||||
active_model = self.pool.get('crm.phonecall').browse(cr, uid, context.get('active_id'), context=context)
|
||||
|
||||
# Find the best matching partner for the active model
|
||||
if (active_model):
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from openerp.osv import osv
|
||||
from openerp.tools.translate import _
|
||||
|
||||
class crm_phonecall2meeting(osv.osv_memory):
|
||||
""" Phonecall to Meeting """
|
||||
|
||||
_name = 'crm.phonecall2meeting'
|
||||
_description = 'Phonecall To Meeting'
|
||||
|
||||
def action_cancel(self, cr, uid, ids, context=None):
|
||||
"""
|
||||
Closes Phonecall to Meeting form
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param ids: List of Phonecall to Meeting IDs
|
||||
@param context: A standard dictionary for contextual values
|
||||
|
||||
"""
|
||||
return {'type':'ir.actions.act_window_close'}
|
||||
|
||||
def action_make_meeting(self, cr, uid, ids, context=None):
|
||||
""" This opens Meeting's calendar view to schedule meeting on current Phonecall
|
||||
@return : Dictionary value for created Meeting view
|
||||
"""
|
||||
res = {}
|
||||
phonecall_id = context and context.get('active_id', False) or False
|
||||
if phonecall_id:
|
||||
phonecall = self.pool.get('crm.phonecall').browse(cr, uid, phonecall_id, context)
|
||||
res = self.pool.get('ir.actions.act_window').for_xml_id(cr, uid, 'calendar', 'action_calendar_event', context)
|
||||
res['context'] = {
|
||||
'default_phonecall_id': phonecall.id,
|
||||
'default_partner_id': phonecall.partner_id and phonecall.partner_id.id or False,
|
||||
'default_user_id': uid,
|
||||
'default_email_from': phonecall.email_from,
|
||||
'default_state': 'open',
|
||||
'default_name': phonecall.name,
|
||||
}
|
||||
return res
|
||||
@@ -1,36 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
|
||||
<!-- Phonecall to meeting view -->
|
||||
|
||||
<record model="ir.ui.view" id="phonecall2phonecall2meeting_view">
|
||||
<field name="name">crm.phonecall2meeting.form</field>
|
||||
<field name="model">crm.phonecall2meeting</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Convert To Meeting">
|
||||
<label string="Are you sure to schedule a Meeting for this Phonecall?"/>
|
||||
<footer>
|
||||
<button name="action_make_meeting" type="object"
|
||||
string="_Schedule" class="oe_highlight"/>
|
||||
or
|
||||
<button string="Cancel" class="oe_link" special="cancel" />
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Phonecall to meeting action -->
|
||||
|
||||
<record model="ir.actions.act_window" id="phonecall2meeting_act">
|
||||
<field name="name">Convert To Meeting</field>
|
||||
<field name="res_model">crm.phonecall2meeting</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="phonecall2phonecall2meeting_view"/>
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -1,79 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from openerp.osv import fields, osv
|
||||
from openerp.tools.translate import _
|
||||
|
||||
import time
|
||||
|
||||
class crm_phonecall2phonecall(osv.osv_memory):
|
||||
_name = 'crm.phonecall2phonecall'
|
||||
_description = 'Phonecall To Phonecall'
|
||||
|
||||
_columns = {
|
||||
'name' : fields.char('Call summary', required=True, select=1),
|
||||
'user_id' : fields.many2one('res.users',"Assign To"),
|
||||
'contact_name':fields.char('Contact'),
|
||||
'phone':fields.char('Phone'),
|
||||
'categ_id': fields.many2one('crm.phonecall.category', 'Category'),
|
||||
'date': fields.datetime('Date'),
|
||||
'team_id':fields.many2one('crm.team','Sales Team', oldname='section_id'),
|
||||
'action': fields.selection([('schedule','Schedule a call'), ('log','Log a call')], 'Action', required=True),
|
||||
'partner_id' : fields.many2one('res.partner', "Partner"),
|
||||
'note':fields.text('Note')
|
||||
}
|
||||
|
||||
|
||||
def action_cancel(self, cr, uid, ids, context=None):
|
||||
"""
|
||||
Closes Phonecall to Phonecall form
|
||||
"""
|
||||
return {'type':'ir.actions.act_window_close'}
|
||||
|
||||
def action_schedule(self, cr, uid, ids, context=None):
|
||||
value = {}
|
||||
if context is None:
|
||||
context = {}
|
||||
phonecall = self.pool.get('crm.phonecall')
|
||||
phonecall_ids = context and context.get('active_ids') or []
|
||||
for this in self.browse(cr, uid, ids, context=context):
|
||||
phocall_ids = phonecall.schedule_another_phonecall(cr, uid, phonecall_ids, this.date, this.name, \
|
||||
this.user_id and this.user_id.id or False, \
|
||||
this.team_id and this.team_id.id or False, \
|
||||
this.categ_id and this.categ_id.id or False, \
|
||||
action=this.action, context=context)
|
||||
|
||||
return phonecall.redirect_phonecall_view(cr, uid, phocall_ids[phonecall_ids[0]], context=context)
|
||||
|
||||
def default_get(self, cr, uid, fields, context=None):
|
||||
"""
|
||||
This function gets default values
|
||||
|
||||
"""
|
||||
res = super(crm_phonecall2phonecall, self).default_get(cr, uid, fields, context=context)
|
||||
record_id = context and context.get('active_id', False) or False
|
||||
res.update({'action': 'schedule', 'date': time.strftime('%Y-%m-%d %H:%M:%S')})
|
||||
if record_id:
|
||||
phonecall = self.pool.get('crm.phonecall').browse(cr, uid, record_id, context=context)
|
||||
|
||||
categ_id = False
|
||||
data_obj = self.pool.get('ir.model.data')
|
||||
try:
|
||||
res_id = data_obj._get_id(cr, uid, 'crm', 'categ_phone2')
|
||||
categ_id = data_obj.browse(cr, uid, res_id, context=context).res_id
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
if 'name' in fields:
|
||||
res.update({'name': phonecall.name})
|
||||
if 'user_id' in fields:
|
||||
res.update({'user_id': phonecall.user_id and phonecall.user_id.id or False})
|
||||
if 'date' in fields:
|
||||
res.update({'date': False})
|
||||
if 'team_id' in fields:
|
||||
res.update({'team_id': phonecall.team_id and phonecall.team_id.id or False})
|
||||
if 'categ_id' in fields:
|
||||
res.update({'categ_id': categ_id})
|
||||
if 'partner_id' in fields:
|
||||
res.update({'partner_id': phonecall.partner_id and phonecall.partner_id.id or False})
|
||||
return res
|
||||
@@ -1,42 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<!-- Phonecall to Phonecall view -->
|
||||
|
||||
<record model="ir.ui.view" id="phonecall_to_phonecall_view">
|
||||
<field name="name">crm.phonecall2phonecall.form</field>
|
||||
<field name="model">crm.phonecall2phonecall</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Schedule/Log a Call">
|
||||
<group col="4">
|
||||
<field name="action"/>
|
||||
<field name="name"/>
|
||||
<field name="date" string="Planned Date" attrs="{'invisible': [('action','=','log')]}"/>
|
||||
<field name="partner_id" readonly="True"/>
|
||||
<field name="user_id" context="{'default_groups_ref': ['base.group_user', 'base.group_partner_manager', 'base.group_sale_salesman_all_leads']}"/>
|
||||
<field name="team_id" groups="base.group_multi_salesteams"/>
|
||||
</group>
|
||||
<footer>
|
||||
<button name="action_schedule" type="object" string="Log Call" attrs="{'invisible' : [('action', '!=', 'log')]}" class="oe_highlight"/>
|
||||
<button name="action_schedule" type="object" string="Schedule Call" attrs="{'invisible' : [('action', '!=', 'schedule')]}" class="oe_highlight"/>
|
||||
or
|
||||
<button string="Cancel" class="oe_link" special="cancel" />
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Phonecall to Phonecall action -->
|
||||
|
||||
<record model="ir.actions.act_window" id="phonecall_to_phonecall_act">
|
||||
<field name="name">Schedule Other Call</field>
|
||||
<field name="res_model">crm.phonecall2phonecall</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="phonecall_to_phonecall_view"/>
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -50,16 +50,6 @@
|
||||
</record>
|
||||
|
||||
|
||||
<record model="gamification.goal.definition" id="definition_crm_nbr_call">
|
||||
<field name="name">Logged Calls</field>
|
||||
<field name="description">Log a certain number of calls to reach this goal</field>
|
||||
<field name="computation_mode">count</field>
|
||||
<field name="suffix">calls</field>
|
||||
<field name="model_id" eval="ref('crm.model_crm_phonecall')" />
|
||||
<field name="field_date_id" eval="ref('crm.field_crm_phonecall_date')" />
|
||||
<field name="domain">[('user_id','=',user.id),('state','=','done')]</field>
|
||||
</record>
|
||||
|
||||
<record model="gamification.goal.definition" id="definition_crm_nbr_new_opportunities">
|
||||
<field name="name">New Opportunities</field>
|
||||
<field name="description">Based on the opening date</field>
|
||||
|
||||
Reference in New Issue
Block a user