diff --git a/crm_phonecall/README.rst b/crm_phonecall/README.rst new file mode 100644 index 00000000000..da5ba06f921 --- /dev/null +++ b/crm_phonecall/README.rst @@ -0,0 +1,59 @@ +.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 + +=============== +CRM phone calls +=============== + +* This module allows to manage phone calls in order to analyze them. + +Usage +===== + +To use this module, you need to: + +#. Go to *Sales > Phone Calls > Logged Calls > Create*. +#. If your user has *Show Scheduled Calls Menu* permission, you will see + scheduled calls menu too. +#. In any moment you can schedule another call, schedule a meeting or convert + call contact to opportunity. +#. Calls can be categorized and you can manage categories in *Sales > + Configuration > Leads & Opportunities > Phone Calls > Categories*. +#. Calls can be analyzed in *Sales > Reports > Phone Calls Analysis*. + +.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas + :alt: Try me on Runbot + :target: https://runbot.odoo-community.org/runbot/134/10.0 + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smash it by providing detailed and welcomed +feedback. + +Credits +======= + +Contributors +------------ + +* Odoo S.A. +* Vicent Cubells + +Maintainer +---------- + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +This module is maintained by the OCA. + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +To contribute to this module, please visit https://odoo-community.org. diff --git a/crm_phonecall/__init__.py b/crm_phonecall/__init__.py new file mode 100644 index 00000000000..f03a8710898 --- /dev/null +++ b/crm_phonecall/__init__.py @@ -0,0 +1,7 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 Tecnativa - Vicent Cubells +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from . import models +from . import wizard +from . import report diff --git a/crm_phonecall/__manifest__.py b/crm_phonecall/__manifest__.py new file mode 100644 index 00000000000..ffdf6c70032 --- /dev/null +++ b/crm_phonecall/__manifest__.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 Tecnativa - Vicent Cubells +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +{ + "name": "CRM Phone Calls", + "version": "10.0.1.0.0", + "category": "Customer Relationship Management", + "author": "Odoo S.A., " + "Tecnativa, " + "Odoo Community Association (OCA)", + "website": "http://www.tecnativa.com", + "license": "AGPL-3", + "depends": [ + 'crm', + 'calendar', + ], + "data": [ + 'security/crm_security.xml', + 'security/ir.model.access.csv', + 'wizard/crm_phonecall_to_phonecall_view.xml', + 'views/crm_phonecall_view.xml', + 'views/res_partner_view.xml', + 'report/crm_phonecall_report_view.xml', + ], + 'installable': True, +} diff --git a/crm_phonecall/i18n/es.po b/crm_phonecall/i18n/es.po new file mode 100644 index 00000000000..bc81d359546 --- /dev/null +++ b/crm_phonecall/i18n/es.po @@ -0,0 +1,707 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * crm_phonecall +# +# Translators: +# OCA Transbot , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-05-01 16:53+0000\n" +"PO-Revision-Date: 2017-05-01 16:53+0000\n" +"Last-Translator: OCA Transbot , 2017\n" +"Language-Team: Spanish (https://www.transifex.com/oca/teams/23907/es/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: es\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: crm_phonecall +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall_report_nbr_cases +msgid "# of Cases" +msgstr "# de casos" + +#. module: crm_phonecall +#: model:ir.ui.view,arch_db:crm_phonecall.crm_case_phone_form_view +msgid " min(s)" +msgstr " minuto(s)" + +#. module: crm_phonecall +#: model:ir.ui.view,arch_db:crm_phonecall.crm_case_phone_form_view +msgid "Convert
To Opportunity
" +msgstr "Convertir
en oportunidad
" + +#. module: crm_phonecall +#: model:ir.ui.view,arch_db:crm_phonecall.crm_case_phone_form_view +msgid "Schedule
A Meeting
" +msgstr "span>Planificar
una reunión" + +#. module: crm_phonecall +#: model:ir.ui.view,arch_db:crm_phonecall.crm_case_phone_form_view +msgid "Schedule
Other Call
" +msgstr "Planificar
otra llamada
" + +#. module: crm_phonecall +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall2phonecall_action +msgid "Action" +msgstr "Acción" + +#. module: crm_phonecall +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall_active +msgid "Active" +msgstr "Activa" + +#. module: crm_phonecall +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall2phonecall_user_id +msgid "Assign To" +msgstr "Asignar a" + +#. module: crm_phonecall +#: model:ir.filters,name:crm_phonecall.filter_crm_phonecall_sales_team +msgid "By Sales Team" +msgstr "Por equipo de ventas" + +#. module: crm_phonecall +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall_name +msgid "Call Summary" +msgstr "Resumen de la llamada" + +#. module: crm_phonecall +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall2phonecall_name +msgid "Call summary" +msgstr "Resumen de la llamada" + +#. module: crm_phonecall +#: model:ir.ui.view,arch_db:crm_phonecall.view_partners_form_crm_calls +msgid "Calls" +msgstr "Llamadas" + +#. module: crm_phonecall +#: model:ir.ui.view,arch_db:crm_phonecall.view_crm_case_phonecalls_filter +msgid "Calls Date by Month" +msgstr "Fechas de las llamadas por mes" + +#. module: crm_phonecall +#: selection:crm.phonecall,state:0 selection:crm.phonecall.report,state:0 +msgid "Cancelled" +msgstr "Cancelada" + +#. module: crm_phonecall +#: model:ir.ui.menu,name:crm_phonecall.menu_crm_case_phonecall-act +msgid "Categories" +msgstr "Categorias" + +#. module: crm_phonecall +#: model:ir.actions.act_window,help:crm_phonecall.crm_phonecall_categ_action +msgid "Click to add a new category." +msgstr "Pulse para añadir una categoría nueva" + +#. module: crm_phonecall +#: model:ir.actions.act_window,help:crm_phonecall.crm_case_categ_phone_incoming0 +msgid "Click to log the summary of a phone call." +msgstr "Pulse para registrar el resumen de una llamada." + +#. module: crm_phonecall +#: model:ir.actions.act_window,help:crm_phonecall.crm_case_categ_phone_outgoing0 +msgid "Click to schedule a call" +msgstr "Pulse para planificar una llamada" + +#. module: crm_phonecall +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall_report_date_closed +msgid "Close Date" +msgstr "Fecha de cierre" + +#. module: crm_phonecall +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall_date_closed +msgid "Closed" +msgstr "Cerrado" + +#. module: crm_phonecall +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall_company_id +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall_report_company_id +msgid "Company" +msgstr "Compañía" + +#. module: crm_phonecall +#: selection:crm.phonecall,state:0 +msgid "Confirmed" +msgstr "Confirmado" + +#. module: crm_phonecall +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall2phonecall_contact_name +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall_partner_id +msgid "Contact" +msgstr "Contacto" + +#. module: crm_phonecall +#: model:ir.ui.view,arch_db:crm_phonecall.crm_case_phone_form_view +msgid "Convert To Opportunity" +msgstr "Convertir en oportunidad" + +#. module: crm_phonecall +#: model:ir.ui.view,arch_db:crm_phonecall.crm_case_inbound_phone_tree_view +#: model:ir.ui.view,arch_db:crm_phonecall.crm_case_phone_tree_view +msgid "Convert to Opportunity" +msgstr "Convertir en oportunidad" + +#. module: crm_phonecall +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall_report_create_date +msgid "Create Date" +msgstr "Fecha de creación" + +#. module: crm_phonecall +#: model:ir.actions.act_window,help:crm_phonecall.crm_phonecall_categ_action +msgid "" +"Create specific phone call categories to better define the type of\n" +" calls tracked in the system." +msgstr "" +"Crear categorías específicas de llamadas para definir mejor el tipo\n" +" de las llamadas registradas en el sistema." + +#. module: crm_phonecall +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall2phonecall_create_uid +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall_create_uid +msgid "Created by" +msgstr "Creado por" + +#. module: crm_phonecall +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall2phonecall_create_date +msgid "Created on" +msgstr "Creado el" + +#. module: crm_phonecall +#: model:ir.ui.view,arch_db:crm_phonecall.view_crm_case_phonecalls_filter +msgid "Creation" +msgstr "Creación" + +#. module: crm_phonecall +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall_create_date +#: model:ir.ui.view,arch_db:crm_phonecall.view_crm_case_phonecalls_filter +msgid "Creation Date" +msgstr "Fecha de creación" + +#. module: crm_phonecall +#: model:ir.ui.view,arch_db:crm_phonecall.view_report_crm_phonecall_filter +msgid "Creation Month" +msgstr "Mes de creación" + +#. module: crm_phonecall +#: model:ir.ui.view,arch_db:crm_phonecall.view_report_crm_phonecall_filter +msgid "Customer" +msgstr "Cliente" + +#. module: crm_phonecall +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall2phonecall_date +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall_date +msgid "Date" +msgstr "Fecha" + +#. module: crm_phonecall +#: model:ir.filters,name:crm_phonecall.filter_crm_phonecall_delay_to_close +msgid "Delay To Close" +msgstr "Tiempo restante para el cierre" + +#. module: crm_phonecall +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall_report_delay_close +msgid "Delay to close" +msgstr "Demora cierre" + +#. module: crm_phonecall +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall_report_delay_open +msgid "Delay to open" +msgstr "Retraso de apertura" + +#. module: crm_phonecall +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall_description +msgid "Description" +msgstr "Descripciòn" + +#. module: crm_phonecall +#: model:ir.ui.view,arch_db:crm_phonecall.crm_case_phone_form_view +msgid "Description..." +msgstr "Descripción..." + +#. module: crm_phonecall +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall2phonecall_display_name +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall_display_name +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall_report_display_name +msgid "Display Name" +msgstr "" + +#. module: crm_phonecall +#: selection:crm.phonecall.report,state:0 +msgid "Draft" +msgstr "Borrador" + +#. module: crm_phonecall +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall_duration +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall_report_duration +msgid "Duration" +msgstr "Duración" + +#. module: crm_phonecall +#: model:ir.model.fields,help:crm_phonecall.field_crm_phonecall_duration +msgid "Duration in minutes and seconds." +msgstr "Duración en minutos y segundos." + +#. module: crm_phonecall +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall_email_from +msgid "Email" +msgstr "Email" + +#. module: crm_phonecall +#: model:ir.model,name:crm_phonecall.model_calendar_event +msgid "Event" +msgstr "Evento" + +#. module: crm_phonecall +#: model:ir.ui.view,arch_db:crm_phonecall.view_report_crm_phonecall_filter +msgid "Extended Filters..." +msgstr "Filtros extendidos..." + +#. module: crm_phonecall +#: model:ir.ui.view,arch_db:crm_phonecall.view_crm_case_phonecalls_filter +#: model:ir.ui.view,arch_db:crm_phonecall.view_report_crm_phonecall_filter +msgid "Group By" +msgstr "Agrupar por" + +#. module: crm_phonecall +#: selection:crm.phonecall,state:0 selection:crm.phonecall.report,state:0 +#: model:ir.ui.view,arch_db:crm_phonecall.view_report_crm_phonecall_filter +msgid "Held" +msgstr "Realizada" + +#. module: crm_phonecall +#: selection:crm.phonecall,priority:0 +#: selection:crm.phonecall.report,priority:0 +msgid "High" +msgstr "Alta" + +#. module: crm_phonecall +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall2phonecall_id +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall_id +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall_report_id +msgid "ID" +msgstr "Identificador" + +#. module: crm_phonecall +#: model:ir.actions.act_window,help:crm_phonecall.crm_case_categ_phone_incoming0 +msgid "" +"In order to follow up on the call, you can trigger a request for\n" +" another call, a meeting or an opportunity." +msgstr "" +"Para seguir una llamada, puede lanzar una petición para otra llamada,\n" +" una reunión o una oportunidad." + +#. module: crm_phonecall +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall_date_action_last +msgid "Last Action" +msgstr "Última acción" + +#. module: crm_phonecall +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall2phonecall___last_update +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall___last_update +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall_report___last_update +msgid "Last Modified on" +msgstr "" + +#. module: crm_phonecall +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall2phonecall_write_uid +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall_write_uid +msgid "Last Updated by" +msgstr "" + +#. module: crm_phonecall +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall2phonecall_write_date +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall_write_date +msgid "Last Updated on" +msgstr "" + +#. module: crm_phonecall +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall_opportunity_id +msgid "Lead/Opportunity" +msgstr "Iniciativa/Oportunidad" + +#. module: crm_phonecall +#: model:ir.ui.view,arch_db:crm_phonecall.phonecall_to_phonecall_view +msgid "Log Call" +msgstr "Registrar llamada" + +#. module: crm_phonecall +#: selection:crm.phonecall2phonecall,action:0 +msgid "Log a call" +msgstr "Registrar una llamada" + +#. module: crm_phonecall +#: model:ir.actions.act_window,name:crm_phonecall.crm_case_categ_phone_incoming0 +#: model:ir.ui.menu,name:crm_phonecall.menu_crm_case_phone_inbound +msgid "Logged Calls" +msgstr "Llamadas registradas" + +#. module: crm_phonecall +#: selection:crm.phonecall,priority:0 +#: selection:crm.phonecall.report,priority:0 +msgid "Low" +msgstr "Bajo" + +#. module: crm_phonecall +#: model:ir.ui.view,arch_db:crm_phonecall.crm_case_inbound_phone_tree_view +#: model:ir.ui.view,arch_db:crm_phonecall.crm_case_phone_tree_view +msgid "Meeting" +msgstr "Reunión" + +#. module: crm_phonecall +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall_partner_mobile +msgid "Mobile" +msgstr "Móvil" + +#. module: crm_phonecall +#: model:ir.ui.view,arch_db:crm_phonecall.view_crm_case_phonecalls_filter +msgid "Month" +msgstr "Mes" + +#. module: crm_phonecall +#: model:ir.ui.view,arch_db:crm_phonecall.view_report_crm_phonecall_filter +msgid "Month of call" +msgstr "Mes de la llamada" + +#. module: crm_phonecall +#: model:ir.ui.view,arch_db:crm_phonecall.view_report_crm_phonecall_filter +msgid "My Phone Calls" +msgstr "Mis llamadas" + +#. module: crm_phonecall +#: model:ir.ui.view,arch_db:crm_phonecall.view_crm_case_phonecalls_filter +msgid "My Phonecalls" +msgstr "Mis llamadas" + +#. module: crm_phonecall +#: model:ir.ui.view,arch_db:crm_phonecall.view_report_crm_phonecall_filter +msgid "My Sales Team(s)" +msgstr "Mis equipos de venta" + +#. module: crm_phonecall +#: model:ir.ui.view,arch_db:crm_phonecall.view_crm_case_phonecalls_filter +msgid "My Team" +msgstr "Mi equipo" + +#. module: crm_phonecall +#: model:ir.ui.view,arch_db:crm_phonecall.view_crm_case_phonecalls_filter +msgid "New Mail" +msgstr "Nuevo correo" + +#. module: crm_phonecall +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall_date_action_next +msgid "Next Action" +msgstr "Siguiente acción" + +#. module: crm_phonecall +#: selection:crm.phonecall,priority:0 +#: selection:crm.phonecall.report,priority:0 +msgid "Normal" +msgstr "Normal" + +#. module: crm_phonecall +#: model:ir.ui.view,arch_db:crm_phonecall.view_report_crm_phonecall_filter +msgid "Not Held" +msgstr "Pendiente" + +#. module: crm_phonecall +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall2phonecall_note +msgid "Note" +msgstr "Nota" + +#. module: crm_phonecall +#: model:ir.model.fields,help:crm_phonecall.field_crm_phonecall_report_delay_close +msgid "Number of Days to close the case" +msgstr "Número de días para cerrar el caso" + +#. module: crm_phonecall +#: model:ir.model.fields,help:crm_phonecall.field_crm_phonecall_report_delay_open +msgid "Number of Days to open the case" +msgstr "Número de días para abrir el caso" + +#. module: crm_phonecall +#: model:ir.actions.act_window,help:crm_phonecall.crm_case_categ_phone_outgoing0 +msgid "" +"Odoo allows you to easily define all the calls to be done\n" +" by your sales team and follow up based on their summary." +msgstr "" +"Odoo le permite definir fácilmente las llamadas a ser realizadas\n" +" por su equipo de ventas y seguirlas basadas en su resumen." + +#. module: crm_phonecall +#: model:ir.actions.act_window,help:crm_phonecall.crm_case_categ_phone_incoming0 +msgid "" +"Odoo allows you to log inbound calls on the fly to track the\n" +" history of the communication with a customer or to inform another\n" +" team member." +msgstr "" +"Odoo le permite registrar las llamadas entrantes sobre la marcha\n" +" para mantener el histórico de comunicación con un cliente o\n" +" informar a otro miembro del equipo." + +#. module: crm_phonecall +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall_date_open +msgid "Opened" +msgstr "Abierto" + +#. module: crm_phonecall +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall_report_opening_date +msgid "Opening date" +msgstr "Fecha de apertura" + +#. module: crm_phonecall +#: model:ir.model,name:crm_phonecall.model_res_partner +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall2phonecall_partner_id +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall_report_partner_id +#: model:ir.ui.view,arch_db:crm_phonecall.view_crm_case_phonecalls_filter +msgid "Partner" +msgstr "Cliente" + +#. module: crm_phonecall +#: selection:crm.phonecall,state:0 selection:crm.phonecall.report,state:0 +msgid "Pending" +msgstr "Pendiente" + +#. module: crm_phonecall +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall2phonecall_phone +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall_partner_phone +#: model:ir.ui.view,arch_db:crm_phonecall.crm_case_phone_form_view +msgid "Phone" +msgstr "Teléfono" + +#. module: crm_phonecall +#: code:addons/crm_phonecall/models/crm_phonecall.py:193 +#: model:ir.ui.view,arch_db:crm_phonecall.crm_case_phone_form_view +#, python-format +msgid "Phone Call" +msgstr "Llamada" + +#. module: crm_phonecall +#: model:ir.actions.act_window,name:crm_phonecall.crm_case_categ_phone0 +#: model:ir.ui.menu,name:crm_phonecall.menu_crm_case_phone +#: model:ir.ui.menu,name:crm_phonecall.menu_crm_config_phonecall +#: model:ir.ui.view,arch_db:crm_phonecall.crm_case_inbound_phone_tree_view +#: model:ir.ui.view,arch_db:crm_phonecall.crm_case_phone_calendar_view +#: model:ir.ui.view,arch_db:crm_phonecall.crm_case_phone_tree_view +msgid "Phone Calls" +msgstr "Llamadas" + +#. module: crm_phonecall +#: model:ir.actions.act_window,name:crm_phonecall.crm_phonecall_report_action +#: model:ir.actions.act_window,name:crm_phonecall.crm_phonecall_report_action_team +#: model:ir.ui.menu,name:crm_phonecall.menu_report_crm_phonecalls_tree +msgid "Phone Calls Analysis" +msgstr "Análisis de llamadas" + +#. module: crm_phonecall +#: model:ir.filters,name:crm_phonecall.filter_crm_phonecall_phone_call_to_do +msgid "Phone Calls To Do" +msgstr "Llamadas por hacer" + +#. module: crm_phonecall +#: model:ir.ui.view,arch_db:crm_phonecall.view_report_crm_phonecall_filter +msgid "Phone Calls that are assigned to me" +msgstr "Llamadas que están asignadas a mí" + +#. module: crm_phonecall +#: model:ir.ui.view,arch_db:crm_phonecall.view_report_crm_phonecall_graph +#: model:ir.ui.view,arch_db:crm_phonecall.view_report_crm_phonecall_pivot +msgid "Phone calls" +msgstr "Llamadas" + +#. module: crm_phonecall +#: model:ir.model,name:crm_phonecall.model_crm_phonecall_report +msgid "Phone calls by user" +msgstr "Llamadas por usuario" + +#. module: crm_phonecall +#: model:ir.ui.view,arch_db:crm_phonecall.view_report_crm_phonecall_filter +msgid "Phone calls that are assigned to one of the sale teams I manage" +msgstr "" +"Las llamadas de teléfono están asignadas a uno de los equipos que yo " +"gestiono." + +#. module: crm_phonecall +#: model:ir.ui.view,arch_db:crm_phonecall.view_report_crm_phonecall_filter +msgid "Phone calls which are in closed state" +msgstr "Llamadas en estado cerrado" + +#. module: crm_phonecall +#: model:ir.ui.view,arch_db:crm_phonecall.view_report_crm_phonecall_filter +msgid "Phone calls which are in draft and open state" +msgstr "Llamadas que están en estado borrador o abierto" + +#. module: crm_phonecall +#: model:ir.ui.view,arch_db:crm_phonecall.view_report_crm_phonecall_filter +msgid "Phone calls which are in pending state" +msgstr "Llamadas con estado pendiente" + +#. module: crm_phonecall +#: model:ir.model,name:crm_phonecall.model_crm_phonecall +#: model:ir.model.fields,field_description:crm_phonecall.field_calendar_event_phonecall_id +msgid "Phonecall" +msgstr "Llamada telefónica" + +#. module: crm_phonecall +#: model:ir.actions.act_window,name:crm_phonecall.crm_phonecall_categ_action +msgid "Phonecall Categories" +msgstr "Categorías de llamadas" + +#. module: crm_phonecall +#: model:ir.model,name:crm_phonecall.model_crm_phonecall2phonecall +msgid "Phonecall To Phonecall" +msgstr "Llamada telefónica a llamada telefónica" + +#. module: crm_phonecall +#: model:ir.model.fields,field_description:crm_phonecall.field_res_partner_phonecall_count +#: model:ir.model.fields,field_description:crm_phonecall.field_res_partner_phonecall_ids +#: model:ir.model.fields,field_description:crm_phonecall.field_res_users_phonecall_count +#: model:ir.model.fields,field_description:crm_phonecall.field_res_users_phonecall_ids +#: model:ir.ui.view,arch_db:crm_phonecall.view_crm_case_phonecalls_filter +msgid "Phonecalls" +msgstr "Llamadas telefónicas" + +#. module: crm_phonecall +#: model:ir.ui.view,arch_db:crm_phonecall.phonecall_to_phonecall_view +msgid "Planned Date" +msgstr "Fecha planificada" + +#. module: crm_phonecall +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall_priority +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall_report_priority +msgid "Priority" +msgstr "Prioridad" + +#. module: crm_phonecall +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall_user_id +#: model:ir.ui.view,arch_db:crm_phonecall.view_crm_case_phonecalls_filter +msgid "Responsible" +msgstr "Responsable" + +#. module: crm_phonecall +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall2phonecall_team_id +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall_team_id +#: model:ir.ui.view,arch_db:crm_phonecall.view_crm_case_phonecalls_filter +#: model:ir.ui.view,arch_db:crm_phonecall.view_report_crm_phonecall_filter +msgid "Sales Team" +msgstr "Equipo de ventas" + +#. module: crm_phonecall +#: model:ir.model.fields,help:crm_phonecall.field_crm_phonecall_team_id +msgid "Sales team to which Case belongs to." +msgstr "Equipo de ventas al qual pertenece." + +#. module: crm_phonecall +#: model:ir.ui.view,arch_db:crm_phonecall.view_report_crm_phonecall_filter +msgid "Salesperson" +msgstr "Comercial" + +#. module: crm_phonecall +#: model:ir.ui.view,arch_db:crm_phonecall.phonecall_to_phonecall_view +msgid "Schedule Call" +msgstr "Llamada planificada" + +#. module: crm_phonecall +#: model:ir.actions.act_window,name:crm_phonecall.phonecall_to_phonecall_act +#: model:ir.ui.view,arch_db:crm_phonecall.crm_case_inbound_phone_tree_view +msgid "Schedule Other Call" +msgstr "Planificar otra llamada" + +#. module: crm_phonecall +#: selection:crm.phonecall2phonecall,action:0 +msgid "Schedule a call" +msgstr "Planificar una llamada" + +#. module: crm_phonecall +#: model:ir.ui.view,arch_db:crm_phonecall.phonecall_to_phonecall_view +msgid "Schedule/Log a Call" +msgstr "Planificar/registrar una llamada" + +#. module: crm_phonecall +#: model:ir.actions.act_window,name:crm_phonecall.crm_case_categ_phone_outgoing0 +#: model:ir.ui.menu,name:crm_phonecall.menu_crm_case_phone_outbound +msgid "Scheduled Calls" +msgstr "Llamadas planificadas" + +#. module: crm_phonecall +#: model:ir.ui.view,arch_db:crm_phonecall.view_report_crm_phonecall_filter +msgid "Search" +msgstr "Buscar" + +#. module: crm_phonecall +#: model:ir.ui.view,arch_db:crm_phonecall.view_crm_case_phonecalls_filter +msgid "Search Phonecalls" +msgstr "Buscar llamadas telefónicas" + +#. module: crm_phonecall +#: model:res.groups,name:crm_phonecall.group_scheduled_calls +msgid "Show Scheduled Calls Menu" +msgstr "Mostrar el menú de llamadas programadas" + +#. module: crm_phonecall +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall_report_state +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall_state +#: model:ir.ui.view,arch_db:crm_phonecall.view_report_crm_phonecall_filter +msgid "Status" +msgstr "Estado" + +#. module: crm_phonecall +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall2phonecall_tag_ids +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall_tag_ids +msgid "Tags" +msgstr "Etiquetas" + +#. module: crm_phonecall +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall_report_team_id +msgid "Team" +msgstr "Equipo" + +#. module: crm_phonecall +#: model:ir.model.fields,help:crm_phonecall.field_crm_phonecall_state +msgid "" +"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." +msgstr "" +"El estado está establecido en Confirmado, cuando se crea un caso.\n" +"Cuando la llamada finaliza, el estado pasa a ser Retenido.\n" +"Si la llamada deja de ser aplicable, el estado pasará a ser Cancelado." + +#. module: crm_phonecall +#: model:ir.model.fields,help:crm_phonecall.field_crm_phonecall_email_from +msgid "These people will receive email." +msgstr "Estas personas recibirán un email." + +#. module: crm_phonecall +#: model:ir.ui.view,arch_db:crm_phonecall.view_crm_case_phonecalls_filter +msgid "To Do" +msgstr "Por hacer" + +#. module: crm_phonecall +#: selection:crm.phonecall.report,state:0 +#: model:ir.ui.view,arch_db:crm_phonecall.view_report_crm_phonecall_filter +msgid "Todo" +msgstr "Por hacer" + +#. module: crm_phonecall +#: model:ir.ui.view,arch_db:crm_phonecall.view_crm_case_phonecalls_filter +msgid "Unassigned" +msgstr "Sin asignar" + +#. module: crm_phonecall +#: model:ir.model.fields,field_description:crm_phonecall.field_crm_phonecall_report_user_id +msgid "User" +msgstr "Usuario" + +#. module: crm_phonecall +#: model:ir.actions.act_window,help:crm_phonecall.crm_case_categ_phone_outgoing0 +msgid "" +"You can use the import feature to massively import a new list of\n" +" prospects to qualify." +msgstr "" +"Puede usar la característica de importación para importar\n" +" masivamente una nueva lista de prospectos a calificar." diff --git a/crm_phonecall/models/__init__.py b/crm_phonecall/models/__init__.py new file mode 100644 index 00000000000..f5da41c1d14 --- /dev/null +++ b/crm_phonecall/models/__init__.py @@ -0,0 +1,7 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 Tecnativa - Vicent Cubells +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import crm_phonecall +from . import calendar +from . import res_partner diff --git a/crm_phonecall/models/calendar.py b/crm_phonecall/models/calendar.py new file mode 100644 index 00000000000..8632916b4a8 --- /dev/null +++ b/crm_phonecall/models/calendar.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2004-today OpenERP SA () +# Copyright (C) 2017 Tecnativa - Vicent Cubells +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import fields, models + + +class CalendarEvent(models.Model): + _inherit = "calendar.event" + + phonecall_id = fields.Many2one( + comodel_name='crm.phonecall', + string='Phonecall', + ) diff --git a/crm_phonecall/models/crm_phonecall.py b/crm_phonecall/models/crm_phonecall.py new file mode 100644 index 00000000000..5df8ab80d1b --- /dev/null +++ b/crm_phonecall/models/crm_phonecall.py @@ -0,0 +1,276 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2004-today OpenERP SA () +# Copyright (C) 2017 Tecnativa - Vicent Cubells +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from datetime import datetime +from odoo import api, fields, models, _ +from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT + + +class CrmPhonecall(models.Model): + """ Model for CRM phonecalls """ + _name = "crm.phonecall" + _description = "Phonecall" + _order = "id desc" + _inherit = ['mail.thread'] + + date_action_last = fields.Datetime( + string='Last Action', + readonly=True, + ) + date_action_next = fields.Datetime( + string='Next Action', + readonly=True, + ) + create_date = fields.Datetime( + string='Creation Date', + readonly=True, + ) + team_id = fields.Many2one( + comodel_name='crm.team', + string='Sales Team', + index=True, + help='Sales team to which Case belongs to.' + ) + user_id = fields.Many2one( + comodel_name='res.users', + string='Responsible', + default=lambda self: self.env.user, + ) + partner_id = fields.Many2one( + comodel_name='res.partner', + string='Contact', + ) + company_id = fields.Many2one( + comodel_name='res.company', + string='Company', + ) + description = fields.Text() + state = fields.Selection( + [('open', 'Confirmed'), + ('cancel', 'Cancelled'), + ('pending', 'Pending'), + ('done', 'Held') + ], + string='Status', + readonly=True, + track_visibility='onchange', + default='open', + 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( + string='Email', + help="These people will receive email.") + date_open = fields.Datetime( + string='Opened', + readonly=True, + ) + name = fields.Char( + string='Call Summary', + required=True, + ) + active = fields.Boolean( + required=False, + default=True, + ) + duration = fields.Float(help='Duration in minutes and seconds.') + tag_ids = fields.Many2many( + comodel_name='crm.lead.tag', + relation='crm_phonecall_tag_rel', + column1='phone_id', + column2='tag_id', + string='Tags', + ) + partner_phone = fields.Char(string='Phone') + partner_mobile = fields.Char('Mobile') + priority = fields.Selection( + selection=[ + ('0', 'Low'), + ('1', 'Normal'), + ('2', 'High') + ], + string='Priority', + default='1', + ) + date_closed = fields.Datetime( + string='Closed', + readonly=True, + ) + date = fields.Datetime(default=fields.Datetime.now) + opportunity_id = fields.Many2one( + comodel_name='crm.lead', + string='Lead/Opportunity', + ) + + @api.onchange('partner_id') + def on_change_partner_id(self): + if self.partner_id: + self.partner_phone = self.partner_id.phone + self.partner_mobile = self.partner_id.mobile + + @api.multi + def write(self, values): + """ 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() + elif values.get('state') == 'open': + values['date_open'] = fields.datetime.now() + values['duration'] = 0.0 + return super(CrmPhonecall, self).write(values) + + @api.multi + def compute_duration(self): + for phonecall in self: + if phonecall.duration <= 0: + duration = datetime.now() - datetime.strptime( + phonecall.date, DEFAULT_SERVER_DATETIME_FORMAT) + values = {'duration': duration.seconds / 60.0} + phonecall.write(values) + return True + + @api.multi + def schedule_another_phonecall(self, schedule_time, call_summary, + user_id=False, team_id=False, + tag_ids=False, action='schedule'): + """ + action :('schedule','Schedule a call'), ('log','Log a call') + """ + phonecall_dict = {} + for call in self: + if not team_id: + team_id = call.team_id.id or False + if not user_id: + user_id = call.user_id.id or False + if not schedule_time: + schedule_time = call.date + values = { + 'name': call_summary, + 'user_id': user_id or False, + 'description': call.description or False, + 'date': schedule_time, + 'team_id': team_id or False, + 'partner_id': call.partner_id.id or False, + 'partner_phone': call.partner_phone, + 'partner_mobile': call.partner_mobile, + 'priority': call.priority, + 'opportunity_id': call.opportunity_id.id or False, + } + if tag_ids: + values.update({'tag_ids': [(6, 0, [tag_ids])]}) + new_id = self.create(values) + if action == 'log': + call.write({'state': 'done'}) + phonecall_dict[call.id] = new_id + return phonecall_dict + + @api.onchange('opportunity_id') + def on_change_opportunity(self): + if self.opportunity_id: + self.team_id = self.opportunity_id.team_id.id + self.partner_phone = self.opportunity_id.phone + self.partner_mobile = self.opportunity_id.mobile + self.partner_id = self.opportunity_id.partner_id.id + self.tag_ids = self.opportunity_id.tag_ids.ids + + @api.multi + def redirect_phonecall_view(self): + model_data = self.env['ir.model.data'] + # Select the view + tree_view = model_data.get_object_reference( + 'crm_phonecall', 'crm_case_phone_tree_view') + form_view = model_data.get_object_reference( + 'crm_phonecall', 'crm_case_phone_form_view') + search_view = model_data.get_object_reference( + 'crm_phonecall', 'view_crm_case_phonecalls_filter') + value = {} + for call in self: + value = { + 'name': _('Phone Call'), + 'view_type': 'form', + 'view_mode': 'tree,form', + 'res_model': 'crm.phonecall', + 'res_id': call.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 + + @api.multi + def convert_opportunity(self, opportunity_summary=False, partner_id=False, + planned_revenue=0.0, probability=0.0): + partner = self.env['res.partner'] + opportunity = self.env['crm.lead'] + opportunity_dict = {} + default_contact = False + for call in self: + if not partner_id: + partner_id = call.partner_id.id or False + if partner_id: + address_id = partner.address_get().get('contact', False) + if address_id: + default_contact = address_id.id + opportunity_id = opportunity.create({ + '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.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, + 'tag_ids': [(6, 0, call.tag_ids.ids)], + }) + vals = { + 'partner_id': partner_id, + 'opportunity_id': opportunity_id.id, + 'state': 'done', + } + call.write(vals) + opportunity_dict[call.id] = opportunity_id + return opportunity_dict + + @api.multi + def action_make_meeting(self): + """ + Open meeting's calendar view to schedule a meeting on current + phonecall. + """ + partner_ids = [ + self.env['res.users'].browse(self.env.uid).partner_id.id] + res = {} + for phonecall in self: + if phonecall.partner_id and phonecall.partner_id.email: + partner_ids.append(phonecall.partner_id.id) + res = self.env['ir.actions.act_window'].for_xml_id( + 'calendar', 'action_calendar_event') + res['context'] = { + 'default_phonecall_id': phonecall.id, + 'default_partner_ids': partner_ids, + 'default_user_id': self.env.uid, + 'default_email_from': phonecall.email_from, + 'default_name': phonecall.name, + } + return res + + @api.multi + def action_button_convert2opportunity(self): + """ + Convert a phonecall into an opp and then redirect to the opp view. + """ + opportunity_dict = {} + for call in self: + opportunity_dict = call.convert_opportunity() + return opportunity_dict[call.id].redirect_opportunity_view() + return opportunity_dict diff --git a/crm_phonecall/models/res_partner.py b/crm_phonecall/models/res_partner.py new file mode 100644 index 00000000000..c91d90ec01e --- /dev/null +++ b/crm_phonecall/models/res_partner.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2004-today OpenERP SA () +# Copyright (C) 2017 Tecnativa - Vicent Cubells +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import api, fields, models + + +class ResPartner(models.Model): + _inherit = "res.partner" + + phonecall_ids = fields.One2many( + comodel_name='crm.phonecall', + inverse_name='partner_id', + string='Phonecalls', + ) + phonecall_count = fields.Integer( + compute='_compute_phonecall_count', + string="Phonecalls", + ) + + @api.multi + def _compute_phonecall_count(self): + for partner in self: + partner.phonecall_count = self.env[ + 'crm.phonecall'].search_count( + [('partner_id', '=', partner.id)]) diff --git a/crm_phonecall/report/__init__.py b/crm_phonecall/report/__init__.py new file mode 100644 index 00000000000..929bbda3d75 --- /dev/null +++ b/crm_phonecall/report/__init__.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- +# Copyright 2004-2010 Tiny SPRL () +# Copyright 2017 Tecnativa - Vicent Cubells +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import crm_phonecall_report diff --git a/crm_phonecall/report/crm_phonecall_report.py b/crm_phonecall/report/crm_phonecall_report.py new file mode 100644 index 00000000000..c62b4c06aef --- /dev/null +++ b/crm_phonecall/report/crm_phonecall_report.py @@ -0,0 +1,132 @@ +# -*- coding: utf-8 -*- +# Copyright 2004-2010 Tiny SPRL () +# Copyright 2017 Tecnativa - Vicent Cubells +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import tools +from odoo import api, fields, models + +AVAILABLE_STATES = [ + ('draft', 'Draft'), + ('open', 'Todo'), + ('cancel', 'Cancelled'), + ('done', 'Held'), + ('pending', 'Pending') +] + + +class CrmPhonecallReport(models.Model): + _name = "crm.phonecall.report" + _description = "Phone calls by user" + _auto = False + + user_id = fields.Many2one( + comodel_name='res.users', + string='User', + readonly=True, + ) + team_id = fields.Many2one( + comodel_name='crm.team', + string='Team', + readonly=True, + ) + priority = fields.Selection( + selection=[ + ('0', 'Low'), + ('1', 'Normal'), + ('2', 'High') + ], + string='Priority', + ) + nbr_cases = fields.Integer( + string='# of Cases', + readonly=True, + ) + state = fields.Selection( + AVAILABLE_STATES, + string='Status', + readonly=True, + ) + create_date = fields.Datetime( + string='Create Date', + readonly=True, + index=True, + ) + delay_close = fields.Float( + string='Delay to close', + digits=(16, 2), + readonly=True, + group_operator="avg", + help="Number of Days to close the case", + ) + duration = fields.Float( + string='Duration', + digits=(16, 2), + readonly=True, + group_operator="avg", + ) + delay_open = fields.Float( + string='Delay to open', + digits=(16, 2), + readonly=True, + group_operator="avg", + help="Number of Days to open the case", + ) + partner_id = fields.Many2one( + comodel_name='res.partner', + string='Partner', + readonly=True, + ) + company_id = fields.Many2one( + comodel_name='res.company', + string='Company', + readonly=True, + ) + opening_date = fields.Datetime( + readonly=True, + index=True, + ) + date_closed = fields.Datetime( + string='Close Date', + readonly=True, + index=True) + + def _select(self): + select_str = """ + select + id, + c.date_open as opening_date, + c.date_closed as date_closed, + c.state, + c.user_id, + c.team_id, + c.partner_id, + c.duration, + c.company_id, + c.priority, + 1 as nbr_cases, + 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 + """ + return select_str + + def _from(self): + from_str = """ + from crm_phonecall c + """ + return from_str + + @api.model_cr + def init(self): + + tools.drop_view_if_exists(self._cr, self._table) + self._cr.execute(""" + create or replace view %s as ( + %s + %s + )""" % (self._table, self._select(), self._from())) diff --git a/crm_phonecall/report/crm_phonecall_report_view.xml b/crm_phonecall/report/crm_phonecall_report_view.xml new file mode 100644 index 00000000000..c5d907b03a3 --- /dev/null +++ b/crm_phonecall/report/crm_phonecall_report_view.xml @@ -0,0 +1,108 @@ + + + + + crm.phonecall.report.graph + crm.phonecall.report + + + + + + + + + + + crm.phonecall.report.pivot + crm.phonecall.report + + + + + + + + + + + + By Sales Team + crm.phonecall.report + [('state','=','done')] + + {'group_by': ['team_id'], 'col_group_by': [], 'measures': ['nbr_cases', 'duration']} + + + Delay To Close + crm.phonecall.report + [('state','=','done')] + + {'group_by': ['team_id'], 'col_group_by': [], 'measures': ['delay_close']} + + + Phone Calls To Do + crm.phonecall.report + [('state','in',('draft','open'))] + + {'group_by': ['team_id'], 'measures': ['nbr_cases']} + + + + crm.phonecall.report.select + crm.phonecall.report + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Phone Calls Analysis + crm.phonecall.report + form + pivot,graph + {} + [] + + + Phone Calls Analysis + crm.phonecall.report + form + pivot,graph + {'search_default_team_id': active_id} + [] + + + + diff --git a/crm_phonecall/security/crm_security.xml b/crm_phonecall/security/crm_security.xml new file mode 100644 index 00000000000..cf05858edd5 --- /dev/null +++ b/crm_phonecall/security/crm_security.xml @@ -0,0 +1,9 @@ + + + + + Show Scheduled Calls Menu + + + + diff --git a/crm_phonecall/security/ir.model.access.csv b/crm_phonecall/security/ir.model.access.csv new file mode 100644 index 00000000000..409d841f452 --- /dev/null +++ b/crm_phonecall/security/ir.model.access.csv @@ -0,0 +1,6 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_crm_phonecall_manager,crm.phonecall.manager,model_crm_phonecall,sales_team.group_sale_manager,1,1,1,1 +access_crm_phonecall,crm.phonecall,model_crm_phonecall,sales_team.group_sale_salesman,1,1,1,0 +access_crm_phonecall_report_user,crm.phonecall.report.user,model_crm_phonecall_report,sales_team.group_sale_salesman,1,0,0,0 +access_crm_phonecall_report_manager,crm.phonecall.report,model_crm_phonecall_report,sales_team.group_sale_manager,1,1,1,1 +access_crm_phonecall_partner_manager,crm.phonecall.partner.manager,model_crm_phonecall,base.group_partner_manager,1,1,1,1 diff --git a/crm_phonecall/static/description/icon.png b/crm_phonecall/static/description/icon.png new file mode 100644 index 00000000000..3a0328b516c Binary files /dev/null and b/crm_phonecall/static/description/icon.png differ diff --git a/crm_phonecall/tests/__init__.py b/crm_phonecall/tests/__init__.py new file mode 100644 index 00000000000..515aa00930b --- /dev/null +++ b/crm_phonecall/tests/__init__.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- +# Copyright 2004-2010 Tiny SPRL () +# Copyright 2017 Tecnativa - Vicent Cubells +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import test_crm_phonecall diff --git a/crm_phonecall/tests/test_crm_phonecall.py b/crm_phonecall/tests/test_crm_phonecall.py new file mode 100644 index 00000000000..e371b4f35d9 --- /dev/null +++ b/crm_phonecall/tests/test_crm_phonecall.py @@ -0,0 +1,98 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 Tecnativa - Vicent Cubells +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo.tests import common + + +class TestCrmPhoneCall(common.SavepointCase): + @classmethod + def setUpClass(cls): + super(TestCrmPhoneCall, cls).setUpClass() + cls.company = cls.env.ref('base.main_company') + partner_obj = cls.env['res.partner'] + cls.partner1 = partner_obj.create({ + 'name': 'Partner1', + 'phone': '123 456 789', + 'mobile': '123 456 789', + 'type': 'contact', + }) + cls.partner2 = partner_obj.create({ + 'name': 'Partner2', + 'phone': '789 654 321', + 'mobile': '789 654 321', + }) + cls.phonecall1 = cls.env['crm.phonecall'].create({ + 'name': 'Call #1 for test', + 'partner_id': cls.partner1.id, + }) + cls.opportunity1 = cls.env['crm.lead'].create({ + 'name': 'Opportunity #1', + 'phone': '12345', + 'mobile': '6789', + 'partner_id': cls.partner1.id, + }) + cls.opportunity2 = cls.env['crm.lead'].create({ + 'name': 'Opportunity #2', + 'phone': '2222', + 'mobile': '3333', + 'partner_id': cls.partner2.id, + }) + cls.tag = cls.env.ref('crm.categ_oppor1') + + def test_on_change_partner(self): + self.phonecall1.partner_id = self.partner2 + self.phonecall1.on_change_partner_id() + self.assertEqual(self.phonecall1.partner_phone, self.partner2.phone) + self.assertEqual(self.phonecall1.partner_mobile, self.partner2.mobile) + + self.assertFalse(self.phonecall1.date_closed) + self.phonecall1.state = 'done' + self.assertTrue(self.phonecall1.date_closed) + self.phonecall1.state = 'open' + self.assertEqual(self.phonecall1.duration, 0.0) + + def test_schedule_another_phonecall(self): + self.phonecall2 = self.phonecall1.schedule_another_phonecall( + schedule_time=False, + call_summary='Test schedule method', + action='schedule', + tag_ids=self.tag.id, + )[self.phonecall1.id] + self.assertEqual(self.phonecall2.id, self.phonecall1.id + 1) + self.assertEqual(self.phonecall1.state, 'open') + self.phonecall3 = self.phonecall1.schedule_another_phonecall( + schedule_time='2017-12-31 00:00:00', + call_summary='Test schedule method2', + action='log', + )[self.phonecall1.id] + self.assertEqual(self.phonecall3.id, self.phonecall1.id + 2) + self.assertEqual(self.phonecall1.state, 'done') + + result = self.phonecall2.redirect_phonecall_view() + self.assertEqual(result['res_id'], self.phonecall2.id) + + def test_on_change_opportunity(self): + self.phonecall1.opportunity_id = self.opportunity1 + self.phonecall1.on_change_opportunity() + self.assertEqual( + self.phonecall1.partner_phone, self.opportunity1.phone) + + def test_convert2opportunity(self): + result = self.phonecall1.action_button_convert2opportunity() + self.assertEqual(result['res_model'], 'crm.lead') + + def test_make_meeting(self): + result = self.phonecall1.action_make_meeting() + self.assertEqual( + result['context']['default_phonecall_id'], self.phonecall1.id) + + def test_wizard(self): + model_data = self.env['ir.model.data'] + wizard = self.env['crm.phonecall2phonecall'].with_context( + active_ids=self.phonecall1.ids, active_id=self.phonecall1.id, + ).create({}) + result = wizard.action_schedule() + search_view = model_data.get_object_reference( + 'crm_phonecall', 'view_crm_case_phonecalls_filter') + self.assertEqual(result['search_view_id'], search_view[1]) diff --git a/crm_phonecall/views/crm_phonecall_view.xml b/crm_phonecall/views/crm_phonecall_view.xml new file mode 100644 index 00000000000..8aa5ba7d2aa --- /dev/null +++ b/crm_phonecall/views/crm_phonecall_view.xml @@ -0,0 +1,317 @@ + + + + + Phonecall Categories + crm.lead.tag + form + + [] + + +

