From 091f1284e447a363ab2eb2b1b3e634ef334f8d95 Mon Sep 17 00:00:00 2001 From: Jairo Llopis Date: Wed, 8 Aug 2018 15:15:57 +0100 Subject: [PATCH 01/41] privacy_consent: Privacy explicit consent tracking tools (#11) Update privacy_consent.pot README.rst README.rst --- privacy_consent/README.rst | 173 +++++ privacy_consent/__init__.py | 3 + privacy_consent/__manifest__.py | 29 + privacy_consent/controllers/__init__.py | 1 + privacy_consent/controllers/main.py | 47 ++ privacy_consent/data/ir_actions_server.xml | 23 + privacy_consent/data/ir_cron.xml | 16 + privacy_consent/data/mail.xml | 155 ++++ privacy_consent/i18n/es.po | 663 ++++++++++++++++++ privacy_consent/i18n/privacy_consent.pot | 487 +++++++++++++ privacy_consent/models/__init__.py | 5 + privacy_consent/models/mail_mail.py | 54 ++ privacy_consent/models/mail_template.py | 33 + privacy_consent/models/privacy_activity.py | 144 ++++ privacy_consent/models/privacy_consent.py | 201 ++++++ privacy_consent/models/res_partner.py | 32 + privacy_consent/readme/CONTRIBUTORS.rst | 3 + privacy_consent/readme/DESCRIPTION.rst | 7 + privacy_consent/readme/INSTALL.rst | 15 + privacy_consent/readme/USAGE.rst | 69 ++ privacy_consent/security/ir.model.access.csv | 3 + privacy_consent/static/description/icon.png | Bin 0 -> 9455 bytes privacy_consent/static/description/index.html | 520 ++++++++++++++ privacy_consent/templates/form.xml | 63 ++ privacy_consent/tests/__init__.py | 1 + privacy_consent/tests/test_consent.py | 247 +++++++ privacy_consent/views/privacy_activity.xml | 89 +++ privacy_consent/views/privacy_consent.xml | 113 +++ privacy_consent/views/res_partner.xml | 35 + privacy_consent/wizards/__init__.py | 1 + .../wizards/mail_compose_message.py | 16 + 31 files changed, 3248 insertions(+) create mode 100644 privacy_consent/README.rst create mode 100644 privacy_consent/__init__.py create mode 100644 privacy_consent/__manifest__.py create mode 100644 privacy_consent/controllers/__init__.py create mode 100644 privacy_consent/controllers/main.py create mode 100644 privacy_consent/data/ir_actions_server.xml create mode 100644 privacy_consent/data/ir_cron.xml create mode 100644 privacy_consent/data/mail.xml create mode 100644 privacy_consent/i18n/es.po create mode 100644 privacy_consent/i18n/privacy_consent.pot create mode 100644 privacy_consent/models/__init__.py create mode 100644 privacy_consent/models/mail_mail.py create mode 100644 privacy_consent/models/mail_template.py create mode 100644 privacy_consent/models/privacy_activity.py create mode 100644 privacy_consent/models/privacy_consent.py create mode 100644 privacy_consent/models/res_partner.py create mode 100644 privacy_consent/readme/CONTRIBUTORS.rst create mode 100644 privacy_consent/readme/DESCRIPTION.rst create mode 100644 privacy_consent/readme/INSTALL.rst create mode 100644 privacy_consent/readme/USAGE.rst create mode 100644 privacy_consent/security/ir.model.access.csv create mode 100644 privacy_consent/static/description/icon.png create mode 100644 privacy_consent/static/description/index.html create mode 100644 privacy_consent/templates/form.xml create mode 100644 privacy_consent/tests/__init__.py create mode 100644 privacy_consent/tests/test_consent.py create mode 100644 privacy_consent/views/privacy_activity.xml create mode 100644 privacy_consent/views/privacy_consent.xml create mode 100644 privacy_consent/views/res_partner.xml create mode 100644 privacy_consent/wizards/__init__.py create mode 100644 privacy_consent/wizards/mail_compose_message.py diff --git a/privacy_consent/README.rst b/privacy_consent/README.rst new file mode 100644 index 00000000..4f928329 --- /dev/null +++ b/privacy_consent/README.rst @@ -0,0 +1,173 @@ +================= +Privacy - Consent +================= + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Production%2FStable-green.png + :target: https://odoo-community.org/page/development-status + :alt: Production/Stable +.. |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%2Fdata--protection-lightgray.png?logo=github + :target: https://github.com/OCA/data-protection/tree/10.0/privacy_consent + :alt: OCA/data-protection +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/data-protection-10-0/data-protection-10-0-privacy_consent + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png + :target: https://runbot.odoo-community.org/runbot/263/10.0 + :alt: Try me on Runbot + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module allows the user to define a set of subjects (partners) +affected by any data processing activity, and establish +a process to ask them for consent to include them in that activity. + +For those that need explicit consent as a lawfulness base for personal data +processing, as required by GDPR (article 6.1.a), this module provides the +needed tools to automate it. + +**Table of contents** + +.. contents:: + :local: + +Installation +============ + +You may want to install, along with this module, one of OCA's +``mail_tracking`` module collection, such as ``mail_tracking_mailgun``, so +you can provide more undeniable proof that some consent request was sent, and +to whom. + +However, the most important proof to provide is the answer itself (more than +the question), and this addon provides enough tooling for that. + +Multi-database instances +~~~~~~~~~~~~~~~~~~~~~~~~ + +To enable multi-database support, you must load this addon as a server-wide +addon. Example command to boot Odoo:: + + odoo-bin --load=web,privacy_consent + +Usage +===== + +New options for data processing activities: + +#. Go to *Privacy > Master Data > Activities* and create one. + +#. Give it a name, such as *Sending mass mailings to customers*. + +#. Go to tab *Consent* and choose one option in *Ask subjects for consent*: + + * *Manual* tells the activity that you will want to create and send the + consent requests manually, and only provides some helpers for you to + be able to batch-generate them. + + * *Automatic* enables this module's full power: send all consent requests + to selected partners automatically, every day and under your demand. + +#. When you do this, all the consent-related options appear. Configure them: + + * A smart button tells you how many consents have been generated, and lets you + access them. + + * Choose one *Email template* to send to subjects. This email itself is what + asks for consent, and it gets recorded, to serve as a proof that it was sent. + The module provides a default template that should be good for most usage + cases; and if you create one directly from that field, some good defaults + are provided for your comfortability. + + * *Subjects filter* defines what partners will be elegible for inclusion in + this data processing activity. + + * You can enable *Accepted by default* if you want to assume subjects + accepted their data processing. You should possibly consult your + lawyer to use this. + + * You can choose a *Server action* (developer mode only) that will + be executed whenever a new non-draft consent request is created, + or when its acceptance status changes. + + This module supplies a server action by default, called + *Update partner's opt out*, that syncs the acceptance status with the + partner's *Elegible for mass mailings* option. + +#. Click on *Generate consent requests* link to create new consent requests. + + * If you chose *Manual* mode, all missing consent request are created as + drafts, and nothing else is done now. + + * If you chose *Automatic* mode, also those requests are sent to subjects + and set as *Sent*. + +#. You will be presented with the list of just-created consent requests. + See below. + +New options for consent requests: + +#. Access the consent requests by either: + + * Generating new consent requests from a data processing activity. + + * Pressing the *Consents* smart button in a data processing activity. + + * Going to *Privacy > Privacy > Consents*. + +#. A consent will include the partner, the activity, the acceptance status, + and the request state. + +#. You can manually ask for consent by pressing the button labeled as + *Ask for consent*. + +#. All consent requests and responses are recorded in the mail thread below. + +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 +~~~~~~~ + +* Tecnativa + +Contributors +~~~~~~~~~~~~ + +* `Tecnativa `_: + + * Jairo Llopis + +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/data-protection `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/privacy_consent/__init__.py b/privacy_consent/__init__.py new file mode 100644 index 00000000..ada0b87b --- /dev/null +++ b/privacy_consent/__init__.py @@ -0,0 +1,3 @@ +from . import controllers +from . import models +from . import wizards diff --git a/privacy_consent/__manifest__.py b/privacy_consent/__manifest__.py new file mode 100644 index 00000000..ee842548 --- /dev/null +++ b/privacy_consent/__manifest__.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- +# Copyright 2018 Tecnativa - Jairo Llopis +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +{ + "name": "Privacy - Consent", + "summary": "Allow people to explicitly accept or reject inclusion " + "in some activity, GDPR compliant", + "version": "10.0.1.0.0", + "development_status": "Production/Stable", + "category": "Privacy", + "website": "https://github.com/OCA/management-activity", + "author": "Tecnativa, Odoo Community Association (OCA)", + "license": "AGPL-3", + "application": False, + "installable": True, + "depends": [ + "privacy", + ], + "data": [ + "security/ir.model.access.csv", + "data/ir_actions_server.xml", + "data/ir_cron.xml", + "data/mail.xml", + "templates/form.xml", + "views/privacy_consent.xml", + "views/privacy_activity.xml", + "views/res_partner.xml", + ], +} diff --git a/privacy_consent/controllers/__init__.py b/privacy_consent/controllers/__init__.py new file mode 100644 index 00000000..12a7e529 --- /dev/null +++ b/privacy_consent/controllers/__init__.py @@ -0,0 +1 @@ +from . import main diff --git a/privacy_consent/controllers/main.py b/privacy_consent/controllers/main.py new file mode 100644 index 00000000..8f243d08 --- /dev/null +++ b/privacy_consent/controllers/main.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +# Copyright 2018 Tecnativa - Jairo Llopis +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from datetime import datetime + +from werkzeug.exceptions import NotFound + +from odoo.http import Controller, request, route + +from odoo.addons.web.controllers.main import ensure_db + + +class ConsentController(Controller): + @route("/privacy/consent//" + "/", + type="http", auth="none", website=True) + def consent(self, choice, consent_id, token, *args, **kwargs): + """Process user's consent acceptance or rejection.""" + ensure_db() + try: + # If there's a website, we need a user to render the template + request.uid = request.website.user_id.id + except AttributeError: + # If there's no website, the default is OK + pass + consent = request.env["privacy.consent"] \ + .with_context(subject_answering=True) \ + .sudo().browse(consent_id) + if not (consent.exists() and consent._token() == token): + raise NotFound + if consent.partner_id.lang: + consent = consent.with_context(lang=consent.partner_id.lang) + request.context = consent.env.context + consent.action_answer(choice == "accept", self._metadata()) + return request.render("privacy_consent.form", { + "consent": consent, + }) + + def _metadata(self): + return (u"User agent: {}\n" + u"Remote IP: {}\n" + u"Date and time: {:%Y-%m-%d %H:%M:%S}").format( + request.httprequest.environ.get("HTTP_USER_AGENT"), + request.httprequest.environ.get("REMOTE_ADDRESS"), + datetime.now(), + ) diff --git a/privacy_consent/data/ir_actions_server.xml b/privacy_consent/data/ir_actions_server.xml new file mode 100644 index 00000000..58788e65 --- /dev/null +++ b/privacy_consent/data/ir_actions_server.xml @@ -0,0 +1,23 @@ + + + + + + + Update partner's opt out + + + object_write + expression + record.partner_id + + + + + + equation + not record.accepted + + + diff --git a/privacy_consent/data/ir_cron.xml b/privacy_consent/data/ir_cron.xml new file mode 100644 index 00000000..cc4bb380 --- /dev/null +++ b/privacy_consent/data/ir_cron.xml @@ -0,0 +1,16 @@ + + + + + + + Request automatic data processing consents + privacy.activity + _cron_new_consents + 1 + work_days + -1 + + + diff --git a/privacy_consent/data/mail.xml b/privacy_consent/data/mail.xml new file mode 100644 index 00000000..c288e937 --- /dev/null +++ b/privacy_consent/data/mail.xml @@ -0,0 +1,155 @@ + + + + + + + + Personal data processing consent request + Data processing consent request for ${object.activity_id.display_name|safe} + + + +
+ + + + + + +
+ + ${object.activity_id.controller_id.display_name|safe} + +
+ + + + + + + + + + + + + +
+

+ Hello, ${object.partner_id.name|safe} +

+

+ We contacted you to ask you to give us your explicit consent to include your data in a data processing activity called + ${object.activity_id.display_name|safe}, property of + ${object.activity_id.controller_id.display_name|safe} +

+ ${object.description or ""} +

+ % if object.state == "answered": + The last time you answered, you + % elif object.state == "sent": + If you do nothing, we will assume you have + % endif + + % if object.accepted: + accepted + % else: + rejected + % endif + such data processing. +

+

+ You can update your preferences below: +

+
+ + Accept + + + + Reject + +
+

+ If you need further information, please respond to this email and we will attend your request as soon as possible. +

+

+ Thank you! +

+
+ + + + + + +
+

+ Sent by + ${object.activity_id.controller_id.display_name|safe}. +

+
+
+
+
+ + + + New Consent + Privacy consent request created + privacy.consent + + + + + + Acceptance Changed by Subject + Acceptance status updated by subject + privacy.consent + + + + + + State Changed + Privacy consent request state changed + privacy.consent + + + + + + + New Consent + Privacy consent request created + privacy.activity + + + + + activity_id + + + Acceptance Changed + Privacy consent request acceptance status changed + privacy.activity + + + + + activity_id + + + State Changed + Privacy consent request state changed + privacy.activity + + + + + activity_id + + +
diff --git a/privacy_consent/i18n/es.po b/privacy_consent/i18n/es.po new file mode 100644 index 00000000..1285c92d --- /dev/null +++ b/privacy_consent/i18n/es.po @@ -0,0 +1,663 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * privacy_consent +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-07-11 08:38+0000\n" +"PO-Revision-Date: 2018-07-11 11:07+0200\n" +"Last-Translator: Jairo Llopis \n" +"Language-Team: \n" +"Language: es_ES\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 2.0.8\n" + +#. module: privacy_consent +#: model:mail.template,body_html:privacy_consent.template_consent +msgid "" +"\n" +"
\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \n" +" \"${object."\n" +" \n" +"
\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
\n" +"

\n" +" Hello, ${object.partner_id.name|safe}\n" +"

\n" +"

\n" +" We contacted you to ask you to give us " +"your explicit consent to include your data in a data processing activity " +"called\n" +" ${object.activity_id.display_name|" +"safe}, property of\n" +" ${object.activity_id.controller_id." +"display_name|safe}\n" +"

\n" +" ${object.description or \"\"}\n" +"

\n" +" % if object.state == \"answered\":\n" +" The last time you answered, you\n" +" % elif object.state == \"sent\":\n" +" If you do nothing, we will assume " +"you have\n" +" % endif\n" +"\n" +" % if object.accepted:\n" +" accepted\n" +" % else:\n" +" rejected\n" +" % endif\n" +" such data processing.\n" +"

\n" +"

\n" +" You can update your preferences below:\n" +"

\n" +"
\n" +" \n" +" Accept\n" +" \n" +" \n" +" \n" +" Reject\n" +" \n" +"
\n" +"

\n" +" If you need further information, please " +"respond to this email and we will attend your request as soon as possible.\n" +"

\n" +"

\n" +" Thank you!\n" +"

\n" +"
\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
\n" +"

\n" +" Sent by\n" +" " +"${object.activity_id.controller_id.display_name|safe}.\n" +"

\n" +"
\n" +"
\n" +" " +msgstr "" +"\n" +"
\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \n" +" \"${object."\n" +" \n" +"
\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
\n" +"

\n" +" Hola, ${object.partner_id.name|safe}\n" +"

\n" +"

\n" +" Le hemos contactado para pedirle su " +"consentimiento explícito para incluir sus datos en una actividad de " +"tratamiento llamada\n" +" ${object.activity_id.display_name|" +"safe}, propiedad de\n" +" ${object.activity_id.controller_id." +"display_name|safe}\n" +"

\n" +" ${object.description or \"\"}\n" +"

\n" +" % if object.state == \"answered\":\n" +" Según su última respuesta,\n" +" % elif object.state == \"sent\":\n" +" Si no recibimos respuesta, " +"asumiremos que\n" +" % endif\n" +"\n" +" % if object.accepted:\n" +" ha aceptado\n" +" % else:\n" +" ha rechazado\n" +" % endif\n" +" dicho procesamiento de datos.\n" +"

\n" +"

\n" +" Puede cambiar sus preferencias aquí " +"abajo:\n" +"

\n" +"
\n" +" \n" +" Aceptar\n" +" \n" +" \n" +" \n" +" Rechazar\n" +" \n" +"
\n" +"

\n" +" Si necesita más información, por favor " +"responda a este correo electrónico y atenderemos su solicitud a la mayor " +"brevedad posible.\n" +"

\n" +"

\n" +" ¡Gracias!\n" +"

\n" +"
\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
\n" +"

\n" +" Enviado por\n" +" " +"${object.activity_id.controller_id.display_name|safe}.\n" +"

\n" +"
\n" +"
\n" +" " + +#. module: privacy_consent +#: model:mail.message.subtype,name:privacy_consent.mt_activity_acceptance_changed +msgid "Acceptance Changed" +msgstr "Aceptación cambiada" + +#. module: privacy_consent +#: model:mail.message.subtype,name:privacy_consent.mt_consent_acceptance_changed +msgid "Acceptance Changed by Subject" +msgstr "Aceptación cambiada por el interesado" + +#. module: privacy_consent +#: model:mail.message.subtype,description:privacy_consent.mt_consent_acceptance_changed +msgid "Acceptance status updated by subject" +msgstr "Estado de aceptación modificado por el interesado" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_accepted +#: model:ir.ui.view,arch_db:privacy_consent.consent_search +msgid "Accepted" +msgstr "Aceptado" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_default_consent +msgid "Accepted by default" +msgstr "Aceptado por defecto" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_active +msgid "Active" +msgstr "Activo" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_activity_id +#: model:ir.ui.view,arch_db:privacy_consent.consent_search +msgid "Activity" +msgstr "Actividad" + +#. module: privacy_consent +#: selection:privacy.consent,state:0 +msgid "Answered" +msgstr "Respondido" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.consent_search +msgid "Archived" +msgstr "Archivado" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.consent_form +msgid "Ask for consent" +msgstr "Solicitar consentimiento" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_required +msgid "Ask subjects for consent" +msgstr "Solicitar consentimiento a los interesados" + +#. module: privacy_consent +#: selection:privacy.activity,consent_required:0 +msgid "Automatically" +msgstr "Automáticamente" + +#. module: privacy_consent +#: selection:privacy.consent,state:0 +msgid "Awaiting response" +msgstr "Esperando respuesta" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.activity_form +msgid "Consent" +msgstr "Consentimiento" + +#. module: privacy_consent +#: model:ir.model,name:privacy_consent.model_privacy_consent +msgid "Consent of data processing" +msgstr "Consentimiento para tratamiento de datos" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_template_default_body_html +msgid "Consent template default body html" +msgstr "HTML por defecto para el cuerpo de la plantilla de consentimiento" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_template_default_subject +msgid "Consent template default subject" +msgstr "HTML por defecto para el asunto de la plantilla de consentimiento" + +#. module: privacy_consent +#: model:ir.actions.act_window,name:privacy_consent.consent_action +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_count +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_ids +#: model:ir.model.fields,field_description:privacy_consent.field_res_partner_privacy_consent_count +#: model:ir.model.fields,field_description:privacy_consent.field_res_users_privacy_consent_count +#: model:ir.ui.menu,name:privacy_consent.menu_privacy_consent +msgid "Consents" +msgstr "Consents" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_create_uid +msgid "Created by" +msgstr "Creado por" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_create_date +msgid "Created on" +msgstr "Creado el" + +#. module: privacy_consent +#: model:ir.model,name:privacy_consent.model_privacy_activity +msgid "Data processing activities" +msgstr "Actividades de tratamiento de datos" + +#. module: privacy_consent +#: model:mail.template,subject:privacy_consent.template_consent +msgid "" +"Data processing consent request for ${object.activity_id.display_name|safe}" +msgstr "" +"Solicitud de consentimiento para el tratamiento de datos personales para " +"${object.activity_id.display_name|safe}" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_display_name +msgid "Display Name" +msgstr "Nombre a mostrar" + +#. module: privacy_consent +#: selection:privacy.consent,state:0 +msgid "Draft" +msgstr "Borrador" + +#. module: privacy_consent +#: sql_constraint:privacy.consent:0 +msgid "Duplicated partner in this data processing activity" +msgstr "Contacto duplicado en esta actividad de tratamiento" + +#. module: privacy_consent +#: model:ir.model,name:privacy_consent.model_mail_template +msgid "Email Templates" +msgstr "Plantillas de correo electrónico" + +#. module: privacy_consent +#: model:ir.model,name:privacy_consent.model_mail_compose_message +msgid "Email composition wizard" +msgstr "Asistente de redacción de correo electrónico" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_template_id +msgid "Email template" +msgstr "Plantilla de correo electrónico" + +#. module: privacy_consent +#: model:ir.model.fields,help:privacy_consent.field_privacy_activity_consent_template_id +msgid "" +"Email to be sent to subjects to ask for consent. A good template should " +"include details about the current consent request status, how to change it, " +"and where to get more information." +msgstr "" +"Correo electrónico a enviar a los interesados para solicitarles el " +"consentimiento. Una buena plantilla debería incluir detalles sobre el estado " +"actual del consentimiento, cómo cambiarlo, y dónde obtener más información." + +#. module: privacy_consent +#: model:ir.model.fields,help:privacy_consent.field_privacy_activity_consent_required +msgid "" +"Enable if you need to track any kind of consent from the affected subjects" +msgstr "" +"Actívelo si necesita registrar cualquier tipo de consentimiento de los " +"interesados." + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.activity_form +msgid "Generate and send missing consent requests" +msgstr "Generar y enviar solicitudes de consentimiento faltantes" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.activity_form +msgid "Generate missing draft consent requests" +msgstr "Generar borradores de las solicitudes de consentimiento faltantes" + +#. module: privacy_consent +#: code:addons/privacy_consent/models/privacy_activity.py:140 +#, python-format +msgid "Generated consents" +msgstr "Consentimientos generados" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.consent_search +msgid "Group By" +msgstr "Agrupar por" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.form +msgid "Hello," +msgstr "Hola," + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.form +msgid "I accept this processing of my data" +msgstr "Acepto este tratamiento de mis datos" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.form +msgid "I reject this processing of my data" +msgstr "Rechazo este tratamiento de mis datos" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_id +msgid "ID" +msgstr "ID" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.form +msgid "If it was a mistake, you can undo it here:" +msgstr "Si ha sido un error, puede deshacerlo aquí:" + +#. module: privacy_consent +#: model:ir.model.fields,help:privacy_consent.field_privacy_consent_accepted +msgid "" +"Indicates current acceptance status, which can come from subject's last " +"answer, or from the default specified in the related data processing " +"activity." +msgstr "" +"Indica el estado actual de la aceptación, el cual puede venir de la última " +"respuesta del interesado, o del estado por defecto especificado en la " +"actividad de tratamiento relacionada." + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent___last_update +msgid "Last Modified on" +msgstr "Última modificación en" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_write_uid +msgid "Last Updated by" +msgstr "Última actualización por" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_write_date +msgid "Last Updated on" +msgstr "Última actualización el" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_last_metadata +msgid "Last metadata" +msgstr "Últimos metadatos" + +#. module: privacy_consent +#: selection:privacy.activity,consent_required:0 +msgid "Manually" +msgstr "Manualmente" + +#. module: privacy_consent +#: model:ir.model.fields,help:privacy_consent.field_privacy_consent_last_metadata +msgid "Metadata from the last acceptance or rejection by the subject" +msgstr "" +"Metadatos de la última aceptación o denegación por parte del interesado" + +#. module: privacy_consent +#: code:addons/privacy_consent/models/mail_template.py:25 +#, python-format +msgid "" +"Missing privacy consent link placeholders. You need at least these two " +"links:\n" +"Accept\n" +"Reject" +msgstr "" +"Faltan los marcadores de posición de los enlaces para el consentimiento. " +"Necesita al menos estos dos enlaces:\n" +"Aceptar\n" +"Rechazar" + +#. module: privacy_consent +#: model:mail.message.subtype,name:privacy_consent.mt_activity_consent_new +#: model:mail.message.subtype,name:privacy_consent.mt_consent_consent_new +msgid "New Consent" +msgstr "Nuevo consentimiento" + +#. module: privacy_consent +#: model:ir.model,name:privacy_consent.model_mail_mail +msgid "Outgoing Mails" +msgstr "Correos electrónicos salientes" + +#. module: privacy_consent +#: model:ir.model,name:privacy_consent.model_res_partner +msgid "Partner" +msgstr "Contacto" + +#. module: privacy_consent +#: model:mail.message.subtype,description:privacy_consent.mt_activity_acceptance_changed +msgid "Privacy consent request acceptance status changed" +msgstr "" +"El estado de aceptación de la solicitud de consentimiento para el " +"tratamiento de datos ha cambiado" + +#. module: privacy_consent +#: model:mail.message.subtype,description:privacy_consent.mt_activity_consent_new +#: model:mail.message.subtype,description:privacy_consent.mt_consent_consent_new +msgid "Privacy consent request created" +msgstr "" +"La solicitud de consentimiento para el tratamiento de datos ha sido creada" + +#. module: privacy_consent +#: model:mail.message.subtype,description:privacy_consent.mt_activity_state_changed +#: model:mail.message.subtype,description:privacy_consent.mt_consent_state_changed +msgid "Privacy consent request state changed" +msgstr "" +"El estado de la solicitud de consentimiento para el tratamiento de datos ha " +"cambiado" + +#. module: privacy_consent +#: model:ir.model.fields,help:privacy_consent.field_res_partner_privacy_consent_count +#: model:ir.model.fields,help:privacy_consent.field_res_users_privacy_consent_count +msgid "Privacy consent requests amount" +msgstr "Cantidad de solicitudes de consentimiento para el tratamiento de datos" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_res_partner_privacy_consent_ids +#: model:ir.model.fields,field_description:privacy_consent.field_res_users_privacy_consent_ids +msgid "Privacy consents" +msgstr "Consentimientos para el tratamiento de datos" + +#. module: privacy_consent +#: code:addons/privacy_consent/models/privacy_activity.py:100 +#, python-format +msgid "Require consent is available only for subjects in current database." +msgstr "" +"La opción de exigir consentimiento solo está disponible para interesados que " +"se encuentren en esta misma base de datos." + +#. module: privacy_consent +#: model:ir.model.fields,help:privacy_consent.field_privacy_activity_server_action_id +msgid "" +"Run this action when a new consent request is created or its acceptance " +"status is updated." +msgstr "" +"Ejecutar esta acción cuando se cree una nueva solicitud de consentimiento, o " +"cuando su estado de aceptación cambie." + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_server_action_id +msgid "Server action" +msgstr "Acción de servidor" + +#. module: privacy_consent +#: model:ir.model.fields,help:privacy_consent.field_privacy_activity_default_consent +msgid "Should we assume the subject has accepted if we receive no response?" +msgstr "" +"¿Hay que asumir que el interesado ha aceptado si no recibimos respuesta?" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.form +msgid "Sincerely,
" +msgstr "Atentamente,
" + +#. module: privacy_consent +#: code:addons/privacy_consent/models/privacy_activity.py:92 +#, python-format +msgid "Specify a mail template to ask automated consent." +msgstr "" +"Especifique una plantilla de correo electrónico para solicitar " +"automáticamente el consentimiento." + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_state +#: model:ir.ui.view,arch_db:privacy_consent.consent_search +msgid "State" +msgstr "Estado" + +#. module: privacy_consent +#: model:mail.message.subtype,name:privacy_consent.mt_activity_state_changed +#: model:mail.message.subtype,name:privacy_consent.mt_consent_state_changed +msgid "State Changed" +msgstr "El estado ha cambiado" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_partner_id +msgid "Subject" +msgstr "Interesado" + +#. module: privacy_consent +#: model:ir.model.fields,help:privacy_consent.field_privacy_consent_partner_id +msgid "Subject asked for consent." +msgstr "Interesado a quien se le pide el consentimiento." + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.form +msgid "Thank you!" +msgstr "¡Gracias!" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.form +msgid "Thanks for your response." +msgstr "Gracias por su respuesta." + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.activity_form +msgid "This could send many consent emails, are you sure to proceed?" +msgstr "" +"Esto podría enviar muchos correos electrónicos solicitando consentimiento " +"para el tratamiento de datos, ¿seguro que quiere continuar?" + +#. module: privacy_consent +#: model:ir.actions.server,name:privacy_consent.update_opt_out +msgid "Update partner's opt out" +msgstr "Sincronizar la opción del contacto para recibir o no envíos masivos" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.form +msgid "" +"We asked you to authorize us to process your data in this data processing " +"activity:" +msgstr "" +"Le hemos solicitado que nos autorice para procesar sus datos personales en " +"esta actividad de tratamiento:" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.form +msgid "We have recorded this action on your side." +msgstr "Hemos registrado esta acción por su parte." + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.form +msgid "You have rejected such processing." +msgstr "Ha rechazado dicho tratamiento." + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.form +msgid "You have accepted such processing." +msgstr "Ha aceptado dicho tratamiento." diff --git a/privacy_consent/i18n/privacy_consent.pot b/privacy_consent/i18n/privacy_consent.pot new file mode 100644 index 00000000..51f7871e --- /dev/null +++ b/privacy_consent/i18n/privacy_consent.pot @@ -0,0 +1,487 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * privacy_consent +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.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: privacy_consent +#: model:mail.template,body_html:privacy_consent.template_consent +msgid "\n" +"
\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \n" +" \"${object.activity_id.controller_id.display_name|safe}\"\n" +" \n" +"
\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
\n" +"

\n" +" Hello, ${object.partner_id.name|safe}\n" +"

\n" +"

\n" +" We contacted you to ask you to give us your explicit consent to include your data in a data processing activity called\n" +" ${object.activity_id.display_name|safe}, property of\n" +" ${object.activity_id.controller_id.display_name|safe}\n" +"

\n" +" ${object.description or \"\"}\n" +"

\n" +" % if object.state == \"answered\":\n" +" The last time you answered, you\n" +" % elif object.state == \"sent\":\n" +" If you do nothing, we will assume you have\n" +" % endif\n" +"\n" +" % if object.accepted:\n" +" accepted\n" +" % else:\n" +" rejected\n" +" % endif\n" +" such data processing.\n" +"

\n" +"

\n" +" You can update your preferences below:\n" +"

\n" +"
\n" +" \n" +" Accept\n" +" \n" +" \n" +" \n" +" Reject\n" +" \n" +"
\n" +"

\n" +" If you need further information, please respond to this email and we will attend your request as soon as possible.\n" +"

\n" +"

\n" +" Thank you!\n" +"

\n" +"
\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
\n" +"

\n" +" Sent by\n" +" ${object.activity_id.controller_id.display_name|safe}.\n" +"

\n" +"
\n" +"
\n" +" " +msgstr "" + +#. module: privacy_consent +#: model:mail.message.subtype,name:privacy_consent.mt_activity_acceptance_changed +msgid "Acceptance Changed" +msgstr "" + +#. module: privacy_consent +#: model:mail.message.subtype,name:privacy_consent.mt_consent_acceptance_changed +msgid "Acceptance Changed by Subject" +msgstr "" + +#. module: privacy_consent +#: model:mail.message.subtype,description:privacy_consent.mt_consent_acceptance_changed +msgid "Acceptance status updated by subject" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_accepted +#: model:ir.ui.view,arch_db:privacy_consent.consent_search +msgid "Accepted" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_default_consent +msgid "Accepted by default" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_active +msgid "Active" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_activity_id +#: model:ir.ui.view,arch_db:privacy_consent.consent_search +msgid "Activity" +msgstr "" + +#. module: privacy_consent +#: selection:privacy.consent,state:0 +msgid "Answered" +msgstr "" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.consent_search +msgid "Archived" +msgstr "" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.consent_form +msgid "Ask for consent" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_required +msgid "Ask subjects for consent" +msgstr "" + +#. module: privacy_consent +#: selection:privacy.activity,consent_required:0 +msgid "Automatically" +msgstr "" + +#. module: privacy_consent +#: selection:privacy.consent,state:0 +msgid "Awaiting response" +msgstr "" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.activity_form +msgid "Consent" +msgstr "" + +#. module: privacy_consent +#: model:ir.model,name:privacy_consent.model_privacy_consent +msgid "Consent of data processing" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_template_default_body_html +msgid "Consent template default body html" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_template_default_subject +msgid "Consent template default subject" +msgstr "" + +#. module: privacy_consent +#: model:ir.actions.act_window,name:privacy_consent.consent_action +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_count +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_ids +#: model:ir.model.fields,field_description:privacy_consent.field_res_partner_privacy_consent_count +#: model:ir.model.fields,field_description:privacy_consent.field_res_users_privacy_consent_count +#: model:ir.ui.menu,name:privacy_consent.menu_privacy_consent +msgid "Consents" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_create_uid +msgid "Created by" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_create_date +msgid "Created on" +msgstr "" + +#. module: privacy_consent +#: model:ir.model,name:privacy_consent.model_privacy_activity +msgid "Data processing activities" +msgstr "" + +#. module: privacy_consent +#: model:mail.template,subject:privacy_consent.template_consent +msgid "Data processing consent request for ${object.activity_id.display_name|safe}" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_display_name +msgid "Display Name" +msgstr "" + +#. module: privacy_consent +#: selection:privacy.consent,state:0 +msgid "Draft" +msgstr "" + +#. module: privacy_consent +#: sql_constraint:privacy.consent:0 +msgid "Duplicated partner in this data processing activity" +msgstr "" + +#. module: privacy_consent +#: model:ir.model,name:privacy_consent.model_mail_template +msgid "Email Templates" +msgstr "" + +#. module: privacy_consent +#: model:ir.model,name:privacy_consent.model_mail_compose_message +msgid "Email composition wizard" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_template_id +msgid "Email template" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,help:privacy_consent.field_privacy_activity_consent_template_id +msgid "Email to be sent to subjects to ask for consent. A good template should include details about the current consent request status, how to change it, and where to get more information." +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,help:privacy_consent.field_privacy_activity_consent_required +msgid "Enable if you need to track any kind of consent from the affected subjects" +msgstr "" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.activity_form +msgid "Generate and send missing consent requests" +msgstr "" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.activity_form +msgid "Generate missing draft consent requests" +msgstr "" + +#. module: privacy_consent +#: code:addons/privacy_consent/models/privacy_activity.py:140 +#, python-format +msgid "Generated consents" +msgstr "" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.consent_search +msgid "Group By" +msgstr "" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.form +msgid "Hello," +msgstr "" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.form +msgid "I accept this processing of my data" +msgstr "" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.form +msgid "I reject this processing of my data" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_id +msgid "ID" +msgstr "" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.form +msgid "If it was a mistake, you can undo it here:" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,help:privacy_consent.field_privacy_consent_accepted +msgid "Indicates current acceptance status, which can come from subject's last answer, or from the default specified in the related data processing activity." +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent___last_update +msgid "Last Modified on" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_write_uid +msgid "Last Updated by" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_write_date +msgid "Last Updated on" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_last_metadata +msgid "Last metadata" +msgstr "" + +#. module: privacy_consent +#: selection:privacy.activity,consent_required:0 +msgid "Manually" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,help:privacy_consent.field_privacy_consent_last_metadata +msgid "Metadata from the last acceptance or rejection by the subject" +msgstr "" + +#. module: privacy_consent +#: code:addons/privacy_consent/models/mail_template.py:25 +#, python-format +msgid "Missing privacy consent link placeholders. You need at least these two links:\n" +"Accept\n" +"Reject" +msgstr "" + +#. module: privacy_consent +#: model:mail.message.subtype,name:privacy_consent.mt_activity_consent_new +#: model:mail.message.subtype,name:privacy_consent.mt_consent_consent_new +msgid "New Consent" +msgstr "" + +#. module: privacy_consent +#: model:ir.model,name:privacy_consent.model_mail_mail +msgid "Outgoing Mails" +msgstr "" + +#. module: privacy_consent +#: model:ir.model,name:privacy_consent.model_res_partner +msgid "Partner" +msgstr "" + +#. module: privacy_consent +#: model:mail.message.subtype,description:privacy_consent.mt_activity_acceptance_changed +msgid "Privacy consent request acceptance status changed" +msgstr "" + +#. module: privacy_consent +#: model:mail.message.subtype,description:privacy_consent.mt_activity_consent_new +#: model:mail.message.subtype,description:privacy_consent.mt_consent_consent_new +msgid "Privacy consent request created" +msgstr "" + +#. module: privacy_consent +#: model:mail.message.subtype,description:privacy_consent.mt_activity_state_changed +#: model:mail.message.subtype,description:privacy_consent.mt_consent_state_changed +msgid "Privacy consent request state changed" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,help:privacy_consent.field_res_partner_privacy_consent_count +#: model:ir.model.fields,help:privacy_consent.field_res_users_privacy_consent_count +msgid "Privacy consent requests amount" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_res_partner_privacy_consent_ids +#: model:ir.model.fields,field_description:privacy_consent.field_res_users_privacy_consent_ids +msgid "Privacy consents" +msgstr "" + +#. module: privacy_consent +#: code:addons/privacy_consent/models/privacy_activity.py:100 +#, python-format +msgid "Require consent is available only for subjects in current database." +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,help:privacy_consent.field_privacy_activity_server_action_id +msgid "Run this action when a new consent request is created or its acceptance status is updated." +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_server_action_id +msgid "Server action" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,help:privacy_consent.field_privacy_activity_default_consent +msgid "Should we assume the subject has accepted if we receive no response?" +msgstr "" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.form +msgid "Sincerely,
" +msgstr "" + +#. module: privacy_consent +#: code:addons/privacy_consent/models/privacy_activity.py:92 +#, python-format +msgid "Specify a mail template to ask automated consent." +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_state +#: model:ir.ui.view,arch_db:privacy_consent.consent_search +msgid "State" +msgstr "" + +#. module: privacy_consent +#: model:mail.message.subtype,name:privacy_consent.mt_activity_state_changed +#: model:mail.message.subtype,name:privacy_consent.mt_consent_state_changed +msgid "State Changed" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_partner_id +msgid "Subject" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,help:privacy_consent.field_privacy_consent_partner_id +msgid "Subject asked for consent." +msgstr "" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.form +msgid "Thank you!" +msgstr "" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.form +msgid "Thanks for your response." +msgstr "" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.activity_form +msgid "This could send many consent emails, are you sure to proceed?" +msgstr "" + +#. module: privacy_consent +#: model:ir.actions.server,name:privacy_consent.update_opt_out +msgid "Update partner's opt out" +msgstr "" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.form +msgid "We asked you to authorize us to process your data in this data processing activity:" +msgstr "" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.form +msgid "We have recorded this action on your side." +msgstr "" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.form +msgid "You have rejected such processing." +msgstr "" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.form +msgid "You have accepted such processing." +msgstr "" + diff --git a/privacy_consent/models/__init__.py b/privacy_consent/models/__init__.py new file mode 100644 index 00000000..e776de37 --- /dev/null +++ b/privacy_consent/models/__init__.py @@ -0,0 +1,5 @@ +from . import mail_mail +from . import mail_template +from . import privacy_activity +from . import privacy_consent +from . import res_partner diff --git a/privacy_consent/models/mail_mail.py b/privacy_consent/models/mail_mail.py new file mode 100644 index 00000000..e53e7fc6 --- /dev/null +++ b/privacy_consent/models/mail_mail.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- +# Copyright 2018 Tecnativa - Jairo Llopis +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import models + + +class MailMail(models.Model): + _inherit = "mail.mail" + + def _postprocess_sent_message(self, mail_sent=True): + """Write consent status after sending message.""" + if mail_sent and self.env.context.get('mark_consent_sent'): + # Get all mails sent to consents + consent_mails = self.filtered( + lambda one: one.mail_message_id.model == "privacy.consent" + ) + # Get related draft consents + consents = self.env["privacy.consent"].browse( + consent_mails.mapped("mail_message_id.res_id"), + self._prefetch + ).filtered(lambda one: one.state == "draft") + # Set as sent + consents.write({ + "state": "sent", + }) + return super(MailMail, self)._postprocess_sent_message(mail_sent) + + def send_get_mail_body(self, partner=None): + """Replace privacy consent magic links. + + This replacement is done here instead of directly writing it into + the ``mail.template`` to avoid writing the tokeinzed URL + in the mail thread for the ``privacy.consent`` record, + which would enable any reader of such thread to impersonate the + subject and choose in its behalf. + """ + result = super(MailMail, self).send_get_mail_body(partner=partner) + # Avoid polluting other model mails + if self.env.context.get("active_model") != "privacy.consent": + return result + # Tokenize consent links + consent = self.env["privacy.consent"] \ + .browse(self.mail_message_id.res_id) \ + .with_prefetch(self._prefetch) + result = result.replace( + "/privacy/consent/accept/", + consent._url(True), + ) + result = result.replace( + "/privacy/consent/reject/", + consent._url(False), + ) + return result diff --git a/privacy_consent/models/mail_template.py b/privacy_consent/models/mail_template.py new file mode 100644 index 00000000..a5fcec23 --- /dev/null +++ b/privacy_consent/models/mail_template.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +# Copyright 2018 Tecnativa - Jairo Llopis +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from lxml import html + +from odoo import _, api, models +from odoo.exceptions import ValidationError + + +class MailTemplate(models.Model): + _inherit = "mail.template" + + @api.constrains("body_html", "model") + def _check_consent_links_in_body_html(self): + """Body for ``privacy.consent`` templates needs placeholder links.""" + links = [u"//a[@href='/privacy/consent/{}/']".format(action) + for action in ("accept", "reject")] + for one in self: + if one.model != "privacy.consent": + continue + doc = html.document_fromstring(one.body_html) + for link in links: + if not doc.xpath(link): + raise ValidationError(_( + "Missing privacy consent link placeholders. " + "You need at least these two links:\n" + 'Accept\n' + 'Reject' + ) % ( + "/privacy/consent/accept/", + "/privacy/consent/reject/", + )) diff --git a/privacy_consent/models/privacy_activity.py b/privacy_consent/models/privacy_activity.py new file mode 100644 index 00000000..c7d20c93 --- /dev/null +++ b/privacy_consent/models/privacy_activity.py @@ -0,0 +1,144 @@ +# -*- coding: utf-8 -*- +# Copyright 2018 Tecnativa - Jairo Llopis +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import _, api, fields, models +from odoo.exceptions import ValidationError +from odoo.tools.safe_eval import safe_eval + + +class PrivacyActivity(models.Model): + _inherit = 'privacy.activity' + + server_action_id = fields.Many2one( + "ir.actions.server", + "Server action", + domain=[ + ("model_id.model", "=", "privacy.consent"), + ], + help="Run this action when a new consent request is created or its " + "acceptance status is updated.", + ) + consent_ids = fields.One2many( + "privacy.consent", + "activity_id", + "Consents", + ) + consent_count = fields.Integer( + "Consents", + compute="_compute_consent_count", + ) + consent_required = fields.Selection( + [("auto", "Automatically"), ("manual", "Manually")], + "Ask subjects for consent", + help="Enable if you need to track any kind of consent " + "from the affected subjects", + ) + consent_template_id = fields.Many2one( + "mail.template", + "Email template", + default=lambda self: self._default_consent_template_id(), + domain=[ + ("model", "=", "privacy.consent"), + ], + help="Email to be sent to subjects to ask for consent. " + "A good template should include details about the current " + "consent request status, how to change it, and where to " + "get more information.", + ) + default_consent = fields.Boolean( + "Accepted by default", + help="Should we assume the subject has accepted if we receive no " + "response?", + ) + + # Hidden helpers help user design new templates + consent_template_default_body_html = fields.Text( + compute="_compute_consent_template_defaults", + ) + consent_template_default_subject = fields.Char( + compute="_compute_consent_template_defaults", + ) + + @api.model + def _default_consent_template_id(self): + return self.env.ref("privacy_consent.template_consent", False) + + @api.depends("consent_ids") + def _compute_consent_count(self): + groups = self.env["privacy.consent"].read_group( + [("activity_id", "in", self.ids)], + ["activity_id"], + ["activity_id"], + ) + for group in groups: + self.browse(group["activity_id"][0], self._prefetch) \ + .consent_count = group["activity_id_count"] + + def _compute_consent_template_defaults(self): + """Used in context values, to help users design new templates.""" + template = self._default_consent_template_id() + if template: + self.update({ + "consent_template_default_body_html": template.body_html, + "consent_template_default_subject": template.subject, + }) + + @api.constrains("consent_required", "consent_template_id") + def _check_auto_consent_has_template(self): + """Require a mail template to automate consent requests.""" + for one in self: + if one.consent_required == "auto" and not one.consent_template_id: + raise ValidationError(_( + "Specify a mail template to ask automated consent." + )) + + @api.constrains("consent_required", "subject_find") + def _check_consent_required_subject_find(self): + for one in self: + if one.consent_required and not one.subject_find: + raise ValidationError(_( + "Require consent is available only for subjects " + "in current database." + )) + + @api.model + def _cron_new_consents(self): + """Ask all missing automatic consent requests.""" + automatic = self.search([("consent_required", "=", "auto")]) + automatic.action_new_consents() + + @api.onchange("consent_required") + def _onchange_consent_required_subject_find(self): + """Find subjects automatically if we require their consent.""" + if self.consent_required: + self.subject_find = True + + def action_new_consents(self): + """Generate new consent requests.""" + consents = self.env["privacy.consent"] + # Skip activitys where consent is not required + for one in self.with_context(active_test=False) \ + .filtered("consent_required"): + domain = safe_eval(one.subject_domain) + domain += [ + ("id", "not in", one.mapped("consent_ids.partner_id").ids), + ("email", "!=", False), + ] + # Create missing consent requests + for missing in self.env["res.partner"].search(domain): + consents |= consents.create({ + "partner_id": missing.id, + "accepted": one.default_consent, + "activity_id": one.id, + }) + # Send consent request emails for automatic activitys + consents.action_auto_ask() + # Redirect user to new consent requests generated + return { + "domain": [("id", "in", consents.ids)], + "name": _("Generated consents"), + "res_model": consents._name, + "type": "ir.actions.act_window", + "view_mode": "tree,form", + } diff --git a/privacy_consent/models/privacy_consent.py b/privacy_consent/models/privacy_consent.py new file mode 100644 index 00000000..6dacd979 --- /dev/null +++ b/privacy_consent/models/privacy_consent.py @@ -0,0 +1,201 @@ +# -*- coding: utf-8 -*- +# Copyright 2018 Tecnativa - Jairo Llopis +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +import hashlib +import hmac + +from odoo import api, fields, models + + +class PrivacyConsent(models.Model): + _name = 'privacy.consent' + _description = "Consent of data processing" + _inherit = "mail.thread" + _rec_name = "partner_id" + _sql_constraints = [ + ("unique_partner_activity", "UNIQUE(partner_id, activity_id)", + "Duplicated partner in this data processing activity"), + ] + + active = fields.Boolean( + default=True, + index=True, + ) + accepted = fields.Boolean( + track_visibility="onchange", + help="Indicates current acceptance status, which can come from " + "subject's last answer, or from the default specified in the " + "related data processing activity.", + ) + last_metadata = fields.Text( + readonly=True, + track_visibility="onchange", + help="Metadata from the last acceptance or rejection by the subject", + ) + partner_id = fields.Many2one( + "res.partner", + "Subject", + required=True, + readonly=True, + track_visibility="onchange", + help="Subject asked for consent.", + ) + activity_id = fields.Many2one( + "privacy.activity", + "Activity", + readonly=True, + required=True, + track_visibility="onchange", + ) + state = fields.Selection( + selection=[ + ("draft", "Draft"), + ("sent", "Awaiting response"), + ("answered", "Answered"), + ], + default="draft", + readonly=True, + required=True, + track_visibility="onchange", + ) + + def _track_subtype(self, init_values): + """Return specific subtypes.""" + if self.env.context.get("subject_answering"): + return "privacy_consent.mt_consent_acceptance_changed" + if "activity_id" in init_values or "partner_id" in init_values: + return "privacy_consent.mt_consent_consent_new" + if "state" in init_values: + return "privacy_consent.mt_consent_state_changed" + return super(PrivacyConsent, self)._track_subtype(init_values) + + def _token(self): + """Secret token to publicly authenticate this record.""" + secret = self.env["ir.config_parameter"].sudo().get_param( + "database.secret") + params = "{}-{}-{}-{}".format( + self.env.cr.dbname, + self.id, + self.partner_id.id, + self.activity_id.id, + ) + return hmac.new( + secret.encode('utf-8'), + params.encode('utf-8'), + hashlib.sha512, + ).hexdigest() + + def _url(self, accept): + """Tokenized URL to let subject decide consent. + + :param bool accept: + Indicates if you want the acceptance URL, or the rejection one. + """ + return "/privacy/consent/{}/{}/{}?db={}".format( + "accept" if accept else "reject", + self.id, + self._token(), + self.env.cr.dbname, + ) + + def _send_consent_notification(self): + """Send email notification to subject.""" + consents_by_template = {} + for one in self.with_context(tpl_force_default_to=True, + mail_notify_user_signature=False, + mail_auto_subscribe_no_notify=True, + mark_consent_sent=True): + # Group consents by template, to send in batch where possible + template_id = one.activity_id.consent_template_id.id + consents_by_template.setdefault(template_id, one) + consents_by_template[template_id] |= one + # Send emails + for template_id, consents in consents_by_template.items(): + consents.message_post_with_template( + template_id, + # This mode always sends email, regardless of partner's + # notification preferences; we use it here because it's very + # likely that we are asking authorisation to send emails + composition_mode="mass_mail", + ) + + def _run_action(self): + """Execute server action defined in data processing activity.""" + for one in self: + # Always skip draft consents + if one.state == "draft": + continue + action = one.activity_id.server_action_id.with_context( + active_id=one.id, + active_ids=one.ids, + active_model=one._name, + ) + action.run() + + @api.model + def create(self, vals): + """Run server action on create.""" + result = super(PrivacyConsent, self).create(vals) + # Sync the default acceptance status + result.sudo()._run_action() + return result + + def write(self, vals): + """Run server action on update.""" + result = super(PrivacyConsent, self).write(vals) + self._run_action() + return result + + def message_get_suggested_recipients(self): + result = super(PrivacyConsent, self) \ + .message_get_suggested_recipients() + reason = self._fields["partner_id"].string + for one in self: + one._message_add_suggested_recipient( + result, + partner=one.partner_id, + reason=reason, + ) + return result + + def action_manual_ask(self): + """Let user manually ask for consent.""" + return { + "context": { + "default_composition_mode": "mass_mail", + "default_model": self._name, + "default_res_id": self.id, + "default_template_id": self.activity_id.consent_template_id.id, + "default_use_template": True, + "mark_consent_sent": True, + "tpl_force_default_to": True, + }, + "force_email": True, + "res_model": "mail.compose.message", + "target": "new", + "type": "ir.actions.act_window", + "view_mode": "form", + } + + def action_auto_ask(self): + """Automatically ask for consent.""" + templated = self.filtered("activity_id.consent_template_id") + automated = templated.filtered( + lambda one: one.activity_id.consent_required == "auto") + automated._send_consent_notification() + + def action_answer(self, answer, metadata=False): + """Process answer. + + :param bool answer: + Did the subject accept? + + :param str metadata: + Metadata from last user acceptance or rejection request. + """ + self.write({ + "state": "answered", + "accepted": answer, + "last_metadata": metadata, + }) diff --git a/privacy_consent/models/res_partner.py b/privacy_consent/models/res_partner.py new file mode 100644 index 00000000..b97eab5c --- /dev/null +++ b/privacy_consent/models/res_partner.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- +# Copyright 2018 Tecnativa - Jairo Llopis +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import api, fields, models + + +class ResPartner(models.Model): + _inherit = "res.partner" + + privacy_consent_ids = fields.One2many( + "privacy.consent", + "partner_id", + "Privacy consents", + ) + privacy_consent_count = fields.Integer( + "Consents", + compute="_compute_privacy_consent_count", + help="Privacy consent requests amount", + ) + + @api.depends("privacy_consent_ids") + def _compute_privacy_consent_count(self): + """Count consent requests.""" + groups = self.env["privacy.consent"].read_group( + [("partner_id", "in", self.ids)], + ["partner_id"], + ["partner_id"], + ) + for group in groups: + self.browse(group["partner_id"][0], self._prefetch) \ + .privacy_consent_count = group["partner_id_count"] diff --git a/privacy_consent/readme/CONTRIBUTORS.rst b/privacy_consent/readme/CONTRIBUTORS.rst new file mode 100644 index 00000000..8c4d9684 --- /dev/null +++ b/privacy_consent/readme/CONTRIBUTORS.rst @@ -0,0 +1,3 @@ +* `Tecnativa `_: + + * Jairo Llopis diff --git a/privacy_consent/readme/DESCRIPTION.rst b/privacy_consent/readme/DESCRIPTION.rst new file mode 100644 index 00000000..dfce06f9 --- /dev/null +++ b/privacy_consent/readme/DESCRIPTION.rst @@ -0,0 +1,7 @@ +This module allows the user to define a set of subjects (partners) +affected by any data processing activity, and establish +a process to ask them for consent to include them in that activity. + +For those that need explicit consent as a lawfulness base for personal data +processing, as required by GDPR (article 6.1.a), this module provides the +needed tools to automate it. diff --git a/privacy_consent/readme/INSTALL.rst b/privacy_consent/readme/INSTALL.rst new file mode 100644 index 00000000..dabd03d5 --- /dev/null +++ b/privacy_consent/readme/INSTALL.rst @@ -0,0 +1,15 @@ +You may want to install, along with this module, one of OCA's +``mail_tracking`` module collection, such as ``mail_tracking_mailgun``, so +you can provide more undeniable proof that some consent request was sent, and +to whom. + +However, the most important proof to provide is the answer itself (more than +the question), and this addon provides enough tooling for that. + +Multi-database instances +~~~~~~~~~~~~~~~~~~~~~~~~ + +To enable multi-database support, you must load this addon as a server-wide +addon. Example command to boot Odoo:: + + odoo-bin --load=web,privacy_consent diff --git a/privacy_consent/readme/USAGE.rst b/privacy_consent/readme/USAGE.rst new file mode 100644 index 00000000..68d4aecf --- /dev/null +++ b/privacy_consent/readme/USAGE.rst @@ -0,0 +1,69 @@ +New options for data processing activities: + +#. Go to *Privacy > Master Data > Activities* and create one. + +#. Give it a name, such as *Sending mass mailings to customers*. + +#. Go to tab *Consent* and choose one option in *Ask subjects for consent*: + + * *Manual* tells the activity that you will want to create and send the + consent requests manually, and only provides some helpers for you to + be able to batch-generate them. + + * *Automatic* enables this module's full power: send all consent requests + to selected partners automatically, every day and under your demand. + +#. When you do this, all the consent-related options appear. Configure them: + + * A smart button tells you how many consents have been generated, and lets you + access them. + + * Choose one *Email template* to send to subjects. This email itself is what + asks for consent, and it gets recorded, to serve as a proof that it was sent. + The module provides a default template that should be good for most usage + cases; and if you create one directly from that field, some good defaults + are provided for your comfortability. + + * *Subjects filter* defines what partners will be elegible for inclusion in + this data processing activity. + + * You can enable *Accepted by default* if you want to assume subjects + accepted their data processing. You should possibly consult your + lawyer to use this. + + * You can choose a *Server action* (developer mode only) that will + be executed whenever a new non-draft consent request is created, + or when its acceptance status changes. + + This module supplies a server action by default, called + *Update partner's opt out*, that syncs the acceptance status with the + partner's *Elegible for mass mailings* option. + +#. Click on *Generate consent requests* link to create new consent requests. + + * If you chose *Manual* mode, all missing consent request are created as + drafts, and nothing else is done now. + + * If you chose *Automatic* mode, also those requests are sent to subjects + and set as *Sent*. + +#. You will be presented with the list of just-created consent requests. + See below. + +New options for consent requests: + +#. Access the consent requests by either: + + * Generating new consent requests from a data processing activity. + + * Pressing the *Consents* smart button in a data processing activity. + + * Going to *Privacy > Privacy > Consents*. + +#. A consent will include the partner, the activity, the acceptance status, + and the request state. + +#. You can manually ask for consent by pressing the button labeled as + *Ask for consent*. + +#. All consent requests and responses are recorded in the mail thread below. diff --git a/privacy_consent/security/ir.model.access.csv b/privacy_consent/security/ir.model.access.csv new file mode 100644 index 00000000..28285e43 --- /dev/null +++ b/privacy_consent/security/ir.model.access.csv @@ -0,0 +1,3 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +privacy_consent_read,Permission to read consents,model_privacy_consent,privacy.group_data_protection_user,1,0,0,0 +privacy_consent_write,Permission to write consents,model_privacy_consent,privacy.group_data_protection_manager,1,1,1,1 diff --git a/privacy_consent/static/description/icon.png b/privacy_consent/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<+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+Zl&#s4&}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/privacy_consent/static/description/index.html b/privacy_consent/static/description/index.html new file mode 100644 index 00000000..58af3e37 --- /dev/null +++ b/privacy_consent/static/description/index.html @@ -0,0 +1,520 @@ + + + + + + +Privacy - Consent + + + + + + diff --git a/privacy_consent/templates/form.xml b/privacy_consent/templates/form.xml new file mode 100644 index 00000000..b0e260b5 --- /dev/null +++ b/privacy_consent/templates/form.xml @@ -0,0 +1,63 @@ + + + + + + + + diff --git a/privacy_consent/tests/__init__.py b/privacy_consent/tests/__init__.py new file mode 100644 index 00000000..42ba786f --- /dev/null +++ b/privacy_consent/tests/__init__.py @@ -0,0 +1 @@ +from . import test_consent diff --git a/privacy_consent/tests/test_consent.py b/privacy_consent/tests/test_consent.py new file mode 100644 index 00000000..7af0a90a --- /dev/null +++ b/privacy_consent/tests/test_consent.py @@ -0,0 +1,247 @@ +# -*- coding: utf-8 -*- +# Copyright 2018 Tecnativa - Jairo Llopis +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from contextlib import contextmanager + +from odoo.exceptions import ValidationError +from odoo.tests.common import at_install, post_install, HttpCase + + +@at_install(False) +@post_install(True) +class ActivityCase(HttpCase): + def setUp(self): + super(ActivityCase, self).setUp() + # HACK https://github.com/odoo/odoo/issues/12237 + # TODO Remove hack in v12 + self._oldenv = self.env + self.env = self._oldenv(self.cursor()) + # HACK end + self.cron = self.env.ref("privacy_consent.cron_auto_consent") + self.update_opt_out = self.env.ref("privacy_consent.update_opt_out") + self.mt_consent_consent_new = self.env.ref( + "privacy_consent.mt_consent_consent_new") + self.mt_consent_acceptance_changed = self.env.ref( + "privacy_consent.mt_consent_acceptance_changed") + self.mt_consent_state_changed = self.env.ref( + "privacy_consent.mt_consent_state_changed") + # Some partners to ask for consent + self.partners = self.env["res.partner"] + self.partners += self.partners.create({ + "name": "consent-partner-0", + "email": "partner0@example.com", + "notify_email": "none", + "opt_out": False, + }) + self.partners += self.partners.create({ + "name": "consent-partner-1", + "email": "partner1@example.com", + "notify_email": "always", + "opt_out": True, + }) + self.partners += self.partners.create({ + "name": "consent-partner-2", + "email": "partner2@example.com", + "opt_out": False, + }) + # Partner without email, on purpose + self.partners += self.partners.create({ + "name": "consent-partner-3", + "opt_out": True, + }) + # Activity without consent + self.activity_noconsent = self.env["privacy.activity"].create({ + "name": "activity_noconsent", + "description": "I'm activity 1", + }) + # Activity with auto consent, for all partners + self.activity_auto = self.env["privacy.activity"].create({ + "name": "activity_auto", + "description": "I'm activity auto", + "subject_find": True, + "subject_domain": repr([("id", "in", self.partners.ids)]), + "consent_required": "auto", + "default_consent": True, + "server_action_id": self.update_opt_out.id, + }) + # Activity with manual consent, skipping partner 0 + self.activity_manual = self.env["privacy.activity"].create({ + "name": "activity_manual", + "description": "I'm activity 3", + "subject_find": True, + "subject_domain": repr([("id", "in", self.partners[1:].ids)]), + "consent_required": "manual", + "default_consent": False, + "server_action_id": self.update_opt_out.id, + }) + + # HACK https://github.com/odoo/odoo/issues/12237 + # TODO Remove hack in v12 + def tearDown(self): + self.env = self._oldenv + super(ActivityCase, self).tearDown() + + # HACK https://github.com/odoo/odoo/issues/12237 + # TODO Remove hack in v12 + @contextmanager + def release_cr(self): + self.env.cr.release() + yield + self.env.cr.acquire() + + def check_activity_auto_properly_sent(self): + """Check emails sent by ``self.activity_auto``.""" + consents = self.env["privacy.consent"].search([ + ("activity_id", "=", self.activity_auto.id), + ]) + # Check sent mails + for consent in consents: + self.assertEqual(consent.state, "sent") + messages = consent.mapped("message_ids") + self.assertEqual(len(messages), 4) + # 2nd message notifies creation + self.assertEqual( + messages[2].subtype_id, + self.mt_consent_consent_new, + ) + # 3rd message notifies subject + # Placeholder links should be logged + self.assertTrue("/privacy/consent/accept/" in messages[1].body) + self.assertTrue("/privacy/consent/reject/" in messages[1].body) + # Tokenized links shouldn't be logged + self.assertFalse(consent._url(True) in messages[1].body) + self.assertFalse(consent._url(False) in messages[1].body) + # 4th message contains the state change + self.assertEqual( + messages[0].subtype_id, + self.mt_consent_state_changed, + ) + # Partner's opt_out should be synced with default consent + self.assertFalse(consent.partner_id.opt_out) + + def test_default_template(self): + """We have a good mail template by default.""" + good = self.env.ref("privacy_consent.template_consent") + self.assertEqual( + self.activity_noconsent.consent_template_id, + good, + ) + self.assertEqual( + self.activity_noconsent.consent_template_default_body_html, + good.body_html, + ) + self.assertEqual( + self.activity_noconsent.consent_template_default_subject, + good.subject, + ) + + def test_find_subject_if_consent_required(self): + """If user wants to require consent, it needs subjects.""" + # Test the onchange helper + onchange_activity1 = self.env["privacy.activity"].new( + self.activity_noconsent.copy_data()[0]) + self.assertFalse(onchange_activity1.subject_find) + onchange_activity1.consent_required = "auto" + onchange_activity1._onchange_consent_required_subject_find() + self.assertTrue(onchange_activity1.subject_find) + # Test very dumb user that forces an error + with self.assertRaises(ValidationError): + self.activity_noconsent.consent_required = "manual" + + def test_template_required_auto(self): + """Automatic consent activities need a template.""" + self.activity_noconsent.subject_find = True + self.activity_noconsent.consent_template_id = False + self.activity_noconsent.consent_required = "manual" + with self.assertRaises(ValidationError): + self.activity_noconsent.consent_required = "auto" + + def test_generate_manually(self): + """Manually-generated consents work as expected.""" + self.partners.write({"opt_out": False}) + result = self.activity_manual.action_new_consents() + self.assertEqual(result["res_model"], "privacy.consent") + consents = self.env[result["res_model"]].search(result["domain"]) + self.assertEqual(consents.mapped("state"), ["draft"] * 2) + self.assertEqual(consents.mapped("partner_id.opt_out"), [False] * 2) + self.assertEqual(consents.mapped("accepted"), [False] * 2) + self.assertEqual(consents.mapped("last_metadata"), [False] * 2) + # Check sent mails + messages = consents.mapped("message_ids") + self.assertEqual(len(messages), 4) + subtypes = messages.mapped("subtype_id") + self.assertTrue(subtypes & self.mt_consent_consent_new) + self.assertFalse(subtypes & self.mt_consent_acceptance_changed) + self.assertFalse(subtypes & self.mt_consent_state_changed) + # Send one manual request + action = consents[0].action_manual_ask() + self.assertEqual(action["res_model"], "mail.compose.message") + composer = self.env[action["res_model"]] \ + .with_context(active_ids=consents[0].ids, + active_model=consents._name, + **action["context"]).create({}) + composer.onchange_template_id_wrapper() + composer.send_mail() + messages = consents.mapped("message_ids") - messages + self.assertEqual(len(messages), 2) + self.assertEqual(messages[0].subtype_id, self.mt_consent_state_changed) + self.assertEqual(consents.mapped("state"), ["sent", "draft"]) + self.assertEqual(consents.mapped("partner_id.opt_out"), [True, False]) + # Placeholder links should be logged + self.assertTrue("/privacy/consent/accept/" in messages[1].body) + self.assertTrue("/privacy/consent/reject/" in messages[1].body) + # Tokenized links shouldn't be logged + accept_url = consents[0]._url(True) + reject_url = consents[0]._url(False) + self.assertNotIn(accept_url, messages[1].body) + self.assertNotIn(reject_url, messages[1].body) + # Visit tokenized accept URL + with self.release_cr(): + result = self.url_open(accept_url).read() + self.assertIn("accepted", result) + self.assertIn(reject_url, result) + self.assertIn(self.activity_manual.name, result) + self.assertIn(self.activity_manual.description, result) + consents.invalidate_cache() + self.assertEqual(consents.mapped("accepted"), [True, False]) + self.assertTrue(consents[0].last_metadata) + self.assertFalse(consents[0].partner_id.opt_out) + self.assertEqual(consents.mapped("state"), ["answered", "draft"]) + self.assertEqual( + consents[0].message_ids[0].subtype_id, + self.mt_consent_acceptance_changed, + ) + # Visit tokenized reject URL + with self.release_cr(): + result = self.url_open(reject_url).read() + self.assertIn("rejected", result) + self.assertIn(accept_url, result) + self.assertIn(self.activity_manual.name, result) + self.assertIn(self.activity_manual.description, result) + consents.invalidate_cache() + self.assertEqual(consents.mapped("accepted"), [False, False]) + self.assertTrue(consents[0].last_metadata) + self.assertTrue(consents[0].partner_id.opt_out) + self.assertEqual(consents.mapped("state"), ["answered", "draft"]) + self.assertEqual( + consents[0].message_ids[0].subtype_id, + self.mt_consent_acceptance_changed, + ) + self.assertFalse(consents[1].last_metadata) + + def test_generate_automatically(self): + """Automatically-generated consents work as expected.""" + result = self.activity_auto.action_new_consents() + self.assertEqual(result["res_model"], "privacy.consent") + self.check_activity_auto_properly_sent() + + def test_generate_cron(self): + """Cron-generated consents work as expected.""" + self.cron.method_direct_trigger() + self.check_activity_auto_properly_sent() + + def test_mail_template_without_links(self): + """Cannot create mail template without needed links.""" + with self.assertRaises(ValidationError): + self.activity_manual.consent_template_id.body_html = "No links :(" diff --git a/privacy_consent/views/privacy_activity.xml b/privacy_consent/views/privacy_activity.xml new file mode 100644 index 00000000..35c9e5f7 --- /dev/null +++ b/privacy_consent/views/privacy_activity.xml @@ -0,0 +1,89 @@ + + + + + + + Add consent fields + privacy.activity + + +
+ + +
+ + + + + + + + + + + + + + + + + + +
+
+ +
diff --git a/privacy_consent/views/privacy_consent.xml b/privacy_consent/views/privacy_consent.xml new file mode 100644 index 00000000..5526a03d --- /dev/null +++ b/privacy_consent/views/privacy_consent.xml @@ -0,0 +1,113 @@ + + + + + + + Privacy Consent Form + privacy.consent + +
+
+
+ +
+ +
+ + + + + + +
+
+ + +
+
+
+
+ + + Privacy Consent Tree + privacy.consent + + + + + + + + + + + + Privacy Consent Search + privacy.consent + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/privacy_consent/views/res_partner.xml b/privacy_consent/views/res_partner.xml new file mode 100644 index 00000000..d1173d98 --- /dev/null +++ b/privacy_consent/views/res_partner.xml @@ -0,0 +1,35 @@ + + + + + + + Add consent smart button + res.partner + + + +
+ + +
+
+
+ +
diff --git a/privacy_consent/wizards/__init__.py b/privacy_consent/wizards/__init__.py new file mode 100644 index 00000000..b528d997 --- /dev/null +++ b/privacy_consent/wizards/__init__.py @@ -0,0 +1 @@ +from . import mail_compose_message diff --git a/privacy_consent/wizards/mail_compose_message.py b/privacy_consent/wizards/mail_compose_message.py new file mode 100644 index 00000000..a63ecc1b --- /dev/null +++ b/privacy_consent/wizards/mail_compose_message.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- +# Copyright 2018 Tecnativa - Jairo Llopis +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import api, models + + +class MailComposeMessage(models.TransientModel): + _inherit = "mail.compose.message" + + @api.multi + def send_mail(self, auto_commit=False): + """Force auto commit when sending consent emails.""" + if self.env.context.get('mark_consent_sent'): + auto_commit = True + return super(MailComposeMessage, self).send_mail(auto_commit) From 1f9f0b4374c3085694ae5930992c0c6276cb4490 Mon Sep 17 00:00:00 2001 From: Pedro Castro Silva Date: Thu, 20 Sep 2018 15:34:04 +0000 Subject: [PATCH 02/41] Added translation using Weblate (Portuguese) --- privacy_consent/i18n/pt.po | 615 +++++++++++++++++++++++++++++++++++++ 1 file changed, 615 insertions(+) create mode 100644 privacy_consent/i18n/pt.po diff --git a/privacy_consent/i18n/pt.po b/privacy_consent/i18n/pt.po new file mode 100644 index 00000000..48892122 --- /dev/null +++ b/privacy_consent/i18n/pt.po @@ -0,0 +1,615 @@ +msgid "" +msgstr "" +"Project-Id-Version: Portuguese (data-protection-10.0)\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2018-09-22 09:44+0000\n" +"Last-Translator: Pedro Castro Silva \n" +"Language-Team: Portuguese \n" +"Language: pt\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" +"X-Generator: Weblate 3.1.1\n" + +#. module: privacy_consent +#: model:mail.template,body_html:privacy_consent.template_consent +msgid "\n" +"
\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \n" +" \"${object.activity_id.controller_id.display_name|safe}\"\n" +" \n" +"
\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
\n" +"

\n" +" Hello, ${object.partner_id.name|safe}\n" +"

\n" +"

\n" +" We contacted you to ask you to give us your explicit consent to include your data in a data processing activity called\n" +" ${object.activity_id.display_name|safe}, property of\n" +" ${object.activity_id.controller_id.display_name|safe}\n" +"

\n" +" ${object.description or \"\"}\n" +"

\n" +" % if object.state == \"answered\":\n" +" The last time you answered, you\n" +" % elif object.state == \"sent\":\n" +" If you do nothing, we will assume you have\n" +" % endif\n" +"\n" +" % if object.accepted:\n" +" accepted\n" +" % else:\n" +" rejected\n" +" % endif\n" +" such data processing.\n" +"

\n" +"

\n" +" You can update your preferences below:\n" +"

\n" +"
\n" +" \n" +" Accept\n" +" \n" +" \n" +" \n" +" Reject\n" +" \n" +"
\n" +"

\n" +" If you need further information, please respond to this email and we will attend your request as soon as possible.\n" +"

\n" +"

\n" +" Thank you!\n" +"

\n" +"
\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
\n" +"

\n" +" Sent by\n" +" ${object.activity_id.controller_id.display_name|safe}.\n" +"

\n" +"
\n" +"
\n" +" " +msgstr "" +"\n" +"
\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \n" +" \""\n" +" \n" +"
\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
\n" +"

\n" +" Olá, ${object.partner_id.name|safe}\n" +"

\n" +"

\n" +" Contactámos, para solicitar o seu " +"consentimento explícito, à inclusão dos seus dados numa atividade de " +"processamento de dados, chamada\n" +" " +"${object.activity_id.display_name|safe}, propriedade de\n" +" " +"${object.activity_id.controller_id.display_name|safe}\n" +"

\n" +" ${object.description or \"\"}\n" +"

\n" +" % if object.state == \"answered\":\n" +" A última vez que nos respondeu, " +"você\n" +" % elif object.state == \"sent\":\n" +" Se nada fizer, assumimos que você\n" +" % endif\n" +"\n" +" % if object.accepted:\n" +" aceitou\n" +" % else:\n" +" rejeitou\n" +" % endif\n" +" esse processamento de dados.\n" +"

\n" +"

\n" +" Pode atualizar as suas preferências " +"abaixo:\n" +"

\n" +"
\n" +" \n" +" Aceito\n" +" \n" +" \n" +" \n" +" Rejeito\n" +" \n" +"
\n" +"

\n" +" Se necessitar de mais informação, por " +"favor responda a este email e nós trataremos de esclarecer assim que " +"possível.\n" +"

\n" +"

\n" +" Obrigado!\n" +"

\n" +"
\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
" +"\n" +"

\n" +" Enviado por\n" +" ${object.activity_id.controller_id.display_name|safe}.\n" +"

\n" +"
\n" +"
\n" +" " + +#. module: privacy_consent +#: model:mail.message.subtype,name:privacy_consent.mt_activity_acceptance_changed +msgid "Acceptance Changed" +msgstr "Aceitação Alterada" + +#. module: privacy_consent +#: model:mail.message.subtype,name:privacy_consent.mt_consent_acceptance_changed +msgid "Acceptance Changed by Subject" +msgstr "Aceitação Alterada por Titular" + +#. module: privacy_consent +#: model:mail.message.subtype,description:privacy_consent.mt_consent_acceptance_changed +msgid "Acceptance status updated by subject" +msgstr "Estado da aceitação atualizado por titular" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_accepted +#: model:ir.ui.view,arch_db:privacy_consent.consent_search +msgid "Accepted" +msgstr "Aceite" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_default_consent +msgid "Accepted by default" +msgstr "Aceite por defeito" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_active +msgid "Active" +msgstr "Ativo" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_activity_id +#: model:ir.ui.view,arch_db:privacy_consent.consent_search +msgid "Activity" +msgstr "Atividade" + +#. module: privacy_consent +#: selection:privacy.consent,state:0 +msgid "Answered" +msgstr "Respondido" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.consent_search +msgid "Archived" +msgstr "Arquivado" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.consent_form +msgid "Ask for consent" +msgstr "Pedir consentimento" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_required +msgid "Ask subjects for consent" +msgstr "Solicitar consentimento aos titulares" + +#. module: privacy_consent +#: selection:privacy.activity,consent_required:0 +msgid "Automatically" +msgstr "Automaticamente" + +#. module: privacy_consent +#: selection:privacy.consent,state:0 +msgid "Awaiting response" +msgstr "À espera de resposta" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.activity_form +msgid "Consent" +msgstr "Consentimento" + +#. module: privacy_consent +#: model:ir.model,name:privacy_consent.model_privacy_consent +msgid "Consent of data processing" +msgstr "Consentimento de processamento de dados" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_template_default_body_html +msgid "Consent template default body html" +msgstr "Corpo predefinido HTML do modelo de consentimento" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_template_default_subject +msgid "Consent template default subject" +msgstr "Modelo predefinido de consentimento do titular" + +#. module: privacy_consent +#: model:ir.actions.act_window,name:privacy_consent.consent_action +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_count +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_ids +#: model:ir.model.fields,field_description:privacy_consent.field_res_partner_privacy_consent_count +#: model:ir.model.fields,field_description:privacy_consent.field_res_users_privacy_consent_count +#: model:ir.ui.menu,name:privacy_consent.menu_privacy_consent +msgid "Consents" +msgstr "Consentimentos" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_create_uid +msgid "Created by" +msgstr "Criado por" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_create_date +msgid "Created on" +msgstr "Criado em" + +#. module: privacy_consent +#: model:ir.model,name:privacy_consent.model_privacy_activity +msgid "Data processing activities" +msgstr "Atividades de processamento de dados" + +#. module: privacy_consent +#: model:mail.template,subject:privacy_consent.template_consent +msgid "Data processing consent request for ${object.activity_id.display_name|safe}" +msgstr "" +"Processamento de dados de pedidos de consentimento para " +"${object.activity_id.display_name|safe}" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_display_name +msgid "Display Name" +msgstr "Nome a Exibir" + +#. module: privacy_consent +#: selection:privacy.consent,state:0 +msgid "Draft" +msgstr "Rascunho" + +#. module: privacy_consent +#: sql_constraint:privacy.consent:0 +msgid "Duplicated partner in this data processing activity" +msgstr "Parceiro duplicado nesta atividade de processamento de dados" + +#. module: privacy_consent +#: model:ir.model,name:privacy_consent.model_mail_template +msgid "Email Templates" +msgstr "Modelos de E-mail" + +#. module: privacy_consent +#: model:ir.model,name:privacy_consent.model_mail_compose_message +msgid "Email composition wizard" +msgstr "Assistente de criação de email" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_template_id +msgid "Email template" +msgstr "Modelo de Email" + +#. module: privacy_consent +#: model:ir.model.fields,help:privacy_consent.field_privacy_activity_consent_template_id +msgid "Email to be sent to subjects to ask for consent. A good template should include details about the current consent request status, how to change it, and where to get more information." +msgstr "" +"Email a ser enviado para os titulares a pedir o consentimento. Um bom modelo " +"deve incluir detalhes sobre o estado atual do pedido de consentimento, como " +"alterá-lo, e onde obter ais informação." + +#. module: privacy_consent +#: model:ir.model.fields,help:privacy_consent.field_privacy_activity_consent_required +msgid "Enable if you need to track any kind of consent from the affected subjects" +msgstr "" +"Ativar se necessita seguir qualquer espécie de consentimento dos titulares " +"afetados" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.activity_form +msgid "Generate and send missing consent requests" +msgstr "Gerar e enviar pedidos de consentimento em falta" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.activity_form +msgid "Generate missing draft consent requests" +msgstr "Gerar pedidos de consentimento em rascunho em falta" + +#. module: privacy_consent +#: code:addons/privacy_consent/models/privacy_activity.py:140 +#, python-format +msgid "Generated consents" +msgstr "Consentimentos gerados" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.consent_search +msgid "Group By" +msgstr "Agrupar Por" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.form +msgid "Hello," +msgstr "Olá" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.form +msgid "I accept this processing of my data" +msgstr "Eu aceito este processamento dos meus dados" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.form +msgid "I reject this processing of my data" +msgstr "Eu rejeito este processamento dos meus dados" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_id +msgid "ID" +msgstr "" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.form +msgid "If it was a mistake, you can undo it here:" +msgstr "Se foi um lapso, pode revertê-lo aqui:" + +#. module: privacy_consent +#: model:ir.model.fields,help:privacy_consent.field_privacy_consent_accepted +msgid "Indicates current acceptance status, which can come from subject's last answer, or from the default specified in the related data processing activity." +msgstr "" +"Indica o estado atual da aceitação, que pode derivar da última resposta do " +"titular, ou estar predefinida nos dados relacionados contidos na atividade " +"em processamento." + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent___last_update +msgid "Last Modified on" +msgstr "Última Modificação em" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_write_uid +msgid "Last Updated by" +msgstr "Última Atualização por" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_write_date +msgid "Last Updated on" +msgstr "Última Atualização em" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_last_metadata +msgid "Last metadata" +msgstr "Últimos Metadados" + +#. module: privacy_consent +#: selection:privacy.activity,consent_required:0 +msgid "Manually" +msgstr "Manualmente" + +#. module: privacy_consent +#: model:ir.model.fields,help:privacy_consent.field_privacy_consent_last_metadata +msgid "Metadata from the last acceptance or rejection by the subject" +msgstr "Metadados da última aceitação ou rejeição pelo titular" + +#. module: privacy_consent +#: code:addons/privacy_consent/models/mail_template.py:25 +#, python-format +msgid "Missing privacy consent link placeholders. You need at least these two links:\n" +"Accept\n" +"Reject" +msgstr "" +"Espaços reservados aos links de consentimento de privacidade em falta. " +"Necessita pelo menos destes dois links:\n" +"Aceito\n" +"Rejeito" + +#. module: privacy_consent +#: model:mail.message.subtype,name:privacy_consent.mt_activity_consent_new +#: model:mail.message.subtype,name:privacy_consent.mt_consent_consent_new +msgid "New Consent" +msgstr "Novo Consentimento" + +#. module: privacy_consent +#: model:ir.model,name:privacy_consent.model_mail_mail +msgid "Outgoing Mails" +msgstr "Mensagens a Enviar" + +#. module: privacy_consent +#: model:ir.model,name:privacy_consent.model_res_partner +msgid "Partner" +msgstr "Parceiro" + +#. module: privacy_consent +#: model:mail.message.subtype,description:privacy_consent.mt_activity_acceptance_changed +msgid "Privacy consent request acceptance status changed" +msgstr "Estado de aceitação do pedido de consentimento de privacidade alterado" + +#. module: privacy_consent +#: model:mail.message.subtype,description:privacy_consent.mt_activity_consent_new +#: model:mail.message.subtype,description:privacy_consent.mt_consent_consent_new +msgid "Privacy consent request created" +msgstr "Pedido de consentimento de privacidade criado" + +#. module: privacy_consent +#: model:mail.message.subtype,description:privacy_consent.mt_activity_state_changed +#: model:mail.message.subtype,description:privacy_consent.mt_consent_state_changed +msgid "Privacy consent request state changed" +msgstr "Estado do pedido de consentimento de privacidade alterado" + +#. module: privacy_consent +#: model:ir.model.fields,help:privacy_consent.field_res_partner_privacy_consent_count +#: model:ir.model.fields,help:privacy_consent.field_res_users_privacy_consent_count +msgid "Privacy consent requests amount" +msgstr "Número de pedidos de consentimento de privacidade" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_res_partner_privacy_consent_ids +#: model:ir.model.fields,field_description:privacy_consent.field_res_users_privacy_consent_ids +msgid "Privacy consents" +msgstr "Consentimentos de privacidade" + +#. module: privacy_consent +#: code:addons/privacy_consent/models/privacy_activity.py:100 +#, python-format +msgid "Require consent is available only for subjects in current database." +msgstr "" +"Requerer consentimento, só está disponível para titulares da base de dados " +"atual." + +#. module: privacy_consent +#: model:ir.model.fields,help:privacy_consent.field_privacy_activity_server_action_id +msgid "Run this action when a new consent request is created or its acceptance status is updated." +msgstr "" +"Execute esta ação quando um novo pedido de consentimento for criado ou seu " +"estado de aceitação for atualizado." + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_server_action_id +msgid "Server action" +msgstr "Ação do servidor" + +#. module: privacy_consent +#: model:ir.model.fields,help:privacy_consent.field_privacy_activity_default_consent +msgid "Should we assume the subject has accepted if we receive no response?" +msgstr "" +"Devemos assumir que o titular dos dados aceitou, se não houver resposta?" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.form +msgid "Sincerely,
" +msgstr "Cumprimentos,
" + +#. module: privacy_consent +#: code:addons/privacy_consent/models/privacy_activity.py:92 +#, python-format +msgid "Specify a mail template to ask automated consent." +msgstr "Especifique um modelo de email para pedido automático de consentimento." + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_state +#: model:ir.ui.view,arch_db:privacy_consent.consent_search +msgid "State" +msgstr "Estado" + +#. module: privacy_consent +#: model:mail.message.subtype,name:privacy_consent.mt_activity_state_changed +#: model:mail.message.subtype,name:privacy_consent.mt_consent_state_changed +msgid "State Changed" +msgstr "Estado Alterado" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_partner_id +msgid "Subject" +msgstr "Titular dos dados" + +#. module: privacy_consent +#: model:ir.model.fields,help:privacy_consent.field_privacy_consent_partner_id +msgid "Subject asked for consent." +msgstr "Foi pedido consentimento ao titular." + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.form +msgid "Thank you!" +msgstr "Obrigado!" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.form +msgid "Thanks for your response." +msgstr "Obrigado pela sua resposta." + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.activity_form +msgid "This could send many consent emails, are you sure to proceed?" +msgstr "" +"Atenção, esta operação pode enviar múltiplo emails de consentimento pretende " +"prosseguir?" + +#. module: privacy_consent +#: model:ir.actions.server,name:privacy_consent.update_opt_out +msgid "Update partner's opt out" +msgstr "Atualizar a Auto Exclusão do parceiro" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.form +msgid "We asked you to authorize us to process your data in this data processing activity:" +msgstr "" +"Pedimos-lhe que nos desse autorização para processarmos os seus dados nesta " +"atividade de processamento:" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.form +msgid "We have recorded this action on your side." +msgstr "Registámos esta ação com seu conhecimento." + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.form +msgid "You have rejected such processing." +msgstr "Você rejeitou este processamento." + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.form +msgid "You have accepted such processing." +msgstr "Você aceitou este processamento." From 04865db3c0df23f8ed31f8530c9c30c71d1b1710 Mon Sep 17 00:00:00 2001 From: Alexandre Fayolle Date: Tue, 11 Dec 2018 19:51:44 +0000 Subject: [PATCH 03/41] Added translation using Weblate (French) --- privacy_consent/i18n/fr.po | 487 +++++++++++++++++++++++++++++++++++++ 1 file changed, 487 insertions(+) create mode 100644 privacy_consent/i18n/fr.po diff --git a/privacy_consent/i18n/fr.po b/privacy_consent/i18n/fr.po new file mode 100644 index 00000000..3a0067b2 --- /dev/null +++ b/privacy_consent/i18n/fr.po @@ -0,0 +1,487 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * privacy_consent +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" + +#. module: privacy_consent +#: model:mail.template,body_html:privacy_consent.template_consent +msgid "\n" +"
\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \n" +" \"${object.activity_id.controller_id.display_name|safe}\"\n" +" \n" +"
\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
\n" +"

\n" +" Hello, ${object.partner_id.name|safe}\n" +"

\n" +"

\n" +" We contacted you to ask you to give us your explicit consent to include your data in a data processing activity called\n" +" ${object.activity_id.display_name|safe}, property of\n" +" ${object.activity_id.controller_id.display_name|safe}\n" +"

\n" +" ${object.description or \"\"}\n" +"

\n" +" % if object.state == \"answered\":\n" +" The last time you answered, you\n" +" % elif object.state == \"sent\":\n" +" If you do nothing, we will assume you have\n" +" % endif\n" +"\n" +" % if object.accepted:\n" +" accepted\n" +" % else:\n" +" rejected\n" +" % endif\n" +" such data processing.\n" +"

\n" +"

\n" +" You can update your preferences below:\n" +"

\n" +"
\n" +" \n" +" Accept\n" +" \n" +" \n" +" \n" +" Reject\n" +" \n" +"
\n" +"

\n" +" If you need further information, please respond to this email and we will attend your request as soon as possible.\n" +"

\n" +"

\n" +" Thank you!\n" +"

\n" +"
\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
\n" +"

\n" +" Sent by\n" +" ${object.activity_id.controller_id.display_name|safe}.\n" +"

\n" +"
\n" +"
\n" +" " +msgstr "" + +#. module: privacy_consent +#: model:mail.message.subtype,name:privacy_consent.mt_activity_acceptance_changed +msgid "Acceptance Changed" +msgstr "" + +#. module: privacy_consent +#: model:mail.message.subtype,name:privacy_consent.mt_consent_acceptance_changed +msgid "Acceptance Changed by Subject" +msgstr "" + +#. module: privacy_consent +#: model:mail.message.subtype,description:privacy_consent.mt_consent_acceptance_changed +msgid "Acceptance status updated by subject" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_accepted +#: model:ir.ui.view,arch_db:privacy_consent.consent_search +msgid "Accepted" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_default_consent +msgid "Accepted by default" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_active +msgid "Active" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_activity_id +#: model:ir.ui.view,arch_db:privacy_consent.consent_search +msgid "Activity" +msgstr "" + +#. module: privacy_consent +#: selection:privacy.consent,state:0 +msgid "Answered" +msgstr "" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.consent_search +msgid "Archived" +msgstr "" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.consent_form +msgid "Ask for consent" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_required +msgid "Ask subjects for consent" +msgstr "" + +#. module: privacy_consent +#: selection:privacy.activity,consent_required:0 +msgid "Automatically" +msgstr "" + +#. module: privacy_consent +#: selection:privacy.consent,state:0 +msgid "Awaiting response" +msgstr "" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.activity_form +msgid "Consent" +msgstr "" + +#. module: privacy_consent +#: model:ir.model,name:privacy_consent.model_privacy_consent +msgid "Consent of data processing" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_template_default_body_html +msgid "Consent template default body html" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_template_default_subject +msgid "Consent template default subject" +msgstr "" + +#. module: privacy_consent +#: model:ir.actions.act_window,name:privacy_consent.consent_action +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_count +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_ids +#: model:ir.model.fields,field_description:privacy_consent.field_res_partner_privacy_consent_count +#: model:ir.model.fields,field_description:privacy_consent.field_res_users_privacy_consent_count +#: model:ir.ui.menu,name:privacy_consent.menu_privacy_consent +msgid "Consents" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_create_uid +msgid "Created by" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_create_date +msgid "Created on" +msgstr "" + +#. module: privacy_consent +#: model:ir.model,name:privacy_consent.model_privacy_activity +msgid "Data processing activities" +msgstr "" + +#. module: privacy_consent +#: model:mail.template,subject:privacy_consent.template_consent +msgid "Data processing consent request for ${object.activity_id.display_name|safe}" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_display_name +msgid "Display Name" +msgstr "" + +#. module: privacy_consent +#: selection:privacy.consent,state:0 +msgid "Draft" +msgstr "" + +#. module: privacy_consent +#: sql_constraint:privacy.consent:0 +msgid "Duplicated partner in this data processing activity" +msgstr "" + +#. module: privacy_consent +#: model:ir.model,name:privacy_consent.model_mail_template +msgid "Email Templates" +msgstr "" + +#. module: privacy_consent +#: model:ir.model,name:privacy_consent.model_mail_compose_message +msgid "Email composition wizard" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_template_id +msgid "Email template" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,help:privacy_consent.field_privacy_activity_consent_template_id +msgid "Email to be sent to subjects to ask for consent. A good template should include details about the current consent request status, how to change it, and where to get more information." +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,help:privacy_consent.field_privacy_activity_consent_required +msgid "Enable if you need to track any kind of consent from the affected subjects" +msgstr "" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.activity_form +msgid "Generate and send missing consent requests" +msgstr "" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.activity_form +msgid "Generate missing draft consent requests" +msgstr "" + +#. module: privacy_consent +#: code:addons/privacy_consent/models/privacy_activity.py:140 +#, python-format +msgid "Generated consents" +msgstr "" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.consent_search +msgid "Group By" +msgstr "" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.form +msgid "Hello," +msgstr "" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.form +msgid "I accept this processing of my data" +msgstr "" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.form +msgid "I reject this processing of my data" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_id +msgid "ID" +msgstr "" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.form +msgid "If it was a mistake, you can undo it here:" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,help:privacy_consent.field_privacy_consent_accepted +msgid "Indicates current acceptance status, which can come from subject's last answer, or from the default specified in the related data processing activity." +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent___last_update +msgid "Last Modified on" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_write_uid +msgid "Last Updated by" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_write_date +msgid "Last Updated on" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_last_metadata +msgid "Last metadata" +msgstr "" + +#. module: privacy_consent +#: selection:privacy.activity,consent_required:0 +msgid "Manually" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,help:privacy_consent.field_privacy_consent_last_metadata +msgid "Metadata from the last acceptance or rejection by the subject" +msgstr "" + +#. module: privacy_consent +#: code:addons/privacy_consent/models/mail_template.py:25 +#, python-format +msgid "Missing privacy consent link placeholders. You need at least these two links:\n" +"Accept\n" +"Reject" +msgstr "" + +#. module: privacy_consent +#: model:mail.message.subtype,name:privacy_consent.mt_activity_consent_new +#: model:mail.message.subtype,name:privacy_consent.mt_consent_consent_new +msgid "New Consent" +msgstr "" + +#. module: privacy_consent +#: model:ir.model,name:privacy_consent.model_mail_mail +msgid "Outgoing Mails" +msgstr "" + +#. module: privacy_consent +#: model:ir.model,name:privacy_consent.model_res_partner +msgid "Partner" +msgstr "" + +#. module: privacy_consent +#: model:mail.message.subtype,description:privacy_consent.mt_activity_acceptance_changed +msgid "Privacy consent request acceptance status changed" +msgstr "" + +#. module: privacy_consent +#: model:mail.message.subtype,description:privacy_consent.mt_activity_consent_new +#: model:mail.message.subtype,description:privacy_consent.mt_consent_consent_new +msgid "Privacy consent request created" +msgstr "" + +#. module: privacy_consent +#: model:mail.message.subtype,description:privacy_consent.mt_activity_state_changed +#: model:mail.message.subtype,description:privacy_consent.mt_consent_state_changed +msgid "Privacy consent request state changed" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,help:privacy_consent.field_res_partner_privacy_consent_count +#: model:ir.model.fields,help:privacy_consent.field_res_users_privacy_consent_count +msgid "Privacy consent requests amount" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_res_partner_privacy_consent_ids +#: model:ir.model.fields,field_description:privacy_consent.field_res_users_privacy_consent_ids +msgid "Privacy consents" +msgstr "" + +#. module: privacy_consent +#: code:addons/privacy_consent/models/privacy_activity.py:100 +#, python-format +msgid "Require consent is available only for subjects in current database." +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,help:privacy_consent.field_privacy_activity_server_action_id +msgid "Run this action when a new consent request is created or its acceptance status is updated." +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_server_action_id +msgid "Server action" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,help:privacy_consent.field_privacy_activity_default_consent +msgid "Should we assume the subject has accepted if we receive no response?" +msgstr "" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.form +msgid "Sincerely,
" +msgstr "" + +#. module: privacy_consent +#: code:addons/privacy_consent/models/privacy_activity.py:92 +#, python-format +msgid "Specify a mail template to ask automated consent." +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_state +#: model:ir.ui.view,arch_db:privacy_consent.consent_search +msgid "State" +msgstr "" + +#. module: privacy_consent +#: model:mail.message.subtype,name:privacy_consent.mt_activity_state_changed +#: model:mail.message.subtype,name:privacy_consent.mt_consent_state_changed +msgid "State Changed" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_partner_id +msgid "Subject" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,help:privacy_consent.field_privacy_consent_partner_id +msgid "Subject asked for consent." +msgstr "" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.form +msgid "Thank you!" +msgstr "" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.form +msgid "Thanks for your response." +msgstr "" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.activity_form +msgid "This could send many consent emails, are you sure to proceed?" +msgstr "" + +#. module: privacy_consent +#: model:ir.actions.server,name:privacy_consent.update_opt_out +msgid "Update partner's opt out" +msgstr "" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.form +msgid "We asked you to authorize us to process your data in this data processing activity:" +msgstr "" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.form +msgid "We have recorded this action on your side." +msgstr "" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.form +msgid "You have rejected such processing." +msgstr "" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.form +msgid "You have accepted such processing." +msgstr "" From cdc975578e2089b7fe031ea79d66f5eefbb11b87 Mon Sep 17 00:00:00 2001 From: alvarorib Date: Fri, 14 Dec 2018 21:38:32 +0000 Subject: [PATCH 04/41] Translated using Weblate (Portuguese) Currently translated at 100.0% (74 of 74 strings) Translation: data-protection-10.0/data-protection-10.0-privacy_consent Translate-URL: https://translation.odoo-community.org/projects/data-protection-10-0/data-protection-10-0-privacy_consent/pt/ --- privacy_consent/i18n/pt.po | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/privacy_consent/i18n/pt.po b/privacy_consent/i18n/pt.po index 48892122..c087e3e6 100644 --- a/privacy_consent/i18n/pt.po +++ b/privacy_consent/i18n/pt.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: Portuguese (data-protection-10.0)\n" "Report-Msgid-Bugs-To: \n" -"PO-Revision-Date: 2018-09-22 09:44+0000\n" -"Last-Translator: Pedro Castro Silva \n" +"PO-Revision-Date: 2018-12-15 21:58+0000\n" +"Last-Translator: alvarorib \n" "Language-Team: Portuguese \n" "Language: pt\n" @@ -11,7 +11,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: \n" "Plural-Forms: nplurals=2; plural=n > 1;\n" -"X-Generator: Weblate 3.1.1\n" +"X-Generator: Weblate 3.3\n" #. module: privacy_consent #: model:mail.template,body_html:privacy_consent.template_consent @@ -409,7 +409,7 @@ msgstr "Eu rejeito este processamento dos meus dados" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_id msgid "ID" -msgstr "" +msgstr "ID" #. module: privacy_consent #: model:ir.ui.view,arch_db:privacy_consent.form From f64b0ad617e30e8f041b142bf20ddd96b0509ad4 Mon Sep 17 00:00:00 2001 From: Jairo Llopis Date: Mon, 21 Jan 2019 12:24:23 +0000 Subject: [PATCH 05/41] privacy_consent: Test at install The purpose of this `@post_install` no longer exists, and by removing these decorators, we avoid test failures in case some custom addon customizes the welcome message. --- privacy_consent/tests/test_consent.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/privacy_consent/tests/test_consent.py b/privacy_consent/tests/test_consent.py index 7af0a90a..6a68e4f9 100644 --- a/privacy_consent/tests/test_consent.py +++ b/privacy_consent/tests/test_consent.py @@ -5,11 +5,9 @@ from contextlib import contextmanager from odoo.exceptions import ValidationError -from odoo.tests.common import at_install, post_install, HttpCase +from odoo.tests.common import HttpCase -@at_install(False) -@post_install(True) class ActivityCase(HttpCase): def setUp(self): super(ActivityCase, self).setUp() From 55eb04854b6d2141988774603c3d05b1b2deda0e Mon Sep 17 00:00:00 2001 From: Cristina Martin Date: Fri, 1 Mar 2019 16:20:20 +0100 Subject: [PATCH 06/41] privacy_consent: set partner lang on mail template --- privacy_consent/data/mail.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/privacy_consent/data/mail.xml b/privacy_consent/data/mail.xml index c288e937..d7dad6c8 100644 --- a/privacy_consent/data/mail.xml +++ b/privacy_consent/data/mail.xml @@ -1,5 +1,6 @@ @@ -10,6 +11,7 @@ Data processing consent request for ${object.activity_id.display_name|safe} + ${object.partner_id.lang}
From 21fb42a81893d49eaa2b75df479dc47badd8da62 Mon Sep 17 00:00:00 2001 From: Jairo Llopis Date: Wed, 6 Mar 2019 11:11:28 +0000 Subject: [PATCH 07/41] privacy_consent: Avoid race condition with mail queue cron Before this patch, all privacy consent emails were forced to be sent under a context with `mark_consent_sent=True` to track the state change and trigger the attached server action. When using the automatic mode, if a separate cron job started running the mail queue, it could happen that mails were being sent from that another worker, losing the context key and, as such, being sent without token and without being marked as sent nor executing the attached server action (if any). To avoid this problem, now the context dependency is removed. After all, the `mail.mail` object is only created when sending in `mass_mail` model, so other kind of notifications or messages are not affected. When a mail of type `mass_mail` is sent, we can assume that it is asking for consent and we can move draft consent requests to sent. Update privacy_consent.pot Update translation files Updated by "Update PO files to match POT (msgmerge)" hook in Weblate. Translation: data-protection-10.0/data-protection-10.0-privacy_consent Translate-URL: https://translation.odoo-community.org/projects/data-protection-10-0/data-protection-10-0-privacy_consent/ --- privacy_consent/__init__.py | 1 - privacy_consent/i18n/es.po | 10 +- privacy_consent/i18n/fr.po | 95 ++++++++---- privacy_consent/i18n/privacy_consent.pot | 7 +- privacy_consent/i18n/pt.po | 141 +++++++++++------- privacy_consent/models/mail_mail.py | 4 +- privacy_consent/models/privacy_activity.py | 5 +- privacy_consent/models/privacy_consent.py | 4 +- privacy_consent/wizards/__init__.py | 1 - .../wizards/mail_compose_message.py | 16 -- 10 files changed, 161 insertions(+), 123 deletions(-) delete mode 100644 privacy_consent/wizards/__init__.py delete mode 100644 privacy_consent/wizards/mail_compose_message.py diff --git a/privacy_consent/__init__.py b/privacy_consent/__init__.py index ada0b87b..91c5580f 100644 --- a/privacy_consent/__init__.py +++ b/privacy_consent/__init__.py @@ -1,3 +1,2 @@ from . import controllers from . import models -from . import wizards diff --git a/privacy_consent/i18n/es.po b/privacy_consent/i18n/es.po index 1285c92d..17832bd3 100644 --- a/privacy_consent/i18n/es.po +++ b/privacy_consent/i18n/es.po @@ -372,11 +372,6 @@ msgstr "Contacto duplicado en esta actividad de tratamiento" msgid "Email Templates" msgstr "Plantillas de correo electrónico" -#. module: privacy_consent -#: model:ir.model,name:privacy_consent.model_mail_compose_message -msgid "Email composition wizard" -msgstr "Asistente de redacción de correo electrónico" - #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_template_id msgid "Email template" @@ -412,7 +407,7 @@ msgid "Generate missing draft consent requests" msgstr "Generar borradores de las solicitudes de consentimiento faltantes" #. module: privacy_consent -#: code:addons/privacy_consent/models/privacy_activity.py:140 +#: code:addons/privacy_consent/models/privacy_activity.py:139 #, python-format msgid "Generated consents" msgstr "Consentimientos generados" @@ -661,3 +656,6 @@ msgstr "Ha rechazado dicho tratamiento." #: model:ir.ui.view,arch_db:privacy_consent.form msgid "You have accepted such processing." msgstr "Ha aceptado dicho tratamiento." + +#~ msgid "Email composition wizard" +#~ msgstr "Asistente de redacción de correo electrónico" diff --git a/privacy_consent/i18n/fr.po b/privacy_consent/i18n/fr.po index 3a0067b2..31c82d9b 100644 --- a/privacy_consent/i18n/fr.po +++ b/privacy_consent/i18n/fr.po @@ -1,6 +1,6 @@ # Translation of Odoo Server. # This file contains the translation of the following modules: -# * privacy_consent +# * privacy_consent # msgid "" msgstr "" @@ -16,37 +16,48 @@ msgstr "" #. module: privacy_consent #: model:mail.template,body_html:privacy_consent.template_consent -msgid "\n" -"
\n" +msgid "" +"\n" +"
\n" "
\n" " \n" " \n" " \n" " \n" " \n" "
\n" " \n" -" \"${object.activity_id.controller_id.display_name|safe}\"\n" +" \"${object."\n" " \n" "
\n" -" \n" +"
\n" " \n" " \n" -" \n" " \n" " \n" -" \n" -" \n" " \n" " \n" -" \n" " \n" "
\n" +" \n" "

\n" " Hello, ${object.partner_id.name|safe}\n" "

\n" "

\n" -" We contacted you to ask you to give us your explicit consent to include your data in a data processing activity called\n" -" ${object.activity_id.display_name|safe}, property of\n" -" ${object.activity_id.controller_id.display_name|safe}\n" +" We contacted you to ask you to give us " +"your explicit consent to include your data in a data processing activity " +"called\n" +" ${object.activity_id.display_name|" +"safe}, property of\n" +" ${object.activity_id.controller_id." +"display_name|safe}\n" "

\n" " ${object.description or \"\"}\n" "

\n" " % if object.state == \"answered\":\n" " The last time you answered, you\n" " % elif object.state == \"sent\":\n" -" If you do nothing, we will assume you have\n" +" If you do nothing, we will assume " +"you have\n" " % endif\n" "\n" " % if object.accepted:\n" @@ -62,21 +73,29 @@ msgid "\n" "

\n" -" \n" +" \n" +" \n" " Accept\n" " \n" " \n" -" \n" +" \n" +" \n" " Reject\n" " \n" "
\n" +" \n" "

\n" -" If you need further information, please respond to this email and we will attend your request as soon as possible.\n" +" If you need further information, please " +"respond to this email and we will attend your request as soon as possible.\n" "

\n" "

\n" " Thank you!\n" @@ -85,13 +104,16 @@ msgid "\n" "

\n" -" \n" +"
\n" " \n" " \n" -" \n" " \n" @@ -215,7 +237,8 @@ msgstr "" #. module: privacy_consent #: model:mail.template,subject:privacy_consent.template_consent -msgid "Data processing consent request for ${object.activity_id.display_name|safe}" +msgid "" +"Data processing consent request for ${object.activity_id.display_name|safe}" msgstr "" #. module: privacy_consent @@ -238,11 +261,6 @@ msgstr "" msgid "Email Templates" msgstr "" -#. module: privacy_consent -#: model:ir.model,name:privacy_consent.model_mail_compose_message -msgid "Email composition wizard" -msgstr "" - #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_template_id msgid "Email template" @@ -250,12 +268,16 @@ msgstr "" #. module: privacy_consent #: model:ir.model.fields,help:privacy_consent.field_privacy_activity_consent_template_id -msgid "Email to be sent to subjects to ask for consent. A good template should include details about the current consent request status, how to change it, and where to get more information." +msgid "" +"Email to be sent to subjects to ask for consent. A good template should " +"include details about the current consent request status, how to change it, " +"and where to get more information." msgstr "" #. module: privacy_consent #: model:ir.model.fields,help:privacy_consent.field_privacy_activity_consent_required -msgid "Enable if you need to track any kind of consent from the affected subjects" +msgid "" +"Enable if you need to track any kind of consent from the affected subjects" msgstr "" #. module: privacy_consent @@ -269,7 +291,7 @@ msgid "Generate missing draft consent requests" msgstr "" #. module: privacy_consent -#: code:addons/privacy_consent/models/privacy_activity.py:140 +#: code:addons/privacy_consent/models/privacy_activity.py:139 #, python-format msgid "Generated consents" msgstr "" @@ -306,7 +328,10 @@ msgstr "" #. module: privacy_consent #: model:ir.model.fields,help:privacy_consent.field_privacy_consent_accepted -msgid "Indicates current acceptance status, which can come from subject's last answer, or from the default specified in the related data processing activity." +msgid "" +"Indicates current acceptance status, which can come from subject's last " +"answer, or from the default specified in the related data processing " +"activity." msgstr "" #. module: privacy_consent @@ -342,7 +367,9 @@ msgstr "" #. module: privacy_consent #: code:addons/privacy_consent/models/mail_template.py:25 #, python-format -msgid "Missing privacy consent link placeholders. You need at least these two links:\n" +msgid "" +"Missing privacy consent link placeholders. You need at least these two " +"links:\n" "Accept\n" "Reject" msgstr "" @@ -400,7 +427,9 @@ msgstr "" #. module: privacy_consent #: model:ir.model.fields,help:privacy_consent.field_privacy_activity_server_action_id -msgid "Run this action when a new consent request is created or its acceptance status is updated." +msgid "" +"Run this action when a new consent request is created or its acceptance " +"status is updated." msgstr "" #. module: privacy_consent @@ -468,7 +497,9 @@ msgstr "" #. module: privacy_consent #: model:ir.ui.view,arch_db:privacy_consent.form -msgid "We asked you to authorize us to process your data in this data processing activity:" +msgid "" +"We asked you to authorize us to process your data in this data processing " +"activity:" msgstr "" #. module: privacy_consent diff --git a/privacy_consent/i18n/privacy_consent.pot b/privacy_consent/i18n/privacy_consent.pot index 51f7871e..a82c662e 100644 --- a/privacy_consent/i18n/privacy_consent.pot +++ b/privacy_consent/i18n/privacy_consent.pot @@ -237,11 +237,6 @@ msgstr "" msgid "Email Templates" msgstr "" -#. module: privacy_consent -#: model:ir.model,name:privacy_consent.model_mail_compose_message -msgid "Email composition wizard" -msgstr "" - #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_template_id msgid "Email template" @@ -268,7 +263,7 @@ msgid "Generate missing draft consent requests" msgstr "" #. module: privacy_consent -#: code:addons/privacy_consent/models/privacy_activity.py:140 +#: code:addons/privacy_consent/models/privacy_activity.py:139 #, python-format msgid "Generated consents" msgstr "" diff --git a/privacy_consent/i18n/pt.po b/privacy_consent/i18n/pt.po index c087e3e6..83bdd044 100644 --- a/privacy_consent/i18n/pt.po +++ b/privacy_consent/i18n/pt.po @@ -15,37 +15,48 @@ msgstr "" #. module: privacy_consent #: model:mail.template,body_html:privacy_consent.template_consent -msgid "\n" -"
\n" +msgid "" +"\n" +"
\n" "
\n" +" \n" "

\n" " Sent by\n" -" ${object.activity_id.controller_id.display_name|safe}.\n" +" " +"${object.activity_id.controller_id.display_name|safe}.\n" "

\n" "
\n" " \n" " \n" " \n" " \n" " \n" "
\n" " \n" -" \"${object.activity_id.controller_id.display_name|safe}\"\n" +" \"${object."\n" " \n" "
\n" -" \n" +"
\n" " \n" " \n" -" \n" " \n" " \n" -" \n" -" \n" " \n" " \n" -" \n" " \n" "
\n" +" \n" "

\n" " Hello, ${object.partner_id.name|safe}\n" "

\n" "

\n" -" We contacted you to ask you to give us your explicit consent to include your data in a data processing activity called\n" -" ${object.activity_id.display_name|safe}, property of\n" -" ${object.activity_id.controller_id.display_name|safe}\n" +" We contacted you to ask you to give us " +"your explicit consent to include your data in a data processing activity " +"called\n" +" ${object.activity_id.display_name|" +"safe}, property of\n" +" ${object.activity_id.controller_id." +"display_name|safe}\n" "

\n" " ${object.description or \"\"}\n" "

\n" " % if object.state == \"answered\":\n" " The last time you answered, you\n" " % elif object.state == \"sent\":\n" -" If you do nothing, we will assume you have\n" +" If you do nothing, we will assume " +"you have\n" " % endif\n" "\n" " % if object.accepted:\n" @@ -61,21 +72,29 @@ msgid "\n" "

\n" -" \n" +" \n" +" \n" " Accept\n" " \n" " \n" -" \n" +" \n" +" \n" " Reject\n" " \n" "
\n" +" \n" "

\n" -" If you need further information, please respond to this email and we will attend your request as soon as possible.\n" +" If you need further information, please " +"respond to this email and we will attend your request as soon as possible.\n" "

\n" "

\n" " Thank you!\n" @@ -84,13 +103,16 @@ msgid "\n" "

\n" -" \n" +"
\n" " \n" " \n" -" \n" " \n" @@ -100,23 +122,23 @@ msgid "\n" " " msgstr "" "\n" -"
\n" +"
\n" "
\n" +" \n" "

\n" " Sent by\n" -" ${object.activity_id.controller_id.display_name|safe}.\n" +" " +"${object.activity_id.controller_id.display_name|safe}.\n" "

\n" "
\n" " \n" " \n" " \n" " \n" " \n" "
\n" " \n" -" \""\n" +" \"${object."\n" " \n" "
\n" -" \n" +"
\n" " \n" " \n" " \n" " \n" " \n" " \n" -" \n" " \n" @@ -320,10 +342,11 @@ msgstr "Atividades de processamento de dados" #. module: privacy_consent #: model:mail.template,subject:privacy_consent.template_consent -msgid "Data processing consent request for ${object.activity_id.display_name|safe}" +msgid "" +"Data processing consent request for ${object.activity_id.display_name|safe}" msgstr "" -"Processamento de dados de pedidos de consentimento para " -"${object.activity_id.display_name|safe}" +"Processamento de dados de pedidos de consentimento para ${object.activity_id." +"display_name|safe}" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_display_name @@ -345,11 +368,6 @@ msgstr "Parceiro duplicado nesta atividade de processamento de dados" msgid "Email Templates" msgstr "Modelos de E-mail" -#. module: privacy_consent -#: model:ir.model,name:privacy_consent.model_mail_compose_message -msgid "Email composition wizard" -msgstr "Assistente de criação de email" - #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_template_id msgid "Email template" @@ -357,7 +375,10 @@ msgstr "Modelo de Email" #. module: privacy_consent #: model:ir.model.fields,help:privacy_consent.field_privacy_activity_consent_template_id -msgid "Email to be sent to subjects to ask for consent. A good template should include details about the current consent request status, how to change it, and where to get more information." +msgid "" +"Email to be sent to subjects to ask for consent. A good template should " +"include details about the current consent request status, how to change it, " +"and where to get more information." msgstr "" "Email a ser enviado para os titulares a pedir o consentimento. Um bom modelo " "deve incluir detalhes sobre o estado atual do pedido de consentimento, como " @@ -365,7 +386,8 @@ msgstr "" #. module: privacy_consent #: model:ir.model.fields,help:privacy_consent.field_privacy_activity_consent_required -msgid "Enable if you need to track any kind of consent from the affected subjects" +msgid "" +"Enable if you need to track any kind of consent from the affected subjects" msgstr "" "Ativar se necessita seguir qualquer espécie de consentimento dos titulares " "afetados" @@ -381,7 +403,7 @@ msgid "Generate missing draft consent requests" msgstr "Gerar pedidos de consentimento em rascunho em falta" #. module: privacy_consent -#: code:addons/privacy_consent/models/privacy_activity.py:140 +#: code:addons/privacy_consent/models/privacy_activity.py:139 #, python-format msgid "Generated consents" msgstr "Consentimentos gerados" @@ -418,7 +440,10 @@ msgstr "Se foi um lapso, pode revertê-lo aqui:" #. module: privacy_consent #: model:ir.model.fields,help:privacy_consent.field_privacy_consent_accepted -msgid "Indicates current acceptance status, which can come from subject's last answer, or from the default specified in the related data processing activity." +msgid "" +"Indicates current acceptance status, which can come from subject's last " +"answer, or from the default specified in the related data processing " +"activity." msgstr "" "Indica o estado atual da aceitação, que pode derivar da última resposta do " "titular, ou estar predefinida nos dados relacionados contidos na atividade " @@ -457,7 +482,9 @@ msgstr "Metadados da última aceitação ou rejeição pelo titular" #. module: privacy_consent #: code:addons/privacy_consent/models/mail_template.py:25 #, python-format -msgid "Missing privacy consent link placeholders. You need at least these two links:\n" +msgid "" +"Missing privacy consent link placeholders. You need at least these two " +"links:\n" "Accept\n" "Reject" msgstr "" @@ -521,7 +548,9 @@ msgstr "" #. module: privacy_consent #: model:ir.model.fields,help:privacy_consent.field_privacy_activity_server_action_id -msgid "Run this action when a new consent request is created or its acceptance status is updated." +msgid "" +"Run this action when a new consent request is created or its acceptance " +"status is updated." msgstr "" "Execute esta ação quando um novo pedido de consentimento for criado ou seu " "estado de aceitação for atualizado." @@ -546,7 +575,8 @@ msgstr "Cumprimentos,
" #: code:addons/privacy_consent/models/privacy_activity.py:92 #, python-format msgid "Specify a mail template to ask automated consent." -msgstr "Especifique um modelo de email para pedido automático de consentimento." +msgstr "" +"Especifique um modelo de email para pedido automático de consentimento." #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_state @@ -594,7 +624,9 @@ msgstr "Atualizar a Auto Exclusão do parceiro" #. module: privacy_consent #: model:ir.ui.view,arch_db:privacy_consent.form -msgid "We asked you to authorize us to process your data in this data processing activity:" +msgid "" +"We asked you to authorize us to process your data in this data processing " +"activity:" msgstr "" "Pedimos-lhe que nos desse autorização para processarmos os seus dados nesta " "atividade de processamento:" @@ -613,3 +645,6 @@ msgstr "Você rejeitou este processamento." #: model:ir.ui.view,arch_db:privacy_consent.form msgid "You have accepted such processing." msgstr "Você aceitou este processamento." + +#~ msgid "Email composition wizard" +#~ msgstr "Assistente de criação de email" diff --git a/privacy_consent/models/mail_mail.py b/privacy_consent/models/mail_mail.py index e53e7fc6..25462e7f 100644 --- a/privacy_consent/models/mail_mail.py +++ b/privacy_consent/models/mail_mail.py @@ -10,7 +10,7 @@ class MailMail(models.Model): def _postprocess_sent_message(self, mail_sent=True): """Write consent status after sending message.""" - if mail_sent and self.env.context.get('mark_consent_sent'): + if mail_sent: # Get all mails sent to consents consent_mails = self.filtered( lambda one: one.mail_message_id.model == "privacy.consent" @@ -37,7 +37,7 @@ def send_get_mail_body(self, partner=None): """ result = super(MailMail, self).send_get_mail_body(partner=partner) # Avoid polluting other model mails - if self.env.context.get("active_model") != "privacy.consent": + if self.model != "privacy.consent": return result # Tokenize consent links consent = self.env["privacy.consent"] \ diff --git a/privacy_consent/models/privacy_activity.py b/privacy_consent/models/privacy_activity.py index c7d20c93..578f2a77 100644 --- a/privacy_consent/models/privacy_activity.py +++ b/privacy_consent/models/privacy_activity.py @@ -120,11 +120,10 @@ def action_new_consents(self): # Skip activitys where consent is not required for one in self.with_context(active_test=False) \ .filtered("consent_required"): - domain = safe_eval(one.subject_domain) - domain += [ + domain = [ ("id", "not in", one.mapped("consent_ids.partner_id").ids), ("email", "!=", False), - ] + ] + safe_eval(one.subject_domain) # Create missing consent requests for missing in self.env["res.partner"].search(domain): consents |= consents.create({ diff --git a/privacy_consent/models/privacy_consent.py b/privacy_consent/models/privacy_consent.py index 6dacd979..fd906781 100644 --- a/privacy_consent/models/privacy_consent.py +++ b/privacy_consent/models/privacy_consent.py @@ -104,8 +104,7 @@ def _send_consent_notification(self): consents_by_template = {} for one in self.with_context(tpl_force_default_to=True, mail_notify_user_signature=False, - mail_auto_subscribe_no_notify=True, - mark_consent_sent=True): + mail_auto_subscribe_no_notify=True): # Group consents by template, to send in batch where possible template_id = one.activity_id.consent_template_id.id consents_by_template.setdefault(template_id, one) @@ -168,7 +167,6 @@ def action_manual_ask(self): "default_res_id": self.id, "default_template_id": self.activity_id.consent_template_id.id, "default_use_template": True, - "mark_consent_sent": True, "tpl_force_default_to": True, }, "force_email": True, diff --git a/privacy_consent/wizards/__init__.py b/privacy_consent/wizards/__init__.py deleted file mode 100644 index b528d997..00000000 --- a/privacy_consent/wizards/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from . import mail_compose_message diff --git a/privacy_consent/wizards/mail_compose_message.py b/privacy_consent/wizards/mail_compose_message.py deleted file mode 100644 index a63ecc1b..00000000 --- a/privacy_consent/wizards/mail_compose_message.py +++ /dev/null @@ -1,16 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright 2018 Tecnativa - Jairo Llopis -# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). - -from odoo import api, models - - -class MailComposeMessage(models.TransientModel): - _inherit = "mail.compose.message" - - @api.multi - def send_mail(self, auto_commit=False): - """Force auto commit when sending consent emails.""" - if self.env.context.get('mark_consent_sent'): - auto_commit = True - return super(MailComposeMessage, self).send_mail(auto_commit) From d09589cd3268daa26965604bc8cf781fcf5ed07e Mon Sep 17 00:00:00 2001 From: Malin Kienke Date: Wed, 20 Mar 2019 14:11:00 +0000 Subject: [PATCH 08/41] Added translation using Weblate (German) --- privacy_consent/i18n/de.po | 482 +++++++++++++++++++++++++++++++++++++ 1 file changed, 482 insertions(+) create mode 100644 privacy_consent/i18n/de.po diff --git a/privacy_consent/i18n/de.po b/privacy_consent/i18n/de.po new file mode 100644 index 00000000..d42a41ef --- /dev/null +++ b/privacy_consent/i18n/de.po @@ -0,0 +1,482 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * privacy_consent +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: de\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +#. module: privacy_consent +#: model:mail.template,body_html:privacy_consent.template_consent +msgid "\n" +"
\n" +"
${object.activity_id.display_name|safe}, propriedade de\n" -" " -"${object.activity_id.controller_id.display_name|safe}\n" +" ${object.activity_id.display_name|" +"safe}, propriedade de\n" +" ${object.activity_id.controller_id." +"display_name|safe}\n" "

\n" " ${object.description or \"\"}\n" "

\n" @@ -158,16 +180,16 @@ msgstr "" "

\n" -" \n" " Aceito\n" " \n" " \n" -" \n" " Rejeito\n" " \n" @@ -192,12 +214,12 @@ msgstr "" "\">\n" "
" -"\n" +" \n" "

\n" " Enviado por\n" -" ${object.activity_id.controller_id.display_name|safe}.\n" +" " +"${object.activity_id.controller_id.display_name|safe}.\n" "

\n" "
\n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \n" +" \"${object.activity_id.controller_id.display_name|safe}\"\n" +" \n" +"
\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
\n" +"

\n" +" Hello, ${object.partner_id.name|safe}\n" +"

\n" +"

\n" +" We contacted you to ask you to give us your explicit consent to include your data in a data processing activity called\n" +" ${object.activity_id.display_name|safe}, property of\n" +" ${object.activity_id.controller_id.display_name|safe}\n" +"

\n" +" ${object.description or \"\"}\n" +"

\n" +" % if object.state == \"answered\":\n" +" The last time you answered, you\n" +" % elif object.state == \"sent\":\n" +" If you do nothing, we will assume you have\n" +" % endif\n" +"\n" +" % if object.accepted:\n" +" accepted\n" +" % else:\n" +" rejected\n" +" % endif\n" +" such data processing.\n" +"

\n" +"

\n" +" You can update your preferences below:\n" +"

\n" +"
\n" +" \n" +" Accept\n" +" \n" +" \n" +" \n" +" Reject\n" +" \n" +"
\n" +"

\n" +" If you need further information, please respond to this email and we will attend your request as soon as possible.\n" +"

\n" +"

\n" +" Thank you!\n" +"

\n" +"
\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
\n" +"

\n" +" Sent by\n" +" ${object.activity_id.controller_id.display_name|safe}.\n" +"

\n" +"
\n" +"
\n" +" " +msgstr "" + +#. module: privacy_consent +#: model:mail.message.subtype,name:privacy_consent.mt_activity_acceptance_changed +msgid "Acceptance Changed" +msgstr "" + +#. module: privacy_consent +#: model:mail.message.subtype,name:privacy_consent.mt_consent_acceptance_changed +msgid "Acceptance Changed by Subject" +msgstr "" + +#. module: privacy_consent +#: model:mail.message.subtype,description:privacy_consent.mt_consent_acceptance_changed +msgid "Acceptance status updated by subject" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_accepted +#: model:ir.ui.view,arch_db:privacy_consent.consent_search +msgid "Accepted" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_default_consent +msgid "Accepted by default" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_active +msgid "Active" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_activity_id +#: model:ir.ui.view,arch_db:privacy_consent.consent_search +msgid "Activity" +msgstr "" + +#. module: privacy_consent +#: selection:privacy.consent,state:0 +msgid "Answered" +msgstr "" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.consent_search +msgid "Archived" +msgstr "" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.consent_form +msgid "Ask for consent" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_required +msgid "Ask subjects for consent" +msgstr "" + +#. module: privacy_consent +#: selection:privacy.activity,consent_required:0 +msgid "Automatically" +msgstr "" + +#. module: privacy_consent +#: selection:privacy.consent,state:0 +msgid "Awaiting response" +msgstr "" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.activity_form +msgid "Consent" +msgstr "" + +#. module: privacy_consent +#: model:ir.model,name:privacy_consent.model_privacy_consent +msgid "Consent of data processing" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_template_default_body_html +msgid "Consent template default body html" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_template_default_subject +msgid "Consent template default subject" +msgstr "" + +#. module: privacy_consent +#: model:ir.actions.act_window,name:privacy_consent.consent_action +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_count +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_ids +#: model:ir.model.fields,field_description:privacy_consent.field_res_partner_privacy_consent_count +#: model:ir.model.fields,field_description:privacy_consent.field_res_users_privacy_consent_count +#: model:ir.ui.menu,name:privacy_consent.menu_privacy_consent +msgid "Consents" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_create_uid +msgid "Created by" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_create_date +msgid "Created on" +msgstr "" + +#. module: privacy_consent +#: model:ir.model,name:privacy_consent.model_privacy_activity +msgid "Data processing activities" +msgstr "" + +#. module: privacy_consent +#: model:mail.template,subject:privacy_consent.template_consent +msgid "Data processing consent request for ${object.activity_id.display_name|safe}" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_display_name +msgid "Display Name" +msgstr "" + +#. module: privacy_consent +#: selection:privacy.consent,state:0 +msgid "Draft" +msgstr "" + +#. module: privacy_consent +#: sql_constraint:privacy.consent:0 +msgid "Duplicated partner in this data processing activity" +msgstr "" + +#. module: privacy_consent +#: model:ir.model,name:privacy_consent.model_mail_template +msgid "Email Templates" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_template_id +msgid "Email template" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,help:privacy_consent.field_privacy_activity_consent_template_id +msgid "Email to be sent to subjects to ask for consent. A good template should include details about the current consent request status, how to change it, and where to get more information." +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,help:privacy_consent.field_privacy_activity_consent_required +msgid "Enable if you need to track any kind of consent from the affected subjects" +msgstr "" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.activity_form +msgid "Generate and send missing consent requests" +msgstr "" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.activity_form +msgid "Generate missing draft consent requests" +msgstr "" + +#. module: privacy_consent +#: code:addons/privacy_consent/models/privacy_activity.py:139 +#, python-format +msgid "Generated consents" +msgstr "" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.consent_search +msgid "Group By" +msgstr "" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.form +msgid "Hello," +msgstr "" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.form +msgid "I accept this processing of my data" +msgstr "" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.form +msgid "I reject this processing of my data" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_id +msgid "ID" +msgstr "" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.form +msgid "If it was a mistake, you can undo it here:" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,help:privacy_consent.field_privacy_consent_accepted +msgid "Indicates current acceptance status, which can come from subject's last answer, or from the default specified in the related data processing activity." +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent___last_update +msgid "Last Modified on" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_write_uid +msgid "Last Updated by" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_write_date +msgid "Last Updated on" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_last_metadata +msgid "Last metadata" +msgstr "" + +#. module: privacy_consent +#: selection:privacy.activity,consent_required:0 +msgid "Manually" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,help:privacy_consent.field_privacy_consent_last_metadata +msgid "Metadata from the last acceptance or rejection by the subject" +msgstr "" + +#. module: privacy_consent +#: code:addons/privacy_consent/models/mail_template.py:25 +#, python-format +msgid "Missing privacy consent link placeholders. You need at least these two links:\n" +"Accept\n" +"Reject" +msgstr "" + +#. module: privacy_consent +#: model:mail.message.subtype,name:privacy_consent.mt_activity_consent_new +#: model:mail.message.subtype,name:privacy_consent.mt_consent_consent_new +msgid "New Consent" +msgstr "" + +#. module: privacy_consent +#: model:ir.model,name:privacy_consent.model_mail_mail +msgid "Outgoing Mails" +msgstr "" + +#. module: privacy_consent +#: model:ir.model,name:privacy_consent.model_res_partner +msgid "Partner" +msgstr "" + +#. module: privacy_consent +#: model:mail.message.subtype,description:privacy_consent.mt_activity_acceptance_changed +msgid "Privacy consent request acceptance status changed" +msgstr "" + +#. module: privacy_consent +#: model:mail.message.subtype,description:privacy_consent.mt_activity_consent_new +#: model:mail.message.subtype,description:privacy_consent.mt_consent_consent_new +msgid "Privacy consent request created" +msgstr "" + +#. module: privacy_consent +#: model:mail.message.subtype,description:privacy_consent.mt_activity_state_changed +#: model:mail.message.subtype,description:privacy_consent.mt_consent_state_changed +msgid "Privacy consent request state changed" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,help:privacy_consent.field_res_partner_privacy_consent_count +#: model:ir.model.fields,help:privacy_consent.field_res_users_privacy_consent_count +msgid "Privacy consent requests amount" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_res_partner_privacy_consent_ids +#: model:ir.model.fields,field_description:privacy_consent.field_res_users_privacy_consent_ids +msgid "Privacy consents" +msgstr "" + +#. module: privacy_consent +#: code:addons/privacy_consent/models/privacy_activity.py:100 +#, python-format +msgid "Require consent is available only for subjects in current database." +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,help:privacy_consent.field_privacy_activity_server_action_id +msgid "Run this action when a new consent request is created or its acceptance status is updated." +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_server_action_id +msgid "Server action" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,help:privacy_consent.field_privacy_activity_default_consent +msgid "Should we assume the subject has accepted if we receive no response?" +msgstr "" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.form +msgid "Sincerely,
" +msgstr "" + +#. module: privacy_consent +#: code:addons/privacy_consent/models/privacy_activity.py:92 +#, python-format +msgid "Specify a mail template to ask automated consent." +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_state +#: model:ir.ui.view,arch_db:privacy_consent.consent_search +msgid "State" +msgstr "" + +#. module: privacy_consent +#: model:mail.message.subtype,name:privacy_consent.mt_activity_state_changed +#: model:mail.message.subtype,name:privacy_consent.mt_consent_state_changed +msgid "State Changed" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_partner_id +msgid "Subject" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,help:privacy_consent.field_privacy_consent_partner_id +msgid "Subject asked for consent." +msgstr "" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.form +msgid "Thank you!" +msgstr "" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.form +msgid "Thanks for your response." +msgstr "" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.activity_form +msgid "This could send many consent emails, are you sure to proceed?" +msgstr "" + +#. module: privacy_consent +#: model:ir.actions.server,name:privacy_consent.update_opt_out +msgid "Update partner's opt out" +msgstr "" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.form +msgid "We asked you to authorize us to process your data in this data processing activity:" +msgstr "" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.form +msgid "We have recorded this action on your side." +msgstr "" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.form +msgid "You have rejected such processing." +msgstr "" + +#. module: privacy_consent +#: model:ir.ui.view,arch_db:privacy_consent.form +msgid "You have accepted such processing." +msgstr "" From 9ea355551298e31fc704fa27c37a7ce82e68e424 Mon Sep 17 00:00:00 2001 From: Jairo Llopis Date: Tue, 7 May 2019 13:04:52 +0100 Subject: [PATCH 09/41] privacy_consent: Avoid race condition when sending emails It could happen that, while Odoo is still sending emails, a subject receives it and clicks on accept/reject links. In such case, he'd get a 404 error because the record wouldn't exist yet in the database. That's because the DB commit was made only after processing all the sent emails. We need to commit in advance to make sure that doesn't happen. --- privacy_consent/models/privacy_activity.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/privacy_consent/models/privacy_activity.py b/privacy_consent/models/privacy_activity.py index 578f2a77..6a37e53b 100644 --- a/privacy_consent/models/privacy_activity.py +++ b/privacy_consent/models/privacy_activity.py @@ -131,6 +131,9 @@ def action_new_consents(self): "accepted": one.default_consent, "activity_id": one.id, }) + # Avoid race condition where a user could click on accept/reject link + # in his email before its consent record is saved to the database + consents.env.cr.commit() # Send consent request emails for automatic activitys consents.action_auto_ask() # Redirect user to new consent requests generated From abccf8765d94e80eb78ce123915f5144a22b16c5 Mon Sep 17 00:00:00 2001 From: dw3gn3r Date: Thu, 11 Apr 2019 07:20:13 +0000 Subject: [PATCH 10/41] Translated using Weblate (German) Currently translated at 79.5% (58 of 73 strings) Translation: data-protection-10.0/data-protection-10.0-privacy_consent Translate-URL: https://translation.odoo-community.org/projects/data-protection-10-0/data-protection-10-0-privacy_consent/de/ Update privacy_consent.pot Update translation files Updated by "Update PO files to match POT (msgmerge)" hook in Weblate. Translation: data-protection-10.0/data-protection-10.0-privacy_consent Translate-URL: https://translation.odoo-community.org/projects/data-protection-10-0/data-protection-10-0-privacy_consent/ --- privacy_consent/i18n/de.po | 212 ++++++++++++++--------- privacy_consent/i18n/es.po | 2 +- privacy_consent/i18n/fr.po | 2 +- privacy_consent/i18n/privacy_consent.pot | 2 +- privacy_consent/i18n/pt.po | 2 +- 5 files changed, 137 insertions(+), 83 deletions(-) diff --git a/privacy_consent/i18n/de.po b/privacy_consent/i18n/de.po index d42a41ef..620ee4b9 100644 --- a/privacy_consent/i18n/de.po +++ b/privacy_consent/i18n/de.po @@ -1,52 +1,65 @@ # Translation of Odoo Server. # This file contains the translation of the following modules: -# * privacy_consent +# * privacy_consent # msgid "" msgstr "" "Project-Id-Version: Odoo Server 10.0\n" "Report-Msgid-Bugs-To: \n" -"Last-Translator: Automatically generated\n" +"PO-Revision-Date: 2019-04-11 11:16+0000\n" +"Last-Translator: dw3gn3r \n" "Language-Team: none\n" "Language: de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: \n" "Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 3.5\n" #. module: privacy_consent #: model:mail.template,body_html:privacy_consent.template_consent -msgid "\n" -"
\n" +msgid "" +"\n" +"
\n" " \n" " \n" " \n" " \n" " \n" " \n" "
\n" " \n" -" \"${object.activity_id.controller_id.display_name|safe}\"\n" +" \"${object."\n" " \n" "
\n" -" \n" +"
\n" " \n" " \n" -" \n" " \n" " \n" -" \n" -" \n" " \n" " \n" -" \n" " \n" "
\n" +" \n" "

\n" " Hello, ${object.partner_id.name|safe}\n" "

\n" "

\n" -" We contacted you to ask you to give us your explicit consent to include your data in a data processing activity called\n" -" ${object.activity_id.display_name|safe}, property of\n" -" ${object.activity_id.controller_id.display_name|safe}\n" +" We contacted you to ask you to give us " +"your explicit consent to include your data in a data processing activity " +"called\n" +" ${object.activity_id.display_name|" +"safe}, property of\n" +" ${object.activity_id.controller_id." +"display_name|safe}\n" "

\n" " ${object.description or \"\"}\n" "

\n" " % if object.state == \"answered\":\n" " The last time you answered, you\n" " % elif object.state == \"sent\":\n" -" If you do nothing, we will assume you have\n" +" If you do nothing, we will assume " +"you have\n" " % endif\n" "\n" " % if object.accepted:\n" @@ -62,21 +75,29 @@ msgid "\n" "

\n" -" \n" +" \n" +" \n" " Accept\n" " \n" " \n" -" \n" +" \n" +" \n" " Reject\n" " \n" "
\n" +" \n" "

\n" -" If you need further information, please respond to this email and we will attend your request as soon as possible.\n" +" If you need further information, please " +"respond to this email and we will attend your request as soon as possible.\n" "

\n" "

\n" " Thank you!\n" @@ -85,13 +106,16 @@ msgid "\n" "

\n" -" \n" +"
\n" " \n" " \n" -" \n" " \n" @@ -109,7 +133,7 @@ msgstr "" #. module: privacy_consent #: model:mail.message.subtype,name:privacy_consent.mt_consent_acceptance_changed msgid "Acceptance Changed by Subject" -msgstr "" +msgstr "Zustimmung durch den Betroffenen geändert" #. module: privacy_consent #: model:mail.message.subtype,description:privacy_consent.mt_consent_acceptance_changed @@ -120,7 +144,7 @@ msgstr "" #: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_accepted #: model:ir.ui.view,arch_db:privacy_consent.consent_search msgid "Accepted" -msgstr "" +msgstr "Akzeptiert" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_default_consent @@ -130,63 +154,63 @@ msgstr "" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_active msgid "Active" -msgstr "" +msgstr "Aktiv" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_activity_id #: model:ir.ui.view,arch_db:privacy_consent.consent_search msgid "Activity" -msgstr "" +msgstr "Aktivität" #. module: privacy_consent #: selection:privacy.consent,state:0 msgid "Answered" -msgstr "" +msgstr "Beantwortet" #. module: privacy_consent #: model:ir.ui.view,arch_db:privacy_consent.consent_search msgid "Archived" -msgstr "" +msgstr "Archiviert" #. module: privacy_consent #: model:ir.ui.view,arch_db:privacy_consent.consent_form msgid "Ask for consent" -msgstr "" +msgstr "Einwilligung einholen" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_required msgid "Ask subjects for consent" -msgstr "" +msgstr "Einwilligung beim Betroffenen einholen" #. module: privacy_consent #: selection:privacy.activity,consent_required:0 msgid "Automatically" -msgstr "" +msgstr "Automatisch" #. module: privacy_consent #: selection:privacy.consent,state:0 msgid "Awaiting response" -msgstr "" +msgstr "Warten auf Antwort" #. module: privacy_consent #: model:ir.ui.view,arch_db:privacy_consent.activity_form msgid "Consent" -msgstr "" +msgstr "Einwilligung" #. module: privacy_consent #: model:ir.model,name:privacy_consent.model_privacy_consent msgid "Consent of data processing" -msgstr "" +msgstr "Einwilligung in die Datenverarbeitung" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_template_default_body_html msgid "Consent template default body html" -msgstr "" +msgstr "Einverständniserklärung Standardtext html" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_template_default_subject msgid "Consent template default subject" -msgstr "" +msgstr "Standardmäßige Einverständniserklärung Betroffener" #. module: privacy_consent #: model:ir.actions.act_window,name:privacy_consent.consent_action @@ -196,47 +220,48 @@ msgstr "" #: model:ir.model.fields,field_description:privacy_consent.field_res_users_privacy_consent_count #: model:ir.ui.menu,name:privacy_consent.menu_privacy_consent msgid "Consents" -msgstr "" +msgstr "Einwilligungen" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_create_uid msgid "Created by" -msgstr "" +msgstr "Erstellt von" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_create_date msgid "Created on" -msgstr "" +msgstr "Erstellt am" #. module: privacy_consent #: model:ir.model,name:privacy_consent.model_privacy_activity msgid "Data processing activities" -msgstr "" +msgstr "Verarbeitungstätigkeiten" #. module: privacy_consent #: model:mail.template,subject:privacy_consent.template_consent -msgid "Data processing consent request for ${object.activity_id.display_name|safe}" -msgstr "" +msgid "" +"Data processing consent request for ${object.activity_id.display_name|safe}" +msgstr "Bitte um Erteilung der Einwilligung zur Datenverarbeitung:" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_display_name msgid "Display Name" -msgstr "" +msgstr "Anzeigename" #. module: privacy_consent #: selection:privacy.consent,state:0 msgid "Draft" -msgstr "" +msgstr "Entwurf" #. module: privacy_consent #: sql_constraint:privacy.consent:0 msgid "Duplicated partner in this data processing activity" -msgstr "" +msgstr "Doppelter Partner in dieser Verarbeitungsaktivität" #. module: privacy_consent #: model:ir.model,name:privacy_consent.model_mail_template msgid "Email Templates" -msgstr "" +msgstr "E-Mail-Vorlagen" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_template_id @@ -245,26 +270,34 @@ msgstr "" #. module: privacy_consent #: model:ir.model.fields,help:privacy_consent.field_privacy_activity_consent_template_id -msgid "Email to be sent to subjects to ask for consent. A good template should include details about the current consent request status, how to change it, and where to get more information." +msgid "" +"Email to be sent to subjects to ask for consent. A good template should " +"include details about the current consent request status, how to change it, " +"and where to get more information." msgstr "" +"E-Mail, die an die Betroffenen geschickt werden soll, um die Einwilligung " +"einzuholen. Eine gute Vorlage sollte Details über den aktuellen Status der " +"Einwilligungsanfrage enthalten, sowie Hinweise darüber, wie man den Status " +"der Einwilligung ändern kann und wo man weitere Informationen erhält." #. module: privacy_consent #: model:ir.model.fields,help:privacy_consent.field_privacy_activity_consent_required -msgid "Enable if you need to track any kind of consent from the affected subjects" +msgid "" +"Enable if you need to track any kind of consent from the affected subjects" msgstr "" #. module: privacy_consent #: model:ir.ui.view,arch_db:privacy_consent.activity_form msgid "Generate and send missing consent requests" -msgstr "" +msgstr "Erstellung und Versand fehlender Einwilligungsanfragen" #. module: privacy_consent #: model:ir.ui.view,arch_db:privacy_consent.activity_form msgid "Generate missing draft consent requests" -msgstr "" +msgstr "Fehlende Entwürfe von Einwilligungsanfragen erstellen" #. module: privacy_consent -#: code:addons/privacy_consent/models/privacy_activity.py:139 +#: code:addons/privacy_consent/models/privacy_activity.py:142 #, python-format msgid "Generated consents" msgstr "" @@ -272,72 +305,80 @@ msgstr "" #. module: privacy_consent #: model:ir.ui.view,arch_db:privacy_consent.consent_search msgid "Group By" -msgstr "" +msgstr "Gruppieren nach" #. module: privacy_consent #: model:ir.ui.view,arch_db:privacy_consent.form msgid "Hello," -msgstr "" +msgstr "Hallo" #. module: privacy_consent #: model:ir.ui.view,arch_db:privacy_consent.form msgid "I accept this processing of my data" -msgstr "" +msgstr "Ich akzeptiere die Verarbeitung meiner Daten" #. module: privacy_consent #: model:ir.ui.view,arch_db:privacy_consent.form msgid "I reject this processing of my data" -msgstr "" +msgstr "Ich lehne die Verarbeitung meiner Daten ab" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_id msgid "ID" -msgstr "" +msgstr "Ausweis" #. module: privacy_consent #: model:ir.ui.view,arch_db:privacy_consent.form msgid "If it was a mistake, you can undo it here:" -msgstr "" +msgstr "Wenn es ein Fehler war, können Sie diesen hier rückgängig machen:" #. module: privacy_consent #: model:ir.model.fields,help:privacy_consent.field_privacy_consent_accepted -msgid "Indicates current acceptance status, which can come from subject's last answer, or from the default specified in the related data processing activity." +msgid "" +"Indicates current acceptance status, which can come from subject's last " +"answer, or from the default specified in the related data processing " +"activity." msgstr "" +"Zeigt den aktuellen Akzeptanzstatus an, der sich aus der letzten Antwort des " +"Betreffenden oder aus dem in der zugehörigen Datenverarbeitungsaktivität " +"angegebenen Standard ergeben kann." #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent___last_update msgid "Last Modified on" -msgstr "" +msgstr "Letzte Änderung am" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_write_uid msgid "Last Updated by" -msgstr "" +msgstr "Zuletzt aktualisiert von" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_write_date msgid "Last Updated on" -msgstr "" +msgstr "Zuletzt aktualisiert am" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_last_metadata msgid "Last metadata" -msgstr "" +msgstr "Letzte Metadaten" #. module: privacy_consent #: selection:privacy.activity,consent_required:0 msgid "Manually" -msgstr "" +msgstr "Manuell" #. module: privacy_consent #: model:ir.model.fields,help:privacy_consent.field_privacy_consent_last_metadata msgid "Metadata from the last acceptance or rejection by the subject" -msgstr "" +msgstr "Metadaten aus der letzten Annahme oder Ablehnung durch den Betroffenen" #. module: privacy_consent #: code:addons/privacy_consent/models/mail_template.py:25 #, python-format -msgid "Missing privacy consent link placeholders. You need at least these two links:\n" +msgid "" +"Missing privacy consent link placeholders. You need at least these two " +"links:\n" "Accept\n" "Reject" msgstr "" @@ -346,46 +387,48 @@ msgstr "" #: model:mail.message.subtype,name:privacy_consent.mt_activity_consent_new #: model:mail.message.subtype,name:privacy_consent.mt_consent_consent_new msgid "New Consent" -msgstr "" +msgstr "Neue Einwilligung" #. module: privacy_consent #: model:ir.model,name:privacy_consent.model_mail_mail msgid "Outgoing Mails" -msgstr "" +msgstr "Ausgehende Mails" #. module: privacy_consent #: model:ir.model,name:privacy_consent.model_res_partner msgid "Partner" -msgstr "" +msgstr "Partner" #. module: privacy_consent #: model:mail.message.subtype,description:privacy_consent.mt_activity_acceptance_changed msgid "Privacy consent request acceptance status changed" msgstr "" +"Der Akzeptanzstatus der Anfrage 'Einwilligung zum Datenschutz' wurde " +"geändert." #. module: privacy_consent #: model:mail.message.subtype,description:privacy_consent.mt_activity_consent_new #: model:mail.message.subtype,description:privacy_consent.mt_consent_consent_new msgid "Privacy consent request created" -msgstr "" +msgstr "Anfrage zur Einwilligung erstellt" #. module: privacy_consent #: model:mail.message.subtype,description:privacy_consent.mt_activity_state_changed #: model:mail.message.subtype,description:privacy_consent.mt_consent_state_changed msgid "Privacy consent request state changed" -msgstr "" +msgstr "Status der Anfrage zur Einwilligung geändert" #. module: privacy_consent #: model:ir.model.fields,help:privacy_consent.field_res_partner_privacy_consent_count #: model:ir.model.fields,help:privacy_consent.field_res_users_privacy_consent_count msgid "Privacy consent requests amount" -msgstr "" +msgstr "Anzahl der Anfragen zur Einwilligung" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_res_partner_privacy_consent_ids #: model:ir.model.fields,field_description:privacy_consent.field_res_users_privacy_consent_ids msgid "Privacy consents" -msgstr "" +msgstr "Einwilligung zum Datenschutz" #. module: privacy_consent #: code:addons/privacy_consent/models/privacy_activity.py:100 @@ -395,13 +438,15 @@ msgstr "" #. module: privacy_consent #: model:ir.model.fields,help:privacy_consent.field_privacy_activity_server_action_id -msgid "Run this action when a new consent request is created or its acceptance status is updated." +msgid "" +"Run this action when a new consent request is created or its acceptance " +"status is updated." msgstr "" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_server_action_id msgid "Server action" -msgstr "" +msgstr "Server-Aktion" #. module: privacy_consent #: model:ir.model.fields,help:privacy_consent.field_privacy_activity_default_consent @@ -411,30 +456,32 @@ msgstr "" #. module: privacy_consent #: model:ir.ui.view,arch_db:privacy_consent.form msgid "Sincerely,
" -msgstr "" +msgstr "Mit freundlichen Grüßen
" #. module: privacy_consent #: code:addons/privacy_consent/models/privacy_activity.py:92 #, python-format msgid "Specify a mail template to ask automated consent." msgstr "" +"Wählen Sie eine E-Mail-Vorlage aus, um eine automatische Einwilligung " +"einzuholen." #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_state #: model:ir.ui.view,arch_db:privacy_consent.consent_search msgid "State" -msgstr "" +msgstr "Status" #. module: privacy_consent #: model:mail.message.subtype,name:privacy_consent.mt_activity_state_changed #: model:mail.message.subtype,name:privacy_consent.mt_consent_state_changed msgid "State Changed" -msgstr "" +msgstr "Status geändert" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_partner_id msgid "Subject" -msgstr "" +msgstr "Betroffener" #. module: privacy_consent #: model:ir.model.fields,help:privacy_consent.field_privacy_consent_partner_id @@ -444,17 +491,19 @@ msgstr "" #. module: privacy_consent #: model:ir.ui.view,arch_db:privacy_consent.form msgid "Thank you!" -msgstr "" +msgstr "Vielen Dank." #. module: privacy_consent #: model:ir.ui.view,arch_db:privacy_consent.form msgid "Thanks for your response." -msgstr "" +msgstr "Vielen Dank für Ihre Antwort." #. module: privacy_consent #: model:ir.ui.view,arch_db:privacy_consent.activity_form msgid "This could send many consent emails, are you sure to proceed?" msgstr "" +"Hiermit könnten viele Einwilligungs-E-Mails verschickt werden. Sind Sie " +"sicher, dass Sie fortfahren wollen?" #. module: privacy_consent #: model:ir.actions.server,name:privacy_consent.update_opt_out @@ -463,7 +512,9 @@ msgstr "" #. module: privacy_consent #: model:ir.ui.view,arch_db:privacy_consent.form -msgid "We asked you to authorize us to process your data in this data processing activity:" +msgid "" +"We asked you to authorize us to process your data in this data processing " +"activity:" msgstr "" #. module: privacy_consent @@ -475,8 +526,11 @@ msgstr "" #: model:ir.ui.view,arch_db:privacy_consent.form msgid "You have rejected such processing." msgstr "" +"Du hast diese Verarbeitungstätigkeit abgelehnt." #. module: privacy_consent #: model:ir.ui.view,arch_db:privacy_consent.form msgid "You have accepted such processing." msgstr "" +"Du hast dieser Verarbeitungstätigkeit zugestimmt." diff --git a/privacy_consent/i18n/es.po b/privacy_consent/i18n/es.po index 17832bd3..6bc168a6 100644 --- a/privacy_consent/i18n/es.po +++ b/privacy_consent/i18n/es.po @@ -407,7 +407,7 @@ msgid "Generate missing draft consent requests" msgstr "Generar borradores de las solicitudes de consentimiento faltantes" #. module: privacy_consent -#: code:addons/privacy_consent/models/privacy_activity.py:139 +#: code:addons/privacy_consent/models/privacy_activity.py:142 #, python-format msgid "Generated consents" msgstr "Consentimientos generados" diff --git a/privacy_consent/i18n/fr.po b/privacy_consent/i18n/fr.po index 31c82d9b..54d87d10 100644 --- a/privacy_consent/i18n/fr.po +++ b/privacy_consent/i18n/fr.po @@ -291,7 +291,7 @@ msgid "Generate missing draft consent requests" msgstr "" #. module: privacy_consent -#: code:addons/privacy_consent/models/privacy_activity.py:139 +#: code:addons/privacy_consent/models/privacy_activity.py:142 #, python-format msgid "Generated consents" msgstr "" diff --git a/privacy_consent/i18n/privacy_consent.pot b/privacy_consent/i18n/privacy_consent.pot index a82c662e..275b3d20 100644 --- a/privacy_consent/i18n/privacy_consent.pot +++ b/privacy_consent/i18n/privacy_consent.pot @@ -263,7 +263,7 @@ msgid "Generate missing draft consent requests" msgstr "" #. module: privacy_consent -#: code:addons/privacy_consent/models/privacy_activity.py:139 +#: code:addons/privacy_consent/models/privacy_activity.py:142 #, python-format msgid "Generated consents" msgstr "" diff --git a/privacy_consent/i18n/pt.po b/privacy_consent/i18n/pt.po index 83bdd044..f8d513d6 100644 --- a/privacy_consent/i18n/pt.po +++ b/privacy_consent/i18n/pt.po @@ -403,7 +403,7 @@ msgid "Generate missing draft consent requests" msgstr "Gerar pedidos de consentimento em rascunho em falta" #. module: privacy_consent -#: code:addons/privacy_consent/models/privacy_activity.py:139 +#: code:addons/privacy_consent/models/privacy_activity.py:142 #, python-format msgid "Generated consents" msgstr "Consentimentos gerados" From abc403264b68e032be1a6561df8cf9ec4b9457ac Mon Sep 17 00:00:00 2001 From: Jairo Llopis Date: Mon, 13 May 2019 18:13:10 +0100 Subject: [PATCH 11/41] privacy_consent: Separate automated emails send process Before https://github.com/OCA/data-protection/pull/29 there was a race condition where an email could be sent while the same transaction that created the `privacy.consent` record still wasn't committed, producing a 404 error if the user clicked on "Accept" or "Reject" before all mails were sent. To avoid that, a raw `cr.commit()` was issued, but this produced another situation where the user had to wait until the full email queue is cleared to get his page loaded. It wasn't an error, but a long queue meant several minutes waiting, and it's ulikely that an average human is so patient. So, here's the final fix (I hope!). The main problem was that I was looking in the wrong place to send the email. It turns out that the `self.post_message_with_template()` method is absolutely helpless in the case at hand, where these criteria must be met: * E-mail must be enqueued, no matter if there are less or more than 50 consents to send. * The template must be processed per record. * In an ideal world, a `cr.commit()` must be issued after each sent mail. The metod that was being used: * Didn't allow to use `auto_commit` mode. * Only allowed to render the template per record if called with `composition_mode="mass_mail"`. * Only allowed to enqueue emails if called with `composition_mode="mass_post"`. Obviously, I cannot set 2 different values for `composition_mode`, so a different strategy had to be used. I discovered that the `mail.template` model has a helpful method called `send_mail()` that, by default: * Renders the template per record * Enqueues the email * The email queue is cleared in `auto_commit=True` mode. So, from now on, problems are gone: * The user click, or the cron run, will just generate the missing `privacy.consent` records and enqueue mails for them. * The mail queue manager will send them later, in `auto_commit` mode. * After sending the e-mail, this module will set the `privacy.consent` record as `sent`. * Thanks to *not* sending the email, the process the user faces when he hits the "generate" button is faster. * Instructions in the README and text in the "generate" button are updated to reflect this new behavior. * Thanks to the `auto_commit` feature, if Odoo is rebooted in the middle of a mail queue clearance, the records that were sent remain properly marked as sent, and the missing mails will be sent after the next boot. * No hardcoded commits. * No locked transactions. * BTW I discovered that 2 different emails were created when creating a new consent. I started using `mail_create_nolog=True` to avoid that problem and only log a single creation message. Note to self: never use again `post_message_with_template()`. Update translation files Updated by "Update PO files to match POT (msgmerge)" hook in Weblate. Translation: data-protection-10.0/data-protection-10.0-privacy_consent Translate-URL: https://translation.odoo-community.org/projects/data-protection-10-0/data-protection-10-0-privacy_consent/ Update privacy_consent.pot Update translation files Updated by "Update PO files to match POT (msgmerge)" hook in Weblate. Translation: data-protection-10.0/data-protection-10.0-privacy_consent Translate-URL: https://translation.odoo-community.org/projects/data-protection-10-0/data-protection-10-0-privacy_consent/ --- privacy_consent/README.rst | 4 ++-- privacy_consent/data/mail.xml | 1 + privacy_consent/i18n/de.po | 11 +++++++--- privacy_consent/i18n/es.po | 22 ++++++++++--------- privacy_consent/i18n/fr.po | 7 +++--- privacy_consent/i18n/privacy_consent.pot | 6 ++--- privacy_consent/i18n/pt.po | 11 +++++++--- privacy_consent/models/privacy_activity.py | 3 --- privacy_consent/models/privacy_consent.py | 18 +++------------ privacy_consent/readme/USAGE.rst | 4 ++-- privacy_consent/static/description/index.html | 4 ++-- privacy_consent/tests/test_consent.py | 14 +++++++++--- privacy_consent/views/privacy_activity.xml | 4 ++-- 13 files changed, 58 insertions(+), 51 deletions(-) diff --git a/privacy_consent/README.rst b/privacy_consent/README.rst index 4f928329..c15174be 100644 --- a/privacy_consent/README.rst +++ b/privacy_consent/README.rst @@ -106,8 +106,8 @@ New options for data processing activities: * If you chose *Manual* mode, all missing consent request are created as drafts, and nothing else is done now. - * If you chose *Automatic* mode, also those requests are sent to subjects - and set as *Sent*. + * If you chose *Automatic* mode, also those request e-mails are enqueued + and, when the mail queue is cleared, they will be set as *Sent*. #. You will be presented with the list of just-created consent requests. See below. diff --git a/privacy_consent/data/mail.xml b/privacy_consent/data/mail.xml index d7dad6c8..f4ab84e1 100644 --- a/privacy_consent/data/mail.xml +++ b/privacy_consent/data/mail.xml @@ -7,6 +7,7 @@ + Personal data processing consent request Data processing consent request for ${object.activity_id.display_name|safe} diff --git a/privacy_consent/i18n/de.po b/privacy_consent/i18n/de.po index 620ee4b9..463d79de 100644 --- a/privacy_consent/i18n/de.po +++ b/privacy_consent/i18n/de.po @@ -6,6 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 10.0\n" "Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-05-13 17:04+0000\n" "PO-Revision-Date: 2019-04-11 11:16+0000\n" "Last-Translator: dw3gn3r \n" "Language-Team: none\n" @@ -288,7 +289,9 @@ msgstr "" #. module: privacy_consent #: model:ir.ui.view,arch_db:privacy_consent.activity_form -msgid "Generate and send missing consent requests" +#, fuzzy +#| msgid "Generate and send missing consent requests" +msgid "Generate and enqueue missing consent requests" msgstr "Erstellung und Versand fehlender Einwilligungsanfragen" #. module: privacy_consent @@ -297,7 +300,7 @@ msgid "Generate missing draft consent requests" msgstr "Fehlende Entwürfe von Einwilligungsanfragen erstellen" #. module: privacy_consent -#: code:addons/privacy_consent/models/privacy_activity.py:142 +#: code:addons/privacy_consent/models/privacy_activity.py:139 #, python-format msgid "Generated consents" msgstr "" @@ -500,7 +503,9 @@ msgstr "Vielen Dank für Ihre Antwort." #. module: privacy_consent #: model:ir.ui.view,arch_db:privacy_consent.activity_form -msgid "This could send many consent emails, are you sure to proceed?" +#, fuzzy +#| msgid "This could send many consent emails, are you sure to proceed?" +msgid "This could enqueue many consent emails, are you sure to proceed?" msgstr "" "Hiermit könnten viele Einwilligungs-E-Mails verschickt werden. Sind Sie " "sicher, dass Sie fortfahren wollen?" diff --git a/privacy_consent/i18n/es.po b/privacy_consent/i18n/es.po index 6bc168a6..d7e0b9c6 100644 --- a/privacy_consent/i18n/es.po +++ b/privacy_consent/i18n/es.po @@ -6,8 +6,8 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 10.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-07-11 08:38+0000\n" -"PO-Revision-Date: 2018-07-11 11:07+0200\n" +"POT-Creation-Date: 2019-05-13 17:04+0000\n" +"PO-Revision-Date: 2019-05-13 18:08+0100\n" "Last-Translator: Jairo Llopis \n" "Language-Team: \n" "Language: es_ES\n" @@ -15,7 +15,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Poedit 2.0.8\n" +"X-Generator: Poedit 2.2.1\n" #. module: privacy_consent #: model:mail.template,body_html:privacy_consent.template_consent @@ -394,12 +394,14 @@ msgid "" "Enable if you need to track any kind of consent from the affected subjects" msgstr "" "Actívelo si necesita registrar cualquier tipo de consentimiento de los " -"interesados." +"interesados" #. module: privacy_consent #: model:ir.ui.view,arch_db:privacy_consent.activity_form -msgid "Generate and send missing consent requests" -msgstr "Generar y enviar solicitudes de consentimiento faltantes" +msgid "Generate and enqueue missing consent requests" +msgstr "" +"Generar y colocar en la bandeja de salida las solicitudes de consentimiento " +"que falten" #. module: privacy_consent #: model:ir.ui.view,arch_db:privacy_consent.activity_form @@ -407,7 +409,7 @@ msgid "Generate missing draft consent requests" msgstr "Generar borradores de las solicitudes de consentimiento faltantes" #. module: privacy_consent -#: code:addons/privacy_consent/models/privacy_activity.py:142 +#: code:addons/privacy_consent/models/privacy_activity.py:139 #, python-format msgid "Generated consents" msgstr "Consentimientos generados" @@ -623,10 +625,10 @@ msgstr "Gracias por su respuesta." #. module: privacy_consent #: model:ir.ui.view,arch_db:privacy_consent.activity_form -msgid "This could send many consent emails, are you sure to proceed?" +msgid "This could enqueue many consent emails, are you sure to proceed?" msgstr "" -"Esto podría enviar muchos correos electrónicos solicitando consentimiento " -"para el tratamiento de datos, ¿seguro que quiere continuar?" +"Esto podría poner en la cola muchos correos electrónicos solicitando " +"consentimiento para el tratamiento de datos, ¿seguro que quiere continuar?" #. module: privacy_consent #: model:ir.actions.server,name:privacy_consent.update_opt_out diff --git a/privacy_consent/i18n/fr.po b/privacy_consent/i18n/fr.po index 54d87d10..d32c4e63 100644 --- a/privacy_consent/i18n/fr.po +++ b/privacy_consent/i18n/fr.po @@ -6,6 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 10.0\n" "Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-05-13 17:04+0000\n" "Last-Translator: Automatically generated\n" "Language-Team: none\n" "Language: fr\n" @@ -282,7 +283,7 @@ msgstr "" #. module: privacy_consent #: model:ir.ui.view,arch_db:privacy_consent.activity_form -msgid "Generate and send missing consent requests" +msgid "Generate and enqueue missing consent requests" msgstr "" #. module: privacy_consent @@ -291,7 +292,7 @@ msgid "Generate missing draft consent requests" msgstr "" #. module: privacy_consent -#: code:addons/privacy_consent/models/privacy_activity.py:142 +#: code:addons/privacy_consent/models/privacy_activity.py:139 #, python-format msgid "Generated consents" msgstr "" @@ -487,7 +488,7 @@ msgstr "" #. module: privacy_consent #: model:ir.ui.view,arch_db:privacy_consent.activity_form -msgid "This could send many consent emails, are you sure to proceed?" +msgid "This could enqueue many consent emails, are you sure to proceed?" msgstr "" #. module: privacy_consent diff --git a/privacy_consent/i18n/privacy_consent.pot b/privacy_consent/i18n/privacy_consent.pot index 275b3d20..8e0642fe 100644 --- a/privacy_consent/i18n/privacy_consent.pot +++ b/privacy_consent/i18n/privacy_consent.pot @@ -254,7 +254,7 @@ msgstr "" #. module: privacy_consent #: model:ir.ui.view,arch_db:privacy_consent.activity_form -msgid "Generate and send missing consent requests" +msgid "Generate and enqueue missing consent requests" msgstr "" #. module: privacy_consent @@ -263,7 +263,7 @@ msgid "Generate missing draft consent requests" msgstr "" #. module: privacy_consent -#: code:addons/privacy_consent/models/privacy_activity.py:142 +#: code:addons/privacy_consent/models/privacy_activity.py:139 #, python-format msgid "Generated consents" msgstr "" @@ -452,7 +452,7 @@ msgstr "" #. module: privacy_consent #: model:ir.ui.view,arch_db:privacy_consent.activity_form -msgid "This could send many consent emails, are you sure to proceed?" +msgid "This could enqueue many consent emails, are you sure to proceed?" msgstr "" #. module: privacy_consent diff --git a/privacy_consent/i18n/pt.po b/privacy_consent/i18n/pt.po index f8d513d6..5928e404 100644 --- a/privacy_consent/i18n/pt.po +++ b/privacy_consent/i18n/pt.po @@ -2,6 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: Portuguese (data-protection-10.0)\n" "Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-05-13 17:04+0000\n" "PO-Revision-Date: 2018-12-15 21:58+0000\n" "Last-Translator: alvarorib \n" "Language-Team: Portuguese Usage
  • If you chose Manual mode, all missing consent request are created as drafts, and nothing else is done now.
  • -
  • If you chose Automatic mode, also those requests are sent to subjects -and set as Sent.
  • +
  • If you chose Automatic mode, also those request e-mails are enqueued +and, when the mail queue is cleared, they will be set as Sent.
  • You will be presented with the list of just-created consent requests. diff --git a/privacy_consent/tests/test_consent.py b/privacy_consent/tests/test_consent.py index 6a68e4f9..4c6f11c8 100644 --- a/privacy_consent/tests/test_consent.py +++ b/privacy_consent/tests/test_consent.py @@ -17,6 +17,8 @@ def setUp(self): self.env = self._oldenv(self.cursor()) # HACK end self.cron = self.env.ref("privacy_consent.cron_auto_consent") + self.cron_mail_queue = self.env.ref( + "mail.ir_cron_mail_scheduler_action") self.update_opt_out = self.env.ref("privacy_consent.update_opt_out") self.mt_consent_consent_new = self.env.ref( "privacy_consent.mt_consent_consent_new") @@ -93,11 +95,17 @@ def check_activity_auto_properly_sent(self): consents = self.env["privacy.consent"].search([ ("activity_id", "=", self.activity_auto.id), ]) + # Check pending mails + for consent in consents: + self.assertEqual(consent.state, "draft") + messages = consent.message_ids + self.assertEqual(len(messages), 2) # Check sent mails + self.cron_mail_queue.method_direct_trigger() for consent in consents: self.assertEqual(consent.state, "sent") - messages = consent.mapped("message_ids") - self.assertEqual(len(messages), 4) + messages = consent.message_ids + self.assertEqual(len(messages), 3) # 2nd message notifies creation self.assertEqual( messages[2].subtype_id, @@ -167,7 +175,7 @@ def test_generate_manually(self): self.assertEqual(consents.mapped("last_metadata"), [False] * 2) # Check sent mails messages = consents.mapped("message_ids") - self.assertEqual(len(messages), 4) + self.assertEqual(len(messages), 2) subtypes = messages.mapped("subtype_id") self.assertTrue(subtypes & self.mt_consent_consent_new) self.assertFalse(subtypes & self.mt_consent_acceptance_changed) diff --git a/privacy_consent/views/privacy_activity.xml b/privacy_consent/views/privacy_activity.xml index 35c9e5f7..b13bce22 100644 --- a/privacy_consent/views/privacy_activity.xml +++ b/privacy_consent/views/privacy_activity.xml @@ -46,8 +46,8 @@ icon="fa-user-plus" name="action_new_consents" type="object" - string="Generate and send missing consent requests" - confirm="This could send many consent emails, are you sure to proceed?" + string="Generate and enqueue missing consent requests" + confirm="This could enqueue many consent emails, are you sure to proceed?" /> From 0f7d66150962cdfee4389ac3e6330f04bb9a530d Mon Sep 17 00:00:00 2001 From: fkantelberg Date: Thu, 4 Jul 2019 14:44:17 +0200 Subject: [PATCH 12/41] Migrate privacy_consent to v11 --- privacy_consent/__manifest__.py | 5 ++--- privacy_consent/controllers/main.py | 1 - privacy_consent/data/ir_actions_server.xml | 13 +++---------- privacy_consent/data/ir_cron.xml | 8 +++++--- privacy_consent/i18n/es.po | 8 +++++--- privacy_consent/i18n/fr.po | 5 ++--- privacy_consent/i18n/privacy_consent.pot | 7 +++++++ privacy_consent/i18n/pt.po | 9 ++------- privacy_consent/models/mail_mail.py | 1 - privacy_consent/models/mail_template.py | 1 - privacy_consent/models/privacy_activity.py | 1 - privacy_consent/models/privacy_consent.py | 1 - privacy_consent/models/res_partner.py | 1 - privacy_consent/readme/CONTRIBUTORS.rst | 4 ++++ privacy_consent/tests/test_consent.py | 5 ++--- 15 files changed, 32 insertions(+), 38 deletions(-) diff --git a/privacy_consent/__manifest__.py b/privacy_consent/__manifest__.py index ee842548..a9d388ba 100644 --- a/privacy_consent/__manifest__.py +++ b/privacy_consent/__manifest__.py @@ -1,15 +1,14 @@ -# -*- coding: utf-8 -*- # Copyright 2018 Tecnativa - Jairo Llopis # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). { "name": "Privacy - Consent", "summary": "Allow people to explicitly accept or reject inclusion " "in some activity, GDPR compliant", - "version": "10.0.1.0.0", + "version": "11.0.1.0.0", "development_status": "Production/Stable", "category": "Privacy", "website": "https://github.com/OCA/management-activity", - "author": "Tecnativa, Odoo Community Association (OCA)", + "author": "Tecnativa, initOS GmbH, Odoo Community Association (OCA)", "license": "AGPL-3", "application": False, "installable": True, diff --git a/privacy_consent/controllers/main.py b/privacy_consent/controllers/main.py index 8f243d08..dddb20b9 100644 --- a/privacy_consent/controllers/main.py +++ b/privacy_consent/controllers/main.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright 2018 Tecnativa - Jairo Llopis # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). diff --git a/privacy_consent/data/ir_actions_server.xml b/privacy_consent/data/ir_actions_server.xml index 58788e65..4e7bc4dd 100644 --- a/privacy_consent/data/ir_actions_server.xml +++ b/privacy_consent/data/ir_actions_server.xml @@ -1,5 +1,6 @@ @@ -8,16 +9,8 @@ Update partner's opt out - object_write - expression - record.partner_id - - - - - - equation - not record.accepted + code + records.mapped('partner_id').write({'opt_out': not record.accepted}) diff --git a/privacy_consent/data/ir_cron.xml b/privacy_consent/data/ir_cron.xml index cc4bb380..72acc370 100644 --- a/privacy_consent/data/ir_cron.xml +++ b/privacy_consent/data/ir_cron.xml @@ -1,15 +1,17 @@ Request automatic data processing consents - privacy.activity - _cron_new_consents + + code + model._cron_new_consents() 1 - work_days + days -1 diff --git a/privacy_consent/i18n/es.po b/privacy_consent/i18n/es.po index d7e0b9c6..5c47d5f5 100644 --- a/privacy_consent/i18n/es.po +++ b/privacy_consent/i18n/es.po @@ -372,6 +372,11 @@ msgstr "Contacto duplicado en esta actividad de tratamiento" msgid "Email Templates" msgstr "Plantillas de correo electrónico" +#. module: privacy_consent +#: model:ir.model,name:privacy_consent.model_mail_compose_message +msgid "Email composition wizard" +msgstr "Asistente de redacción de correo electrónico" + #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_template_id msgid "Email template" @@ -658,6 +663,3 @@ msgstr "Ha rechazado dicho tratamiento." #: model:ir.ui.view,arch_db:privacy_consent.form msgid "You have accepted such processing." msgstr "Ha aceptado dicho tratamiento." - -#~ msgid "Email composition wizard" -#~ msgstr "Asistente de redacción de correo electrónico" diff --git a/privacy_consent/i18n/fr.po b/privacy_consent/i18n/fr.po index d32c4e63..31c82d9b 100644 --- a/privacy_consent/i18n/fr.po +++ b/privacy_consent/i18n/fr.po @@ -6,7 +6,6 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 10.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-05-13 17:04+0000\n" "Last-Translator: Automatically generated\n" "Language-Team: none\n" "Language: fr\n" @@ -283,7 +282,7 @@ msgstr "" #. module: privacy_consent #: model:ir.ui.view,arch_db:privacy_consent.activity_form -msgid "Generate and enqueue missing consent requests" +msgid "Generate and send missing consent requests" msgstr "" #. module: privacy_consent @@ -488,7 +487,7 @@ msgstr "" #. module: privacy_consent #: model:ir.ui.view,arch_db:privacy_consent.activity_form -msgid "This could enqueue many consent emails, are you sure to proceed?" +msgid "This could send many consent emails, are you sure to proceed?" msgstr "" #. module: privacy_consent diff --git a/privacy_consent/i18n/privacy_consent.pot b/privacy_consent/i18n/privacy_consent.pot index 8e0642fe..cf3cd1af 100644 --- a/privacy_consent/i18n/privacy_consent.pot +++ b/privacy_consent/i18n/privacy_consent.pot @@ -6,6 +6,8 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 10.0\n" "Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-05-13 17:04+0000\n" +"PO-Revision-Date: 2019-05-13 17:04+0000\n" "Last-Translator: <>\n" "Language-Team: \n" "MIME-Version: 1.0\n" @@ -237,6 +239,11 @@ msgstr "" msgid "Email Templates" msgstr "" +#. module: privacy_consent +#: model:ir.model,name:privacy_consent.model_mail_compose_message +msgid "Email composition wizard" +msgstr "" + #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_template_id msgid "Email template" diff --git a/privacy_consent/i18n/pt.po b/privacy_consent/i18n/pt.po index 5928e404..83bdd044 100644 --- a/privacy_consent/i18n/pt.po +++ b/privacy_consent/i18n/pt.po @@ -2,7 +2,6 @@ msgid "" msgstr "" "Project-Id-Version: Portuguese (data-protection-10.0)\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-05-13 17:04+0000\n" "PO-Revision-Date: 2018-12-15 21:58+0000\n" "Last-Translator: alvarorib \n" "Language-Team: Portuguese `_: * Jairo Llopis + +* `initOS GmbH `_: + + * Florian Kantelberg diff --git a/privacy_consent/tests/test_consent.py b/privacy_consent/tests/test_consent.py index 4c6f11c8..8de1e566 100644 --- a/privacy_consent/tests/test_consent.py +++ b/privacy_consent/tests/test_consent.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright 2018 Tecnativa - Jairo Llopis # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). @@ -204,7 +203,7 @@ def test_generate_manually(self): self.assertNotIn(reject_url, messages[1].body) # Visit tokenized accept URL with self.release_cr(): - result = self.url_open(accept_url).read() + result = self.url_open(accept_url).text self.assertIn("accepted", result) self.assertIn(reject_url, result) self.assertIn(self.activity_manual.name, result) @@ -220,7 +219,7 @@ def test_generate_manually(self): ) # Visit tokenized reject URL with self.release_cr(): - result = self.url_open(reject_url).read() + result = self.url_open(reject_url).text self.assertIn("rejected", result) self.assertIn(accept_url, result) self.assertIn(self.activity_manual.name, result) From 7915e8ccc1c490f5a2b7aae65cb8149d1d12847e Mon Sep 17 00:00:00 2001 From: fkantelberg Date: Fri, 5 Jul 2019 09:39:09 +0200 Subject: [PATCH 13/41] Change icon to handshake [UPD] Update privacy_consent.pot [UPD] README.rst --- privacy_consent/README.rst | 15 +++-- privacy_consent/i18n/privacy_consent.pot | 56 +++++++++---------- privacy_consent/static/description/index.html | 11 +++- privacy_consent/views/privacy_activity.xml | 3 +- privacy_consent/views/res_partner.xml | 3 +- 5 files changed, 48 insertions(+), 40 deletions(-) diff --git a/privacy_consent/README.rst b/privacy_consent/README.rst index c15174be..d5c56b82 100644 --- a/privacy_consent/README.rst +++ b/privacy_consent/README.rst @@ -14,13 +14,13 @@ Privacy - Consent :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fdata--protection-lightgray.png?logo=github - :target: https://github.com/OCA/data-protection/tree/10.0/privacy_consent + :target: https://github.com/OCA/data-protection/tree/11.0/privacy_consent :alt: OCA/data-protection .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/data-protection-10-0/data-protection-10-0-privacy_consent + :target: https://translation.odoo-community.org/projects/data-protection-11-0/data-protection-11-0-privacy_consent :alt: Translate me on Weblate .. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png - :target: https://runbot.odoo-community.org/runbot/263/10.0 + :target: https://runbot.odoo-community.org/runbot/263/11.0 :alt: Try me on Runbot |badge1| |badge2| |badge3| |badge4| |badge5| @@ -136,7 +136,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. @@ -147,6 +147,7 @@ Authors ~~~~~~~ * Tecnativa +* initOS GmbH Contributors ~~~~~~~~~~~~ @@ -155,6 +156,10 @@ Contributors * Jairo Llopis +* `initOS GmbH `_: + + * Florian Kantelberg + Maintainers ~~~~~~~~~~~ @@ -168,6 +173,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/data-protection `_ project on GitHub. +This module is part of the `OCA/data-protection `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/privacy_consent/i18n/privacy_consent.pot b/privacy_consent/i18n/privacy_consent.pot index cf3cd1af..a444d243 100644 --- a/privacy_consent/i18n/privacy_consent.pot +++ b/privacy_consent/i18n/privacy_consent.pot @@ -4,10 +4,8 @@ # msgid "" msgstr "" -"Project-Id-Version: Odoo Server 10.0\n" +"Project-Id-Version: Odoo Server 11.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-05-13 17:04+0000\n" -"PO-Revision-Date: 2019-05-13 17:04+0000\n" "Last-Translator: <>\n" "Language-Team: \n" "MIME-Version: 1.0\n" @@ -175,18 +173,18 @@ msgid "Consent" msgstr "" #. module: privacy_consent -#: model:ir.model,name:privacy_consent.model_privacy_consent -msgid "Consent of data processing" +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_template_default_body_html +msgid "Consent Template Default Body Html" msgstr "" #. module: privacy_consent -#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_template_default_body_html -msgid "Consent template default body html" +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_template_default_subject +msgid "Consent Template Default Subject" msgstr "" #. module: privacy_consent -#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_template_default_subject -msgid "Consent template default subject" +#: model:ir.model,name:privacy_consent.model_privacy_consent +msgid "Consent of data processing" msgstr "" #. module: privacy_consent @@ -199,6 +197,11 @@ msgstr "" msgid "Consents" msgstr "" +#. module: privacy_consent +#: model:ir.model,name:privacy_consent.model_res_partner +msgid "Contact" +msgstr "" + #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_create_uid msgid "Created by" @@ -239,11 +242,6 @@ msgstr "" msgid "Email Templates" msgstr "" -#. module: privacy_consent -#: model:ir.model,name:privacy_consent.model_mail_compose_message -msgid "Email composition wizard" -msgstr "" - #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_template_id msgid "Email template" @@ -270,7 +268,7 @@ msgid "Generate missing draft consent requests" msgstr "" #. module: privacy_consent -#: code:addons/privacy_consent/models/privacy_activity.py:139 +#: code:addons/privacy_consent/models/privacy_activity.py:138 #, python-format msgid "Generated consents" msgstr "" @@ -310,6 +308,11 @@ msgstr "" msgid "Indicates current acceptance status, which can come from subject's last answer, or from the default specified in the related data processing activity." msgstr "" +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_last_metadata +msgid "Last Metadata" +msgstr "" + #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent___last_update msgid "Last Modified on" @@ -325,11 +328,6 @@ msgstr "" msgid "Last Updated on" msgstr "" -#. module: privacy_consent -#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_last_metadata -msgid "Last metadata" -msgstr "" - #. module: privacy_consent #: selection:privacy.activity,consent_required:0 msgid "Manually" @@ -341,7 +339,7 @@ msgid "Metadata from the last acceptance or rejection by the subject" msgstr "" #. module: privacy_consent -#: code:addons/privacy_consent/models/mail_template.py:25 +#: code:addons/privacy_consent/models/mail_template.py:24 #, python-format msgid "Missing privacy consent link placeholders. You need at least these two links:\n" "Accept\n" @@ -359,11 +357,6 @@ msgstr "" msgid "Outgoing Mails" msgstr "" -#. module: privacy_consent -#: model:ir.model,name:privacy_consent.model_res_partner -msgid "Partner" -msgstr "" - #. module: privacy_consent #: model:mail.message.subtype,description:privacy_consent.mt_activity_acceptance_changed msgid "Privacy consent request acceptance status changed" @@ -394,7 +387,14 @@ msgid "Privacy consents" msgstr "" #. module: privacy_consent -#: code:addons/privacy_consent/models/privacy_activity.py:100 +#: model:ir.actions.server,name:privacy_consent.cron_auto_consent_ir_actions_server +#: model:ir.cron,cron_name:privacy_consent.cron_auto_consent +#: model:ir.cron,name:privacy_consent.cron_auto_consent +msgid "Request automatic data processing consents" +msgstr "" + +#. module: privacy_consent +#: code:addons/privacy_consent/models/privacy_activity.py:99 #, python-format msgid "Require consent is available only for subjects in current database." msgstr "" @@ -420,7 +420,7 @@ msgid "Sincerely,
    " msgstr "" #. module: privacy_consent -#: code:addons/privacy_consent/models/privacy_activity.py:92 +#: code:addons/privacy_consent/models/privacy_activity.py:91 #, python-format msgid "Specify a mail template to ask automated consent." msgstr "" diff --git a/privacy_consent/static/description/index.html b/privacy_consent/static/description/index.html index 058144a6..7e69756b 100644 --- a/privacy_consent/static/description/index.html +++ b/privacy_consent/static/description/index.html @@ -367,7 +367,7 @@

    Privacy - Consent

    !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> -

    Production/Stable License: AGPL-3 OCA/data-protection Translate me on Weblate Try me on Runbot

    +

    Production/Stable License: AGPL-3 OCA/data-protection Translate me on Weblate Try me on Runbot

    This module allows the user to define a set of subjects (partners) affected by any data processing activity, and establish a process to ask them for consent to include them in that activity.

    @@ -484,7 +484,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.

    @@ -493,6 +493,7 @@

    Credits

    Authors

    • Tecnativa
    • +
    • initOS GmbH
    @@ -502,6 +503,10 @@

    Contributors

  • Jairo Llopis
  • +
  • initOS GmbH:
      +
    • Florian Kantelberg
    • +
    +
  • @@ -511,7 +516,7 @@

    Maintainers

    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/data-protection project on GitHub.

    +

    This module is part of the OCA/data-protection project on GitHub.

    You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

    diff --git a/privacy_consent/views/privacy_activity.xml b/privacy_consent/views/privacy_activity.xml index b13bce22..ef722759 100644 --- a/privacy_consent/views/privacy_activity.xml +++ b/privacy_consent/views/privacy_activity.xml @@ -10,12 +10,11 @@
    -
    - + @@ -60,7 +60,7 @@ /> Date: Tue, 10 Jun 2025 16:08:12 +0200 Subject: [PATCH 34/41] [IMP] privacy_consent: pre-commit auto fixes --- privacy_consent/data/mail.xml | 24 +++++++++++------------ privacy_consent/models/privacy_consent.py | 7 ++----- privacy_consent/templates/form.xml | 22 ++++++++++----------- 3 files changed, 25 insertions(+), 28 deletions(-) diff --git a/privacy_consent/data/mail.xml b/privacy_consent/data/mail.xml index 49b73a60..ed016deb 100644 --- a/privacy_consent/data/mail.xml +++ b/privacy_consent/data/mail.xml @@ -47,11 +47,11 @@

    We contacted you to ask you to give us your explicit consent to include your data in a data processing activity called , property of + t-out="object.activity_id.display_name" + />, property of + t-out="object.activity_id.controller_id.display_name" + />

    @@ -63,11 +63,11 @@ - accepted - + accepted + - rejected - + rejected + such data processing.

    @@ -119,10 +119,10 @@

    Sent by - - . + + .

    diff --git a/privacy_consent/models/privacy_consent.py b/privacy_consent/models/privacy_consent.py index e04d909f..c90797eb 100644 --- a/privacy_consent/models/privacy_consent.py +++ b/privacy_consent/models/privacy_consent.py @@ -73,11 +73,8 @@ def _track_subtype(self, init_values): def _token(self): """Secret token to publicly authenticate this record.""" secret = self.env["ir.config_parameter"].sudo().get_param("database.secret") - params = "{}-{}-{}-{}".format( - self.env.cr.dbname, - self.id, - self.partner_id.id, - self.activity_id.id, + params = ( + f"{self.env.cr.dbname}-{self.id}-{self.partner_id.id}-{self.activity_id.id}" ) return hmac.new( secret.encode("utf-8"), diff --git a/privacy_consent/templates/form.xml b/privacy_consent/templates/form.xml index eae86031..650dabc5 100644 --- a/privacy_consent/templates/form.xml +++ b/privacy_consent/templates/form.xml @@ -31,21 +31,21 @@

    If it was a mistake, you can undo it here:

    +

    Thanks for your response. From 9c4115b370a14adf64d9178c4906c6801a5f2aa8 Mon Sep 17 00:00:00 2001 From: michelerusti Date: Tue, 10 Jun 2025 16:52:07 +0200 Subject: [PATCH 35/41] [MIG] privacy_consent: Migration to 18.0 --- privacy_consent/README.rst | 16 ++--- privacy_consent/__manifest__.py | 2 +- privacy_consent/controllers/main.py | 2 +- privacy_consent/data/ir_cron.xml | 1 - privacy_consent/models/mail_template.py | 4 +- privacy_consent/models/privacy_activity.py | 10 ++-- privacy_consent/static/description/index.html | 34 +++++------ privacy_consent/tests/test_consent.py | 58 ++++++++----------- privacy_consent/views/privacy_activity.xml | 4 +- privacy_consent/views/privacy_consent.xml | 18 +++--- 10 files changed, 62 insertions(+), 87 deletions(-) diff --git a/privacy_consent/README.rst b/privacy_consent/README.rst index f1d97e96..0312a498 100644 --- a/privacy_consent/README.rst +++ b/privacy_consent/README.rst @@ -1,7 +1,3 @@ -.. image:: https://odoo-community.org/readme-banner-image - :target: https://odoo-community.org/get-involved?utm_source=readme - :alt: Odoo Community Association - ================= Privacy - Consent ================= @@ -17,17 +13,17 @@ Privacy - Consent .. |badge1| image:: https://img.shields.io/badge/maturity-Production%2FStable-green.png :target: https://odoo-community.org/page/development-status :alt: Production/Stable -.. |badge2| image:: https://img.shields.io/badge/license-AGPL--3-blue.png +.. |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%2Fdata--protection-lightgray.png?logo=github - :target: https://github.com/OCA/data-protection/tree/17.0/privacy_consent + :target: https://github.com/OCA/data-protection/tree/18.0/privacy_consent :alt: OCA/data-protection .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/data-protection-17-0/data-protection-17-0-privacy_consent + :target: https://translation.odoo-community.org/projects/data-protection-18-0/data-protection-18-0-privacy_consent :alt: Translate me on Weblate .. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png - :target: https://runboat.odoo-community.org/builds?repo=OCA/data-protection&target_branch=17.0 + :target: https://runboat.odoo-community.org/builds?repo=OCA/data-protection&target_branch=18.0 :alt: Try me on Runboat |badge1| |badge2| |badge3| |badge4| |badge5| @@ -144,7 +140,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 to smash it by providing a detailed and welcomed -`feedback `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -181,6 +177,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/data-protection `_ project on GitHub. +This module is part of the `OCA/data-protection `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/privacy_consent/__manifest__.py b/privacy_consent/__manifest__.py index dc699cdd..20b0659a 100644 --- a/privacy_consent/__manifest__.py +++ b/privacy_consent/__manifest__.py @@ -4,7 +4,7 @@ "name": "Privacy - Consent", "summary": "Allow people to explicitly accept or reject inclusion " "in some activity, GDPR compliant", - "version": "17.0.1.0.1", + "version": "18.0.1.0.0", "development_status": "Production/Stable", "category": "Privacy", "website": "https://github.com/OCA/data-protection", diff --git a/privacy_consent/controllers/main.py b/privacy_consent/controllers/main.py index f31f1526..b8db4ad6 100644 --- a/privacy_consent/controllers/main.py +++ b/privacy_consent/controllers/main.py @@ -47,6 +47,6 @@ def _metadata(self): "User agent: {}\n" "Remote IP: {}\n" "Date and time: {:%Y-%m-%d %H:%M:%S}" ).format( request.httprequest.environ.get("HTTP_USER_AGENT"), - request.httprequest.environ.get("REMOTE_ADDRESS"), + request.httprequest.environ.get("REMOTE_ADDR"), datetime.now(), ) diff --git a/privacy_consent/data/ir_cron.xml b/privacy_consent/data/ir_cron.xml index d008b86d..5115caa9 100644 --- a/privacy_consent/data/ir_cron.xml +++ b/privacy_consent/data/ir_cron.xml @@ -10,6 +10,5 @@ model._cron_new_consents() 1 days - -1 diff --git a/privacy_consent/models/mail_template.py b/privacy_consent/models/mail_template.py index 7347fc51..14abac4c 100644 --- a/privacy_consent/models/mail_template.py +++ b/privacy_consent/models/mail_template.py @@ -3,7 +3,7 @@ from lxml import html -from odoo import _, api, models +from odoo import api, models from odoo.exceptions import ValidationError @@ -24,7 +24,7 @@ def _check_consent_links_in_body_html(self): for link in links: if not doc.xpath(link): raise ValidationError( - _( + self.env._( "Missing privacy consent link placeholders. " "You need at least these two links:\n" 'Accept\n' diff --git a/privacy_consent/models/privacy_activity.py b/privacy_consent/models/privacy_activity.py index 1af696b0..e7f5e07e 100644 --- a/privacy_consent/models/privacy_activity.py +++ b/privacy_consent/models/privacy_activity.py @@ -1,7 +1,7 @@ # Copyright 2018 Tecnativa - Jairo Llopis # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -from odoo import _, api, fields, models +from odoo import api, fields, models from odoo.exceptions import ValidationError from odoo.tools.safe_eval import safe_eval @@ -88,7 +88,7 @@ def _check_auto_consent_has_template(self): for one in self: if one.consent_required == "auto" and not one.consent_template_id: raise ValidationError( - _("Specify a mail template to ask automated consent.") + self.env._("Specify a mail template to ask automated consent.") ) @api.constrains("consent_required", "subject_find") @@ -96,7 +96,7 @@ def _check_consent_required_subject_find(self): for one in self: if one.consent_required and not one.subject_find: raise ValidationError( - _( + self.env._( "Require consent is available only for subjects " "in current database." ) @@ -138,8 +138,8 @@ def action_new_consents(self): # Redirect user to new consent requests generated return { "domain": [("id", "in", consents.ids)], - "name": _("Generated consents"), + "name": self.env._("Generated consents"), "res_model": consents._name, "type": "ir.actions.act_window", - "view_mode": "tree,form", + "view_mode": "list,form", } diff --git a/privacy_consent/static/description/index.html b/privacy_consent/static/description/index.html index 21576f3d..88e7c137 100644 --- a/privacy_consent/static/description/index.html +++ b/privacy_consent/static/description/index.html @@ -3,7 +3,7 @@ -README.rst +Privacy - Consent -

    + -
    diff --git a/privacy_consent/tests/test_consent.py b/privacy_consent/tests/test_consent.py index 8f863af9..2e7b6a5d 100644 --- a/privacy_consent/tests/test_consent.py +++ b/privacy_consent/tests/test_consent.py @@ -9,30 +9,30 @@ import odoo.tests from odoo import http from odoo.exceptions import AccessError, ValidationError -from odoo.tests import users -from odoo.tests.common import Form +from odoo.tests import Form, users from odoo.addons.base.models.ir_mail_server import IrMailServer from odoo.addons.mail.tests.common import mail_new_test_user class ActivityCase(odoo.tests.HttpCase): - def setUp(self): - super().setUp() - self.cron = self.env.ref("privacy_consent.cron_auto_consent") - self.cron_mail_queue = self.env.ref("mail.ir_cron_mail_scheduler_action") - self.sync_blacklist = self.env.ref("privacy_consent.sync_blacklist") - self.mt_consent_consent_new = self.env.ref( + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.cron = cls.env.ref("privacy_consent.cron_auto_consent") + cls.cron_mail_queue = cls.env.ref("mail.ir_cron_mail_scheduler_action") + cls.sync_blacklist = cls.env.ref("privacy_consent.sync_blacklist") + cls.mt_consent_consent_new = cls.env.ref( "privacy_consent.mt_consent_consent_new" ) - self.mt_consent_acceptance_changed = self.env.ref( + cls.mt_consent_acceptance_changed = cls.env.ref( "privacy_consent.mt_consent_acceptance_changed" ) - self.mt_consent_state_changed = self.env.ref( + cls.mt_consent_state_changed = cls.env.ref( "privacy_consent.mt_consent_state_changed" ) # Some partners to ask for consent - self.partners = self.env["res.partner"].create( + cls.partners = cls.env["res.partner"].create( [ {"name": "consent-partner-0", "email": "partner0@example.com"}, {"name": "consent-partner-1", "email": "partner1@example.com"}, @@ -44,34 +44,34 @@ def setUp(self): ] ) # Blacklist some partners - self.blacklists = self.env["mail.blacklist"] - self.blacklists += self.blacklists._add("partner1@example.com") + cls.blacklists = cls.env["mail.blacklist"] + cls.blacklists += cls.blacklists._add("partner1@example.com") # Activity without consent - self.activity_noconsent = self.env["privacy.activity"].create( + cls.activity_noconsent = cls.env["privacy.activity"].create( {"name": "activity_noconsent", "description": "I'm activity 1"} ) # Activity with auto consent, for all partners - self.activity_auto = self.env["privacy.activity"].create( + cls.activity_auto = cls.env["privacy.activity"].create( { "name": "activity_auto", "description": "I'm activity auto", "subject_find": True, - "subject_domain": repr([("id", "in", self.partners.ids)]), + "subject_domain": repr([("id", "in", cls.partners.ids)]), "consent_required": "auto", "default_consent": True, - "server_action_id": self.sync_blacklist.id, + "server_action_id": cls.sync_blacklist.id, } ) # Activity with manual consent, skipping partner 0 - self.activity_manual = self.env["privacy.activity"].create( + cls.activity_manual = cls.env["privacy.activity"].create( { "name": "activity_manual", "description": "I'm activity 3", "subject_find": True, - "subject_domain": repr([("id", "in", self.partners[1:].ids)]), + "subject_domain": repr([("id", "in", cls.partners[1:].ids)]), "consent_required": "manual", "default_consent": False, - "server_action_id": self.sync_blacklist.id, + "server_action_id": cls.sync_blacklist.id, } ) @@ -361,10 +361,10 @@ def test_message_get_suggested_recipients(self): } ) suggested_recipients = consent._message_get_suggested_recipients() - recipient_data = suggested_recipients.get(consent.id) - self.assertEqual(consent.partner_id.id, recipient_data[0][0]) - self.assertIn(consent.partner_id.name, recipient_data[0][1]) - self.assertIn(consent.partner_id.email, recipient_data[0][1]) + recipient = suggested_recipients[0] + self.assertEqual(consent.partner_id.id, recipient["partner_id"]) + self.assertIn(consent.partner_id.name, recipient["name"]) + self.assertIn(consent.partner_id.email, recipient["email"]) def test_compute_consent_count(self): """Test that consent_count is correctly updated.""" @@ -420,23 +420,13 @@ def setUpClass(cls): cls.user_admin = cls.env.ref("base.user_admin") cls.user_privacy_user = mail_new_test_user( cls.env, - company_id=cls.user_admin.company_id.id, - country_id=cls.env.ref("base.be").id, groups="base.group_user,privacy.group_data_protection_user", login="user_privacy_user", - name="Patrick Privacy User", - notification_type="inbox", - signature="--\nPatrick", ) cls.user_privacy_manager = mail_new_test_user( cls.env, - company_id=cls.user_admin.company_id.id, - country_id=cls.env.ref("base.be").id, groups="base.group_user,privacy.group_data_protection_manager", login="user_privacy_manager", - name="Patricia Privacy Manager", - notification_type="inbox", - signature="--\nPatricia", ) @classmethod diff --git a/privacy_consent/views/privacy_activity.xml b/privacy_consent/views/privacy_activity.xml index ab9b078a..52366944 100644 --- a/privacy_consent/views/privacy_activity.xml +++ b/privacy_consent/views/privacy_activity.xml @@ -9,7 +9,7 @@
    - + diff --git a/privacy_consent/views/privacy_consent.xml b/privacy_consent/views/privacy_consent.xml index b72e3547..ccc9e290 100644 --- a/privacy_consent/views/privacy_consent.xml +++ b/privacy_consent/views/privacy_consent.xml @@ -18,12 +18,11 @@
    -
    @@ -33,23 +32,20 @@
    -
    - - -
    +
    - - Privacy Consent Tree + + Privacy Consent List privacy.consent - + - + @@ -92,7 +88,7 @@ Consents ir.actions.act_window privacy.consent - tree,form + list,form Date: Wed, 2 Jul 2025 14:02:16 +0000 Subject: [PATCH 36/41] [UPD] Update privacy_consent.pot --- privacy_consent/i18n/privacy_consent.pot | 28 ++++++++++-------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/privacy_consent/i18n/privacy_consent.pot b/privacy_consent/i18n/privacy_consent.pot index ea1189f6..f1a992bf 100644 --- a/privacy_consent/i18n/privacy_consent.pot +++ b/privacy_consent/i18n/privacy_consent.pot @@ -4,7 +4,7 @@ # msgid "" msgstr "" -"Project-Id-Version: Odoo Server 17.0\n" +"Project-Id-Version: Odoo Server 18.0\n" "Report-Msgid-Bugs-To: \n" "Last-Translator: \n" "Language-Team: \n" @@ -22,7 +22,7 @@ msgid "" "
    \n" " \n" " \n" @@ -33,14 +33,14 @@ msgid "" " \n" " \n" " \n" @@ -304,7 +304,6 @@ msgstr "" #. module: privacy_consent #. odoo-python #: code:addons/privacy_consent/models/privacy_activity.py:0 -#, python-format msgid "Generated consents" msgstr "" @@ -404,7 +403,6 @@ msgstr "" #. module: privacy_consent #. odoo-python #: code:addons/privacy_consent/models/mail_template.py:0 -#, python-format msgid "" "Missing privacy consent link placeholders. You need at least these two links:\n" "Accept\n" @@ -484,7 +482,6 @@ msgstr "" #. module: privacy_consent #. odoo-python #: code:addons/privacy_consent/models/privacy_activity.py:0 -#, python-format msgid "Require consent is available only for subjects in current database." msgstr "" @@ -513,7 +510,6 @@ msgstr "" #. module: privacy_consent #. odoo-python #: code:addons/privacy_consent/models/privacy_activity.py:0 -#, python-format msgid "Specify a mail template to ask automated consent." msgstr "" From 8ee8a0c4d1df07e318a67fa55677a2affb068ff8 Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Wed, 2 Jul 2025 14:04:21 +0000 Subject: [PATCH 37/41] [BOT] post-merge updates --- privacy_consent/README.rst | 8 +++-- privacy_consent/static/description/index.html | 32 +++++++++++-------- 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/privacy_consent/README.rst b/privacy_consent/README.rst index 0312a498..92bd6b8a 100644 --- a/privacy_consent/README.rst +++ b/privacy_consent/README.rst @@ -1,3 +1,7 @@ +.. image:: https://odoo-community.org/readme-banner-image + :target: https://odoo-community.org/get-involved?utm_source=readme + :alt: Odoo Community Association + ================= Privacy - Consent ================= @@ -7,13 +11,13 @@ Privacy - Consent !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:ced0876b7a2158b58b368897f592f9e935aa65fa1bbadd68aef7ee61b05925b9 + !! source digest: sha256:a1bc87f33b1755f112f2b02a4eed8fdf8576c046d801f3a73fd085f5c9de029f !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Production%2FStable-green.png :target: https://odoo-community.org/page/development-status :alt: Production/Stable -.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png +.. |badge2| image:: https://img.shields.io/badge/license-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%2Fdata--protection-lightgray.png?logo=github diff --git a/privacy_consent/static/description/index.html b/privacy_consent/static/description/index.html index 88e7c137..27b96035 100644 --- a/privacy_consent/static/description/index.html +++ b/privacy_consent/static/description/index.html @@ -3,7 +3,7 @@ -Privacy - Consent +README.rst - From 713075155fa6e3a4f3677523608170e5bc75060a Mon Sep 17 00:00:00 2001 From: Matjaz Mozetic Date: Fri, 26 Jun 2026 14:48:07 +0000 Subject: [PATCH 38/41] Added translation using Weblate (Slovenian) --- privacy_consent/i18n/sl.po | 580 +++++++++++++++++++++++++++++++++++++ 1 file changed, 580 insertions(+) create mode 100644 privacy_consent/i18n/sl.po diff --git a/privacy_consent/i18n/sl.po b/privacy_consent/i18n/sl.po new file mode 100644 index 00000000..791b5803 --- /dev/null +++ b/privacy_consent/i18n/sl.po @@ -0,0 +1,580 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * privacy_consent +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 18.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: sl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=4; plural=n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || " +"n%100==4 ? 2 : 3;\n" + +#. module: privacy_consent +#: model:mail.template,body_html:privacy_consent.template_consent +msgid "" +"
    \n" +"
    \n" +" \n" "

    \n" " Sent by\n" -" ${object.activity_id.controller_id.display_name|safe}.\n" +" " +"${object.activity_id.controller_id.display_name|safe}.\n" "

    \n" "
    \n" " \n" -" \n" +" \n" " \n" "
    \n" "

    \n" -" Hello, \n" +" Hello, \n" "

    \n" "

    \n" " We contacted you to ask you to give us your explicit consent to include your data in a data processing activity called\n" -" , property of\n" -" \n" +" , property of\n" +" \n" "

    \n" -" \n" +" \n" "

    \n" " \n" " The last time you answered, you\n" @@ -50,11 +50,11 @@ msgid "" " \n" "\n" " \n" -" accepted\n" -" \n" +" accepted\n" +" \n" " \n" -" rejected\n" -" \n" +" rejected\n" +" \n" " such data processing.\n" "

    \n" "

    \n" @@ -93,8 +93,8 @@ msgid "" "

    \n" " Sent by\n" " \n" -" \n" -" .\n" +" \n" +" .\n" "

    \n" "
    \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
    \n" +" \n" +" \n" +" \n" +"
    \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
    \n" +"

    \n" +" Hello, \n" +"

    \n" +"

    \n" +" We contacted you to ask you to give us your explicit consent to include your data in a data processing activity called\n" +" , property of\n" +" \n" +"

    \n" +" \n" +"

    \n" +" \n" +" The last time you answered, you\n" +" \n" +" \n" +" If you do nothing, we will assume you have\n" +" \n" +"\n" +" \n" +" accepted\n" +" \n" +" \n" +" rejected\n" +" \n" +" such data processing.\n" +"

    \n" +"

    \n" +" You can update your preferences below:\n" +"

    \n" +"
    \n" +" \n" +" Accept\n" +" \n" +" \n" +" \n" +" Reject\n" +" \n" +"
    \n" +"

    \n" +" If you need further information, please respond to this email and we will attend your request as soon as possible.\n" +"

    \n" +"

    \n" +" Thank you!\n" +"

    \n" +"
    \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
    \n" +"

    \n" +" Sent by\n" +" \n" +" \n" +" .\n" +"

    \n" +"
    \n" +"
    \n" +" " +msgstr "" + +#. module: privacy_consent +#: model:mail.message.subtype,name:privacy_consent.mt_activity_acceptance_changed +msgid "Acceptance Changed" +msgstr "" + +#. module: privacy_consent +#: model:mail.message.subtype,name:privacy_consent.mt_consent_acceptance_changed +msgid "Acceptance Changed by Subject" +msgstr "" + +#. module: privacy_consent +#: model:mail.message.subtype,description:privacy_consent.mt_consent_acceptance_changed +msgid "Acceptance status updated by subject" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__accepted +#: model_terms:ir.ui.view,arch_db:privacy_consent.consent_search +msgid "Accepted" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity__default_consent +msgid "Accepted by default" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__message_needaction +msgid "Action Needed" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__active +msgid "Active" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__activity_id +#: model_terms:ir.ui.view,arch_db:privacy_consent.consent_search +msgid "Activity" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields.selection,name:privacy_consent.selection__privacy_consent__state__answered +msgid "Answered" +msgstr "" + +#. module: privacy_consent +#: model_terms:ir.ui.view,arch_db:privacy_consent.consent_form +#: model_terms:ir.ui.view,arch_db:privacy_consent.consent_search +msgid "Archived" +msgstr "" + +#. module: privacy_consent +#: model_terms:ir.ui.view,arch_db:privacy_consent.consent_form +msgid "Ask for consent" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity__consent_required +msgid "Ask subjects for consent" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__message_attachment_count +msgid "Attachment Count" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields.selection,name:privacy_consent.selection__privacy_activity__consent_required__auto +msgid "Automatically" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields.selection,name:privacy_consent.selection__privacy_consent__state__sent +msgid "Awaiting response" +msgstr "" + +#. module: privacy_consent +#: model_terms:ir.ui.view,arch_db:privacy_consent.activity_form +msgid "Consent" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity__consent_template_default_body_html +msgid "Consent Template Default Body Html" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity__consent_template_default_subject +msgid "Consent Template Default Subject" +msgstr "" + +#. module: privacy_consent +#: model:ir.model,name:privacy_consent.model_privacy_consent +msgid "Consent of data processing" +msgstr "" + +#. module: privacy_consent +#: model:ir.actions.act_window,name:privacy_consent.consent_action +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity__consent_ids +#: model:ir.model.fields,field_description:privacy_consent.field_res_partner__privacy_consent_count +#: model:ir.model.fields,field_description:privacy_consent.field_res_users__privacy_consent_count +#: model:ir.ui.menu,name:privacy_consent.menu_privacy_consent +msgid "Consents" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity__consent_count +msgid "Consents count" +msgstr "" + +#. module: privacy_consent +#: model:ir.model,name:privacy_consent.model_res_partner +msgid "Contact" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__create_uid +msgid "Created by" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__create_date +msgid "Created on" +msgstr "" + +#. module: privacy_consent +#: model:ir.model,name:privacy_consent.model_privacy_activity +msgid "Data processing activities" +msgstr "" + +#. module: privacy_consent +#: model:mail.template,subject:privacy_consent.template_consent +msgid "" +"Data processing consent request for {{ object.activity_id.display_name }}" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__display_name +msgid "Display Name" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields.selection,name:privacy_consent.selection__privacy_consent__state__draft +msgid "Draft" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.constraint,message:privacy_consent.constraint_privacy_consent_unique_partner_activity +msgid "Duplicated partner in this data processing activity" +msgstr "" + +#. module: privacy_consent +#: model:ir.model,name:privacy_consent.model_mail_template +msgid "Email Templates" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity__consent_template_id +msgid "Email template" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,help:privacy_consent.field_privacy_activity__consent_template_id +msgid "" +"Email to be sent to subjects to ask for consent. A good template should " +"include details about the current consent request status, how to change it, " +"and where to get more information." +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,help:privacy_consent.field_privacy_activity__consent_required +msgid "" +"Enable if you need to track any kind of consent from the affected subjects" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__message_follower_ids +msgid "Followers" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__message_partner_ids +msgid "Followers (Partners)" +msgstr "" + +#. module: privacy_consent +#: model_terms:ir.ui.view,arch_db:privacy_consent.activity_form +msgid "Generate and enqueue missing consent requests" +msgstr "" + +#. module: privacy_consent +#: model_terms:ir.ui.view,arch_db:privacy_consent.activity_form +msgid "Generate missing draft consent requests" +msgstr "" + +#. module: privacy_consent +#. odoo-python +#: code:addons/privacy_consent/models/privacy_activity.py:0 +msgid "Generated consents" +msgstr "" + +#. module: privacy_consent +#: model_terms:ir.ui.view,arch_db:privacy_consent.consent_search +msgid "Group By" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__has_message +msgid "Has Message" +msgstr "" + +#. module: privacy_consent +#: model_terms:ir.ui.view,arch_db:privacy_consent.form +msgid "Hello," +msgstr "" + +#. module: privacy_consent +#: model_terms:ir.ui.view,arch_db:privacy_consent.form +msgid "I accept this processing of my data" +msgstr "" + +#. module: privacy_consent +#: model_terms:ir.ui.view,arch_db:privacy_consent.form +msgid "I reject this processing of my data" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__id +msgid "ID" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,help:privacy_consent.field_privacy_consent__message_needaction +msgid "If checked, new messages require your attention." +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,help:privacy_consent.field_privacy_consent__message_has_error +msgid "If checked, some messages have a delivery error." +msgstr "" + +#. module: privacy_consent +#: model_terms:ir.ui.view,arch_db:privacy_consent.form +msgid "If it was a mistake, you can undo it here:" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,help:privacy_consent.field_privacy_consent__accepted +msgid "" +"Indicates current acceptance status, which can come from subject's last " +"answer, or from the default specified in the related data processing " +"activity." +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__message_is_follower +msgid "Is Follower" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__last_metadata +msgid "Last Metadata" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__write_date +msgid "Last Updated on" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields.selection,name:privacy_consent.selection__privacy_activity__consent_required__manual +msgid "Manually" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__message_has_error +msgid "Message Delivery error" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__message_ids +msgid "Messages" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,help:privacy_consent.field_privacy_consent__last_metadata +msgid "Metadata from the last acceptance or rejection by the subject" +msgstr "" + +#. module: privacy_consent +#. odoo-python +#: code:addons/privacy_consent/models/mail_template.py:0 +msgid "" +"Missing privacy consent link placeholders. You need at least these two links:\n" +"Accept\n" +"Reject" +msgstr "" + +#. module: privacy_consent +#: model:mail.message.subtype,name:privacy_consent.mt_activity_consent_new +#: model:mail.message.subtype,name:privacy_consent.mt_consent_consent_new +msgid "New Consent" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__message_needaction_counter +msgid "Number of Actions" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__message_has_error_counter +msgid "Number of errors" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,help:privacy_consent.field_privacy_consent__message_needaction_counter +msgid "Number of messages requiring action" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,help:privacy_consent.field_privacy_consent__message_has_error_counter +msgid "Number of messages with delivery error" +msgstr "" + +#. module: privacy_consent +#: model:ir.model,name:privacy_consent.model_mail_mail +msgid "Outgoing Mails" +msgstr "" + +#. module: privacy_consent +#: model:mail.template,name:privacy_consent.template_consent +msgid "Personal data processing consent request" +msgstr "" + +#. module: privacy_consent +#: model:mail.message.subtype,description:privacy_consent.mt_activity_acceptance_changed +msgid "Privacy consent request acceptance status changed" +msgstr "" + +#. module: privacy_consent +#: model:mail.message.subtype,description:privacy_consent.mt_activity_consent_new +#: model:mail.message.subtype,description:privacy_consent.mt_consent_consent_new +msgid "Privacy consent request created" +msgstr "" + +#. module: privacy_consent +#: model:mail.message.subtype,description:privacy_consent.mt_activity_state_changed +#: model:mail.message.subtype,description:privacy_consent.mt_consent_state_changed +msgid "Privacy consent request state changed" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,help:privacy_consent.field_res_partner__privacy_consent_count +#: model:ir.model.fields,help:privacy_consent.field_res_users__privacy_consent_count +msgid "Privacy consent requests amount" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_res_partner__privacy_consent_ids +#: model:ir.model.fields,field_description:privacy_consent.field_res_users__privacy_consent_ids +msgid "Privacy consents" +msgstr "" + +#. module: privacy_consent +#: model:ir.actions.server,name:privacy_consent.cron_auto_consent_ir_actions_server +msgid "Request automatic data processing consents" +msgstr "" + +#. module: privacy_consent +#. odoo-python +#: code:addons/privacy_consent/models/privacy_activity.py:0 +msgid "Require consent is available only for subjects in current database." +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,help:privacy_consent.field_privacy_activity__server_action_id +msgid "" +"Run this action when a new consent request is created or its acceptance " +"status is updated." +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity__server_action_id +msgid "Server action" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,help:privacy_consent.field_privacy_activity__default_consent +msgid "Should we assume the subject has accepted if we receive no response?" +msgstr "" + +#. module: privacy_consent +#: model_terms:ir.ui.view,arch_db:privacy_consent.form +msgid "Sincerely,
    " +msgstr "" + +#. module: privacy_consent +#. odoo-python +#: code:addons/privacy_consent/models/privacy_activity.py:0 +msgid "Specify a mail template to ask automated consent." +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__state +#: model_terms:ir.ui.view,arch_db:privacy_consent.consent_search +msgid "State" +msgstr "" + +#. module: privacy_consent +#: model:mail.message.subtype,name:privacy_consent.mt_activity_state_changed +#: model:mail.message.subtype,name:privacy_consent.mt_consent_state_changed +msgid "State Changed" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__partner_id +msgid "Subject" +msgstr "" + +#. module: privacy_consent +#: model:ir.model.fields,help:privacy_consent.field_privacy_consent__partner_id +msgid "Subject asked for consent." +msgstr "" + +#. module: privacy_consent +#: model:ir.actions.server,name:privacy_consent.sync_blacklist +msgid "Sync partner's email blacklist status" +msgstr "" + +#. module: privacy_consent +#: model_terms:ir.ui.view,arch_db:privacy_consent.form +msgid "Thank you!" +msgstr "" + +#. module: privacy_consent +#: model_terms:ir.ui.view,arch_db:privacy_consent.form +msgid "Thanks for your response." +msgstr "" + +#. module: privacy_consent +#: model_terms:ir.ui.view,arch_db:privacy_consent.activity_form +msgid "This could enqueue many consent emails, are you sure to proceed?" +msgstr "" + +#. module: privacy_consent +#: model_terms:ir.ui.view,arch_db:privacy_consent.form +msgid "" +"We asked you to authorize us to process your data in this data processing " +"activity:" +msgstr "" + +#. module: privacy_consent +#: model_terms:ir.ui.view,arch_db:privacy_consent.form +msgid "We have recorded this action on your side." +msgstr "" + +#. module: privacy_consent +#: model_terms:ir.ui.view,arch_db:privacy_consent.form +msgid "You have rejected such processing." +msgstr "" + +#. module: privacy_consent +#: model_terms:ir.ui.view,arch_db:privacy_consent.form +msgid "You have accepted such processing." +msgstr "" From ee20c5c8402b43f011127b8f045874afd6bf5255 Mon Sep 17 00:00:00 2001 From: Matjaz Mozetic Date: Fri, 26 Jun 2026 15:01:55 +0000 Subject: [PATCH 39/41] Translated using Weblate (Slovenian) Currently translated at 40.4% (36 of 89 strings) Translation: data-protection-18.0/data-protection-18.0-privacy_consent Translate-URL: https://translation.odoo-community.org/projects/data-protection-18-0/data-protection-18-0-privacy_consent/sl/ --- privacy_consent/i18n/sl.po | 76 ++++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 36 deletions(-) diff --git a/privacy_consent/i18n/sl.po b/privacy_consent/i18n/sl.po index 791b5803..67f2a107 100644 --- a/privacy_consent/i18n/sl.po +++ b/privacy_consent/i18n/sl.po @@ -6,7 +6,8 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 18.0\n" "Report-Msgid-Bugs-To: \n" -"Last-Translator: Automatically generated\n" +"PO-Revision-Date: 2026-06-26 15:02+0000\n" +"Last-Translator: Matjaz Mozetic \n" "Language-Team: none\n" "Language: sl\n" "MIME-Version: 1.0\n" @@ -14,6 +15,7 @@ msgstr "" "Content-Transfer-Encoding: \n" "Plural-Forms: nplurals=4; plural=n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || " "n%100==4 ? 2 : 3;\n" +"X-Generator: Weblate 5.15.2\n" #. module: privacy_consent #: model:mail.template,body_html:privacy_consent.template_consent @@ -125,7 +127,7 @@ msgstr "" #: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__accepted #: model_terms:ir.ui.view,arch_db:privacy_consent.consent_search msgid "Accepted" -msgstr "" +msgstr "Sprejeto" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity__default_consent @@ -135,18 +137,18 @@ msgstr "" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__message_needaction msgid "Action Needed" -msgstr "" +msgstr "Potrebno ukrepanje" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__active msgid "Active" -msgstr "" +msgstr "Aktivno" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__activity_id #: model_terms:ir.ui.view,arch_db:privacy_consent.consent_search msgid "Activity" -msgstr "" +msgstr "Aktivnost" #. module: privacy_consent #: model:ir.model.fields.selection,name:privacy_consent.selection__privacy_consent__state__answered @@ -157,7 +159,7 @@ msgstr "" #: model_terms:ir.ui.view,arch_db:privacy_consent.consent_form #: model_terms:ir.ui.view,arch_db:privacy_consent.consent_search msgid "Archived" -msgstr "" +msgstr "Arhivirano" #. module: privacy_consent #: model_terms:ir.ui.view,arch_db:privacy_consent.consent_form @@ -172,12 +174,12 @@ msgstr "" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__message_attachment_count msgid "Attachment Count" -msgstr "" +msgstr "Št. priponk" #. module: privacy_consent #: model:ir.model.fields.selection,name:privacy_consent.selection__privacy_activity__consent_required__auto msgid "Automatically" -msgstr "" +msgstr "Samodejno" #. module: privacy_consent #: model:ir.model.fields.selection,name:privacy_consent.selection__privacy_consent__state__sent @@ -221,22 +223,22 @@ msgstr "" #. module: privacy_consent #: model:ir.model,name:privacy_consent.model_res_partner msgid "Contact" -msgstr "" +msgstr "Stik" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__create_uid msgid "Created by" -msgstr "" +msgstr "Ustvaril" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__create_date msgid "Created on" -msgstr "" +msgstr "Ustvarjeno" #. module: privacy_consent #: model:ir.model,name:privacy_consent.model_privacy_activity msgid "Data processing activities" -msgstr "" +msgstr "Dejavnosti obdelave podatkov" #. module: privacy_consent #: model:mail.template,subject:privacy_consent.template_consent @@ -247,12 +249,12 @@ msgstr "" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__display_name msgid "Display Name" -msgstr "" +msgstr "Prikazani naziv" #. module: privacy_consent #: model:ir.model.fields.selection,name:privacy_consent.selection__privacy_consent__state__draft msgid "Draft" -msgstr "" +msgstr "Osnutek" #. module: privacy_consent #: model:ir.model.constraint,message:privacy_consent.constraint_privacy_consent_unique_partner_activity @@ -262,12 +264,12 @@ msgstr "" #. module: privacy_consent #: model:ir.model,name:privacy_consent.model_mail_template msgid "Email Templates" -msgstr "" +msgstr "Predloge e-pošte" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity__consent_template_id msgid "Email template" -msgstr "" +msgstr "Predloga e-pošte" #. module: privacy_consent #: model:ir.model.fields,help:privacy_consent.field_privacy_activity__consent_template_id @@ -286,12 +288,12 @@ msgstr "" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__message_follower_ids msgid "Followers" -msgstr "" +msgstr "Sledilci" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__message_partner_ids msgid "Followers (Partners)" -msgstr "" +msgstr "Sledilci (partnerji)" #. module: privacy_consent #: model_terms:ir.ui.view,arch_db:privacy_consent.activity_form @@ -312,17 +314,17 @@ msgstr "" #. module: privacy_consent #: model_terms:ir.ui.view,arch_db:privacy_consent.consent_search msgid "Group By" -msgstr "" +msgstr "Združi po" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__has_message msgid "Has Message" -msgstr "" +msgstr "Vsebuje sporočilo" #. module: privacy_consent #: model_terms:ir.ui.view,arch_db:privacy_consent.form msgid "Hello," -msgstr "" +msgstr "Pozdravljeni." #. module: privacy_consent #: model_terms:ir.ui.view,arch_db:privacy_consent.form @@ -337,17 +339,19 @@ msgstr "" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__id msgid "ID" -msgstr "" +msgstr "ID" #. module: privacy_consent #: model:ir.model.fields,help:privacy_consent.field_privacy_consent__message_needaction msgid "If checked, new messages require your attention." -msgstr "" +msgstr "Če je označeno, nova sporočila zahtevajo vašo pozornost." #. module: privacy_consent #: model:ir.model.fields,help:privacy_consent.field_privacy_consent__message_has_error msgid "If checked, some messages have a delivery error." msgstr "" +"Kadar je označeno, pomeni, da je pri nekaterih sporočilih prišlo do napake " +"pri dostavi." #. module: privacy_consent #: model_terms:ir.ui.view,arch_db:privacy_consent.form @@ -365,7 +369,7 @@ msgstr "" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__message_is_follower msgid "Is Follower" -msgstr "" +msgstr "Je sledilec" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__last_metadata @@ -375,27 +379,27 @@ msgstr "" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__write_uid msgid "Last Updated by" -msgstr "" +msgstr "Zadnji posodobil" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__write_date msgid "Last Updated on" -msgstr "" +msgstr "Zadnjič posodobljeno" #. module: privacy_consent #: model:ir.model.fields.selection,name:privacy_consent.selection__privacy_activity__consent_required__manual msgid "Manually" -msgstr "" +msgstr "Ročno" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__message_has_error msgid "Message Delivery error" -msgstr "" +msgstr "Napaka ob dostavi sporočila" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__message_ids msgid "Messages" -msgstr "" +msgstr "Sporočila" #. module: privacy_consent #: model:ir.model.fields,help:privacy_consent.field_privacy_consent__last_metadata @@ -420,27 +424,27 @@ msgstr "" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__message_needaction_counter msgid "Number of Actions" -msgstr "" +msgstr "Število ukrepov" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__message_has_error_counter msgid "Number of errors" -msgstr "" +msgstr "Število napak" #. module: privacy_consent #: model:ir.model.fields,help:privacy_consent.field_privacy_consent__message_needaction_counter msgid "Number of messages requiring action" -msgstr "" +msgstr "Število sporočil, ki zahtevajo ukrepanje" #. module: privacy_consent #: model:ir.model.fields,help:privacy_consent.field_privacy_consent__message_has_error_counter msgid "Number of messages with delivery error" -msgstr "" +msgstr "Število sporočil, ki niso bila pravilno dostavljena" #. module: privacy_consent #: model:ir.model,name:privacy_consent.model_mail_mail msgid "Outgoing Mails" -msgstr "" +msgstr "Izhodna pošta" #. module: privacy_consent #: model:mail.template,name:privacy_consent.template_consent @@ -497,7 +501,7 @@ msgstr "" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity__server_action_id msgid "Server action" -msgstr "" +msgstr "Strežniško dejanje" #. module: privacy_consent #: model:ir.model.fields,help:privacy_consent.field_privacy_activity__default_consent @@ -545,7 +549,7 @@ msgstr "" #. module: privacy_consent #: model_terms:ir.ui.view,arch_db:privacy_consent.form msgid "Thank you!" -msgstr "" +msgstr "Hvala!" #. module: privacy_consent #: model_terms:ir.ui.view,arch_db:privacy_consent.form From 15b9f9ccf179d4b00c6d8126266f600168dba5af Mon Sep 17 00:00:00 2001 From: Matjaz Mozetic Date: Fri, 26 Jun 2026 15:05:51 +0000 Subject: [PATCH 40/41] Translated using Weblate (Slovenian) Currently translated at 100.0% (89 of 89 strings) Translation: data-protection-18.0/data-protection-18.0-privacy_consent Translate-URL: https://translation.odoo-community.org/projects/data-protection-18-0/data-protection-18-0-privacy_consent/sl/ --- privacy_consent/i18n/sl.po | 220 +++++++++++++++++++++++++++++-------- 1 file changed, 176 insertions(+), 44 deletions(-) diff --git a/privacy_consent/i18n/sl.po b/privacy_consent/i18n/sl.po index 67f2a107..331817ab 100644 --- a/privacy_consent/i18n/sl.po +++ b/privacy_consent/i18n/sl.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 18.0\n" "Report-Msgid-Bugs-To: \n" -"PO-Revision-Date: 2026-06-26 15:02+0000\n" +"PO-Revision-Date: 2026-06-26 15:08+0000\n" "Last-Translator: Matjaz Mozetic \n" "Language-Team: none\n" "Language: sl\n" @@ -107,21 +107,131 @@ msgid "" "
    \n" " " msgstr "" +"
    \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
    \n" +" \n" +" \n" +" \n" +"
    \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
    \n" +"

    \n" +" Pozdravljeni, \n" +"

    \n" +"

    \n" +" Obračamo se na vas, da nam podate " +"izrecno privolitev za vključitev svojih podatkov v dejavnost obdelave " +"podatkov z nazivom\n" +" , upravljavca\n" +" \n" +"

    \n" +" " +"\n" +"

    \n" +" \n" +" Ob zadnjem odgovoru ste\n" +" \n" +" \n" +" Če ne storite ničesar, bomo šteli, " +"da ste\n" +" \n" +"\n" +" \n" +" sprejeli\n" +" \n" +" \n" +" zavrnili\n" +" \n" +" takšno obdelavo podatkov.\n" +"

    \n" +"

    \n" +" Svoje nastavitve lahko posodobite " +"spodaj:\n" +"

    \n" +"
    \n" +" \n" +" Sprejmi\n" +" \n" +" \n" +" \n" +" Zavrni\n" +" \n" +"
    \n" +"

    \n" +" Če potrebujete dodatne informacije, " +"odgovorite na to e-pošto in vašo zahtevo bomo obravnavali čim prej.\n" +"

    \n" +"

    \n" +" Hvala!\n" +"

    \n" +"
    \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
    " +"\n" +"

    \n" +" Poslal\n" +" \n" +" \n" +" .\n" +"

    \n" +"
    \n" +"
    \n" +" " #. module: privacy_consent #: model:mail.message.subtype,name:privacy_consent.mt_activity_acceptance_changed msgid "Acceptance Changed" -msgstr "" +msgstr "Sprejem spremenjen" #. module: privacy_consent #: model:mail.message.subtype,name:privacy_consent.mt_consent_acceptance_changed msgid "Acceptance Changed by Subject" -msgstr "" +msgstr "Sprejem spremenil posameznik" #. module: privacy_consent #: model:mail.message.subtype,description:privacy_consent.mt_consent_acceptance_changed msgid "Acceptance status updated by subject" -msgstr "" +msgstr "Status sprejema je posodobil posameznik" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__accepted @@ -132,7 +242,7 @@ msgstr "Sprejeto" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity__default_consent msgid "Accepted by default" -msgstr "" +msgstr "Privzeto sprejeto" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__message_needaction @@ -153,7 +263,7 @@ msgstr "Aktivnost" #. module: privacy_consent #: model:ir.model.fields.selection,name:privacy_consent.selection__privacy_consent__state__answered msgid "Answered" -msgstr "" +msgstr "Odgovorjeno" #. module: privacy_consent #: model_terms:ir.ui.view,arch_db:privacy_consent.consent_form @@ -164,12 +274,12 @@ msgstr "Arhivirano" #. module: privacy_consent #: model_terms:ir.ui.view,arch_db:privacy_consent.consent_form msgid "Ask for consent" -msgstr "" +msgstr "Zaprosi za privolitev" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity__consent_required msgid "Ask subjects for consent" -msgstr "" +msgstr "Zaprosi posameznike za privolitev" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__message_attachment_count @@ -184,27 +294,27 @@ msgstr "Samodejno" #. module: privacy_consent #: model:ir.model.fields.selection,name:privacy_consent.selection__privacy_consent__state__sent msgid "Awaiting response" -msgstr "" +msgstr "Čakanje na odgovor" #. module: privacy_consent #: model_terms:ir.ui.view,arch_db:privacy_consent.activity_form msgid "Consent" -msgstr "" +msgstr "Privolitev" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity__consent_template_default_body_html msgid "Consent Template Default Body Html" -msgstr "" +msgstr "Privzeta vsebina HTML predloge privolitve" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity__consent_template_default_subject msgid "Consent Template Default Subject" -msgstr "" +msgstr "Privzeta zadeva predloge privolitve" #. module: privacy_consent #: model:ir.model,name:privacy_consent.model_privacy_consent msgid "Consent of data processing" -msgstr "" +msgstr "Privolitev v obdelavo podatkov" #. module: privacy_consent #: model:ir.actions.act_window,name:privacy_consent.consent_action @@ -213,12 +323,12 @@ msgstr "" #: model:ir.model.fields,field_description:privacy_consent.field_res_users__privacy_consent_count #: model:ir.ui.menu,name:privacy_consent.menu_privacy_consent msgid "Consents" -msgstr "" +msgstr "Privolitve" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity__consent_count msgid "Consents count" -msgstr "" +msgstr "Število privolitev" #. module: privacy_consent #: model:ir.model,name:privacy_consent.model_res_partner @@ -245,6 +355,8 @@ msgstr "Dejavnosti obdelave podatkov" msgid "" "Data processing consent request for {{ object.activity_id.display_name }}" msgstr "" +"Zahtevek za privolitev v obdelavo podatkov za {{ " +"object.activity_id.display_name }}" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__display_name @@ -259,7 +371,7 @@ msgstr "Osnutek" #. module: privacy_consent #: model:ir.model.constraint,message:privacy_consent.constraint_privacy_consent_unique_partner_activity msgid "Duplicated partner in this data processing activity" -msgstr "" +msgstr "Podvojen partner v tej dejavnosti obdelave podatkov" #. module: privacy_consent #: model:ir.model,name:privacy_consent.model_mail_template @@ -278,12 +390,17 @@ msgid "" "include details about the current consent request status, how to change it, " "and where to get more information." msgstr "" +"E-pošta, poslana posameznikom za pridobitev privolitve. Dobra predloga mora " +"vsebovati podrobnosti o trenutnem statusu zahtevka za privolitev, kako ga " +"spremeniti in kje dobiti več informacij." #. module: privacy_consent #: model:ir.model.fields,help:privacy_consent.field_privacy_activity__consent_required msgid "" "Enable if you need to track any kind of consent from the affected subjects" msgstr "" +"Omogočite, če morate spremljati katero koli vrsto privolitve prizadetih " +"posameznikov" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__message_follower_ids @@ -298,18 +415,18 @@ msgstr "Sledilci (partnerji)" #. module: privacy_consent #: model_terms:ir.ui.view,arch_db:privacy_consent.activity_form msgid "Generate and enqueue missing consent requests" -msgstr "" +msgstr "Ustvari in uvrsti manjkajoče zahtevke za privolitev v čakalno vrsto" #. module: privacy_consent #: model_terms:ir.ui.view,arch_db:privacy_consent.activity_form msgid "Generate missing draft consent requests" -msgstr "" +msgstr "Ustvari manjkajoče osnutke zahtevkov za privolitev" #. module: privacy_consent #. odoo-python #: code:addons/privacy_consent/models/privacy_activity.py:0 msgid "Generated consents" -msgstr "" +msgstr "Ustvarjene privolitve" #. module: privacy_consent #: model_terms:ir.ui.view,arch_db:privacy_consent.consent_search @@ -329,12 +446,12 @@ msgstr "Pozdravljeni." #. module: privacy_consent #: model_terms:ir.ui.view,arch_db:privacy_consent.form msgid "I accept this processing of my data" -msgstr "" +msgstr "Sprejemam to obdelavo svojih podatkov" #. module: privacy_consent #: model_terms:ir.ui.view,arch_db:privacy_consent.form msgid "I reject this processing of my data" -msgstr "" +msgstr "Zavračam to obdelavo svojih podatkov" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__id @@ -356,7 +473,7 @@ msgstr "" #. module: privacy_consent #: model_terms:ir.ui.view,arch_db:privacy_consent.form msgid "If it was a mistake, you can undo it here:" -msgstr "" +msgstr "Če je šlo za napako, jo lahko razveljavite tukaj:" #. module: privacy_consent #: model:ir.model.fields,help:privacy_consent.field_privacy_consent__accepted @@ -365,6 +482,9 @@ msgid "" "answer, or from the default specified in the related data processing " "activity." msgstr "" +"Označuje trenutni status sprejema, ki lahko izhaja iz zadnjega odgovora " +"posameznika ali iz privzete vrednosti, določene v povezani dejavnosti " +"obdelave podatkov." #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__message_is_follower @@ -374,7 +494,7 @@ msgstr "Je sledilec" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__last_metadata msgid "Last Metadata" -msgstr "" +msgstr "Zadnji metapodatki" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__write_uid @@ -404,7 +524,7 @@ msgstr "Sporočila" #. module: privacy_consent #: model:ir.model.fields,help:privacy_consent.field_privacy_consent__last_metadata msgid "Metadata from the last acceptance or rejection by the subject" -msgstr "" +msgstr "Metapodatki zadnjega sprejema ali zavrnitve s strani posameznika" #. module: privacy_consent #. odoo-python @@ -414,12 +534,16 @@ msgid "" "Accept\n" "Reject" msgstr "" +"Manjkajo ograde povezav za privolitev glede zasebnosti. Potrebujete vsaj ti " +"dve povezavi:\n" +"Sprejmi\n" +"Zavrni" #. module: privacy_consent #: model:mail.message.subtype,name:privacy_consent.mt_activity_consent_new #: model:mail.message.subtype,name:privacy_consent.mt_consent_consent_new msgid "New Consent" -msgstr "" +msgstr "Nova privolitev" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__message_needaction_counter @@ -449,47 +573,49 @@ msgstr "Izhodna pošta" #. module: privacy_consent #: model:mail.template,name:privacy_consent.template_consent msgid "Personal data processing consent request" -msgstr "" +msgstr "Zahtevek za privolitev v obdelavo osebnih podatkov" #. module: privacy_consent #: model:mail.message.subtype,description:privacy_consent.mt_activity_acceptance_changed msgid "Privacy consent request acceptance status changed" -msgstr "" +msgstr "Status sprejema zahtevka za privolitev glede zasebnosti se je spremenil" #. module: privacy_consent #: model:mail.message.subtype,description:privacy_consent.mt_activity_consent_new #: model:mail.message.subtype,description:privacy_consent.mt_consent_consent_new msgid "Privacy consent request created" -msgstr "" +msgstr "Zahtevek za privolitev glede zasebnosti je bil ustvarjen" #. module: privacy_consent #: model:mail.message.subtype,description:privacy_consent.mt_activity_state_changed #: model:mail.message.subtype,description:privacy_consent.mt_consent_state_changed msgid "Privacy consent request state changed" -msgstr "" +msgstr "Stanje zahtevka za privolitev glede zasebnosti se je spremenilo" #. module: privacy_consent #: model:ir.model.fields,help:privacy_consent.field_res_partner__privacy_consent_count #: model:ir.model.fields,help:privacy_consent.field_res_users__privacy_consent_count msgid "Privacy consent requests amount" -msgstr "" +msgstr "Število zahtevkov za privolitev glede zasebnosti" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_res_partner__privacy_consent_ids #: model:ir.model.fields,field_description:privacy_consent.field_res_users__privacy_consent_ids msgid "Privacy consents" -msgstr "" +msgstr "Privolitve glede zasebnosti" #. module: privacy_consent #: model:ir.actions.server,name:privacy_consent.cron_auto_consent_ir_actions_server msgid "Request automatic data processing consents" -msgstr "" +msgstr "Zahtevaj samodejne privolitve v obdelavo podatkov" #. module: privacy_consent #. odoo-python #: code:addons/privacy_consent/models/privacy_activity.py:0 msgid "Require consent is available only for subjects in current database." msgstr "" +"Zahteva za privolitev je na voljo samo za posameznike v trenutni bazi " +"podatkov." #. module: privacy_consent #: model:ir.model.fields,help:privacy_consent.field_privacy_activity__server_action_id @@ -497,6 +623,8 @@ msgid "" "Run this action when a new consent request is created or its acceptance " "status is updated." msgstr "" +"Zaženi to dejanje, ko je ustvarjen nov zahtevek za privolitev ali ko je " +"posodobljen njegov status sprejema." #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity__server_action_id @@ -506,45 +634,45 @@ msgstr "Strežniško dejanje" #. module: privacy_consent #: model:ir.model.fields,help:privacy_consent.field_privacy_activity__default_consent msgid "Should we assume the subject has accepted if we receive no response?" -msgstr "" +msgstr "Ali naj štejemo, da je posameznik sprejel, če ne prejmemo odgovora?" #. module: privacy_consent #: model_terms:ir.ui.view,arch_db:privacy_consent.form msgid "Sincerely,
    " -msgstr "" +msgstr "Lep pozdrav,
    " #. module: privacy_consent #. odoo-python #: code:addons/privacy_consent/models/privacy_activity.py:0 msgid "Specify a mail template to ask automated consent." -msgstr "" +msgstr "Določite poštno predlogo za samodejno pridobivanje privolitve." #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__state #: model_terms:ir.ui.view,arch_db:privacy_consent.consent_search msgid "State" -msgstr "" +msgstr "Stanje" #. module: privacy_consent #: model:mail.message.subtype,name:privacy_consent.mt_activity_state_changed #: model:mail.message.subtype,name:privacy_consent.mt_consent_state_changed msgid "State Changed" -msgstr "" +msgstr "Stanje spremenjeno" #. module: privacy_consent #: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__partner_id msgid "Subject" -msgstr "" +msgstr "Posameznik" #. module: privacy_consent #: model:ir.model.fields,help:privacy_consent.field_privacy_consent__partner_id msgid "Subject asked for consent." -msgstr "" +msgstr "Posameznik, zaprošen za privolitev." #. module: privacy_consent #: model:ir.actions.server,name:privacy_consent.sync_blacklist msgid "Sync partner's email blacklist status" -msgstr "" +msgstr "Sinhroniziraj status partnerjevega e-poštnega črnega seznama" #. module: privacy_consent #: model_terms:ir.ui.view,arch_db:privacy_consent.form @@ -554,12 +682,14 @@ msgstr "Hvala!" #. module: privacy_consent #: model_terms:ir.ui.view,arch_db:privacy_consent.form msgid "Thanks for your response." -msgstr "" +msgstr "Hvala za vaš odgovor." #. module: privacy_consent #: model_terms:ir.ui.view,arch_db:privacy_consent.activity_form msgid "This could enqueue many consent emails, are you sure to proceed?" msgstr "" +"To lahko v čakalno vrsto uvrsti veliko e-poštnih sporočil za privolitev. Ali " +"res želite nadaljevati?" #. module: privacy_consent #: model_terms:ir.ui.view,arch_db:privacy_consent.form @@ -567,18 +697,20 @@ msgid "" "We asked you to authorize us to process your data in this data processing " "activity:" msgstr "" +"Prosili smo vas, da nam dovolite obdelavo svojih podatkov v tej dejavnosti " +"obdelave podatkov:" #. module: privacy_consent #: model_terms:ir.ui.view,arch_db:privacy_consent.form msgid "We have recorded this action on your side." -msgstr "" +msgstr "To vaše dejanje smo zabeležili." #. module: privacy_consent #: model_terms:ir.ui.view,arch_db:privacy_consent.form msgid "You have rejected such processing." -msgstr "" +msgstr "Takšno obdelavo ste zavrnili." #. module: privacy_consent #: model_terms:ir.ui.view,arch_db:privacy_consent.form msgid "You have accepted such processing." -msgstr "" +msgstr "Takšno obdelavo ste sprejeli." From f3a319a40464eafb9d35c5908aaa23aff8e29c17 Mon Sep 17 00:00:00 2001 From: Francesco Bellingeri Date: Mon, 3 Aug 2026 11:59:04 +0200 Subject: [PATCH 41/41] [MIG] privacy_consent: Migration to 19.0 Co-Authored-By: Claude Sonnet 5 --- privacy_consent/README.rst | 85 ++++++++--------- privacy_consent/__manifest__.py | 2 +- privacy_consent/controllers/main.py | 2 +- privacy_consent/models/mail_mail.py | 3 +- privacy_consent/models/privacy_activity.py | 14 ++- privacy_consent/models/privacy_consent.py | 26 ++---- privacy_consent/models/res_partner.py | 12 +-- privacy_consent/static/description/index.html | 37 ++++---- privacy_consent/tests/test_consent.py | 92 ++++++++++++++----- privacy_consent/views/privacy_consent.xml | 2 +- 10 files changed, 158 insertions(+), 117 deletions(-) diff --git a/privacy_consent/README.rst b/privacy_consent/README.rst index 92bd6b8a..14b7d489 100644 --- a/privacy_consent/README.rst +++ b/privacy_consent/README.rst @@ -21,13 +21,13 @@ Privacy - Consent :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fdata--protection-lightgray.png?logo=github - :target: https://github.com/OCA/data-protection/tree/18.0/privacy_consent + :target: https://github.com/OCA/data-protection/tree/19.0/privacy_consent :alt: OCA/data-protection .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/data-protection-18-0/data-protection-18-0-privacy_consent + :target: https://translation.odoo-community.org/projects/data-protection-19-0/data-protection-19-0-privacy_consent :alt: Translate me on Weblate .. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png - :target: https://runboat.odoo-community.org/builds?repo=OCA/data-protection&target_branch=18.0 + :target: https://runboat.odoo-community.org/builds?repo=OCA/data-protection&target_branch=19.0 :alt: Try me on Runboat |badge1| |badge2| |badge3| |badge4| |badge5| @@ -76,49 +76,49 @@ New options for data processing activities: 3. Go to tab *Consent* and choose one option in *Ask subjects for consent*: - - *Manual* tells the activity that you will want to create and send - the consent requests manually, and only provides some helpers for - you to be able to batch-generate them. - - *Automatic* enables this module's full power: send all consent - requests to selected partners automatically, every day and under - your demand. + - *Manual* tells the activity that you will want to create and send + the consent requests manually, and only provides some helpers for + you to be able to batch-generate them. + - *Automatic* enables this module's full power: send all consent + requests to selected partners automatically, every day and under + your demand. 4. When you do this, all the consent-related options appear. Configure them: - - A smart button tells you how many consents have been generated, and - lets you access them. + - A smart button tells you how many consents have been generated, + and lets you access them. - - Choose one *Email template* to send to subjects. This email itself - is what asks for consent, and it gets recorded, to serve as a proof - that it was sent. The module provides a default template that - should be good for most usage cases; and if you create one directly - from that field, some good defaults are provided for your - comfortability. + - Choose one *Email template* to send to subjects. This email itself + is what asks for consent, and it gets recorded, to serve as a + proof that it was sent. The module provides a default template + that should be good for most usage cases; and if you create one + directly from that field, some good defaults are provided for your + comfortability. - - *Subjects filter* defines what partners will be elegible for - inclusion in this data processing activity. + - *Subjects filter* defines what partners will be elegible for + inclusion in this data processing activity. - - You can enable *Accepted by default* if you want to assume subjects - accepted their data processing. You should possibly consult your - lawyer to use this. + - You can enable *Accepted by default* if you want to assume + subjects accepted their data processing. You should possibly + consult your lawyer to use this. - - You can choose a *Server action* (developer mode only) that will be - executed whenever a new non-draft consent request is created, or - when its acceptance status changes. + - You can choose a *Server action* (developer mode only) that will + be executed whenever a new non-draft consent request is created, + or when its acceptance status changes. - This module supplies a server action by default, called *Update - partner's opt out*, that syncs the acceptance status with the - partner's *Elegible for mass mailings* option. + This module supplies a server action by default, called *Update + partner's opt out*, that syncs the acceptance status with the + partner's *Elegible for mass mailings* option. 5. Click on *Generate consent requests* link to create new consent requests. - - If you chose *Manual* mode, all missing consent request are created - as drafts, and nothing else is done now. - - If you chose *Automatic* mode, also those request e-mails are - enqueued and, when the mail queue is cleared, they will be set as - *Sent*. + - If you chose *Manual* mode, all missing consent request are + created as drafts, and nothing else is done now. + - If you chose *Automatic* mode, also those request e-mails are + enqueued and, when the mail queue is cleared, they will be set as + *Sent*. 6. You will be presented with the list of just-created consent requests. See below. @@ -127,9 +127,10 @@ New options for consent requests: 1. Access the consent requests by either: - - Generating new consent requests from a data processing activity. - - Pressing the *Consents* smart button in a data processing activity. - - Going to *Privacy > Privacy > Consents*. + - Generating new consent requests from a data processing activity. + - Pressing the *Consents* smart button in a data processing + activity. + - Going to *Privacy > Privacy > Consents*. 2. A consent will include the partner, the activity, the acceptance status, and the request state. @@ -144,7 +145,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 to smash it by providing a detailed and welcomed -`feedback `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -160,13 +161,13 @@ Authors Contributors ------------ -- `Tecnativa `__: +- `Tecnativa `__: - - Jairo Llopis + - Jairo Llopis -- `initOS GmbH `__: +- `initOS GmbH `__: - - Florian Kantelberg + - Florian Kantelberg Maintainers ----------- @@ -181,6 +182,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/data-protection `_ project on GitHub. +This module is part of the `OCA/data-protection `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/privacy_consent/__manifest__.py b/privacy_consent/__manifest__.py index 20b0659a..793ba1b3 100644 --- a/privacy_consent/__manifest__.py +++ b/privacy_consent/__manifest__.py @@ -4,7 +4,7 @@ "name": "Privacy - Consent", "summary": "Allow people to explicitly accept or reject inclusion " "in some activity, GDPR compliant", - "version": "18.0.1.0.0", + "version": "19.0.1.0.0", "development_status": "Production/Stable", "category": "Privacy", "website": "https://github.com/OCA/data-protection", diff --git a/privacy_consent/controllers/main.py b/privacy_consent/controllers/main.py index b8db4ad6..edc9995d 100644 --- a/privacy_consent/controllers/main.py +++ b/privacy_consent/controllers/main.py @@ -44,7 +44,7 @@ def consent(self, choice, consent_id, token, *args, **kwargs): def _metadata(self): return ( - "User agent: {}\n" "Remote IP: {}\n" "Date and time: {:%Y-%m-%d %H:%M:%S}" + "User agent: {}\nRemote IP: {}\nDate and time: {:%Y-%m-%d %H:%M:%S}" ).format( request.httprequest.environ.get("HTTP_USER_AGENT"), request.httprequest.environ.get("REMOTE_ADDR"), diff --git a/privacy_consent/models/mail_mail.py b/privacy_consent/models/mail_mail.py index 0355ce95..6d612b1a 100644 --- a/privacy_consent/models/mail_mail.py +++ b/privacy_consent/models/mail_mail.py @@ -9,7 +9,7 @@ class MailMail(models.Model): _inherit = "mail.mail" def _postprocess_sent_message( - self, success_pids, failure_reason=False, failure_type=None + self, success_pids, success_emails, failure_reason=False, failure_type=None ): """Write consent status after sending message.""" # Know if mail was successfully sent to a privacy consent @@ -34,6 +34,7 @@ def _postprocess_sent_message( consents.write({"state": "sent"}) return super()._postprocess_sent_message( success_pids=success_pids, + success_emails=success_emails, failure_reason=failure_reason, failure_type=failure_type, ) diff --git a/privacy_consent/models/privacy_activity.py b/privacy_consent/models/privacy_activity.py index e7f5e07e..71bcbe86 100644 --- a/privacy_consent/models/privacy_activity.py +++ b/privacy_consent/models/privacy_activity.py @@ -43,7 +43,7 @@ class PrivacyActivity(models.Model): ) default_consent = fields.Boolean( string="Accepted by default", - help="Should we assume the subject has accepted if we receive no " "response?", + help="Should we assume the subject has accepted if we receive no response?", ) # Hidden helpers help user design new templates @@ -60,16 +60,14 @@ def _default_consent_template_id(self): @api.depends("consent_ids") def _compute_consent_count(self): - self.consent_count = 0 - groups = self.env["privacy.consent"].read_group( + groups = self.env["privacy.consent"]._read_group( [("activity_id", "in", self.ids)], ["activity_id"], - ["activity_id"], + ["__count"], ) - for group in groups: - self.browse(group["activity_id"][0]).consent_count = group[ - "activity_id_count" - ] + mapping = {activity.id: count for activity, count in groups} + for one in self: + one.consent_count = mapping.get(one.id, 0) def _compute_consent_template_defaults(self): """Used in context values, to help users design new templates.""" diff --git a/privacy_consent/models/privacy_consent.py b/privacy_consent/models/privacy_consent.py index c90797eb..ec6c7c8b 100644 --- a/privacy_consent/models/privacy_consent.py +++ b/privacy_consent/models/privacy_consent.py @@ -12,13 +12,10 @@ class PrivacyConsent(models.Model): _description = "Consent of data processing" _inherit = "mail.thread" _rec_name = "partner_id" - _sql_constraints = [ - ( - "unique_partner_activity", - "UNIQUE(partner_id, activity_id)", - "Duplicated partner in this data processing activity", - ), - ] + _unique_partner_activity = models.Constraint( + "UNIQUE(partner_id, activity_id)", + "Duplicated partner in this data processing activity", + ) active = fields.Boolean( default=True, @@ -130,16 +127,13 @@ def write(self, vals): self._run_action() return result - def _message_get_suggested_recipients(self): - result = super()._message_get_suggested_recipients() - reason = self._fields["partner_id"].string + def _message_add_suggested_recipients(self, force_primary_email=False): + suggested = super()._message_add_suggested_recipients( + force_primary_email=force_primary_email + ) for one in self: - one._message_add_suggested_recipient( - result, - partner=one.partner_id, - reason=reason, - ) - return result + suggested[one.id]["partners"] += one.partner_id + return suggested def action_manual_ask(self): """Let user manually ask for consent.""" diff --git a/privacy_consent/models/res_partner.py b/privacy_consent/models/res_partner.py index c37e4d0c..0e99ad1c 100644 --- a/privacy_consent/models/res_partner.py +++ b/privacy_consent/models/res_partner.py @@ -21,13 +21,11 @@ class ResPartner(models.Model): @api.depends("privacy_consent_ids") def _compute_privacy_consent_count(self): """Count consent requests.""" - self.privacy_consent_count = 0 - groups = self.env["privacy.consent"].read_group( + groups = self.env["privacy.consent"]._read_group( [("partner_id", "in", self.ids)], ["partner_id"], - ["partner_id"], + ["__count"], ) - for group in groups: - self.browse(group["partner_id"][0]).privacy_consent_count = group[ - "partner_id_count" - ] + mapping = {partner.id: count for partner, count in groups} + for one in self: + one.privacy_consent_count = mapping.get(one.id, 0) diff --git a/privacy_consent/static/description/index.html b/privacy_consent/static/description/index.html index 27b96035..ef83a840 100644 --- a/privacy_consent/static/description/index.html +++ b/privacy_consent/static/description/index.html @@ -374,7 +374,7 @@

    Privacy - Consent

    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! source digest: sha256:a1bc87f33b1755f112f2b02a4eed8fdf8576c046d801f3a73fd085f5c9de029f !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> -

    Production/Stable License: AGPL-3 OCA/data-protection Translate me on Weblate Try me on Runboat

    +

    Production/Stable License: AGPL-3 OCA/data-protection Translate me on Weblate Try me on Runboat

    This module allows the user to define a set of subjects (partners) affected by any data processing activity, and establish a process to ask them for consent to include them in that activity.

    @@ -437,26 +437,26 @@

    Usage

  • When you do this, all the consent-related options appear. Configure them:

      -
    • A smart button tells you how many consents have been generated, and -lets you access them.

      +
    • A smart button tells you how many consents have been generated, +and lets you access them.

    • Choose one Email template to send to subjects. This email itself -is what asks for consent, and it gets recorded, to serve as a proof -that it was sent. The module provides a default template that -should be good for most usage cases; and if you create one directly -from that field, some good defaults are provided for your +is what asks for consent, and it gets recorded, to serve as a +proof that it was sent. The module provides a default template +that should be good for most usage cases; and if you create one +directly from that field, some good defaults are provided for your comfortability.

    • Subjects filter defines what partners will be elegible for inclusion in this data processing activity.

    • -
    • You can enable Accepted by default if you want to assume subjects -accepted their data processing. You should possibly consult your -lawyer to use this.

      +
    • You can enable Accepted by default if you want to assume +subjects accepted their data processing. You should possibly +consult your lawyer to use this.

    • -
    • You can choose a Server action (developer mode only) that will be -executed whenever a new non-draft consent request is created, or -when its acceptance status changes.

      +
    • You can choose a Server action (developer mode only) that will +be executed whenever a new non-draft consent request is created, +or when its acceptance status changes.

      This module supplies a server action by default, called Update partner’s opt out, that syncs the acceptance status with the partner’s Elegible for mass mailings option.

      @@ -466,8 +466,8 @@

      Usage

    • Click on Generate consent requests link to create new consent requests.

        -
      • If you chose Manual mode, all missing consent request are created -as drafts, and nothing else is done now.
      • +
      • If you chose Manual mode, all missing consent request are +created as drafts, and nothing else is done now.
      • If you chose Automatic mode, also those request e-mails are enqueued and, when the mail queue is cleared, they will be set as Sent.
      • @@ -481,7 +481,8 @@

        Usage

        1. Access the consent requests by either:
          • Generating new consent requests from a data processing activity.
          • -
          • Pressing the Consents smart button in a data processing activity.
          • +
          • Pressing the Consents smart button in a data processing +activity.
          • Going to Privacy > Privacy > Consents.
        2. @@ -498,7 +499,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 to smash it by providing a detailed and welcomed -feedback.

          +feedback.

          Do not contact contributors directly about support or help with technical issues.

          @@ -532,7 +533,7 @@

          Maintainers

          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/data-protection project on GitHub.

          +

          This module is part of the OCA/data-protection project on GitHub.

          You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

          diff --git a/privacy_consent/tests/test_consent.py b/privacy_consent/tests/test_consent.py index 2e7b6a5d..f65526b4 100644 --- a/privacy_consent/tests/test_consent.py +++ b/privacy_consent/tests/test_consent.py @@ -11,7 +11,7 @@ from odoo.exceptions import AccessError, ValidationError from odoo.tests import Form, users -from odoo.addons.base.models.ir_mail_server import IrMailServer +from odoo.addons.base.models.ir_mail_server import IrMail_Server from odoo.addons.mail.tests.common import mail_new_test_user @@ -19,6 +19,14 @@ class ActivityCase(odoo.tests.HttpCase): @classmethod def setUpClass(cls): super().setUpClass() + # Odoo no longer installs demo data by default, so the classic + # "portal"/"portal" demo user can't be relied upon: create our own. + cls.user_portal = mail_new_test_user( + cls.env, + login="privacy_consent_portal", + groups="base.group_portal", + password="privacy_consent_portal", + ) cls.cron = cls.env.ref("privacy_consent.cron_auto_consent") cls.cron_mail_queue = cls.env.ref("mail.ir_cron_mail_scheduler_action") cls.sync_blacklist = cls.env.ref("privacy_consent.sync_blacklist") @@ -77,7 +85,15 @@ def setUpClass(cls): @contextmanager def _patch_build(self): - build_email_origin = IrMailServer.build_email + # Odoo 19 added an early `_disable_send()` guard at the very top of + # `mail.mail._send()`, before the message is even built: under + # `--test-enable` it returns True and `_send()` bails out doing + # nothing (mail stays "outgoing"), unless monkeypatched - see the + # "unless monkeypatched" note in `_send()`'s source. So besides + # capturing the built body (as before), we also need to force + # `_disable_send()` to False and fake the SMTP session, mirroring + # `odoo.addons.base.tests.common.MockSmtplibCase`. + build_email_origin = IrMail_Server._build_email__ self._built_messages = [] def _build_email(_self, email_from, email_to, subject, body, *args, **kwargs): @@ -86,13 +102,39 @@ def _build_email(_self, email_from, email_to, subject, body, *args, **kwargs): _self, email_from, email_to, subject, body, *args, **kwargs ) - with patch.object( - IrMailServer, - "build_email", - autospec=True, - wraps=build_email_origin, - side_effect=_build_email, - ) as build_email_mocked: + class _FakeSMTPSession: + def quit(self): + pass + + def send_message(self, message, smtp_from, smtp_to_list): + pass + + def set_debuglevel(self, smtp_debug): + pass + + def ehlo_or_helo_if_needed(self): + pass + + def login(self, user, password): + pass + + def starttls(self, keyfile=None, certfile=None, context=None): + pass + + fake_session = _FakeSMTPSession() + + with ( + patch("smtplib.SMTP_SSL", side_effect=lambda *a, **k: fake_session), + patch("smtplib.SMTP", side_effect=lambda *a, **k: fake_session), + patch.object(IrMail_Server, "_disable_send", lambda self: False), + patch.object( + IrMail_Server, + "_build_email__", + autospec=True, + wraps=build_email_origin, + side_effect=_build_email, + ) as build_email_mocked, + ): self.build_email_mocked = build_email_mocked yield @@ -125,25 +167,33 @@ def check_activity_auto_properly_sent(self): consent.state, "sent" if good_email else "draft", ) - self.assertEqual(len(consent.message_ids), 2) + # Writing state="sent" is tracked (state has tracking=True), so + # it logs one extra "State Changed" message on top of the usual + # 2 (creation + subject notification) - but only when the state + # actually transitions, i.e. only for the good_email consents. + self.assertEqual(len(consent.message_ids), 3 if good_email else 2) # message notifies creation self.assertTrue( self.mt_consent_consent_new in consent.message_ids.mapped("subtype_id") ) # message notifies subject - # Placeholder links should be logged - message_subject = consent.message_ids.filtered( - lambda x: x.subtype_id != self.mt_consent_consent_new - ) + # Placeholder links should be logged. The actual per-recipient + # notification message has no subtype (unlike the "New Consent" + # creation message or, when state actually transitions, the + # tracked "State Changed" message), so filter on that instead. + message_subject = consent.message_ids.filtered(lambda x: not x.subtype_id) self.assertIn("/privacy/consent/accept/", message_subject.body) self.assertIn("/privacy/consent/reject/", message_subject.body) # Tokenized links shouldn't be logged self.assertNotIn(consent._url(True), message_subject.body) self.assertNotIn(consent._url(False), message_subject.body) - # without state change (only in test mode) - self.assertTrue( + # state change is tracked only when the state actually flips to + # "sent" (good_email); it stays untouched (still "draft") for + # the invalid-email consent, so no tracking message there. + self.assertEqual( self.mt_consent_state_changed - not in consent.message_ids.mapped("subtype_id") + in consent.message_ids.mapped("subtype_id"), + good_email, ) # Partner's is_blacklisted should be synced with default consent self.assertFalse(consent.partner_id.is_blacklisted) @@ -265,7 +315,7 @@ def test_generate_manually(self): self.assertNotIn(accept_url, messages.body) self.assertNotIn(reject_url, messages.body) # Visit tokenized accept URL - self.authenticate("portal", "portal") + self.authenticate("privacy_consent_portal", "privacy_consent_portal") http.root.session_store.save(self.session) result = self.url_open(accept_url).text self.assertIn("accepted", result) @@ -361,10 +411,8 @@ def test_message_get_suggested_recipients(self): } ) suggested_recipients = consent._message_get_suggested_recipients() - recipient = suggested_recipients[0] - self.assertEqual(consent.partner_id.id, recipient["partner_id"]) - self.assertIn(consent.partner_id.name, recipient["name"]) - self.assertIn(consent.partner_id.email, recipient["email"]) + partner_ids = [r["partner_id"] for r in suggested_recipients] + self.assertIn(consent.partner_id.id, partner_ids) def test_compute_consent_count(self): """Test that consent_count is correctly updated.""" diff --git a/privacy_consent/views/privacy_consent.xml b/privacy_consent/views/privacy_consent.xml index ccc9e290..7eee0023 100644 --- a/privacy_consent/views/privacy_consent.xml +++ b/privacy_consent/views/privacy_consent.xml @@ -64,7 +64,7 @@ domain="[('active', '=', False)]" /> - +