From 8b2b994d88b44f1e88d5a306f0328662952de640 Mon Sep 17 00:00:00 2001
From: Valentin Vinagre Urteaga
Date: Fri, 26 Nov 2021 17:12:52 +0100
Subject: [PATCH 1/7] [ADD] crm_salesperson_planner
[UPD] Update crm_salesperson_planner.pot
[UPD] README.rst
---
crm_salesperson_planner/README.rst | 95 ++
crm_salesperson_planner/__init__.py | 5 +
crm_salesperson_planner/__manifest__.py | 27 +
.../data/crm_salesperson_planner_sequence.xml | 17 +
crm_salesperson_planner/data/ir_cron_data.xml | 15 +
.../i18n/crm_salesperson_planner.pot | 1070 ++++++++++++++++
crm_salesperson_planner/i18n/es.po | 1081 +++++++++++++++++
crm_salesperson_planner/models/__init__.py | 9 +
.../models/calendar_event.py | 54 +
crm_salesperson_planner/models/crm_lead.py | 16 +
.../models/crm_salesperson_planner_visit.py | 189 +++
..._salesperson_planner_visit_close_reason.py | 19 +
.../crm_salesperson_planner_visit_template.py | 224 ++++
crm_salesperson_planner/models/res_partner.py | 33 +
crm_salesperson_planner/readme/CONFIGURE.rst | 3 +
.../readme/CONTRIBUTORS.rst | 4 +
.../readme/DESCRIPTION.rst | 3 +
crm_salesperson_planner/readme/USAGE.rst | 6 +
.../crm_salesperson_planner_security.xml | 55 +
.../security/ir.model.access.csv | 5 +
.../static/description/icon.png | Bin 0 -> 9455 bytes
.../static/description/index.html | 443 +++++++
crm_salesperson_planner/tests/__init__.py | 5 +
.../test_crm_salesperson_planner_visit.py | 147 +++
..._crm_salesperson_planner_visit_template.py | 185 +++
crm_salesperson_planner/views/crm_lead.xml | 19 +
.../views/crm_salesperson_planner_menu.xml | 49 +
...erson_planner_visit_close_reason_views.xml | 60 +
...lesperson_planner_visit_template_views.xml | 179 +++
.../crm_salesperson_planner_visit_views.xml | 299 +++++
crm_salesperson_planner/views/res_partner.xml | 28 +
crm_salesperson_planner/wizards/__init__.py | 5 +
...crm_salesperson_planner_visit_close_wiz.py | 65 +
...lesperson_planner_visit_close_wiz_view.xml | 60 +
...lesperson_planner_visit_template_create.py | 40 +
...esperson_planner_visit_template_create.xml | 42 +
36 files changed, 4556 insertions(+)
create mode 100644 crm_salesperson_planner/README.rst
create mode 100644 crm_salesperson_planner/__init__.py
create mode 100644 crm_salesperson_planner/__manifest__.py
create mode 100644 crm_salesperson_planner/data/crm_salesperson_planner_sequence.xml
create mode 100644 crm_salesperson_planner/data/ir_cron_data.xml
create mode 100644 crm_salesperson_planner/i18n/crm_salesperson_planner.pot
create mode 100644 crm_salesperson_planner/i18n/es.po
create mode 100644 crm_salesperson_planner/models/__init__.py
create mode 100644 crm_salesperson_planner/models/calendar_event.py
create mode 100644 crm_salesperson_planner/models/crm_lead.py
create mode 100644 crm_salesperson_planner/models/crm_salesperson_planner_visit.py
create mode 100644 crm_salesperson_planner/models/crm_salesperson_planner_visit_close_reason.py
create mode 100644 crm_salesperson_planner/models/crm_salesperson_planner_visit_template.py
create mode 100644 crm_salesperson_planner/models/res_partner.py
create mode 100644 crm_salesperson_planner/readme/CONFIGURE.rst
create mode 100644 crm_salesperson_planner/readme/CONTRIBUTORS.rst
create mode 100644 crm_salesperson_planner/readme/DESCRIPTION.rst
create mode 100644 crm_salesperson_planner/readme/USAGE.rst
create mode 100644 crm_salesperson_planner/security/crm_salesperson_planner_security.xml
create mode 100644 crm_salesperson_planner/security/ir.model.access.csv
create mode 100644 crm_salesperson_planner/static/description/icon.png
create mode 100644 crm_salesperson_planner/static/description/index.html
create mode 100644 crm_salesperson_planner/tests/__init__.py
create mode 100644 crm_salesperson_planner/tests/test_crm_salesperson_planner_visit.py
create mode 100644 crm_salesperson_planner/tests/test_crm_salesperson_planner_visit_template.py
create mode 100644 crm_salesperson_planner/views/crm_lead.xml
create mode 100644 crm_salesperson_planner/views/crm_salesperson_planner_menu.xml
create mode 100644 crm_salesperson_planner/views/crm_salesperson_planner_visit_close_reason_views.xml
create mode 100644 crm_salesperson_planner/views/crm_salesperson_planner_visit_template_views.xml
create mode 100644 crm_salesperson_planner/views/crm_salesperson_planner_visit_views.xml
create mode 100644 crm_salesperson_planner/views/res_partner.xml
create mode 100644 crm_salesperson_planner/wizards/__init__.py
create mode 100644 crm_salesperson_planner/wizards/crm_salesperson_planner_visit_close_wiz.py
create mode 100644 crm_salesperson_planner/wizards/crm_salesperson_planner_visit_close_wiz_view.xml
create mode 100644 crm_salesperson_planner/wizards/crm_salesperson_planner_visit_template_create.py
create mode 100644 crm_salesperson_planner/wizards/crm_salesperson_planner_visit_template_create.xml
diff --git a/crm_salesperson_planner/README.rst b/crm_salesperson_planner/README.rst
new file mode 100644
index 00000000000..21e6f64c17e
--- /dev/null
+++ b/crm_salesperson_planner/README.rst
@@ -0,0 +1,95 @@
+=======================
+Crm Salesperson Planner
+=======================
+
+.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ !! This file is generated by oca-gen-addon-readme !!
+ !! changes will be overwritten. !!
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
+ :target: https://odoo-community.org/page/development-status
+ :alt: Beta
+.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
+ :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
+ :alt: License: AGPL-3
+.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fcrm-lightgray.png?logo=github
+ :target: https://github.com/OCA/crm/tree/13.0/crm_salesperson_planner
+ :alt: OCA/crm
+.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
+ :target: https://translation.odoo-community.org/projects/crm-13-0/crm-13-0-crm_salesperson_planner
+ :alt: Translate me on Weblate
+.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
+ :target: https://runbot.odoo-community.org/runbot/111/13.0
+ :alt: Try me on Runbot
+
+|badge1| |badge2| |badge3| |badge4| |badge5|
+
+This application allows you to track and schedule salespeople visits to your customers, allowing you to determine which opportunities are going to be dealt on each visit. Visits create an all day event in calendar, and they can be easily rescheduled.
+Visits can be automatically created from a template, in which it is possible to select the frequency of visits, as well as the start and end dates. The last visit can also be calculated by selecting the total number of repetitions.
+This module creates a cron that generates visits from templates, but an option to create them manually is available from the template form view when the template is validated.
+
+**Table of contents**
+
+.. contents::
+ :local:
+
+Configuration
+=============
+
+To configure this module, you need to:
+
+* Go to new menu **CRM > Configuration > Salesperson Planner > Close Reasons** and create a close reason for 'Cancel' and 'Incident' types.
+
+Usage
+=====
+
+Go to new menu **CRM > Salesperson Planner > My Visits or All Visits** and create a new visit.
+or
+Go to **CRM > Salesperson Planner > Visit Templates** and create a new recurring template for create periodical visits. In this case, it is necessary to select a start date. The date of the last repetition can be calculated by selection the total number of repetitions or an end date.
+There are two options available to reschedule visits that is already validated:
+* Change the date from the visit.
+* Change the date straight from the event automatically created in the calendar.
+
+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 smashing it by providing a detailed and welcomed
+`feedback `_.
+
+Do not contact contributors directly about support or help with technical issues.
+
+Credits
+=======
+
+Authors
+~~~~~~~
+
+* Sygel Technology
+
+Contributors
+~~~~~~~~~~~~
+
+* `Sygel `__:
+
+ * Valentin Vinagre
+ * Manuel Regidor
+
+Maintainers
+~~~~~~~~~~~
+
+This module is maintained by the OCA.
+
+.. image:: https://odoo-community.org/logo.png
+ :alt: Odoo Community Association
+ :target: https://odoo-community.org
+
+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.
+
+This module is part of the `OCA/crm `_ project on GitHub.
+
+You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
diff --git a/crm_salesperson_planner/__init__.py b/crm_salesperson_planner/__init__.py
new file mode 100644
index 00000000000..120d03e7590
--- /dev/null
+++ b/crm_salesperson_planner/__init__.py
@@ -0,0 +1,5 @@
+# Copyright 2021 Sygel - Valentin Vinagre
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html)
+
+from . import models
+from . import wizards
diff --git a/crm_salesperson_planner/__manifest__.py b/crm_salesperson_planner/__manifest__.py
new file mode 100644
index 00000000000..57b894682d6
--- /dev/null
+++ b/crm_salesperson_planner/__manifest__.py
@@ -0,0 +1,27 @@
+# Copyright 2021 Sygel - Valentin Vinagre
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html)
+{
+ "name": "Crm Salesperson Planner",
+ "version": "13.0.1.0.0",
+ "development_status": "Beta",
+ "category": "Customer Relationship Management",
+ "author": "Sygel Technology," "Odoo Community Association (OCA)",
+ "website": "https://github.com/OCA/crm",
+ "license": "AGPL-3",
+ "depends": ["crm", "calendar"],
+ "data": [
+ "data/crm_salesperson_planner_sequence.xml",
+ "wizards/crm_salesperson_planner_visit_close_wiz_view.xml",
+ "wizards/crm_salesperson_planner_visit_template_create.xml",
+ "views/crm_salesperson_planner_visit_views.xml",
+ "views/crm_salesperson_planner_visit_close_reason_views.xml",
+ "views/crm_salesperson_planner_visit_template_views.xml",
+ "views/crm_salesperson_planner_menu.xml",
+ "views/res_partner.xml",
+ "views/crm_lead.xml",
+ "data/ir_cron_data.xml",
+ "security/crm_salesperson_planner_security.xml",
+ "security/ir.model.access.csv",
+ ],
+ "installable": True,
+}
diff --git a/crm_salesperson_planner/data/crm_salesperson_planner_sequence.xml b/crm_salesperson_planner/data/crm_salesperson_planner_sequence.xml
new file mode 100644
index 00000000000..4c21eda4c04
--- /dev/null
+++ b/crm_salesperson_planner/data/crm_salesperson_planner_sequence.xml
@@ -0,0 +1,17 @@
+
+
+
+
+ Salesperson Planner visit Code
+ salesperson.planner.visit
+
+ SPPV/
+
+
+ Salesperson Planner visit Template Code
+ salesperson.planner.visit.template
+
+ SPPVT/
+
+
diff --git a/crm_salesperson_planner/data/ir_cron_data.xml b/crm_salesperson_planner/data/ir_cron_data.xml
new file mode 100644
index 00000000000..c9bd2385f89
--- /dev/null
+++ b/crm_salesperson_planner/data/ir_cron_data.xml
@@ -0,0 +1,15 @@
+
+
+
+
+ CRM: Create salesperson visits
+ 1
+ days
+ -1
+
+
+ model._cron_create_visits(days=7)
+ code
+
+
diff --git a/crm_salesperson_planner/i18n/crm_salesperson_planner.pot b/crm_salesperson_planner/i18n/crm_salesperson_planner.pot
new file mode 100644
index 00000000000..e552dccafa2
--- /dev/null
+++ b/crm_salesperson_planner/i18n/crm_salesperson_planner.pot
@@ -0,0 +1,1070 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * crm_salesperson_planner
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 13.0\n"
+"Report-Msgid-Bugs-To: \n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: \n"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__message_needaction
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__message_needaction
+msgid "Action Needed"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__active
+msgid "Active"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__activity_ids
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__activity_ids
+msgid "Activities"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__activity_exception_decoration
+msgid "Activity Exception Decoration"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__activity_state
+msgid "Activity State"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_form_view
+msgid "Add a description..."
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__allday
+msgid "All Day"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.ui.menu,name:crm_salesperson_planner.menu_crm_salesperson_planner_visits
+msgid "All Visits"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_wiz__allow_reschedule
+msgid "Allow Reschedule"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__message_attachment_count
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__message_attachment_count
+msgid "Attachment Count"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__is_attendee
+msgid "Attendee"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__attendee_status
+msgid "Attendee Status"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__auto_validate
+msgid "Auto Validate"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__byday
+msgid "By day"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.actions.server,name:crm_salesperson_planner.ir_cron_create_visits_ir_actions_server
+#: model:ir.cron,cron_name:crm_salesperson_planner.ir_cron_create_visits
+#: model:ir.cron,name:crm_salesperson_planner.ir_cron_create_visits
+msgid "CRM: Create salesperson visits"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model,name:crm_salesperson_planner.model_calendar_event
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__calendar_event_id
+msgid "Calendar Event"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields.selection,name:crm_salesperson_planner.selection__crm_salesperson_planner_visit_close_reason__close_type__cancel
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_close_wiz_view_form
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_form_view
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_template_create_view_form
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_template_form_view
+msgid "Cancel"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields.selection,name:crm_salesperson_planner.selection__crm_salesperson_planner_visit__state__cancel
+#: model:ir.model.fields.selection,name:crm_salesperson_planner.selection__crm_salesperson_planner_visit_template__state__cancel
+msgid "Cancelled"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_form_view
+msgid "Close Info"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.actions.act_window,name:crm_salesperson_planner.crm_salesperson_planner_visit_close_reason_action
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__close_reason_id
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_close_reason_form_view
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_close_wiz_view_form
+msgid "Close Reason"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__close_reason_image
+msgid "Close Reason Image"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__close_reason_notes
+msgid "Close Reason Notes"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.actions.act_window,name:crm_salesperson_planner.crm_salesperson_planner_visit_close_wiz_action
+#: model:ir.ui.menu,name:crm_salesperson_planner.menu_crm_config_salesperson_planner_close_reason
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_close_reason_tree_view
+msgid "Close Reasons"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__company_id
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__company_id
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_filter
+msgid "Company"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_form_view
+msgid "Confirm"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model,name:crm_salesperson_planner.model_res_partner
+msgid "Contact"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_template_create_view_form
+msgid "Create"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.actions.act_window,name:crm_salesperson_planner.crm_salesperson_planner_visit_template_create_action
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_template_create_view_form
+msgid "Create Visits"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model_terms:ir.actions.act_window,help:crm_salesperson_planner.crm_salesperson_planner_visit_template_action
+msgid "Create and plan commercial visit templates"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__create_uid
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_reason__create_uid
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_wiz__create_uid
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__create_uid
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template_create__create_uid
+msgid "Created by"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__create_date
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_reason__create_date
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_wiz__create_date
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__create_date
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template_create__create_date
+msgid "Created on"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model,name:crm_salesperson_planner.model_crm_salesperson_planner_visit_template
+msgid "Crm Salesperson Planner Visit Template"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__partner_id
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__partner_ids
+msgid "Customer"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__date
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__display_start
+msgid "Date"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__day
+msgid "Date of month"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template_create__date_to
+msgid "Date to"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_template_form_view
+msgid "Day of Month"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__description
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_reason__name
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__description
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_template_form_view
+msgid "Description"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__display_name
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_reason__display_name
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_wiz__display_name
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__display_name
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template_create__display_name
+msgid "Display Name"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__res_id
+msgid "Document ID"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__res_model_id
+msgid "Document Model"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__res_model
+msgid "Document Model Name"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields.selection,name:crm_salesperson_planner.selection__crm_salesperson_planner_visit_template__state__done
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_form_view
+msgid "Done"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields.selection,name:crm_salesperson_planner.selection__crm_salesperson_planner_visit__state__draft
+#: model:ir.model.fields.selection,name:crm_salesperson_planner.selection__crm_salesperson_planner_visit_template__state__draft
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_form_view
+msgid "Draft"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__duration
+msgid "Duration"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__stop_date
+msgid "End Date"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__stop_datetime
+msgid "End Datetime"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: code:addons/crm_salesperson_planner/models/calendar_event.py:0
+#, python-format
+msgid ""
+"Event %s is related to salesperson visit %s. Cancel it to delete this "
+"event.\n"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__display_time
+msgid "Event Time"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__message_follower_ids
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__message_follower_ids
+msgid "Followers"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__message_channel_ids
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__message_channel_ids
+msgid "Followers (Channels)"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__message_partner_ids
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__message_partner_ids
+msgid "Followers (Partners)"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__fr
+msgid "Fri"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_filter
+msgid "Future Visits"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model,name:crm_salesperson_planner.model_crm_salesperson_planner_visit_close_wiz
+msgid "Get Close Reason"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_filter
+msgid "Group By"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__id
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_reason__id
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_wiz__id
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__id
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template_create__id
+msgid "ID"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__activity_exception_icon
+msgid "Icon"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit__activity_exception_icon
+msgid "Icon to indicate an exception activity."
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit__message_needaction
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit__message_unread
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__message_needaction
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__message_unread
+msgid "If checked, new messages require your attention."
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit__message_has_error
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit__message_has_sms_error
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__message_has_error
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__message_has_sms_error
+msgid "If checked, some messages have a delivery error."
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__active
+msgid ""
+"If the active field is set to false, it will allow you to hide the event "
+"alarm information without removing it."
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_wiz__image
+msgid "Image"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields.selection,name:crm_salesperson_planner.selection__crm_salesperson_planner_visit_template__state__in-progress
+msgid "In Progress"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields.selection,name:crm_salesperson_planner.selection__crm_salesperson_planner_visit__state__incident
+#: model:ir.model.fields.selection,name:crm_salesperson_planner.selection__crm_salesperson_planner_visit_close_reason__close_type__incident
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_form_view
+msgid "Incident"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_form_view
+msgid "Internal Notes"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__message_is_follower
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__message_is_follower
+msgid "Is Follower"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__is_highlighted
+msgid "Is the Event Highlighted"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit____last_update
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_reason____last_update
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_wiz____last_update
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template____last_update
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template_create____last_update
+msgid "Last Modified on"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__write_uid
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_reason__write_uid
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_wiz__write_uid
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__write_uid
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template_create__write_uid
+msgid "Last Updated by"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__write_date
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_reason__write_date
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_wiz__write_date
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__write_date
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template_create__write_date
+msgid "Last Updated on"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__last_visit_date
+msgid "Last Visit Date"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_filter
+msgid "Late Visits"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model,name:crm_salesperson_planner.model_crm_lead
+msgid "Lead/Opportunity"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__rrule_type
+msgid "Let the event automatically repeat at that interval"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__location
+msgid "Location"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__location
+msgid "Location of Event"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__message_main_attachment_id
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__message_main_attachment_id
+msgid "Main Attachment"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_template_form_view
+msgid "Manually Create Visits"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__message_has_error
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__message_has_error
+msgid "Message Delivery error"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__message_ids
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__message_ids
+msgid "Messages"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__partner_mobile
+msgid "Mobile"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__mo
+msgid "Mon"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.ui.menu,name:crm_salesperson_planner.menu_crm_salesperson_planner_my_visits
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_filter
+msgid "My Visits"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_wiz__new_date
+msgid "New Date"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__activity_date_deadline
+msgid "Next Activity Deadline"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__activity_summary
+msgid "Next Activity Summary"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__activity_type_id
+msgid "Next Activity Type"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_wiz__notes
+msgid "Notes"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__message_needaction_counter
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__message_needaction_counter
+msgid "Number of Actions"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__visit_ids_count
+msgid "Number of Sales Person Visits"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_res_partner__salesperson_planner_visit_count
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_res_users__salesperson_planner_visit_count
+msgid "Number of Salesperson Visits"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__message_has_error_counter
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__message_has_error_counter
+msgid "Number of errors"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit__message_needaction_counter
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__message_needaction_counter
+msgid "Number of messages which requires an action"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit__message_has_error_counter
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__message_has_error_counter
+msgid "Number of messages with delivery error"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit__message_unread_counter
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__message_unread_counter
+msgid "Number of unread messages"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: code:addons/crm_salesperson_planner/models/crm_salesperson_planner_visit_template.py:0
+#, python-format
+msgid "Only one customer is allowed"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__opportunity_ids
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_form_view
+msgid "Opportunities"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__opportunity_id
+msgid "Opportunity"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__month_by
+msgid "Option"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__attendee_ids
+msgid "Participant"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_filter
+msgid "Partner"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__partner_id
+msgid "Partner-related data of the user"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__partner_phone
+msgid "Phone"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__phonecall_id
+msgid "Phonecall"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__privacy
+msgid "Privacy"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_wiz__reason_id
+msgid "Reason"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model_terms:ir.actions.act_window,help:crm_salesperson_planner.all_crm_salesperson_planner_visit_action
+msgid "Record and track all sales commercial visits."
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model_terms:ir.actions.act_window,help:crm_salesperson_planner.my_crm_salesperson_planner_visit_action
+msgid "Record and track my sales commercial visits."
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model_terms:ir.actions.act_window,help:crm_salesperson_planner.crm_salesperson_planner_visit_close_reason_action
+msgid "Record reason for close commercial visits."
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__rrule_type
+msgid "Recurrence"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__end_type
+msgid "Recurrence Termination"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__recurrency
+msgid "Recurrent"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__recurrent_id
+msgid "Recurrent ID"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__recurrent_id_date
+msgid "Recurrent ID date"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__recurrency
+msgid "Recurrent Meeting"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__rrule
+msgid "Recurrent Rule"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__alarm_ids
+msgid "Reminders"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__count
+msgid "Repeat"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__interval
+msgid "Repeat Every"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__final_date
+msgid "Repeat Until"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__interval
+msgid "Repeat every (Days/Week/Month/Year)"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__count
+msgid "Repeat x times"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_reason__require_image
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_wiz__require_image
+msgid "Require Image"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_reason__reschedule
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_wiz__reschedule
+msgid "Reschedule"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__partner_id
+msgid "Responsible"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__activity_user_id
+msgid "Responsible User"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__message_has_sms_error
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__message_has_sms_error
+msgid "SMS Delivery error"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_template_form_view
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.partner_view_crm_salesperson_planner
+msgid "Sales Visits"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model,name:crm_salesperson_planner.model_crm_salesperson_planner_visit_close_reason
+msgid "SalesPerson Planner Visit Close Reason"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__user_id
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__user_id
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_filter
+msgid "Salesperson"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.ui.menu,name:crm_salesperson_planner.menu_crm_config_salesperson_planner
+#: model:ir.ui.menu,name:crm_salesperson_planner.menu_salesperson_planner
+msgid "Salesperson Planner"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model,name:crm_salesperson_planner.model_crm_salesperson_planner_visit
+msgid "Salesperson Planner Visit"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_calendar_event__salesperson_planner_visit_ids
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__salesperson_planner_visit_ids
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_lead_crm_salesperson_planner
+msgid "Salesperson Visits"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__sa
+msgid "Sat"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_filter
+msgid "Search Visits"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_template_form_view
+msgid "Send to Draft"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__sequence
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_wiz__new_sequence
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__sequence
+msgid "Sequence"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__show_as
+msgid "Show Time as"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__start
+msgid "Start"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__start_date
+msgid "Start Date"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__start_datetime
+msgid "Start DateTime"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__start
+msgid "Start date of an event, without time for full days events"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_filter
+msgid "State"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__state
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__state
+msgid "Status"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit__activity_state
+msgid ""
+"Status based on activities\n"
+"Overdue: Due date is already passed\n"
+"Today: Activity date is today\n"
+"Planned: Future activities."
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__stop
+msgid "Stop"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__stop
+msgid "Stop date of an event, without time for full days events"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_close_wiz_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__su
+msgid "Sun"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__categ_ids
+msgid "Tags"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_template_form_view
+msgid "The"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: code:addons/crm_salesperson_planner/wizards/crm_salesperson_planner_visit_close_wiz.py:0
+#, python-format
+msgid "The close reason type haven't a function."
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: code:addons/crm_salesperson_planner/wizards/crm_salesperson_planner_visit_template_create.py:0
+#, python-format
+msgid "The date can't be earlier than today"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: code:addons/crm_salesperson_planner/models/crm_salesperson_planner_visit.py:0
+#, python-format
+msgid "The visit must be in cancelled, incident or visited state"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: code:addons/crm_salesperson_planner/models/crm_salesperson_planner_visit.py:0
+#, python-format
+msgid "The visit must be in confirmed state"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: code:addons/crm_salesperson_planner/models/crm_salesperson_planner_visit.py:0
+#: code:addons/crm_salesperson_planner/models/crm_salesperson_planner_visit.py:0
+#, python-format
+msgid "The visit must be in draft or validated state"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: code:addons/crm_salesperson_planner/models/crm_salesperson_planner_visit.py:0
+#, python-format
+msgid "The visit must be in draft state"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.constraint,message:crm_salesperson_planner.constraint_crm_salesperson_planner_visit_crm_salesperson_planner_visit_name
+msgid "The visit number must be unique!"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.constraint,message:crm_salesperson_planner.constraint_crm_salesperson_planner_visit_template_crm_salesperson_planner_visit_template_name
+msgid "The visit template number must be unique!"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__th
+msgid "Thu"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__event_tz
+msgid "Timezone"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_filter
+msgid "Today Visits"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__tu
+msgid "Tue"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_reason__close_type
+msgid "Type"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit__activity_exception_decoration
+msgid "Type of the exception activity on record."
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__message_unread
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__message_unread
+msgid "Unread Messages"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__message_unread_counter
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__message_unread_counter
+msgid "Unread Messages Counter"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_template_form_view
+msgid "Until"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit__sequence
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_wiz__new_sequence
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__sequence
+msgid "Used to order Visits in the different views"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_template_form_view
+msgid "Validate"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields.selection,name:crm_salesperson_planner.selection__crm_salesperson_planner_visit__state__confirm
+msgid "Validated"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_form_view
+msgid "Visit"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__name
+msgid "Visit Number"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__visit_template_id
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__visit_ids
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_template_form_view
+msgid "Visit Template"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__name
+msgid "Visit Template Number"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.actions.act_window,name:crm_salesperson_planner.crm_salesperson_planner_visit_template_action
+#: model:ir.ui.menu,name:crm_salesperson_planner.menu_crm_salesperson_planner_visit_template
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_template_tree_view
+msgid "Visit Templates"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_filter
+msgid "Visit by Date"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields.selection,name:crm_salesperson_planner.selection__crm_salesperson_planner_visit__state__done
+msgid "Visited"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.actions.act_window,name:crm_salesperson_planner.all_crm_salesperson_planner_visit_action
+#: model:ir.actions.act_window,name:crm_salesperson_planner.my_crm_salesperson_planner_visit_action
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_lead__crm_salesperson_planner_visit_ids
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_tree_view
+msgid "Visits"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: code:addons/crm_salesperson_planner/models/crm_salesperson_planner_visit.py:0
+#, python-format
+msgid "Visits must be in cancelled state"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_filter
+msgid "Visits that are assigned to me"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__website_message_ids
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__website_message_ids
+msgid "Website Messages"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit__website_message_ids
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__website_message_ids
+msgid "Website communication history"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__we
+msgid "Wed"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__week_list
+msgid "Weekday"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model,name:crm_salesperson_planner.model_crm_salesperson_planner_visit_template_create
+msgid "crm salesperson planner visit template create"
+msgstr ""
diff --git a/crm_salesperson_planner/i18n/es.po b/crm_salesperson_planner/i18n/es.po
new file mode 100644
index 00000000000..65062585b5d
--- /dev/null
+++ b/crm_salesperson_planner/i18n/es.po
@@ -0,0 +1,1081 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * crm_salesperson_planner
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 13.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2022-01-12 14:00+0000\n"
+"PO-Revision-Date: 2022-01-12 14:00+0000\n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: \n"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__message_needaction
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__message_needaction
+msgid "Action Needed"
+msgstr "Acción requerida"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__active
+msgid "Active"
+msgstr "Activo"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__activity_ids
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__activity_ids
+msgid "Activities"
+msgstr "Actividades"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__activity_exception_decoration
+msgid "Activity Exception Decoration"
+msgstr "Decoración de Actividad de Excepción"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__activity_state
+msgid "Activity State"
+msgstr "Estado de la Actividad"
+
+#. module: crm_salesperson_planner
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_form_view
+msgid "Add a description..."
+msgstr "Agregar descripción…"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__allday
+msgid "All Day"
+msgstr "Todo el día"
+
+#. module: crm_salesperson_planner
+#: model:ir.ui.menu,name:crm_salesperson_planner.menu_crm_salesperson_planner_visits
+msgid "All Visits"
+msgstr "Todas las visitas"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_wiz__allow_reschedule
+msgid "Allow Reschedule"
+msgstr "Permitir reprogramación"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__message_attachment_count
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__message_attachment_count
+msgid "Attachment Count"
+msgstr "Número de Adjuntos"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__is_attendee
+msgid "Attendee"
+msgstr "Asistente"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__attendee_status
+msgid "Attendee Status"
+msgstr "Estado de asistente"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__auto_validate
+msgid "Auto Validate"
+msgstr "Auto validar"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__byday
+msgid "By day"
+msgstr "Por día"
+
+#. module: crm_salesperson_planner
+#: model:ir.actions.server,name:crm_salesperson_planner.ir_cron_create_visits_ir_actions_server
+#: model:ir.cron,cron_name:crm_salesperson_planner.ir_cron_create_visits
+#: model:ir.cron,name:crm_salesperson_planner.ir_cron_create_visits
+msgid "CRM: Create salesperson visits"
+msgstr "CRM: Crear visitas comerciales"
+
+#. module: crm_salesperson_planner
+#: model:ir.model,name:crm_salesperson_planner.model_calendar_event
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__calendar_event_id
+msgid "Calendar Event"
+msgstr "Evento de calendario"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields.selection,name:crm_salesperson_planner.selection__crm_salesperson_planner_visit_close_reason__close_type__cancel
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_close_wiz_view_form
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_form_view
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_template_create_view_form
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_template_form_view
+msgid "Cancel"
+msgstr "Cancelar"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields.selection,name:crm_salesperson_planner.selection__crm_salesperson_planner_visit__state__cancel
+#: model:ir.model.fields.selection,name:crm_salesperson_planner.selection__crm_salesperson_planner_visit_template__state__cancel
+msgid "Cancelled"
+msgstr "Cancelado"
+
+#. module: crm_salesperson_planner
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_form_view
+msgid "Close Info"
+msgstr "Información de cierre"
+
+#. module: crm_salesperson_planner
+#: model:ir.actions.act_window,name:crm_salesperson_planner.crm_salesperson_planner_visit_close_reason_action
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__close_reason_id
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_close_reason_form_view
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_close_wiz_view_form
+msgid "Close Reason"
+msgstr "Motivo de cierre"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__close_reason_image
+msgid "Close Reason Image"
+msgstr "Imagen de motivo de cierre"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__close_reason_notes
+msgid "Close Reason Notes"
+msgstr "Notas de motivo de cierre"
+
+#. module: crm_salesperson_planner
+#: model:ir.actions.act_window,name:crm_salesperson_planner.crm_salesperson_planner_visit_close_wiz_action
+#: model:ir.ui.menu,name:crm_salesperson_planner.menu_crm_config_salesperson_planner_close_reason
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_close_reason_tree_view
+msgid "Close Reasons"
+msgstr "Motivos de cierre"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__company_id
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__company_id
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_filter
+msgid "Company"
+msgstr "Compañía"
+
+#. module: crm_salesperson_planner
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_form_view
+msgid "Confirm"
+msgstr "Confirmar"
+
+#. module: crm_salesperson_planner
+#: model:ir.model,name:crm_salesperson_planner.model_res_partner
+msgid "Contact"
+msgstr "Contacto"
+
+#. module: crm_salesperson_planner
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_template_create_view_form
+msgid "Create"
+msgstr "Crear"
+
+#. module: crm_salesperson_planner
+#: model:ir.actions.act_window,name:crm_salesperson_planner.crm_salesperson_planner_visit_template_create_action
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_template_create_view_form
+msgid "Create Visits"
+msgstr "Crear visitas"
+
+#. module: crm_salesperson_planner
+#: model_terms:ir.actions.act_window,help:crm_salesperson_planner.crm_salesperson_planner_visit_template_action
+msgid "Create and plan commercial visit templates"
+msgstr "Crear y planificar plantillas de visitas comerciales"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__create_uid
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_reason__create_uid
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_wiz__create_uid
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__create_uid
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template_create__create_uid
+msgid "Created by"
+msgstr "Creado por"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__create_date
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_reason__create_date
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_wiz__create_date
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__create_date
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template_create__create_date
+msgid "Created on"
+msgstr "Creado el"
+
+#. module: crm_salesperson_planner
+#: model:ir.model,name:crm_salesperson_planner.model_crm_salesperson_planner_visit_template
+msgid "Crm Salesperson Planner Visit Template"
+msgstr "Crm Salesperson Planner Visit Template"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__partner_id
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__partner_ids
+msgid "Customer"
+msgstr "Cliente"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__date
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__display_start
+msgid "Date"
+msgstr "Fecha"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__day
+msgid "Date of month"
+msgstr "Fecha del mes"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template_create__date_to
+msgid "Date to"
+msgstr "Fecha hasta"
+
+#. module: crm_salesperson_planner
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_template_form_view
+msgid "Day of Month"
+msgstr "Día del mes"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__description
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_reason__name
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__description
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_template_form_view
+msgid "Description"
+msgstr "Descripción"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__display_name
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_reason__display_name
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_wiz__display_name
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__display_name
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template_create__display_name
+msgid "Display Name"
+msgstr "Nombre mostrado"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__res_id
+msgid "Document ID"
+msgstr "ID del documento"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__res_model_id
+msgid "Document Model"
+msgstr "Modelo del documento"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__res_model
+msgid "Document Model Name"
+msgstr "Nombre del modelo del documento"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields.selection,name:crm_salesperson_planner.selection__crm_salesperson_planner_visit_template__state__done
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_form_view
+msgid "Done"
+msgstr "Hecho"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields.selection,name:crm_salesperson_planner.selection__crm_salesperson_planner_visit__state__draft
+#: model:ir.model.fields.selection,name:crm_salesperson_planner.selection__crm_salesperson_planner_visit_template__state__draft
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_form_view
+msgid "Draft"
+msgstr "Borrador"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__duration
+msgid "Duration"
+msgstr "Duración"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__stop_date
+msgid "End Date"
+msgstr "Fecha de finalización"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__stop_datetime
+msgid "End Datetime"
+msgstr "Fecha y hora de finalización"
+
+#. module: crm_salesperson_planner
+#: code:addons/crm_salesperson_planner/models/calendar_event.py:0
+#, python-format
+msgid ""
+"Event %s is related to salesperson visit %s. Cancel it to delete this "
+"event.\n"
+msgstr ""
+"El evento %s está relacionado con la visita comercial %s. Cancelela para "
+"eliminar este evento.\n"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__display_time
+msgid "Event Time"
+msgstr "Hora del evento"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__message_follower_ids
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__message_follower_ids
+msgid "Followers"
+msgstr "Seguidores"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__message_channel_ids
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__message_channel_ids
+msgid "Followers (Channels)"
+msgstr "Seguidores (Canales)"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__message_partner_ids
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__message_partner_ids
+msgid "Followers (Partners)"
+msgstr "Seguidores (Socios)"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__fr
+msgid "Fri"
+msgstr "Viernes"
+
+#. module: crm_salesperson_planner
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_filter
+msgid "Future Visits"
+msgstr "Visitas futuras"
+
+#. module: crm_salesperson_planner
+#: model:ir.model,name:crm_salesperson_planner.model_crm_salesperson_planner_visit_close_wiz
+msgid "Get Close Reason"
+msgstr "Motivo de cierre"
+
+#. module: crm_salesperson_planner
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_filter
+msgid "Group By"
+msgstr "Agrupar por"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__id
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_reason__id
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_wiz__id
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__id
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template_create__id
+msgid "ID"
+msgstr "ID"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__activity_exception_icon
+msgid "Icon"
+msgstr "Icono"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit__activity_exception_icon
+msgid "Icon to indicate an exception activity."
+msgstr "Icono para indicar una actividad de excepción."
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit__message_needaction
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit__message_unread
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__message_needaction
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__message_unread
+msgid "If checked, new messages require your attention."
+msgstr "Si está marcado, hay nuevos mensajes que requieren su atención."
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit__message_has_error
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit__message_has_sms_error
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__message_has_error
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__message_has_sms_error
+msgid "If checked, some messages have a delivery error."
+msgstr "Si se encuentra marcado, algunos mensajes tienen error de envío."
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__active
+msgid ""
+"If the active field is set to false, it will allow you to hide the event "
+"alarm information without removing it."
+msgstr ""
+"Si el campo activo es falso, le permitirá ocultar la notificación de aviso "
+"del evento sin eliminarlo."
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_wiz__image
+msgid "Image"
+msgstr "Imagen"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields.selection,name:crm_salesperson_planner.selection__crm_salesperson_planner_visit_template__state__in-progress
+msgid "In Progress"
+msgstr "En progreso"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields.selection,name:crm_salesperson_planner.selection__crm_salesperson_planner_visit__state__incident
+#: model:ir.model.fields.selection,name:crm_salesperson_planner.selection__crm_salesperson_planner_visit_close_reason__close_type__incident
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_form_view
+msgid "Incident"
+msgstr "Incidencia"
+
+#. module: crm_salesperson_planner
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_form_view
+msgid "Internal Notes"
+msgstr "Notas internas"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__message_is_follower
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__message_is_follower
+msgid "Is Follower"
+msgstr "És seguidor"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__is_highlighted
+msgid "Is the Event Highlighted"
+msgstr "Es el Evento Resaltado"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit____last_update
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_reason____last_update
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_wiz____last_update
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template____last_update
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template_create____last_update
+msgid "Last Modified on"
+msgstr "Última modificación el"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__write_uid
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_reason__write_uid
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_wiz__write_uid
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__write_uid
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template_create__write_uid
+msgid "Last Updated by"
+msgstr "Última modificación el"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__write_date
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_reason__write_date
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_wiz__write_date
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__write_date
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template_create__write_date
+msgid "Last Updated on"
+msgstr "Última modificación el"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__last_visit_date
+msgid "Last Visit Date"
+msgstr "Fecha última visita"
+
+#. module: crm_salesperson_planner
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_filter
+msgid "Late Visits"
+msgstr "Visitas tardías"
+
+#. module: crm_salesperson_planner
+#: model:ir.model,name:crm_salesperson_planner.model_crm_lead
+msgid "Lead/Opportunity"
+msgstr "Iniciativa/Oportunidad"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__rrule_type
+msgid "Let the event automatically repeat at that interval"
+msgstr "Permite que el evento se repita automáticamente en ese intervalo"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__location
+msgid "Location"
+msgstr "Ubicación"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__location
+msgid "Location of Event"
+msgstr "Ubicación del evento"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__message_main_attachment_id
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__message_main_attachment_id
+msgid "Main Attachment"
+msgstr "Adjunto principal"
+
+#. module: crm_salesperson_planner
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_template_form_view
+msgid "Manually Create Visits"
+msgstr "Creación manual de visitas"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__message_has_error
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__message_has_error
+msgid "Message Delivery error"
+msgstr "Mensaje de error de entrega"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__message_ids
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__message_ids
+msgid "Messages"
+msgstr "Mensajes"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__partner_mobile
+msgid "Mobile"
+msgstr "Móvil"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__mo
+msgid "Mon"
+msgstr "Lunes"
+
+#. module: crm_salesperson_planner
+#: model:ir.ui.menu,name:crm_salesperson_planner.menu_crm_salesperson_planner_my_visits
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_filter
+msgid "My Visits"
+msgstr "Mis visitas"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_wiz__new_date
+msgid "New Date"
+msgstr "Nueva fecha"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__activity_date_deadline
+msgid "Next Activity Deadline"
+msgstr "Siguiente plazo de actividad"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__activity_summary
+msgid "Next Activity Summary"
+msgstr "Resumen de la siguiente actividad"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__activity_type_id
+msgid "Next Activity Type"
+msgstr "Tipo de la siguiente actividad"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_wiz__notes
+msgid "Notes"
+msgstr "Notas"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__message_needaction_counter
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__message_needaction_counter
+msgid "Number of Actions"
+msgstr "Número de acciones"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__visit_ids_count
+msgid "Number of Sales Person Visits"
+msgstr "Número de visitas comerciales"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_res_partner__salesperson_planner_visit_count
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_res_users__salesperson_planner_visit_count
+msgid "Number of Salesperson Visits"
+msgstr "Número de visitas comerciales"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__message_has_error_counter
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__message_has_error_counter
+msgid "Number of errors"
+msgstr "Número de errores"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit__message_needaction_counter
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__message_needaction_counter
+msgid "Number of messages which requires an action"
+msgstr "Número de mensajes que requieren una acción"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit__message_has_error_counter
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__message_has_error_counter
+msgid "Number of messages with delivery error"
+msgstr "Número de mensajes con error de envío"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit__message_unread_counter
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__message_unread_counter
+msgid "Number of unread messages"
+msgstr "Número de mensajes no leidos"
+
+#. module: crm_salesperson_planner
+#: code:addons/crm_salesperson_planner/models/crm_salesperson_planner_visit_template.py:0
+#, python-format
+msgid "Only one customer is allowed"
+msgstr "Solo se permite un cliente"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__opportunity_ids
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_form_view
+msgid "Opportunities"
+msgstr "Oportunidades"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__opportunity_id
+msgid "Opportunity"
+msgstr "Oportunidad"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__month_by
+msgid "Option"
+msgstr "Opción"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__attendee_ids
+msgid "Participant"
+msgstr "Participante"
+
+#. module: crm_salesperson_planner
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_filter
+msgid "Partner"
+msgstr "Cliente"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__partner_id
+msgid "Partner-related data of the user"
+msgstr "Datos del usuario relativos a la empresa"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__partner_phone
+msgid "Phone"
+msgstr "Teléfono"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__phonecall_id
+#, fuzzy
+msgid "Phonecall"
+msgstr "Teléfono"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__privacy
+msgid "Privacy"
+msgstr "Privacitat"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_wiz__reason_id
+msgid "Reason"
+msgstr "Razón"
+
+#. module: crm_salesperson_planner
+#: model_terms:ir.actions.act_window,help:crm_salesperson_planner.all_crm_salesperson_planner_visit_action
+msgid "Record and track all sales commercial visits."
+msgstr "Registre y rastree todas las visitas comerciales."
+
+#. module: crm_salesperson_planner
+#: model_terms:ir.actions.act_window,help:crm_salesperson_planner.my_crm_salesperson_planner_visit_action
+msgid "Record and track my sales commercial visits."
+msgstr "Registrar y rastrear mis visitas comerciales."
+
+#. module: crm_salesperson_planner
+#: model_terms:ir.actions.act_window,help:crm_salesperson_planner.crm_salesperson_planner_visit_close_reason_action
+msgid "Record reason for close commercial visits."
+msgstr "Registrar el motivo de cierre de las visitas comerciales."
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__rrule_type
+msgid "Recurrence"
+msgstr "Recurrencia"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__end_type
+msgid "Recurrence Termination"
+msgstr "Finalizar recurrencia"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__recurrency
+msgid "Recurrent"
+msgstr "Recurrente"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__recurrent_id
+msgid "Recurrent ID"
+msgstr "ID recurrencia"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__recurrent_id_date
+msgid "Recurrent ID date"
+msgstr "Fecha ID recurrencia"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__recurrency
+msgid "Recurrent Meeting"
+msgstr "Reunión periódica"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__rrule
+msgid "Recurrent Rule"
+msgstr "Regla recurrente"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__alarm_ids
+msgid "Reminders"
+msgstr "Recordatorios"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__count
+msgid "Repeat"
+msgstr "Repetir"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__interval
+msgid "Repeat Every"
+msgstr "Repite cada"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__final_date
+msgid "Repeat Until"
+msgstr "Repetir hasta"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__interval
+msgid "Repeat every (Days/Week/Month/Year)"
+msgstr "Repetir cada (días/semana/mes/año)"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__count
+msgid "Repeat x times"
+msgstr "Repetir x veces"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_reason__require_image
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_wiz__require_image
+msgid "Require Image"
+msgstr "Requiere una imagen"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_reason__reschedule
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_wiz__reschedule
+msgid "Reschedule"
+msgstr "Reprogramar"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__partner_id
+msgid "Responsible"
+msgstr "Responsable"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__activity_user_id
+msgid "Responsible User"
+msgstr "Usuario responsable"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__message_has_sms_error
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__message_has_sms_error
+msgid "SMS Delivery error"
+msgstr "SMS de error en la entrega"
+
+#. module: crm_salesperson_planner
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_template_form_view
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.partner_view_crm_salesperson_planner
+msgid "Sales Visits"
+msgstr "Visitas de comerciales"
+
+#. module: crm_salesperson_planner
+#: model:ir.model,name:crm_salesperson_planner.model_crm_salesperson_planner_visit_close_reason
+msgid "SalesPerson Planner Visit Close Reason"
+msgstr "Crm Salesperson Planner Visit Template"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__user_id
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__user_id
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_filter
+msgid "Salesperson"
+msgstr "Comercial"
+
+#. module: crm_salesperson_planner
+#: model:ir.ui.menu,name:crm_salesperson_planner.menu_crm_config_salesperson_planner
+#: model:ir.ui.menu,name:crm_salesperson_planner.menu_salesperson_planner
+msgid "Salesperson Planner"
+msgstr "Planificador comercial"
+
+#. module: crm_salesperson_planner
+#: model:ir.model,name:crm_salesperson_planner.model_crm_salesperson_planner_visit
+msgid "Salesperson Planner Visit"
+msgstr "Planificador de visitas comerciales"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_calendar_event__salesperson_planner_visit_ids
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__salesperson_planner_visit_ids
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_lead_crm_salesperson_planner
+msgid "Salesperson Visits"
+msgstr "Visitas comerciales"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__sa
+msgid "Sat"
+msgstr "Sabado"
+
+#. module: crm_salesperson_planner
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_filter
+msgid "Search Visits"
+msgstr "Búsqueda de visitas"
+
+#. module: crm_salesperson_planner
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_template_form_view
+msgid "Send to Draft"
+msgstr "Enviar a Borrador"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__sequence
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_wiz__new_sequence
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__sequence
+msgid "Sequence"
+msgstr "Secuencia"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__show_as
+msgid "Show Time as"
+msgstr "Mostrar hora como"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__start
+msgid "Start"
+msgstr "Iniciar"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__start_date
+msgid "Start Date"
+msgstr "Fecha de inicio"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__start_datetime
+msgid "Start DateTime"
+msgstr "Fecha y hora de inicio"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__start
+msgid "Start date of an event, without time for full days events"
+msgstr "Fecha de inicio del evento, sin horas para eventos de día completo"
+
+#. module: crm_salesperson_planner
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_filter
+msgid "State"
+msgstr "Estado"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__state
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__state
+msgid "Status"
+msgstr "Estado"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit__activity_state
+msgid ""
+"Status based on activities\n"
+"Overdue: Due date is already passed\n"
+"Today: Activity date is today\n"
+"Planned: Future activities."
+msgstr ""
+"Estado basado en las actividades \n"
+"Retraso: Fecha de vencimiento ya es pasado \n"
+"Hoy: Fecha actividad es hoy \n"
+"Planificado: Actividades futuras."
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__stop
+msgid "Stop"
+msgstr "Parar"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__stop
+msgid "Stop date of an event, without time for full days events"
+msgstr "Fecha fin del evento, sin horas para eventos de día completo"
+
+#. module: crm_salesperson_planner
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_close_wiz_view_form
+msgid "Submit"
+msgstr "Enviar"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__su
+msgid "Sun"
+msgstr "Domingo"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__categ_ids
+msgid "Tags"
+msgstr "Etiquetas"
+
+#. module: crm_salesperson_planner
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_template_form_view
+msgid "The"
+msgstr "The"
+
+#. module: crm_salesperson_planner
+#: code:addons/crm_salesperson_planner/wizards/crm_salesperson_planner_visit_close_wiz.py:0
+#, python-format
+msgid "The close reason type haven't a function."
+msgstr "El tipo de motivo de cierre no tiene una función."
+
+#. module: crm_salesperson_planner
+#: code:addons/crm_salesperson_planner/wizards/crm_salesperson_planner_visit_template_create.py:0
+#, python-format
+msgid "The date can't be earlier than today"
+msgstr "La fecha no puede ser anterior a hoy"
+
+#. module: crm_salesperson_planner
+#: code:addons/crm_salesperson_planner/models/crm_salesperson_planner_visit.py:0
+#, python-format
+msgid "The visit must be in cancelled, incident or visited state"
+msgstr "La visita debe estar en estado cancelado, incidente o visitado"
+
+#. module: crm_salesperson_planner
+#: code:addons/crm_salesperson_planner/models/crm_salesperson_planner_visit.py:0
+#, python-format
+msgid "The visit must be in confirmed state"
+msgstr "La visita debe estar en estado confirmado"
+
+#. module: crm_salesperson_planner
+#: code:addons/crm_salesperson_planner/models/crm_salesperson_planner_visit.py:0
+#, python-format
+msgid "The visit must be in draft or validated state"
+msgstr "La visita debe estar en estado borrador o validado"
+
+#. module: crm_salesperson_planner
+#: code:addons/crm_salesperson_planner/models/crm_salesperson_planner_visit.py:0
+#, python-format
+msgid "The visit must be in draft state"
+msgstr "La visita debe estar en estado de borrador"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.constraint,message:crm_salesperson_planner.constraint_crm_salesperson_planner_visit_crm_salesperson_planner_visit_name
+msgid "The visit number must be unique!"
+msgstr "¡El número de visita debe ser único!"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.constraint,message:crm_salesperson_planner.constraint_crm_salesperson_planner_visit_template_crm_salesperson_planner_visit_template_name
+msgid "The visit template number must be unique!"
+msgstr "¡El número de plantilla de visita debe ser único!"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__th
+msgid "Thu"
+msgstr "Jueves"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__event_tz
+msgid "Timezone"
+msgstr "Zona horaria"
+
+#. module: crm_salesperson_planner
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_filter
+msgid "Today Visits"
+msgstr "Visitas de hoy"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__tu
+msgid "Tue"
+msgstr "Martes"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_reason__close_type
+msgid "Type"
+msgstr "Tipo"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit__activity_exception_decoration
+msgid "Type of the exception activity on record."
+msgstr "Tipo de la actividad de excepción registrada."
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__message_unread
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__message_unread
+msgid "Unread Messages"
+msgstr "Número de mensajes no leídos"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__message_unread_counter
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__message_unread_counter
+msgid "Unread Messages Counter"
+msgstr "Nº de mensajes sin leer"
+
+#. module: crm_salesperson_planner
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_template_form_view
+msgid "Until"
+msgstr "Hasta"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit__sequence
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_wiz__new_sequence
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__sequence
+msgid "Used to order Visits in the different views"
+msgstr "Utilizado para ordenar Visitas en las diferentes vistas"
+
+#. module: crm_salesperson_planner
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_template_form_view
+msgid "Validate"
+msgstr "Validar"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields.selection,name:crm_salesperson_planner.selection__crm_salesperson_planner_visit__state__confirm
+msgid "Validated"
+msgstr "Validado"
+
+#. module: crm_salesperson_planner
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_form_view
+msgid "Visit"
+msgstr "Visita"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__name
+msgid "Visit Number"
+msgstr "Número de visita"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__visit_template_id
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__visit_ids
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_template_form_view
+msgid "Visit Template"
+msgstr "Plantilla de visita"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__name
+msgid "Visit Template Number"
+msgstr "Número de plantilla de visita"
+
+#. module: crm_salesperson_planner
+#: model:ir.actions.act_window,name:crm_salesperson_planner.crm_salesperson_planner_visit_template_action
+#: model:ir.ui.menu,name:crm_salesperson_planner.menu_crm_salesperson_planner_visit_template
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_template_tree_view
+msgid "Visit Templates"
+msgstr "Plantillas de visitas"
+
+#. module: crm_salesperson_planner
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_filter
+msgid "Visit by Date"
+msgstr "Visita por fecha"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields.selection,name:crm_salesperson_planner.selection__crm_salesperson_planner_visit__state__done
+msgid "Visited"
+msgstr "Visitado"
+
+#. module: crm_salesperson_planner
+#: model:ir.actions.act_window,name:crm_salesperson_planner.all_crm_salesperson_planner_visit_action
+#: model:ir.actions.act_window,name:crm_salesperson_planner.my_crm_salesperson_planner_visit_action
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_lead__crm_salesperson_planner_visit_ids
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_tree_view
+msgid "Visits"
+msgstr "Visitas"
+
+#. module: crm_salesperson_planner
+#: code:addons/crm_salesperson_planner/models/crm_salesperson_planner_visit.py:0
+#, fuzzy, python-format
+msgid "Visits must be in cancelled state"
+msgstr "La visita debe estar en estado cancelado"
+
+#. module: crm_salesperson_planner
+#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_filter
+msgid "Visits that are assigned to me"
+msgstr "Visitas asignadas a mi"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__website_message_ids
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__website_message_ids
+msgid "Website Messages"
+msgstr "Mensajes del sitio web"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit__website_message_ids
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__website_message_ids
+msgid "Website communication history"
+msgstr "Historial de comunicación del sitio web"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__we
+msgid "Wed"
+msgstr "Miercoles"
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__week_list
+msgid "Weekday"
+msgstr "Día de la semana"
+
+#. module: crm_salesperson_planner
+#: model:ir.model,name:crm_salesperson_planner.model_crm_salesperson_planner_visit_template_create
+msgid "crm salesperson planner visit template create"
+msgstr "crm salesperson planner visit template create"
diff --git a/crm_salesperson_planner/models/__init__.py b/crm_salesperson_planner/models/__init__.py
new file mode 100644
index 00000000000..1a34f478297
--- /dev/null
+++ b/crm_salesperson_planner/models/__init__.py
@@ -0,0 +1,9 @@
+# Copyright 2021 Sygel - Valentin Vinagre
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html)
+
+from . import crm_salesperson_planner_visit
+from . import crm_salesperson_planner_visit_template
+from . import crm_salesperson_planner_visit_close_reason
+from . import res_partner
+from . import crm_lead
+from . import calendar_event
diff --git a/crm_salesperson_planner/models/calendar_event.py b/crm_salesperson_planner/models/calendar_event.py
new file mode 100644
index 00000000000..87fdf603056
--- /dev/null
+++ b/crm_salesperson_planner/models/calendar_event.py
@@ -0,0 +1,54 @@
+# Copyright 2021 Sygel - Manuel Regidor
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html)
+
+from odoo import _, fields, models
+from odoo.exceptions import ValidationError
+
+
+class CalendarEvent(models.Model):
+ _inherit = "calendar.event"
+
+ salesperson_planner_visit_ids = fields.One2many(
+ string="Salesperson Visits",
+ comodel_name="crm.salesperson.planner.visit",
+ inverse_name="calendar_event_id",
+ )
+
+ def write(self, values):
+ if values.get("start") or values.get("user_id"):
+ salesperson_visit_events = self.filtered(
+ lambda a: a.res_model == "crm.salesperson.planner.visit"
+ )
+ if salesperson_visit_events:
+ new_vals = {}
+ if values.get("start"):
+ new_vals["date"] = values.get("start")
+ if values.get("user_id"):
+ new_vals["user_id"] = values.get("user_id")
+ user_id = self.env["res.users"].browse(values.get("user_id"))
+ if user_id:
+ partner_ids = self.partner_ids.filtered(
+ lambda a: a != self.user_id.partner_id
+ ).ids
+ partner_ids.append(user_id.partner_id.id)
+ values["partner_ids"] = [(6, 0, partner_ids)]
+ salesperson_visit_events.mapped(
+ "salesperson_planner_visit_ids"
+ ).with_context(bypass_update_event=True).write(new_vals)
+ return super(CalendarEvent, self).write(values)
+
+ def unlink(self, can_be_deleted=True):
+ if not self.env.context.get("bypass_cancel_visit"):
+ salesperson_visit_events = self.filtered(
+ lambda a: a.res_model == "crm.salesperson.planner.visit"
+ and a.salesperson_planner_visit_ids
+ )
+ if salesperson_visit_events:
+ error_msg = ""
+ for event in salesperson_visit_events:
+ error_msg += _(
+ "Event %s is related to salesperson visit %s. "
+ "Cancel it to delete this event.\n"
+ ) % (event.name, event.salesperson_planner_visit_ids[0].name)
+ raise ValidationError(error_msg)
+ return super(CalendarEvent, self).unlink(can_be_deleted)
diff --git a/crm_salesperson_planner/models/crm_lead.py b/crm_salesperson_planner/models/crm_lead.py
new file mode 100644
index 00000000000..2737e575bb5
--- /dev/null
+++ b/crm_salesperson_planner/models/crm_lead.py
@@ -0,0 +1,16 @@
+# Copyright 2021 Sygel - Valentin Vinagre
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html)
+
+from odoo import fields, models
+
+
+class CrmLead(models.Model):
+ _inherit = "crm.lead"
+
+ crm_salesperson_planner_visit_ids = fields.Many2many(
+ comodel_name="crm.salesperson.planner.visit",
+ relation="crm_salesperson_planner_visit_crm_lead_rel",
+ string="Visits",
+ copy=False,
+ domain="[('partner_id', 'child_of', partner_id)]",
+ )
diff --git a/crm_salesperson_planner/models/crm_salesperson_planner_visit.py b/crm_salesperson_planner/models/crm_salesperson_planner_visit.py
new file mode 100644
index 00000000000..97c8f61886a
--- /dev/null
+++ b/crm_salesperson_planner/models/crm_salesperson_planner_visit.py
@@ -0,0 +1,189 @@
+# Copyright 2021 Sygel - Valentin Vinagre
+# Copyright 2021 Sygel - Manuel Regidor
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html)
+
+from odoo import _, api, fields, models
+from odoo.exceptions import ValidationError
+
+
+class CrmSalespersonPlannerVisit(models.Model):
+ _name = "crm.salesperson.planner.visit"
+ _description = "Salesperson Planner Visit"
+ _order = "date desc,sequence"
+ _inherit = ["mail.thread", "mail.activity.mixin"]
+
+ name = fields.Char(
+ string="Visit Number", required=True, default="/", readonly=True, copy=False,
+ )
+ partner_id = fields.Many2one(
+ comodel_name="res.partner", string="Customer", required=True,
+ )
+ partner_phone = fields.Char(string="Phone", related="partner_id.phone")
+ partner_mobile = fields.Char(string="Mobile", related="partner_id.mobile")
+ date = fields.Date(string="Date", default=fields.Date.context_today, required=True,)
+ sequence = fields.Integer(
+ string="Sequence",
+ help="Used to order Visits in the different views",
+ default=20,
+ )
+ company_id = fields.Many2one(
+ comodel_name="res.company",
+ string="Company",
+ default=lambda self: self.env.company,
+ )
+ user_id = fields.Many2one(
+ comodel_name="res.users",
+ string="Salesperson",
+ index=True,
+ tracking=True,
+ default=lambda self: self.env.user,
+ domain=lambda self: [
+ ("groups_id", "in", self.env.ref("sales_team.group_sale_salesman").id)
+ ],
+ )
+ opportunity_ids = fields.Many2many(
+ comodel_name="crm.lead",
+ relation="crm_salesperson_planner_visit_crm_lead_rel",
+ string="Opportunities",
+ copy=False,
+ domain="[('type', '=', 'opportunity'), ('partner_id', 'child_of', partner_id)]",
+ )
+ description = fields.Html(string="Description")
+ state = fields.Selection(
+ string="Status",
+ required=True,
+ readonly=True,
+ copy=False,
+ tracking=True,
+ selection=[
+ ("draft", "Draft"),
+ ("confirm", "Validated"),
+ ("done", "Visited"),
+ ("cancel", "Cancelled"),
+ ("incident", "Incident"),
+ ],
+ default="draft",
+ )
+ close_reason_id = fields.Many2one(
+ comodel_name="crm.salesperson.planner.visit.close.reason", string="Close Reason"
+ )
+ close_reason_image = fields.Image(
+ string="Close Reason Image", max_width=1024, max_height=1024, attachment=True
+ )
+ close_reason_notes = fields.Text(string="Close Reason Notes")
+ visit_template_id = fields.Many2one(
+ comodel_name="crm.salesperson.planner.visit.template", string="Visit Template"
+ )
+ calendar_event_id = fields.Many2one(
+ comodel_name="calendar.event", string="Calendar Event"
+ )
+
+ _sql_constraints = [
+ (
+ "crm_salesperson_planner_visit_name",
+ "UNIQUE (name)",
+ "The visit number must be unique!",
+ ),
+ ]
+
+ @api.model_create_multi
+ def create(self, vals_list):
+ for vals in vals_list:
+ if vals.get("name", "/") == "/":
+ vals["name"] = self.env["ir.sequence"].next_by_code(
+ "salesperson.planner.visit"
+ )
+ return super().create(vals_list)
+
+ def action_draft(self):
+ if self.state not in ["cancel", "incident", "done"]:
+ raise ValidationError(
+ _("The visit must be in cancelled, incident or visited state")
+ )
+ if self.calendar_event_id:
+ self.calendar_event_id.with_context(bypass_cancel_visit=True).unlink()
+ self.write({"state": "draft"})
+
+ def action_confirm(self):
+ if self.filtered(lambda a: not a.state == "draft"):
+ raise ValidationError(_("The visit must be in draft state"))
+ events = self.create_calendar_event()
+ if events:
+ self.browse(events.mapped("res_id")).write({"state": "confirm"})
+
+ def action_done(self):
+ if not self.state == "confirm":
+ raise ValidationError(_("The visit must be in confirmed state"))
+ self.write({"state": "done"})
+
+ def action_cancel(self, reason_id, image=None, notes=None):
+ if self.state not in ["draft", "confirm"]:
+ raise ValidationError(_("The visit must be in draft or validated state"))
+ if self.calendar_event_id:
+ self.calendar_event_id.with_context(bypass_cancel_visit=True).unlink()
+ self.write(
+ {
+ "state": "cancel",
+ "close_reason_id": reason_id.id,
+ "close_reason_image": image,
+ "close_reason_notes": notes,
+ }
+ )
+
+ def create_calendar_event(self):
+ events = self.env["calendar.event"]
+ model_id = self.env.ref(
+ "crm_salesperson_planner.model_crm_salesperson_planner_visit"
+ ).id
+ for sel in self:
+ event_vals = {
+ "name": sel.name,
+ "partner_ids": [(6, 0, [sel.partner_id.id, sel.user_id.partner_id.id])],
+ "user_id": sel.user_id.id,
+ "start_date": sel.date,
+ "stop_date": sel.date,
+ "start": sel.date,
+ "stop": sel.date,
+ "allday": True,
+ "res_model_id": model_id,
+ "res_id": sel.id,
+ }
+ event = self.env["calendar.event"].create(event_vals)
+ if event:
+ event.activity_ids.unlink()
+ event.write({"res_model": "crm.salesperson.planner.visit"})
+ sel.write({"calendar_event_id": event.id})
+ events += event
+ return events
+
+ def action_incident(self, reason_id, image=None, notes=None):
+ if self.state not in ["draft", "confirm"]:
+ raise ValidationError(_("The visit must be in draft or validated state"))
+ self.write(
+ {
+ "state": "incident",
+ "close_reason_id": reason_id.id,
+ "close_reason_image": image,
+ "close_reason_notes": notes,
+ }
+ )
+
+ def unlink(self):
+ if any(sel.state not in ["draft", "cancel"] for sel in self):
+ raise ValidationError(_("Visits must be in cancelled state"))
+ return super(CrmSalespersonPlannerVisit, self).unlink()
+
+ def write(self, values):
+ ret_val = super(CrmSalespersonPlannerVisit, self).write(values)
+ if (values.get("date") or values.get("user_id")) and not self.env.context.get(
+ "bypass_update_event"
+ ):
+ new_vals = {}
+ for sel in self.filtered(lambda a: a.calendar_event_id):
+ if values.get("date"):
+ new_vals["start"] = values.get("date")
+ new_vals["stop"] = values.get("date")
+ if values.get("user_id"):
+ new_vals["user_id"] = values.get("user_id")
+ sel.calendar_event_id.write(new_vals)
+ return ret_val
diff --git a/crm_salesperson_planner/models/crm_salesperson_planner_visit_close_reason.py b/crm_salesperson_planner/models/crm_salesperson_planner_visit_close_reason.py
new file mode 100644
index 00000000000..a8d119ebd94
--- /dev/null
+++ b/crm_salesperson_planner/models/crm_salesperson_planner_visit_close_reason.py
@@ -0,0 +1,19 @@
+# Copyright 2021 Sygel - Valentin Vinagre
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html)
+
+from odoo import fields, models
+
+
+class CrmSalespersonPlannerVisitCloseReason(models.Model):
+ _name = "crm.salesperson.planner.visit.close.reason"
+ _description = "SalesPerson Planner Visit Close Reason"
+
+ name = fields.Char(string="Description", required=True, translate=True)
+ close_type = fields.Selection(
+ selection=[("cancel", "Cancel"), ("incident", "Incident")],
+ string="Type",
+ required=True,
+ default="cancel",
+ )
+ require_image = fields.Boolean(string="Require Image", default=False)
+ reschedule = fields.Boolean(string="Reschedule", default=False)
diff --git a/crm_salesperson_planner/models/crm_salesperson_planner_visit_template.py b/crm_salesperson_planner/models/crm_salesperson_planner_visit_template.py
new file mode 100644
index 00000000000..7ed1ebb801f
--- /dev/null
+++ b/crm_salesperson_planner/models/crm_salesperson_planner_visit_template.py
@@ -0,0 +1,224 @@
+# Copyright 2021 Sygel - Valentin Vinagre
+# Copyright 2021 Sygel - Manuel Regidor
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html)
+
+from dateutil.relativedelta import relativedelta
+
+from odoo import _, api, fields, models
+from odoo.exceptions import ValidationError
+
+
+class CrmSalespersonPlannerVisitTemplate(models.Model):
+ _name = "crm.salesperson.planner.visit.template"
+ _description = "Crm Salesperson Planner Visit Template"
+ _inherit = "calendar.event"
+
+ name = fields.Char(
+ string="Visit Template Number", default="/", readonly=True, copy=False,
+ )
+ partner_ids = fields.Many2many(
+ string="Customer",
+ relation="salesperson_planner_res_partner_rel",
+ default=False,
+ required=True,
+ )
+ sequence = fields.Integer(
+ string="Sequence",
+ help="Used to order Visits in the different views",
+ default=20,
+ )
+ company_id = fields.Many2one(
+ comodel_name="res.company",
+ string="Company",
+ default=lambda self: self.env.company,
+ )
+ user_id = fields.Many2one(
+ string="Salesperson",
+ tracking=True,
+ default=lambda self: self.env.user,
+ domain=lambda self: [
+ ("groups_id", "in", self.env.ref("sales_team.group_sale_salesman").id)
+ ],
+ )
+ categ_ids = fields.Many2many(relation="visit_category_rel",)
+ alarm_ids = fields.Many2many(relation="visit_calendar_event_rel")
+ state = fields.Selection(
+ string="Status",
+ required=True,
+ copy=False,
+ tracking=True,
+ selection=[
+ ("draft", "Draft"),
+ ("in-progress", "In Progress"),
+ ("done", "Done"),
+ ("cancel", "Cancelled"),
+ ],
+ default="draft",
+ )
+ visit_ids = fields.One2many(
+ comodel_name="crm.salesperson.planner.visit",
+ inverse_name="visit_template_id",
+ string="Visit Template",
+ )
+ visit_ids_count = fields.Integer(
+ string="Number of Sales Person Visits", compute="_compute_visit_ids_count"
+ )
+ auto_validate = fields.Boolean(string="Auto Validate", default=True)
+ rrule_type = fields.Selection(default="daily", required=True,)
+ last_visit_date = fields.Date(
+ string="Last Visit Date", compute="_compute_last_visit_date", store=True
+ )
+ final_date = fields.Date(string="Repeat Until")
+ allday = fields.Boolean(default=True)
+ recurrency = fields.Boolean(default=True)
+
+ _sql_constraints = [
+ (
+ "crm_salesperson_planner_visit_template_name",
+ "UNIQUE (name)",
+ "The visit template number must be unique!",
+ ),
+ ]
+
+ def _compute_visit_ids_count(self):
+ visit_data = self.env["crm.salesperson.planner.visit"].read_group(
+ [("visit_template_id", "in", self.ids)],
+ ["visit_template_id"],
+ ["visit_template_id"],
+ )
+ mapped_data = {
+ m["visit_template_id"][0]: m["visit_template_id_count"] for m in visit_data
+ }
+ for sel in self:
+ sel.visit_ids_count = mapped_data.get(sel.id, 0)
+
+ @api.depends("visit_ids.date")
+ def _compute_last_visit_date(self):
+ for sel in self.filtered(lambda x: x.visit_ids):
+ sel.last_visit_date = sel.visit_ids.sorted(lambda x: x.date)[-1].date
+ self.filtered(lambda x: not x.visit_ids).write({"last_visit_date": False})
+
+ # overwrite
+ # default _search method gives an error when trying to access
+ # instances of the model
+ def _search(
+ self,
+ args,
+ offset=0,
+ limit=None,
+ order=None,
+ count=False,
+ access_rights_uid=None,
+ ):
+ return super(models.Model, self)._search(args)
+
+ @api.constrains("partner_ids")
+ def _constrains_partner_ids(self):
+ for sel in self:
+ if len(sel.partner_ids) > 1:
+ raise ValidationError(_("Only one customer is allowed"))
+
+ @api.model_create_multi
+ def create(self, vals_list):
+ for vals in vals_list:
+ if vals.get("name", "/") == "/":
+ vals["name"] = self.env["ir.sequence"].next_by_code(
+ "salesperson.planner.visit.template"
+ )
+ return super().create(vals_list)
+
+ # overwrite
+ # Calling _update_cron from default write funciont is not
+ # necessary in this case
+ def write(self, vals):
+ return super(models.Model, self).write(vals)
+
+ # overwrite
+ # default unlink method gives an error when trying to access
+ # instances of the model
+ def unlink(self, can_be_deleted=True):
+ return super(models.Model, self).unlink()
+
+ def action_view_salesperson_planner_visit(self):
+ action = self.env.ref(
+ "crm_salesperson_planner.all_crm_salesperson_planner_visit_action"
+ ).read()[0]
+ action["domain"] = [("id", "=", self.visit_ids.ids)]
+ action["context"] = {
+ "default_partner_id": self.partner_id.id,
+ "default_visit_template_id": self.id,
+ "default_description": self.description,
+ }
+ return action
+
+ def action_validate(self):
+ self.write({"state": "in-progress"})
+
+ def action_cancel(self):
+ self.write({"state": "cancel"})
+
+ def action_draft(self):
+ self.write({"state": "draft"})
+
+ def filter_dates(self, recurrences, days="7"):
+ last_date = recurrences[-1].date()
+ reference_date = self.start_date
+ visit_date = fields.Datetime.from_string(reference_date)
+ last_visit_date = False
+ if not self.last_visit_date:
+ last_visit_date = visit_date
+ else:
+ last_visit_date = fields.Datetime.from_string(
+ self.last_visit_date + relativedelta(days=1)
+ )
+ max_date = fields.Date.today() + relativedelta(
+ days=days, hours=23, minutes=59, seconds=59
+ )
+ recurrences = list(
+ filter(
+ lambda a: a.replace(tzinfo=None) <= max_date
+ and a.replace(tzinfo=None) > last_visit_date,
+ recurrences,
+ )
+ )
+ return recurrences, last_date
+
+ def _create_visits(self, days=7):
+ visits_vals = []
+ for sel in self:
+ recurrences = self._get_recurrent_date_by_event()
+ days, last_date = sel.filter_dates(recurrences, days)
+ for day in days:
+ visits_vals.append(
+ {
+ "partner_id": sel.partner_ids[0].id,
+ "date": day.date(),
+ "sequence": sel.sequence,
+ "user_id": sel.user_id.id,
+ "description": sel.description,
+ "company_id": sel.company_id.id,
+ "visit_template_id": sel.id,
+ }
+ )
+ if days and days[-1].date() >= last_date:
+ sel.write({"state": "done"})
+ return visits_vals
+
+ def create_visits(self, days=7):
+ for sel in self:
+ visit_vals = sel._create_visits(days=days)
+ visits = self.env["crm.salesperson.planner.visit"].create(visit_vals)
+ if visits and sel.auto_validate:
+ visits.action_confirm()
+
+ def _cron_create_visits(self, days=7):
+ templates = self.search([("state", "=", "in-progress")])
+ templates.create_visits(days=days)
+
+ # overwrite
+ def get_recurrent_ids(self, domain, order=None):
+ return self.search([domain], order=order)
+
+ # overwrite
+ def create_attendees(self):
+ return []
diff --git a/crm_salesperson_planner/models/res_partner.py b/crm_salesperson_planner/models/res_partner.py
new file mode 100644
index 00000000000..7e8e09a77b3
--- /dev/null
+++ b/crm_salesperson_planner/models/res_partner.py
@@ -0,0 +1,33 @@
+# Copyright 2021 Sygel - Valentin Vinagre
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html)
+
+from odoo import fields, models
+
+
+class ResPartner(models.Model):
+ _inherit = "res.partner"
+
+ salesperson_planner_visit_count = fields.Integer(
+ string="Number of Salesperson Visits",
+ compute="_compute_salesperson_planner_visit_count",
+ )
+
+ def _compute_salesperson_planner_visit_count(self):
+ partners = self | self.mapped("child_ids")
+ partner_data = self.env["crm.salesperson.planner.visit"].read_group(
+ [("partner_id", "in", partners.ids)], ["partner_id"], ["partner_id"]
+ )
+ mapped_data = {m["partner_id"][0]: m["partner_id_count"] for m in partner_data}
+ for partner in self:
+ visit_count = mapped_data.get(partner.id, 0)
+ for child in partner.child_ids:
+ visit_count += mapped_data.get(child.id, 0)
+ partner.salesperson_planner_visit_count = visit_count
+
+ def action_view_salesperson_planner_visit(self):
+ action = self.env.ref(
+ "crm_salesperson_planner.all_crm_salesperson_planner_visit_action"
+ ).read()[0]
+ operator = "child_of" if self.is_company else "="
+ action["domain"] = [("partner_id", operator, self.id)]
+ return action
diff --git a/crm_salesperson_planner/readme/CONFIGURE.rst b/crm_salesperson_planner/readme/CONFIGURE.rst
new file mode 100644
index 00000000000..b21e85f5692
--- /dev/null
+++ b/crm_salesperson_planner/readme/CONFIGURE.rst
@@ -0,0 +1,3 @@
+To configure this module, you need to:
+
+* Go to new menu **CRM > Configuration > Salesperson Planner > Close Reasons** and create a close reason for 'Cancel' and 'Incident' types.
diff --git a/crm_salesperson_planner/readme/CONTRIBUTORS.rst b/crm_salesperson_planner/readme/CONTRIBUTORS.rst
new file mode 100644
index 00000000000..35f658858eb
--- /dev/null
+++ b/crm_salesperson_planner/readme/CONTRIBUTORS.rst
@@ -0,0 +1,4 @@
+* `Sygel `__:
+
+ * Valentin Vinagre
+ * Manuel Regidor
diff --git a/crm_salesperson_planner/readme/DESCRIPTION.rst b/crm_salesperson_planner/readme/DESCRIPTION.rst
new file mode 100644
index 00000000000..7f40eb8e8cc
--- /dev/null
+++ b/crm_salesperson_planner/readme/DESCRIPTION.rst
@@ -0,0 +1,3 @@
+This application allows you to track and schedule salespeople visits to your customers, allowing you to determine which opportunities are going to be dealt on each visit. Visits create an all day event in calendar, and they can be easily rescheduled.
+Visits can be automatically created from a template, in which it is possible to select the frequency of visits, as well as the start and end dates. The last visit can also be calculated by selecting the total number of repetitions.
+This module creates a cron that generates visits from templates, but an option to create them manually is available from the template form view when the template is validated.
diff --git a/crm_salesperson_planner/readme/USAGE.rst b/crm_salesperson_planner/readme/USAGE.rst
new file mode 100644
index 00000000000..cc440b32e2e
--- /dev/null
+++ b/crm_salesperson_planner/readme/USAGE.rst
@@ -0,0 +1,6 @@
+Go to new menu **CRM > Salesperson Planner > My Visits or All Visits** and create a new visit.
+or
+Go to **CRM > Salesperson Planner > Visit Templates** and create a new recurring template for create periodical visits. In this case, it is necessary to select a start date. The date of the last repetition can be calculated by selection the total number of repetitions or an end date.
+There are two options available to reschedule visits that is already validated:
+* Change the date from the visit.
+* Change the date straight from the event automatically created in the calendar.
diff --git a/crm_salesperson_planner/security/crm_salesperson_planner_security.xml b/crm_salesperson_planner/security/crm_salesperson_planner_security.xml
new file mode 100644
index 00000000000..6881e80bb30
--- /dev/null
+++ b/crm_salesperson_planner/security/crm_salesperson_planner_security.xml
@@ -0,0 +1,55 @@
+
+
+
+
+ CRM Salesperson planner visit multi-company
+
+
+ ['|', ('company_id', '=', False), ('company_id', 'in', company_ids)]
+
+
+ CRM Salesperson planner visit template multi-company
+
+
+ ['|', ('company_id', '=', False), ('company_id', 'in', company_ids)]
+
+
+ Personal Salesperson Planner Visit
+
+ ['|',('user_id','=',user.id),('user_id','=',False)]
+
+
+
+ All Salesperson Planner Visit
+
+ [(1,'=',1)]
+
+
+
+ Personal Salesperson Planner Visit Template
+
+ ['|',('user_id','=',user.id),('user_id','=',False)]
+
+
+
+ All Salesperson Planner Visit Template
+
+ [(1,'=',1)]
+
+
+
diff --git a/crm_salesperson_planner/security/ir.model.access.csv b/crm_salesperson_planner/security/ir.model.access.csv
new file mode 100644
index 00000000000..764c085ab20
--- /dev/null
+++ b/crm_salesperson_planner/security/ir.model.access.csv
@@ -0,0 +1,5 @@
+id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
+access_crm_salesperson_planner_visit_user,crm.salesperson.planner.visit.user,model_crm_salesperson_planner_visit,sales_team.group_sale_salesman,1,1,1,1
+access_crm_salesperson_planner_visit_close_reason_user,crm.salesperson.planner.visit.close.reason.user,model_crm_salesperson_planner_visit_close_reason,sales_team.group_sale_salesman,1,0,0,0
+access_crm_salesperson_planner_visit_close_reason_manager,crm.salesperson.planner.visit.close.reason.manager,model_crm_salesperson_planner_visit_close_reason,sales_team.group_sale_manager,1,1,1,1
+access_crm_salesperson_planner_visit_template_user,crm.salesperson.planner.visit.template.user,model_crm_salesperson_planner_visit_template,sales_team.group_sale_salesman,1,1,1,1
diff --git a/crm_salesperson_planner/static/description/icon.png b/crm_salesperson_planner/static/description/icon.png
new file mode 100644
index 0000000000000000000000000000000000000000..3a0328b516c4980e8e44cdb63fd945757ddd132d
GIT binary patch
literal 9455
zcmW++2RxMjAAjx~&dlBk9S+%}OXg)AGE&Cb*&}d0jUxM@u(PQx^-s)697TX`ehR4?GS^qbkof1cslKgkU)h65qZ9Oc=ml_0temigYLJfnz{IDzUf>bGs4N!v3=Z3jMq&A#7%rM5eQ#dc?k~!
zVpnB`o+K7|Al`Q_U;eD$B
zfJtP*jH`siUq~{KE)`jP2|#TUEFGRryE2`i0**z#*^6~AI|YzIWy$Cu#CSLW3q=GA
z6`?GZymC;dCPk~rBS%eCb`5OLr;RUZ;D`}um=H)BfVIq%7VhiMr)_#G0N#zrNH|__
zc+blN2UAB0=617@>_u;MPHN;P;N#YoE=)R#i$k_`UAA>WWCcEVMh~L_
zj--gtp&|K1#58Yz*AHCTMziU1Jzt_jG0I@qAOHsk$2}yTmVkBp_eHuY$A9)>P6o~I
z%aQ?!(GqeQ-Y+b0I(m9pwgi(IIZZzsbMv+9w{PFtd_<_(LA~0H(xz{=FhLB@(1&qHA5EJw1>>=%q2f&^X>IQ{!GJ4e9U
z&KlB)z(84HmNgm2hg2C0>WM{E(DdPr+EeU_N@57;PC2&DmGFW_9kP&%?X4}+xWi)(
z;)z%wI5>D4a*5XwD)P--sPkoY(a~WBw;E~AW`Yue4kFa^LM3X`8x|}ZUeMnqr}>kH
zG%WWW>3ml$Yez?i%)2pbKPI7?5o?hydokgQyZsNEr{a|mLdt;X2TX(#B1j35xPnPW
z*bMSSOauW>o;*=kO8ojw91VX!qoOQb)zHJ!odWB}d+*K?#sY_jqPdg{Sm2HdYzdEx
zOGVPhVRTGPtv0o}RfVP;Nd(|CB)I;*t&QO8h
zFfekr30S!-LHmV_Su-W+rEwYXJ^;6&3|L$mMC8*bQptyOo9;>Qb9Q9`ySe3%V$A*9
zeKEe+b0{#KWGp$F+tga)0RtI)nhMa-K@JS}2krK~n8vJ=Ngm?R!9G<~RyuU0d?nz#
z-5EK$o(!F?hmX*2Yt6+coY`6jGbb7tF#6nHA
zuKk=GGJ;ZwON1iAfG$E#Y7MnZVmrY|j0eVI(DN_MNFJmyZ|;w4tf@=CCDZ#5N_0K=
z$;R~bbk?}TpfDjfB&aiQ$VA}s?P}xPERJG{kxk5~R`iRS(SK5d+Xs9swCozZISbnS
zk!)I0>t=A<-^z(cmSFz3=jZ23u13X><0b)P)^1T_))Kr`e!-pb#q&J*Q`p+B6la%C
zuVl&0duN<;uOsB3%T9Fp8t{ED108)`y_~Hnd9AUX7h-H?jVuU|}My+C=TjH(jKz
zqMVr0re3S$H@t{zI95qa)+Crz*5Zj}Ao%4Z><+W(nOZd?gDnfNBC3>M8WE61$So|P
zVvqH0SNtDTcsUdzaMDpT=Ty0pDHHNL@Z0w$Y`XO
z2M-_r1S+GaH%pz#Uy0*w$Vdl=X=rQXEzO}d6J^R6zjM1u&c9vYLvLp?W7w(?np9x1
zE_0JSAJCPB%i7p*Wvg)pn5T`8k3-uR?*NT|J`eS#_#54p>!p(mLDvmc-3o0mX*mp_
zN*AeS<>#^-{S%W<*mz^!X$w_2dHWpcJ6^j64qFBft-o}o_Vx80o0>}Du;>kLts;$8
zC`7q$QI(dKYG`Wa8#wl@V4jVWBRGQ@1dr-hstpQL)Tl+aqVpGpbSfN>5i&QMXfiZ>
zaA?T1VGe?rpQ@;+pkrVdd{klI&jVS@I5_iz!=UMpTsa~mBga?1r}aRBm1WS;TT*s0f0lY=JBl66Upy)-k4J}lh=P^8(SXk~0xW=T9v*B|gzIhN
z>qsO7dFd~mgxAy4V?&)=5ieYq?zi?ZEoj)&2o)RLy=@hbCRcfT5jigwtQGE{L*8<@Yd{zg;CsL5mvzfDY}P-wos_6PfprFVaeqNE%h
zKZhLtcQld;ZD+>=nqN~>GvROfueSzJD&BE*}XfU|H&(FssBqY=hPCt`d
zH?@s2>I(|;fcW&YM6#V#!kUIP8$Nkdh0A(bEVj``-AAyYgwY~jB
zT|I7Bf@%;7aL7Wf4dZ%VqF$eiaC38OV6oy3Z#TER2G+fOCd9Iaoy6aLYbPTN{XRPz
z;U!V|vBf%H!}52L2gH_+j;`bTcQRXB+y9onc^wLm5wi3-Be}U>k_u>2Eg$=k!(l@I
zcCg+flakT2Nej3i0yn+g+}%NYb?ta;R?(g5SnwsQ49U8Wng8d|{B+lyRcEDvR3+`O{zfmrmvFrL6acVP%yG98X
zo&+VBg@px@i)%o?dG(`T;n*$S5*rnyiR#=wW}}GsAcfyQpE|>a{=$Hjg=-*_K;UtD
z#z-)AXwSRY?OPefw^iI+
z)AXz#PfEjlwTes|_{sB?4(O@fg0AJ^g8gP}ex9Ucf*@_^J(s_5jJV}c)s$`Myn|Kd
z$6>}#q^n{4vN@+Os$m7KV+`}c%4)4pv@06af4-x5#wj!KKb%caK{A&Y#Rfs
z-po?Dcb1({W=6FKIUirH&(yg=*6aLCekcKwyfK^JN5{wcA3nhO(o}SK#!CINhI`-I
z1)6&n7O&ZmyFMuNwvEic#IiOAwNkR=u5it{B9n2sAJV5pNhar=j5`*N!Na;c7g!l$
z3aYBqUkqqTJ=Re-;)s!EOeij=7SQZ3Hq}ZRds%IM*PtM$wV
z@;rlc*NRK7i3y5BETSKuumEN`Xu_8GP1Ri=OKQ$@I^ko8>H6)4rjiG5{VBM>B|%`&&s^)jS|-_95&yc=GqjNo{zFkw%%HHhS~e=s
zD#sfS+-?*t|J!+ozP6KvtOl!R)@@-z24}`9{QaVLD^9VCSR2b`b!KC#o;Ki<+wXB6
zx3&O0LOWcg4&rv4QG0)4yb}7BFSEg~=IR5#ZRj8kg}dS7_V&^%#Do==#`u
zpy6{ox?jWuR(;pg+f@mT>#HGWHAJRRDDDv~@(IDw&R>9643kK#HN`!1vBJHnC+RM&yIh8{gG2q
zA%e*U3|N0XSRa~oX-3EAneep)@{h2vvd3Xvy$7og(sayr@95+e6~Xvi1tUqnIxoIH
zVWo*OwYElb#uyW{Imam6f2rGbjR!Y3`#gPqkv57dB6K^wRGxc9B(t|aYDGS=m$&S!NmCtrMMaUg(c
zc2qC=2Z`EEFMW-me5B)24AqF*bV5Dr-M5ig(l-WPS%CgaPzs6p_gnCIvTJ=Y<6!gT
zVt@AfYCzjjsMEGi=rDQHo0yc;HqoRNnNFeWZgcm?f;cp(6CNylj36DoL(?TS7eU#+
z7&mfr#y))+CJOXQKUMZ7QIdS9@#-}7y2K1{8)cCt0~-X0O!O?Qx#E4Og+;A2SjalQ
zs7r?qn0H044=sDN$SRG$arw~n=+T_DNdSrarmu)V6@|?1-ZB#hRn`uilTGPJ@fqEy
zGt(f0B+^JDP&f=r{#Y_wi#AVDf-y!RIXU^0jXsFpf>=Ji*TeqSY!H~AMbJdCGLhC)
zn7Rx+sXw6uYj;WRYrLd^5IZq@6JI1C^YkgnedZEYy<&4(z%Q$5yv#Boo{AH8n$a
zhb4Y3PWdr269&?V%uI$xMcUrMzl=;w<_nm*qr=c3Rl@i5wWB;e-`t7D&c-mcQl7x!
zZWB`UGcw=Y2=}~wzrfLx=uet<;m3~=8I~ZRuzvMQUQdr+yTV|ATf1Uuomr__nDf=X
zZ3WYJtHp_ri(}SQAPjv+Y+0=fH4krOP@S&=zZ-t1jW1o@}z;xk8
z(Nz1co&El^HK^NrhVHa-_;&88vTU>_J33=%{if;BEY*J#1n59=07jrGQ#IP>@u#3A
z;!q+E1Rj3ZJ+!4bq9F8PXJ@yMgZL;>&gYA0%_Kbi8?S=XGM~dnQZQ!yBSgcZhY96H
zrWnU;k)qy`rX&&xlDyA%(a1Hhi5CWkmg(`Gb%m(HKi-7Z!LKGRP_B8@`7&hdDy5n=
z`OIxqxiVfX@OX1p(mQu>0Ai*v_cTMiw4qRt3~NBvr9oBy0)r>w3p~V0SCm=An6@3n)>@z!|o-$HvDK
z|3D2ZMJkLE5loMKl6R^ez@Zz%S$&mbeoqH5`Bb){Ei21q&VP)hWS2tjShfFtGE+$z
zzCR$P#uktu+#!w)cX!lWN1XU%K-r=s{|j?)Akf@q#3b#{6cZCuJ~gCxuMXRmI$nGtnH+-h
z+GEi!*X=AP<|fG`1>MBdTb?28JYc=fGvAi2I<$B(rs$;eoJCyR6_bc~p!XR@O-+sD
z=eH`-ye})I5ic1eL~TDmtfJ|8`0VJ*Yr=hNCd)G1p2MMz4C3^Mj?7;!w|Ly%JqmuW
zlIEW^Ft%z?*|fpXda>Jr^1noFZEwFgVV%|*XhH@acv8rdGxeEX{M$(vG{Zw+x(ei@
zmfXb22}8-?Fi`vo-YVrTH*C?a8%M=Hv9MqVH7H^J$KsD?>!SFZ;ZsvnHr_gn=7acz
z#W?0eCdVhVMWN12VV^$>WlQ?f;P^{(&pYTops|btm6aj>_Uz+hqpGwB)vWp0Cf5y<
zft8-je~nn?W11plq}N)4A{l8I7$!ks_x$PXW-2XaRFswX_BnF{R#6YIwMhAgd5F9X
zGmwdadS6(a^fjHtXg8=l?Rc0Sm%hk6E9!5cLVloEy4eh(=FwgP`)~I^5~pBEWo+F6
zSf2ncyMurJN91#cJTy_u8Y}@%!bq1RkGC~-bV@SXRd4F{R-*V`bS+6;W5vZ(&+I<9$;-V|eNfLa5n-6%
z2(}&uGRF;p92eS*sE*oR$@pexaqr*meB)VhmIg@h{uzkk$9~qh#cHhw#>O%)b@+(|
z^IQgqzuj~Sk(J;swEM-3TrJAPCq9k^^^`q{IItKBRXYe}e0Tdr=Huf7da3$l4PdpwWDop%^}n;dD#K4s#DYA8SHZ
z&1!riV4W4R7R#C))JH1~axJ)RYnM$$lIR%6fIVA@zV{XVyx}C+a-Dt8Y9M)^KU0+H
zR4IUb2CJ{Hg>CuaXtD50jB(_Tcx=Z$^WYu2u5kubqmwp%drJ6
z?Fo40g!Qd<-l=TQxqHEOuPX0;^z7iX?Ke^a%XT<13TA^5`4Xcw6D@Ur&VT&CUe0d}
z1GjOVF1^L@>O)l@?bD~$wzgf(nxX1OGD8fEV?TdJcZc2KoUe|oP1#=$$7ee|xbY)A
zDZq+cuTpc(fFdj^=!;{k03C69lMQ(|>uhRfRu%+!k&YOi-3|1QKB
z
z?n?eq1XP>p-IM$Z^C;2L3itnbJZAip*Zo0aw2bs8@(s^~*8T9go!%dHcAz2lM;`yp
zD=7&xjFV$S&5uDaiScyD?B-i1ze`+CoRtz`Wn+Zls4&}MO{@N!ufrzjG$B79)Y2d3tBk&)TxUTw@QS0TEL_?njX|@vq?Uz(nBFK5Pq7*xj#u*R&i|?7+6#
z+|r_n#SW&LXhtheZdah{ZVoqwyT{D>MC3nkFF#N)xLi{p7J1jXlmVeb;cP5?e(=f#
zuT7fvjSbjS781v?7{)-X3*?>tq?)Yd)~|1{BDS(pqC
zC}~H#WXlkUW*H5CDOo<)#x7%RY)A;ShGhI5s*#cRDA8YgqG(HeKDx+#(ZQ?386dv!
zlXCO)w91~Vw4AmOcATuV653fa9R$fyK8ul%rG
z-wfS
zihugoZyr38Im?Zuh6@RcF~t1anQu7>#lPpb#}4cOA!EM11`%f*07RqOVkmX{p~KJ9
z^zP;K#|)$`^Rb{rnHGH{~>1(fawV0*Z#)}M`m8-?ZJV<+e}s9wE#
z)l&az?w^5{)`S(%MRzxdNqrs1n*-=jS^_jqE*5XDrA0+VE`5^*p3CuM<&dZEeCjoz
zR;uu_H9ZPZV|fQq`Cyw4nscrVwi!fE6ciMmX$!_hN7uF;jjKG)d2@aC4ropY)8etW=xJvni)8eHi`H$%#zn^WJ5NLc-rqk|u&&4Z6fD_m&JfSI1Bvb?b<*n&sfl0^t
z=HnmRl`XrFvMKB%9}>PaA`m-fK6a0(8=qPkWS5bb4=v?XcWi&hRY?O5HdulRi4?fN
zlsJ*N-0Qw+Yic@s0(2uy%F@ib;GjXt01Fmx5XbRo6+n|pP(&nodMoap^z{~q
ziEeaUT@Mxe3vJSfI6?uLND(CNr=#^W<1b}jzW58bIfyWTDle$mmS(|x-0|2UlX+9k
zQ^EX7Nw}?EzVoBfT(-LT|=9N@^hcn-_p&sqG
z&*oVs2JSU+N4ZD`FhCAWaS;>|wH2G*Id|?pa#@>tyxX`+4HyIArWDvVrX)2WAOQff
z0qyHu&-S@i^MS-+j--!pr4fPBj~_8({~e1bfcl0wI1kaoN>mJL6KUPQm5N7lB(ui1
zE-o%kq)&djzWJ}ob<-GfDlkB;F31j-VHKvQUGQ3sp`CwyGJk_i!y^sD0fqC@$9|jO
zOqN!r!8-p==F@ZVP=U$qSpY(gQ0)59P1&t@y?5rvg<}E+GB}26NYPp4f2YFQrQtot5mn3wu_qprZ=>Ig-$
zbW26Ws~IgY>}^5w`vTB(G`PTZaDiGBo5o(tp)qli|NeV(
z@H_=R8V39rt5J5YB2Ky?4eJJ#b`_iBe2ot~6%7mLt5t8Vwi^Jy7|jWXqa3amOIoRb
zOr}WVFP--DsS`1WpN%~)t3R!arKF^Q$e12KEqU36AWwnCBICpH4XCsfnyrHr>$I$4
z!DpKX$OKLWarN7nv@!uIA+~RNO)l$$w}p(;b>mx8pwYvu;dD_unryX_NhT8*Tj>BTrTTL&!?O+%Rv;b?B??gSzdp?6Uug9{
zd@V08Z$BdI?fpoCS$)t4mg4rT8Q_I}h`0d-vYZ^|dOB*Q^S|xqTV*vIg?@fVFSmMpaw0qtTRbx}
z({Pg?#{2`sc9)M5N$*N|4;^t$+QP?#mov
zGVC@I*lBVrOU-%2y!7%)fAKjpEFsgQc4{amtiHb95KQEwvf<(3T<9-Zm$xIew#P22
zc2Ix|App^>v6(3L_MCU0d3W##AB0M~3D00EWoKZqsJYT(#@w$Y_H7G22M~ApVFTRHMI_3be)Lkn#0F*V8Pq
zc}`Cjy$bE;FJ6H7p=0y#R>`}-m4(0F>%@P|?7fx{=R^uFdISRnZ2W_xQhD{YuR3t<
z{6yxu=4~JkeA;|(J6_nv#>Nvs&FuLA&PW^he@t(UwFFE8)|a!R{`E`K`i^ZnyE4$k
z;(749Ix|oi$c3QbEJ3b~D_kQsPz~fIUKym($a_7dJ?o+40*OLl^{=&oq$<#Q(yyrp
z{J-FAniyAw9tPbe&IhQ|a`DqFTVQGQ&Gq3!C2==4x{6EJwiPZ8zub-iXoUtkJiG{}
zPaR&}_fn8_z~(=;5lD-aPWD3z8PZS@AaUiomF!G8I}Mf>e~0g#BelA-5#`cj;O5>N
Xviia!U7SGha1wx#SCgwmn*{w2TRX*I
literal 0
HcmV?d00001
diff --git a/crm_salesperson_planner/static/description/index.html b/crm_salesperson_planner/static/description/index.html
new file mode 100644
index 00000000000..3b53184f1ce
--- /dev/null
+++ b/crm_salesperson_planner/static/description/index.html
@@ -0,0 +1,443 @@
+
+
+
+
+
+
+Crm Salesperson Planner
+
+
+
+
+
Crm Salesperson Planner
+
+
+
+
This application allows you to track and schedule salespeople visits to your customers, allowing you to determine which opportunities are going to be dealt on each visit. Visits create an all day event in calendar, and they can be easily rescheduled.
+Visits can be automatically created from a template, in which it is possible to select the frequency of visits, as well as the start and end dates. The last visit can also be calculated by selecting the total number of repetitions.
+This module creates a cron that generates visits from templates, but an option to create them manually is available from the template form view when the template is validated.
Go to new menu CRM > Salesperson Planner > My Visits or All Visits and create a new visit.
+or
+Go to CRM > Salesperson Planner > Visit Templates and create a new recurring template for create periodical visits. In this case, it is necessary to select a start date. The date of the last repetition can be calculated by selection the total number of repetitions or an end date.
+There are two options available to reschedule visits that is already validated:
+* Change the date from the visit.
+* Change the date straight from the event automatically created in the calendar.
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 smashing it by providing a detailed and welcomed
+feedback.
+
Do not contact contributors directly about support or help with technical issues.
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.
+
This module is part of the OCA/crm project on GitHub.
+
+
+
diff --git a/crm_salesperson_planner/views/res_partner.xml b/crm_salesperson_planner/views/res_partner.xml
new file mode 100644
index 00000000000..a63ee417537
--- /dev/null
+++ b/crm_salesperson_planner/views/res_partner.xml
@@ -0,0 +1,28 @@
+
+
+
+
+ partner.view.crm.salesperson.planner
+ res.partner
+
+
+
+
+
+
+
+
diff --git a/crm_salesperson_planner/wizards/__init__.py b/crm_salesperson_planner/wizards/__init__.py
new file mode 100644
index 00000000000..1c13423b276
--- /dev/null
+++ b/crm_salesperson_planner/wizards/__init__.py
@@ -0,0 +1,5 @@
+# Copyright 2021 Sygel - Valentin Vinagre
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html)
+
+from . import crm_salesperson_planner_visit_close_wiz
+from . import crm_salesperson_planner_visit_template_create
diff --git a/crm_salesperson_planner/wizards/crm_salesperson_planner_visit_close_wiz.py b/crm_salesperson_planner/wizards/crm_salesperson_planner_visit_close_wiz.py
new file mode 100644
index 00000000000..83c3858dce5
--- /dev/null
+++ b/crm_salesperson_planner/wizards/crm_salesperson_planner_visit_close_wiz.py
@@ -0,0 +1,65 @@
+# Copyright 2021 Sygel - Valentin Vinagre
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html)
+
+from odoo import _, fields, models
+
+
+class CrmSalespersonPlannerVisitCloseWiz(models.TransientModel):
+ _name = "crm.salesperson.planner.visit.close.wiz"
+ _description = "Get Close Reason"
+
+ def _default_new_date(self):
+ visits = self.env["crm.salesperson.planner.visit"].browse(
+ self.env.context.get("active_id")
+ )
+ return visits.date
+
+ def _default_new_sequence(self):
+ visits = self.env["crm.salesperson.planner.visit"].browse(
+ self.env.context.get("active_id")
+ )
+ return visits.sequence
+
+ reason_id = fields.Many2one(
+ comodel_name="crm.salesperson.planner.visit.close.reason",
+ string="Reason",
+ required=True,
+ )
+ image = fields.Image(string="Image", max_width=1024, max_height=1024)
+ new_date = fields.Date(
+ string="New Date", default=lambda self: self._default_new_date()
+ )
+ new_sequence = fields.Integer(
+ string="Sequence",
+ help="Used to order Visits in the different views",
+ default=lambda self: self._default_new_sequence(),
+ )
+ require_image = fields.Boolean(
+ string="Require Image", related="reason_id.require_image"
+ )
+ reschedule = fields.Boolean(string="Reschedule", default=True)
+ allow_reschedule = fields.Boolean(
+ string="Allow Reschedule", related="reason_id.reschedule"
+ )
+ notes = fields.Text(string="Notes")
+
+ def action_close_reason_apply(self):
+ visits = self.env["crm.salesperson.planner.visit"].browse(
+ self.env.context.get("active_id")
+ )
+ visit_close_find_method_name = "action_%s" % self.reason_id.close_type
+ if hasattr(visits, visit_close_find_method_name):
+ getattr(visits, visit_close_find_method_name)(
+ self.reason_id, self.image, self.notes
+ )
+ if self.allow_reschedule and self.reschedule:
+ visits.copy(
+ {
+ "date": self.new_date,
+ "sequence": self.new_sequence,
+ "opportunity_ids": visits.opportunity_ids.ids,
+ }
+ ).action_confirm()
+ else:
+ raise ValueError(_("The close reason type haven't a function."))
+ return {"type": "ir.actions.act_window_close"}
diff --git a/crm_salesperson_planner/wizards/crm_salesperson_planner_visit_close_wiz_view.xml b/crm_salesperson_planner/wizards/crm_salesperson_planner_visit_close_wiz_view.xml
new file mode 100644
index 00000000000..71d4d9d8265
--- /dev/null
+++ b/crm_salesperson_planner/wizards/crm_salesperson_planner_visit_close_wiz_view.xml
@@ -0,0 +1,60 @@
+
+
+
+
+ crm.salesperson.lost.form
+ crm.salesperson.planner.visit.close.wiz
+
+
+
+
+
+ Close Reasons
+ ir.actions.act_window
+ crm.salesperson.planner.visit.close.wiz
+ form
+
+ new
+
+
diff --git a/crm_salesperson_planner/wizards/crm_salesperson_planner_visit_template_create.py b/crm_salesperson_planner/wizards/crm_salesperson_planner_visit_template_create.py
new file mode 100644
index 00000000000..ed1fd389b5c
--- /dev/null
+++ b/crm_salesperson_planner/wizards/crm_salesperson_planner_visit_template_create.py
@@ -0,0 +1,40 @@
+# Copyright 2021 Sygel - Valentin Vinagre
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html)
+
+from datetime import timedelta
+
+from odoo import _, fields, models
+from odoo.exceptions import ValidationError
+
+
+class CrmSalespersonPlannerVisitTemplateCreate(models.TransientModel):
+ _name = "crm.salesperson.planner.visit.template.create"
+ _description = "crm salesperson planner visit template create"
+
+ def _default_date_to(self):
+ template = self.env["crm.salesperson.planner.visit.template"].browse(
+ self.env.context.get("active_id")
+ )
+ date = False
+ if template and template.last_visit_date:
+ date = template.last_visit_date + timedelta(days=7)
+ else:
+ date = fields.Date.context_today(self) + timedelta(days=7)
+ return date
+
+ date_to = fields.Date(
+ string="Date to", default=lambda self: self._default_date_to(), required=True
+ )
+
+ def create_visits(self):
+ template = self.env["crm.salesperson.planner.visit.template"].browse(
+ self.env.context.get("active_id")
+ )
+ days = (self.date_to - fields.Date.context_today(self)).days
+ if days < 0:
+ raise ValidationError(_("The date can't be earlier than today"))
+ visit_vals = template._create_visits(days=days)
+ visits = self.env["crm.salesperson.planner.visit"].create(visit_vals)
+ if visits and template.auto_validate:
+ visits.action_confirm()
+ return {"type": "ir.actions.act_window_close"}
diff --git a/crm_salesperson_planner/wizards/crm_salesperson_planner_visit_template_create.xml b/crm_salesperson_planner/wizards/crm_salesperson_planner_visit_template_create.xml
new file mode 100644
index 00000000000..5f29eb654a3
--- /dev/null
+++ b/crm_salesperson_planner/wizards/crm_salesperson_planner_visit_template_create.xml
@@ -0,0 +1,42 @@
+
+
+
+
+ crm.salesperson.planner.visit.template.create.form
+ crm.salesperson.planner.visit.template.create
+
+
+
+
+
+ Create Visits
+ ir.actions.act_window
+ crm.salesperson.planner.visit.template.create
+ form
+
+ new
+
+
From ca12bee1ca8b810bde016c18210c50e2dff2792a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?V=C3=ADctor=20Mart=C3=ADnez?=
Date: Wed, 23 Nov 2022 16:03:00 +0100
Subject: [PATCH 2/7] [IMP] crm_salesperson_planner: black, isort, prettier
---
.../models/crm_salesperson_planner_visit.py | 16 +++++++++++++---
.../crm_salesperson_planner_visit_template.py | 14 +++++++++++---
2 files changed, 24 insertions(+), 6 deletions(-)
diff --git a/crm_salesperson_planner/models/crm_salesperson_planner_visit.py b/crm_salesperson_planner/models/crm_salesperson_planner_visit.py
index 97c8f61886a..c300051c4b1 100644
--- a/crm_salesperson_planner/models/crm_salesperson_planner_visit.py
+++ b/crm_salesperson_planner/models/crm_salesperson_planner_visit.py
@@ -13,14 +13,24 @@ class CrmSalespersonPlannerVisit(models.Model):
_inherit = ["mail.thread", "mail.activity.mixin"]
name = fields.Char(
- string="Visit Number", required=True, default="/", readonly=True, copy=False,
+ string="Visit Number",
+ required=True,
+ default="/",
+ readonly=True,
+ copy=False,
)
partner_id = fields.Many2one(
- comodel_name="res.partner", string="Customer", required=True,
+ comodel_name="res.partner",
+ string="Customer",
+ required=True,
)
partner_phone = fields.Char(string="Phone", related="partner_id.phone")
partner_mobile = fields.Char(string="Mobile", related="partner_id.mobile")
- date = fields.Date(string="Date", default=fields.Date.context_today, required=True,)
+ date = fields.Date(
+ string="Date",
+ default=fields.Date.context_today,
+ required=True,
+ )
sequence = fields.Integer(
string="Sequence",
help="Used to order Visits in the different views",
diff --git a/crm_salesperson_planner/models/crm_salesperson_planner_visit_template.py b/crm_salesperson_planner/models/crm_salesperson_planner_visit_template.py
index 7ed1ebb801f..b628d1186dd 100644
--- a/crm_salesperson_planner/models/crm_salesperson_planner_visit_template.py
+++ b/crm_salesperson_planner/models/crm_salesperson_planner_visit_template.py
@@ -14,7 +14,10 @@ class CrmSalespersonPlannerVisitTemplate(models.Model):
_inherit = "calendar.event"
name = fields.Char(
- string="Visit Template Number", default="/", readonly=True, copy=False,
+ string="Visit Template Number",
+ default="/",
+ readonly=True,
+ copy=False,
)
partner_ids = fields.Many2many(
string="Customer",
@@ -40,7 +43,9 @@ class CrmSalespersonPlannerVisitTemplate(models.Model):
("groups_id", "in", self.env.ref("sales_team.group_sale_salesman").id)
],
)
- categ_ids = fields.Many2many(relation="visit_category_rel",)
+ categ_ids = fields.Many2many(
+ relation="visit_category_rel",
+ )
alarm_ids = fields.Many2many(relation="visit_calendar_event_rel")
state = fields.Selection(
string="Status",
@@ -64,7 +69,10 @@ class CrmSalespersonPlannerVisitTemplate(models.Model):
string="Number of Sales Person Visits", compute="_compute_visit_ids_count"
)
auto_validate = fields.Boolean(string="Auto Validate", default=True)
- rrule_type = fields.Selection(default="daily", required=True,)
+ rrule_type = fields.Selection(
+ default="daily",
+ required=True,
+ )
last_visit_date = fields.Date(
string="Last Visit Date", compute="_compute_last_visit_date", store=True
)
From bd5ae85b68a5904356a3f4b6fb720f832c0b8808 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?V=C3=ADctor=20Mart=C3=ADnez?=
Date: Wed, 23 Nov 2022 17:05:31 +0100
Subject: [PATCH 3/7] [MIG] crm_salesperson_planner: Migration to 15.0
TT38992
---
crm_salesperson_planner/README.rst | 10 +-
crm_salesperson_planner/__manifest__.py | 2 +-
.../i18n/crm_salesperson_planner.pot | 162 ++++++++++++------
.../migrations/15.0.1.0.0/pre-migration.py | 63 +++++++
.../models/calendar_event.py | 17 +-
.../models/crm_salesperson_planner_visit.py | 59 ++++---
..._salesperson_planner_visit_close_reason.py | 4 +-
.../crm_salesperson_planner_visit_template.py | 143 +++++++---------
crm_salesperson_planner/models/res_partner.py | 4 +-
.../security/ir.model.access.csv | 2 +
.../static/description/index.html | 6 +-
.../test_crm_salesperson_planner_visit.py | 4 +-
..._crm_salesperson_planner_visit_template.py | 20 +--
...erson_planner_visit_close_reason_views.xml | 4 +-
...lesperson_planner_visit_template_views.xml | 20 +--
.../crm_salesperson_planner_visit_views.xml | 1 -
...crm_salesperson_planner_visit_close_wiz.py | 10 +-
...lesperson_planner_visit_template_create.py | 13 +-
18 files changed, 314 insertions(+), 230 deletions(-)
create mode 100644 crm_salesperson_planner/migrations/15.0.1.0.0/pre-migration.py
diff --git a/crm_salesperson_planner/README.rst b/crm_salesperson_planner/README.rst
index 21e6f64c17e..0c053f17de1 100644
--- a/crm_salesperson_planner/README.rst
+++ b/crm_salesperson_planner/README.rst
@@ -14,13 +14,13 @@ Crm Salesperson Planner
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fcrm-lightgray.png?logo=github
- :target: https://github.com/OCA/crm/tree/13.0/crm_salesperson_planner
+ :target: https://github.com/OCA/crm/tree/15.0/crm_salesperson_planner
:alt: OCA/crm
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
- :target: https://translation.odoo-community.org/projects/crm-13-0/crm-13-0-crm_salesperson_planner
+ :target: https://translation.odoo-community.org/projects/crm-15-0/crm-15-0-crm_salesperson_planner
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
- :target: https://runbot.odoo-community.org/runbot/111/13.0
+ :target: https://runbot.odoo-community.org/runbot/111/15.0
:alt: Try me on Runbot
|badge1| |badge2| |badge3| |badge4| |badge5|
@@ -57,7 +57,7 @@ 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 smashing it by providing a detailed and welcomed
-`feedback `_.
+`feedback `_.
Do not contact contributors directly about support or help with technical issues.
@@ -90,6 +90,6 @@ 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.
-This module is part of the `OCA/crm `_ project on GitHub.
+This module is part of the `OCA/crm `_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
diff --git a/crm_salesperson_planner/__manifest__.py b/crm_salesperson_planner/__manifest__.py
index 57b894682d6..cd935d97f43 100644
--- a/crm_salesperson_planner/__manifest__.py
+++ b/crm_salesperson_planner/__manifest__.py
@@ -2,7 +2,7 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html)
{
"name": "Crm Salesperson Planner",
- "version": "13.0.1.0.0",
+ "version": "15.0.1.0.0",
"development_status": "Beta",
"category": "Customer Relationship Management",
"author": "Sygel Technology," "Odoo Community Association (OCA)",
diff --git a/crm_salesperson_planner/i18n/crm_salesperson_planner.pot b/crm_salesperson_planner/i18n/crm_salesperson_planner.pot
index e552dccafa2..7b198963938 100644
--- a/crm_salesperson_planner/i18n/crm_salesperson_planner.pot
+++ b/crm_salesperson_planner/i18n/crm_salesperson_planner.pot
@@ -4,7 +4,7 @@
#
msgid ""
msgstr ""
-"Project-Id-Version: Odoo Server 13.0\n"
+"Project-Id-Version: Odoo Server 15.0\n"
"Report-Msgid-Bugs-To: \n"
"Last-Translator: \n"
"Language-Team: \n"
@@ -40,6 +40,11 @@ msgstr ""
msgid "Activity State"
msgstr ""
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__activity_type_icon
+msgid "Activity Type Icon"
+msgstr ""
+
#. module: crm_salesperson_planner
#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_form_view
msgid "Add a description..."
@@ -66,11 +71,6 @@ msgstr ""
msgid "Attachment Count"
msgstr ""
-#. module: crm_salesperson_planner
-#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__is_attendee
-msgid "Attendee"
-msgstr ""
-
#. module: crm_salesperson_planner
#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__attendee_status
msgid "Attendee Status"
@@ -83,7 +83,7 @@ msgstr ""
#. module: crm_salesperson_planner
#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__byday
-msgid "By day"
+msgid "Byday"
msgstr ""
#. module: crm_salesperson_planner
@@ -114,13 +114,26 @@ msgstr ""
msgid "Cancelled"
msgstr ""
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__is_organizer_alone
+msgid ""
+"Check if the organizer is alone in the event, i.e. if the organizer is the only one that hasn't declined\n"
+" the event (only if the organizer is not the only attendee)"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__recurrence_update
+msgid ""
+"Choose what to do with other events in the recurrence. Updating All Events "
+"is not allowed when dates or time is modified"
+msgstr ""
+
#. module: crm_salesperson_planner
#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_form_view
msgid "Close Info"
msgstr ""
#. module: crm_salesperson_planner
-#: model:ir.actions.act_window,name:crm_salesperson_planner.crm_salesperson_planner_visit_close_reason_action
#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__close_reason_id
#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_close_reason_form_view
#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_close_wiz_view_form
@@ -138,9 +151,9 @@ msgid "Close Reason Notes"
msgstr ""
#. module: crm_salesperson_planner
+#: model:ir.actions.act_window,name:crm_salesperson_planner.crm_salesperson_planner_visit_close_reason_action
#: model:ir.actions.act_window,name:crm_salesperson_planner.crm_salesperson_planner_visit_close_wiz_action
#: model:ir.ui.menu,name:crm_salesperson_planner.menu_crm_config_salesperson_planner_close_reason
-#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_close_reason_tree_view
msgid "Close Reasons"
msgstr ""
@@ -208,7 +221,6 @@ msgstr ""
#. module: crm_salesperson_planner
#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__date
-#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__display_start
msgid "Date"
msgstr ""
@@ -235,6 +247,11 @@ msgstr ""
msgid "Description"
msgstr ""
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__display_description
+msgid "Display Description"
+msgstr ""
+
#. module: crm_salesperson_planner
#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__display_name
#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_reason__display_name
@@ -282,17 +299,12 @@ msgstr ""
msgid "End Date"
msgstr ""
-#. module: crm_salesperson_planner
-#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__stop_datetime
-msgid "End Datetime"
-msgstr ""
-
#. module: crm_salesperson_planner
#: code:addons/crm_salesperson_planner/models/calendar_event.py:0
#, python-format
msgid ""
-"Event %s is related to salesperson visit %s. Cancel it to delete this "
-"event.\n"
+"Event %(event_name)s is related to salesperson visit %(partner_name)s. "
+"Cancel it to delete this event.\n"
msgstr ""
#. module: crm_salesperson_planner
@@ -301,15 +313,14 @@ msgid "Event Time"
msgstr ""
#. module: crm_salesperson_planner
-#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__message_follower_ids
-#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__message_follower_ids
-msgid "Followers"
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__follow_recurrence
+msgid "Follow Recurrence"
msgstr ""
#. module: crm_salesperson_planner
-#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__message_channel_ids
-#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__message_channel_ids
-msgid "Followers (Channels)"
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__message_follower_ids
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__message_follower_ids
+msgid "Followers"
msgstr ""
#. module: crm_salesperson_planner
@@ -319,7 +330,12 @@ msgid "Followers (Partners)"
msgstr ""
#. module: crm_salesperson_planner
-#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__fr
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit__activity_type_icon
+msgid "Font awesome icon e.g. fa-tasks"
+msgstr ""
+
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__fri
msgid "Fri"
msgstr ""
@@ -338,6 +354,12 @@ msgstr ""
msgid "Group By"
msgstr ""
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__has_message
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__has_message
+msgid "Has Message"
+msgstr ""
+
#. module: crm_salesperson_planner
#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__id
#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_reason__id
@@ -380,6 +402,13 @@ msgid ""
"alarm information without removing it."
msgstr ""
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__show_as
+msgid ""
+"If the time is shown as 'busy', this event will be visible to other people with either the full information or simply 'busy' written depending on its privacy. Use this option to let other people know that you are unavailable during that period of time. \n"
+" If the time is shown as 'free', this event won't be visible to other people at all. Use this option to let other people know that you are available during that period of time."
+msgstr ""
+
#. module: crm_salesperson_planner
#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_wiz__image
msgid "Image"
@@ -413,6 +442,11 @@ msgstr ""
msgid "Is the Event Highlighted"
msgstr ""
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__is_organizer_alone
+msgid "Is the Organizer Alone"
+msgstr ""
+
#. module: crm_salesperson_planner
#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit____last_update
#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_close_reason____last_update
@@ -481,6 +515,11 @@ msgstr ""
msgid "Manually Create Visits"
msgstr ""
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__videocall_location
+msgid "Meeting URL"
+msgstr ""
+
#. module: crm_salesperson_planner
#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__message_has_error
#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__message_has_error
@@ -499,10 +538,15 @@ msgid "Mobile"
msgstr ""
#. module: crm_salesperson_planner
-#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__mo
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__mon
msgid "Mon"
msgstr ""
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__my_activity_date_deadline
+msgid "My Activity Deadline"
+msgstr ""
+
#. module: crm_salesperson_planner
#: model:ir.ui.menu,name:crm_salesperson_planner.menu_crm_salesperson_planner_my_visits
#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_filter
@@ -514,6 +558,11 @@ msgstr ""
msgid "New Date"
msgstr ""
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__activity_calendar_event_id
+msgid "Next Activity Calendar Event"
+msgstr ""
+
#. module: crm_salesperson_planner
#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__activity_date_deadline
msgid "Next Activity Deadline"
@@ -534,6 +583,11 @@ msgstr ""
msgid "Notes"
msgstr ""
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__alarm_ids
+msgid "Notifications sent to all attendees to remind of the meeting."
+msgstr ""
+
#. module: crm_salesperson_planner
#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__message_needaction_counter
#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__message_needaction_counter
@@ -612,6 +666,11 @@ msgstr ""
msgid "Partner-related data of the user"
msgstr ""
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__privacy
+msgid "People to whom this event will be visible."
+msgstr ""
+
#. module: crm_salesperson_planner
#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__partner_phone
msgid "Phone"
@@ -653,28 +712,23 @@ msgid "Recurrence"
msgstr ""
#. module: crm_salesperson_planner
-#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__end_type
-msgid "Recurrence Termination"
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__recurrence_id
+msgid "Recurrence Rule"
msgstr ""
#. module: crm_salesperson_planner
-#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__recurrency
-msgid "Recurrent"
-msgstr ""
-
-#. module: crm_salesperson_planner
-#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__recurrent_id
-msgid "Recurrent ID"
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__end_type
+msgid "Recurrence Termination"
msgstr ""
#. module: crm_salesperson_planner
-#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__recurrent_id_date
-msgid "Recurrent ID date"
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__recurrence_update
+msgid "Recurrence Update"
msgstr ""
#. module: crm_salesperson_planner
-#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__recurrency
-msgid "Recurrent Meeting"
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__recurrency
+msgid "Recurrent"
msgstr ""
#. module: crm_salesperson_planner
@@ -724,11 +778,6 @@ msgstr ""
msgid "Reschedule"
msgstr ""
-#. module: crm_salesperson_planner
-#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__partner_id
-msgid "Responsible"
-msgstr ""
-
#. module: crm_salesperson_planner
#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit__activity_user_id
msgid "Responsible User"
@@ -777,10 +826,15 @@ msgid "Salesperson Visits"
msgstr ""
#. module: crm_salesperson_planner
-#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__sa
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__sat
msgid "Sat"
msgstr ""
+#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__partner_id
+msgid "Scheduled by"
+msgstr ""
+
#. module: crm_salesperson_planner
#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_filter
msgid "Search Visits"
@@ -800,7 +854,7 @@ msgstr ""
#. module: crm_salesperson_planner
#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__show_as
-msgid "Show Time as"
+msgid "Show as"
msgstr ""
#. module: crm_salesperson_planner
@@ -813,11 +867,6 @@ msgstr ""
msgid "Start Date"
msgstr ""
-#. module: crm_salesperson_planner
-#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__start_datetime
-msgid "Start DateTime"
-msgstr ""
-
#. module: crm_salesperson_planner
#: model:ir.model.fields,help:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__start
msgid "Start date of an event, without time for full days events"
@@ -859,7 +908,7 @@ msgid "Submit"
msgstr ""
#. module: crm_salesperson_planner
-#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__su
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__sun
msgid "Sun"
msgstr ""
@@ -921,7 +970,7 @@ msgid "The visit template number must be unique!"
msgstr ""
#. module: crm_salesperson_planner
-#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__th
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__thu
msgid "Thu"
msgstr ""
@@ -936,7 +985,7 @@ msgid "Today Visits"
msgstr ""
#. module: crm_salesperson_planner
-#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__tu
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__tue
msgid "Tue"
msgstr ""
@@ -963,6 +1012,7 @@ msgid "Unread Messages Counter"
msgstr ""
#. module: crm_salesperson_planner
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__until
#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_template_form_view
msgid "Until"
msgstr ""
@@ -1009,7 +1059,6 @@ msgstr ""
#. module: crm_salesperson_planner
#: model:ir.actions.act_window,name:crm_salesperson_planner.crm_salesperson_planner_visit_template_action
#: model:ir.ui.menu,name:crm_salesperson_planner.menu_crm_salesperson_planner_visit_template
-#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_template_tree_view
msgid "Visit Templates"
msgstr ""
@@ -1027,7 +1076,6 @@ msgstr ""
#: model:ir.actions.act_window,name:crm_salesperson_planner.all_crm_salesperson_planner_visit_action
#: model:ir.actions.act_window,name:crm_salesperson_planner.my_crm_salesperson_planner_visit_action
#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_lead__crm_salesperson_planner_visit_ids
-#: model_terms:ir.ui.view,arch_db:crm_salesperson_planner.crm_salesperson_planner_visit_tree_view
msgid "Visits"
msgstr ""
@@ -1055,12 +1103,12 @@ msgid "Website communication history"
msgstr ""
#. module: crm_salesperson_planner
-#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__we
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__wed
msgid "Wed"
msgstr ""
#. module: crm_salesperson_planner
-#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__week_list
+#: model:ir.model.fields,field_description:crm_salesperson_planner.field_crm_salesperson_planner_visit_template__weekday
msgid "Weekday"
msgstr ""
diff --git a/crm_salesperson_planner/migrations/15.0.1.0.0/pre-migration.py b/crm_salesperson_planner/migrations/15.0.1.0.0/pre-migration.py
new file mode 100644
index 00000000000..af35398900a
--- /dev/null
+++ b/crm_salesperson_planner/migrations/15.0.1.0.0/pre-migration.py
@@ -0,0 +1,63 @@
+from openupgradelib import openupgrade
+
+field_spec = [
+ (
+ "crm.salesperson.planner.visit.template",
+ "crm_salesperson_planner_visit_template",
+ "start_datetime",
+ "start",
+ ),
+ (
+ "crm.salesperson.planner.visit.template",
+ "crm_salesperson_planner_visit_template",
+ "week_list",
+ "weekday",
+ ),
+ (
+ "crm.salesperson.planner.visit.template",
+ "crm_salesperson_planner_visit_template",
+ "mo",
+ "mon",
+ ),
+ (
+ "crm.salesperson.planner.visit.template",
+ "crm_salesperson_planner_visit_template",
+ "tu",
+ "tue",
+ ),
+ (
+ "crm.salesperson.planner.visit.template",
+ "crm_salesperson_planner_visit_template",
+ "we",
+ "wed",
+ ),
+ (
+ "crm.salesperson.planner.visit.template",
+ "crm_salesperson_planner_visit_template",
+ "th",
+ "thu",
+ ),
+ (
+ "crm.salesperson.planner.visit.template",
+ "crm_salesperson_planner_visit_template",
+ "fr",
+ "fri",
+ ),
+ (
+ "crm.salesperson.planner.visit.template",
+ "crm_salesperson_planner_visit_template",
+ "sa",
+ "sat",
+ ),
+ (
+ "crm.salesperson.planner.visit.template",
+ "crm_salesperson_planner_visit_template",
+ "su",
+ "sun",
+ ),
+]
+
+
+@openupgrade.migrate()
+def migrate(env, version):
+ openupgrade.rename_fields(env, field_spec, False)
diff --git a/crm_salesperson_planner/models/calendar_event.py b/crm_salesperson_planner/models/calendar_event.py
index 87fdf603056..102d7bc1f88 100644
--- a/crm_salesperson_planner/models/calendar_event.py
+++ b/crm_salesperson_planner/models/calendar_event.py
@@ -35,9 +35,9 @@ def write(self, values):
salesperson_visit_events.mapped(
"salesperson_planner_visit_ids"
).with_context(bypass_update_event=True).write(new_vals)
- return super(CalendarEvent, self).write(values)
+ return super().write(values)
- def unlink(self, can_be_deleted=True):
+ def unlink(self):
if not self.env.context.get("bypass_cancel_visit"):
salesperson_visit_events = self.filtered(
lambda a: a.res_model == "crm.salesperson.planner.visit"
@@ -47,8 +47,13 @@ def unlink(self, can_be_deleted=True):
error_msg = ""
for event in salesperson_visit_events:
error_msg += _(
- "Event %s is related to salesperson visit %s. "
- "Cancel it to delete this event.\n"
- ) % (event.name, event.salesperson_planner_visit_ids[0].name)
+ "Event %(event_name)s is related to salesperson visit "
+ "%(partner_name)s. Cancel it to delete this event.\n"
+ ) % {
+ "event_name": event.name,
+ "partner_name": fields.first(
+ event.salesperson_planner_visit_ids
+ ).name,
+ }
raise ValidationError(error_msg)
- return super(CalendarEvent, self).unlink(can_be_deleted)
+ return super().unlink()
diff --git a/crm_salesperson_planner/models/crm_salesperson_planner_visit.py b/crm_salesperson_planner/models/crm_salesperson_planner_visit.py
index c300051c4b1..4bd850926ef 100644
--- a/crm_salesperson_planner/models/crm_salesperson_planner_visit.py
+++ b/crm_salesperson_planner/models/crm_salesperson_planner_visit.py
@@ -27,12 +27,10 @@ class CrmSalespersonPlannerVisit(models.Model):
partner_phone = fields.Char(string="Phone", related="partner_id.phone")
partner_mobile = fields.Char(string="Mobile", related="partner_id.mobile")
date = fields.Date(
- string="Date",
default=fields.Date.context_today,
required=True,
)
sequence = fields.Integer(
- string="Sequence",
help="Used to order Visits in the different views",
default=20,
)
@@ -58,7 +56,7 @@ class CrmSalespersonPlannerVisit(models.Model):
copy=False,
domain="[('type', '=', 'opportunity'), ('partner_id', 'child_of', partner_id)]",
)
- description = fields.Html(string="Description")
+ description = fields.Html()
state = fields.Selection(
string="Status",
required=True,
@@ -77,10 +75,8 @@ class CrmSalespersonPlannerVisit(models.Model):
close_reason_id = fields.Many2one(
comodel_name="crm.salesperson.planner.visit.close.reason", string="Close Reason"
)
- close_reason_image = fields.Image(
- string="Close Reason Image", max_width=1024, max_height=1024, attachment=True
- )
- close_reason_notes = fields.Text(string="Close Reason Notes")
+ close_reason_image = fields.Image(max_width=1024, max_height=1024, attachment=True)
+ close_reason_notes = fields.Text()
visit_template_id = fields.Many2one(
comodel_name="crm.salesperson.planner.visit.template", string="Visit Template"
)
@@ -140,29 +136,32 @@ def action_cancel(self, reason_id, image=None, notes=None):
}
)
+ def _prepare_calendar_event_vals(self):
+ return {
+ "name": self.name,
+ "partner_ids": [(6, 0, [self.partner_id.id, self.user_id.partner_id.id])],
+ "user_id": self.user_id.id,
+ "start_date": self.date,
+ "stop_date": self.date,
+ "start": self.date,
+ "stop": self.date,
+ "allday": True,
+ "res_model": self._name,
+ "res_model_id": self.env.ref(
+ "crm_salesperson_planner.model_crm_salesperson_planner_visit"
+ ).id,
+ "res_id": self.id,
+ }
+
def create_calendar_event(self):
events = self.env["calendar.event"]
- model_id = self.env.ref(
- "crm_salesperson_planner.model_crm_salesperson_planner_visit"
- ).id
- for sel in self:
- event_vals = {
- "name": sel.name,
- "partner_ids": [(6, 0, [sel.partner_id.id, sel.user_id.partner_id.id])],
- "user_id": sel.user_id.id,
- "start_date": sel.date,
- "stop_date": sel.date,
- "start": sel.date,
- "stop": sel.date,
- "allday": True,
- "res_model_id": model_id,
- "res_id": sel.id,
- }
- event = self.env["calendar.event"].create(event_vals)
+ for item in self:
+ event = self.env["calendar.event"].create(
+ item._prepare_calendar_event_vals()
+ )
if event:
event.activity_ids.unlink()
- event.write({"res_model": "crm.salesperson.planner.visit"})
- sel.write({"calendar_event_id": event.id})
+ item.calendar_event_id = event
events += event
return events
@@ -181,19 +180,19 @@ def action_incident(self, reason_id, image=None, notes=None):
def unlink(self):
if any(sel.state not in ["draft", "cancel"] for sel in self):
raise ValidationError(_("Visits must be in cancelled state"))
- return super(CrmSalespersonPlannerVisit, self).unlink()
+ return super().unlink()
def write(self, values):
- ret_val = super(CrmSalespersonPlannerVisit, self).write(values)
+ ret_val = super().write(values)
if (values.get("date") or values.get("user_id")) and not self.env.context.get(
"bypass_update_event"
):
new_vals = {}
- for sel in self.filtered(lambda a: a.calendar_event_id):
+ for item in self.filtered(lambda a: a.calendar_event_id):
if values.get("date"):
new_vals["start"] = values.get("date")
new_vals["stop"] = values.get("date")
if values.get("user_id"):
new_vals["user_id"] = values.get("user_id")
- sel.calendar_event_id.write(new_vals)
+ item.calendar_event_id.write(new_vals)
return ret_val
diff --git a/crm_salesperson_planner/models/crm_salesperson_planner_visit_close_reason.py b/crm_salesperson_planner/models/crm_salesperson_planner_visit_close_reason.py
index a8d119ebd94..12adbbcb1e4 100644
--- a/crm_salesperson_planner/models/crm_salesperson_planner_visit_close_reason.py
+++ b/crm_salesperson_planner/models/crm_salesperson_planner_visit_close_reason.py
@@ -15,5 +15,5 @@ class CrmSalespersonPlannerVisitCloseReason(models.Model):
required=True,
default="cancel",
)
- require_image = fields.Boolean(string="Require Image", default=False)
- reschedule = fields.Boolean(string="Reschedule", default=False)
+ require_image = fields.Boolean(default=False)
+ reschedule = fields.Boolean(default=False)
diff --git a/crm_salesperson_planner/models/crm_salesperson_planner_visit_template.py b/crm_salesperson_planner/models/crm_salesperson_planner_visit_template.py
index b628d1186dd..1c86af5c53b 100644
--- a/crm_salesperson_planner/models/crm_salesperson_planner_visit_template.py
+++ b/crm_salesperson_planner/models/crm_salesperson_planner_visit_template.py
@@ -2,7 +2,7 @@
# Copyright 2021 Sygel - Manuel Regidor
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html)
-from dateutil.relativedelta import relativedelta
+from datetime import timedelta
from odoo import _, api, fields, models
from odoo.exceptions import ValidationError
@@ -26,7 +26,6 @@ class CrmSalespersonPlannerVisitTemplate(models.Model):
required=True,
)
sequence = fields.Integer(
- string="Sequence",
help="Used to order Visits in the different views",
default=20,
)
@@ -68,14 +67,12 @@ class CrmSalespersonPlannerVisitTemplate(models.Model):
visit_ids_count = fields.Integer(
string="Number of Sales Person Visits", compute="_compute_visit_ids_count"
)
- auto_validate = fields.Boolean(string="Auto Validate", default=True)
+ auto_validate = fields.Boolean(default=True)
rrule_type = fields.Selection(
default="daily",
required=True,
)
- last_visit_date = fields.Date(
- string="Last Visit Date", compute="_compute_last_visit_date", store=True
- )
+ last_visit_date = fields.Date(compute="_compute_last_visit_date", store=True)
final_date = fields.Date(string="Repeat Until")
allday = fields.Boolean(default=True)
recurrency = fields.Boolean(default=True)
@@ -104,26 +101,11 @@ def _compute_visit_ids_count(self):
def _compute_last_visit_date(self):
for sel in self.filtered(lambda x: x.visit_ids):
sel.last_visit_date = sel.visit_ids.sorted(lambda x: x.date)[-1].date
- self.filtered(lambda x: not x.visit_ids).write({"last_visit_date": False})
-
- # overwrite
- # default _search method gives an error when trying to access
- # instances of the model
- def _search(
- self,
- args,
- offset=0,
- limit=None,
- order=None,
- count=False,
- access_rights_uid=None,
- ):
- return super(models.Model, self)._search(args)
@api.constrains("partner_ids")
def _constrains_partner_ids(self):
- for sel in self:
- if len(sel.partner_ids) > 1:
+ for item in self:
+ if len(item.partner_ids) > 1:
raise ValidationError(_("Only one customer is allowed"))
@api.model_create_multi
@@ -141,16 +123,10 @@ def create(self, vals_list):
def write(self, vals):
return super(models.Model, self).write(vals)
- # overwrite
- # default unlink method gives an error when trying to access
- # instances of the model
- def unlink(self, can_be_deleted=True):
- return super(models.Model, self).unlink()
-
def action_view_salesperson_planner_visit(self):
- action = self.env.ref(
+ action = self.env["ir.actions.act_window"]._for_xml_id(
"crm_salesperson_planner.all_crm_salesperson_planner_visit_action"
- ).read()[0]
+ )
action["domain"] = [("id", "=", self.visit_ids.ids)]
action["context"] = {
"default_partner_id": self.partner_id.id,
@@ -168,65 +144,62 @@ def action_cancel(self):
def action_draft(self):
self.write({"state": "draft"})
- def filter_dates(self, recurrences, days="7"):
- last_date = recurrences[-1].date()
- reference_date = self.start_date
- visit_date = fields.Datetime.from_string(reference_date)
- last_visit_date = False
- if not self.last_visit_date:
- last_visit_date = visit_date
- else:
- last_visit_date = fields.Datetime.from_string(
- self.last_visit_date + relativedelta(days=1)
- )
- max_date = fields.Date.today() + relativedelta(
- days=days, hours=23, minutes=59, seconds=59
- )
- recurrences = list(
- filter(
- lambda a: a.replace(tzinfo=None) <= max_date
- and a.replace(tzinfo=None) > last_visit_date,
- recurrences,
- )
- )
- return recurrences, last_date
+ def _prepare_crm_salesperson_planner_visit_vals(self, dates):
+ return [
+ {
+ "partner_id": (
+ fields.first(self.partner_ids).id if self.partner_ids else False
+ ),
+ "date": date,
+ "sequence": self.sequence,
+ "user_id": self.user_id.id,
+ "description": self.description,
+ "company_id": self.company_id.id,
+ "visit_template_id": self.id,
+ }
+ for date in dates
+ ]
+
+ def _get_max_date(self):
+ return self._increase_date(self.start_date, self.count)
+
+ def _increase_date(self, date, value):
+ if self.rrule_type == "daily":
+ date += timedelta(days=value)
+ elif self.rrule_type == "weekly":
+ date += timedelta(weeks=value)
+ elif self.rrule_type == "monthly":
+ date += timedelta(months=value)
+ elif self.rrule_type == "yearly":
+ date += timedelta(years=value)
+ return date
+
+ def _get_recurrence_dates(self, items):
+ dates = []
+ max_date = self._get_max_date()
+ from_date = self._increase_date(self.last_visit_date or self.start_date, 1)
+ if max_date > from_date:
+ for _x in range(items):
+ if from_date <= max_date:
+ dates.append(from_date)
+ from_date = self._increase_date(from_date, 1)
+ return dates
def _create_visits(self, days=7):
- visits_vals = []
- for sel in self:
- recurrences = self._get_recurrent_date_by_event()
- days, last_date = sel.filter_dates(recurrences, days)
- for day in days:
- visits_vals.append(
- {
- "partner_id": sel.partner_ids[0].id,
- "date": day.date(),
- "sequence": sel.sequence,
- "user_id": sel.user_id.id,
- "description": sel.description,
- "company_id": sel.company_id.id,
- "visit_template_id": sel.id,
- }
- )
- if days and days[-1].date() >= last_date:
- sel.write({"state": "done"})
- return visits_vals
+ return self._prepare_crm_salesperson_planner_visit_vals(
+ self._get_recurrence_dates(days)
+ )
def create_visits(self, days=7):
- for sel in self:
- visit_vals = sel._create_visits(days=days)
- visits = self.env["crm.salesperson.planner.visit"].create(visit_vals)
- if visits and sel.auto_validate:
+ for item in self:
+ visits = self.env["crm.salesperson.planner.visit"].create(
+ item._create_visits(days)
+ )
+ if visits and item.auto_validate:
visits.action_confirm()
+ if item.last_visit_date >= item._get_max_date():
+ item.state = "done"
def _cron_create_visits(self, days=7):
templates = self.search([("state", "=", "in-progress")])
- templates.create_visits(days=days)
-
- # overwrite
- def get_recurrent_ids(self, domain, order=None):
- return self.search([domain], order=order)
-
- # overwrite
- def create_attendees(self):
- return []
+ templates.create_visits(days)
diff --git a/crm_salesperson_planner/models/res_partner.py b/crm_salesperson_planner/models/res_partner.py
index 7e8e09a77b3..c09f897f673 100644
--- a/crm_salesperson_planner/models/res_partner.py
+++ b/crm_salesperson_planner/models/res_partner.py
@@ -25,9 +25,9 @@ def _compute_salesperson_planner_visit_count(self):
partner.salesperson_planner_visit_count = visit_count
def action_view_salesperson_planner_visit(self):
- action = self.env.ref(
+ action = self.env["ir.actions.act_window"]._for_xml_id(
"crm_salesperson_planner.all_crm_salesperson_planner_visit_action"
- ).read()[0]
+ )
operator = "child_of" if self.is_company else "="
action["domain"] = [("partner_id", operator, self.id)]
return action
diff --git a/crm_salesperson_planner/security/ir.model.access.csv b/crm_salesperson_planner/security/ir.model.access.csv
index 764c085ab20..ec153a4e19c 100644
--- a/crm_salesperson_planner/security/ir.model.access.csv
+++ b/crm_salesperson_planner/security/ir.model.access.csv
@@ -3,3 +3,5 @@ access_crm_salesperson_planner_visit_user,crm.salesperson.planner.visit.user,mod
access_crm_salesperson_planner_visit_close_reason_user,crm.salesperson.planner.visit.close.reason.user,model_crm_salesperson_planner_visit_close_reason,sales_team.group_sale_salesman,1,0,0,0
access_crm_salesperson_planner_visit_close_reason_manager,crm.salesperson.planner.visit.close.reason.manager,model_crm_salesperson_planner_visit_close_reason,sales_team.group_sale_manager,1,1,1,1
access_crm_salesperson_planner_visit_template_user,crm.salesperson.planner.visit.template.user,model_crm_salesperson_planner_visit_template,sales_team.group_sale_salesman,1,1,1,1
+crm_salesperson_planner.access_crm_salesperson_planner_visit_close_wiz,access_crm_salesperson_planner_visit_close_wiz,crm_salesperson_planner.model_crm_salesperson_planner_visit_close_wiz,sales_team.group_sale_salesman,1,1,1,1
+crm_salesperson_planner.access_crm_salesperson_planner_visit_template_create,access_crm_salesperson_planner_visit_template_create,crm_salesperson_planner.model_crm_salesperson_planner_visit_template_create,sales_team.group_sale_salesman,1,1,1,1
diff --git a/crm_salesperson_planner/static/description/index.html b/crm_salesperson_planner/static/description/index.html
index 3b53184f1ce..f36f851e956 100644
--- a/crm_salesperson_planner/static/description/index.html
+++ b/crm_salesperson_planner/static/description/index.html
@@ -367,7 +367,7 @@
Crm Salesperson Planner
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
-
+
This application allows you to track and schedule salespeople visits to your customers, allowing you to determine which opportunities are going to be dealt on each visit. Visits create an all day event in calendar, and they can be easily rescheduled.
Visits can be automatically created from a template, in which it is possible to select the frequency of visits, as well as the start and end dates. The last visit can also be calculated by selecting the total number of repetitions.
This module creates a cron that generates visits from templates, but an option to create them manually is available from the template form view when the template is validated.
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 smashing it by providing a detailed and welcomed
-feedback.
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.
-
This module is part of the OCA/crm project on GitHub.
+
This module is part of the OCA/crm project on GitHub.