+ Click to add a new category. +

+ Create specific phone call categories to better define the type of + calls tracked in the system. +

+
+
+ + + + + CRM - Phone Calls Tree + crm.phonecall + + + + + + + + + +
+
+
+

+
+
+

+
+ + + + + + + +
+ + +
+ +
+
+ + + CRM - Logged Phone Calls Tree + crm.phonecall + + + + + + + + + + + + + + + + + + +
diff --git a/crm_phonecall/wizard/__init__.py b/crm_phonecall/wizard/__init__.py new file mode 100644 index 00000000000..3e208a9eb0f --- /dev/null +++ b/crm_phonecall/wizard/__init__.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- +# Copyright 2004-2010 Tiny SPRL () +# Copyright 2017 Tecnativa - Vicent Cubells +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import crm_phonecall_to_phonecall diff --git a/crm_phonecall/wizard/crm_phonecall_to_phonecall.py b/crm_phonecall/wizard/crm_phonecall_to_phonecall.py new file mode 100644 index 00000000000..bc73e8b2547 --- /dev/null +++ b/crm_phonecall/wizard/crm_phonecall_to_phonecall.py @@ -0,0 +1,94 @@ +# -*- coding: utf-8 -*- +# Copyright 2004-2010 Tiny SPRL () +# Copyright 2017 Tecnativa - Vicent Cubells +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import api, fields, models + +import time + + +class CrmPhonecall2phonecall(models.TransientModel): + _name = 'crm.phonecall2phonecall' + _description = 'Phonecall To Phonecall' + + name = fields.Char( + string='Call summary', + required=True, + index=True, + ) + user_id = fields.Many2one( + comodel_name='res.users', + string="Assign To", + ) + contact_name = fields.Char( + string='Contact', + ) + phone = fields.Char() + tag_ids = fields.Many2many( + comodel_name='crm.lead.tag', + relation='crm_phonecall_tag_rel', + column1='phone_id', + column2='tag_id', + string='Tags', + ) + date = fields.Datetime() + team_id = fields.Many2one( + comodel_name='crm.team', + string='Sales Team' + ) + action = fields.Selection( + selection=[ + ('schedule', 'Schedule a call'), + ('log', 'Log a call') + ], + string='Action', + required=True, + ) + partner_id = fields.Many2one( + comodel_name='res.partner', + string="Partner", + ) + note = fields.Text() + + @api.multi + def action_schedule(self): + phonecall_obj = self.env['crm.phonecall'] + phonecalls = phonecall_obj.browse(self._context.get('active_ids', [])) + for this in self: + phonecalls.schedule_another_phonecall( + this.date, + this.name, + this.user_id.id, + this.team_id.id or False, + this.tag_ids.ids, + action=this.action, + ) + + return phonecalls.redirect_phonecall_view() + + @api.model + def default_get(self, fields): + """ + This function gets default values + + """ + res = super(CrmPhonecall2phonecall, self).default_get(fields) + res.update({ + 'action': 'schedule', + 'date': time.strftime('%Y-%m-%d %H:%M:%S') + }) + for phonecall in self.env['crm.phonecall'].browse( + self.env.context.get('active_id')): + if 'tag_ids' in fields: + res.update({'tag_ids': phonecall.tag_ids.ids}) + if 'user_id' in fields: + res.update({'user_id': phonecall.user_id.id}) + if 'team_id' in fields: + res.update({'team_id': phonecall.team_id.id}) + if 'partner_id' in fields: + res.update({'partner_id': phonecall.partner_id.id}) + for field in ('name', 'date'): + if field in fields: + res[field] = getattr(phonecall, field) + return res diff --git a/crm_phonecall/wizard/crm_phonecall_to_phonecall_view.xml b/crm_phonecall/wizard/crm_phonecall_to_phonecall_view.xml new file mode 100644 index 00000000000..27282c3ed6c --- /dev/null +++ b/crm_phonecall/wizard/crm_phonecall_to_phonecall_view.xml @@ -0,0 +1,35 @@ + + + + + crm.phonecall2phonecall.form + crm.phonecall2phonecall + +
+ + + + + + + + + +
+
+
+
+
+ + + Schedule Other Call + crm.phonecall2phonecall + form + form + + new + + +