Browse Source

Merge afa0615158 into ae3860c2e3

pull/56/merge
Valtteri Lattu 3 years ago
committed by GitHub
parent
commit
93634208bb
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 178
      privacy_consent/README.rst
  2. 2
      privacy_consent/__init__.py
  3. 27
      privacy_consent/__manifest__.py
  4. 1
      privacy_consent/controllers/__init__.py
  5. 43
      privacy_consent/controllers/main.py
  6. 26
      privacy_consent/data/ir_actions_server.xml
  7. 15
      privacy_consent/data/ir_cron.xml
  8. 186
      privacy_consent/data/mail.xml
  9. 652
      privacy_consent/i18n/de.po
  10. 779
      privacy_consent/i18n/es.po
  11. 624
      privacy_consent/i18n/fr.po
  12. 588
      privacy_consent/i18n/privacy_consent.pot
  13. 768
      privacy_consent/i18n/pt.po
  14. 5
      privacy_consent/models/__init__.py
  15. 62
      privacy_consent/models/mail_mail.py
  16. 37
      privacy_consent/models/mail_template.py
  17. 145
      privacy_consent/models/privacy_activity.py
  18. 186
      privacy_consent/models/privacy_consent.py
  19. 33
      privacy_consent/models/res_partner.py
  20. 7
      privacy_consent/readme/CONTRIBUTORS.rst
  21. 7
      privacy_consent/readme/DESCRIPTION.rst
  22. 15
      privacy_consent/readme/INSTALL.rst
  23. 69
      privacy_consent/readme/USAGE.rst
  24. 3
      privacy_consent/security/ir.model.access.csv
  25. BIN
      privacy_consent/static/description/icon.png
  26. 525
      privacy_consent/static/description/index.html
  27. 7
      privacy_consent/static/src/css/privacy_consent.scss
  28. 13
      privacy_consent/templates/assets.xml
  29. 63
      privacy_consent/templates/form.xml
  30. 1
      privacy_consent/tests/__init__.py
  31. 291
      privacy_consent/tests/test_consent.py
  32. 76
      privacy_consent/views/privacy_activity.xml
  33. 97
      privacy_consent/views/privacy_consent.xml
  34. 28
      privacy_consent/views/res_partner.xml
  35. 1
      setup/privacy_consent/odoo/addons/privacy_consent
  36. 6
      setup/privacy_consent/setup.py

178
privacy_consent/README.rst

@ -0,0 +1,178 @@
=================
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/13.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-13-0/data-protection-13-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/13.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 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.
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 <https://github.com/OCA/data-protection/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 <https://github.com/OCA/data-protection/issues/new?body=module:%20privacy_consent%0Aversion:%2013.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
Do not contact contributors directly about support or help with technical issues.
Credits
=======
Authors
~~~~~~~
* Tecnativa
* initOS GmbH
Contributors
~~~~~~~~~~~~
* `Tecnativa <https://www.tecnativa.com>`_:
* Jairo Llopis
* `initOS GmbH <https://www.initos.com>`_:
* Florian Kantelberg
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 <https://github.com/OCA/data-protection/tree/13.0/privacy_consent>`_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

2
privacy_consent/__init__.py

@ -0,0 +1,2 @@
from . import controllers
from . import models

27
privacy_consent/__manifest__.py

@ -0,0 +1,27 @@
# 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": "14.0.1.0.0",
"development_status": "Production/Stable",
"category": "Privacy",
"website": "https://github.com/OCA/data-protection",
"author": "Tecnativa, initOS GmbH, 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/assets.xml",
"templates/form.xml",
"views/privacy_consent.xml",
"views/privacy_activity.xml",
"views/res_partner.xml",
],
}

1
privacy_consent/controllers/__init__.py

@ -0,0 +1 @@
from . import main

43
privacy_consent/controllers/main.py

@ -0,0 +1,43 @@
# 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
class ConsentController(Controller):
@route(
"/privacy/consent/<any(accept,reject):choice>/<int:consent_id>/<token>",
type="http",
auth="public",
website=True,
)
def consent(self, choice, consent_id, token, *args, **kwargs):
"""Process user's consent acceptance or rejection."""
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(),
)

26
privacy_consent/data/ir_actions_server.xml

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2018 Tecnativa - Jairo Llopis
Copyright 2019 initOS GmbH - Florian Kantelberg
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
<data>
<record id="sync_blacklist" model="ir.actions.server">
<field name="name">Sync partner's email blacklist status</field>
<field name="model_id" ref="model_privacy_consent" />
<field name="crud_model_id" ref="base.model_res_partner" />
<field name="state">code</field>
<field name="code">
for consent in records:
email = consent.partner_id.email
# Skip records without email, although highly improbable
if not email:
continue
# Choose method to sync acceptance and blacklisting
if consent.accepted:
method = env["mail.blacklist"]._remove
else:
method = env["mail.blacklist"]._add
# Apply user desire
method(email)
</field>
</record>
</data>

15
privacy_consent/data/ir_cron.xml

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2018 Tecnativa - Jairo Llopis
Copyright 2019 initOS GmbH - Florian Kantelberg
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
<data>
<record id="cron_auto_consent" model="ir.cron">
<field name="name">Request automatic data processing consents</field>
<field name="model_id" ref="model_privacy_activity" />
<field name="state">code</field>
<field name="code">model._cron_new_consents()</field>
<field name="interval_number">1</field>
<field name="interval_type">days</field>
<field name="numbercall">-1</field>
</record>
</data>

186
privacy_consent/data/mail.xml

@ -0,0 +1,186 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2018 Tecnativa - Jairo Llopis
Copyright 2019 Tecnativa - Cristina Martin R.
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
<data>
<!-- Mail templates -->
<record id="template_consent" model="mail.template">
<field name="auto_delete" eval="False" />
<field name="name">Personal data processing consent request</field>
<field
name="subject"
>Data processing consent request for ${object.activity_id.display_name|safe}</field>
<field name="model_id" ref="model_privacy_consent" />
<field name="use_default_to" eval="True" />
<field name="lang">${object.partner_id.lang}</field>
<field name="body_html" type="xml">
<div
style="background:#F3F5F6;color:#515166;padding:25px 0px;font-family:Arial,Helvetica,sans-serif;font-size:14px;"
>
<table style="width:600px;margin:5px auto;">
<tbody>
<tr>
<td>
<a href="/">
<img
src="/logo"
alt="${object.activity_id.controller_id.display_name|safe}"
style="vertical-align:baseline;max-width:100px;"
/>
</a>
</td>
</tr>
</tbody>
</table>
<table
style="width:600px;margin:0px auto;background:white;border:1px solid #e1e1e1;"
>
<tbody>
<tr>
<td
colspan="2"
style="padding:15px 20px 0px 20px; font-size:16px;"
>
<p>
Hello, ${object.partner_id.name|safe}
</p>
<p>
We contacted you to ask you to give us your explicit consent to include your data in a data processing activity called
<b
>${object.activity_id.display_name|safe}</b>, property of
<i
>${object.activity_id.controller_id.display_name|safe}</i>
</p>
${object.description or ""}
<p>
% 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:
<b>accepted</b>
% else:
<b>rejected</b>
% endif
such data processing.
</p>
<p>
You can update your preferences below:
</p>
</td>
</tr>
<tr>
<td
style="padding:15px 20px 0px 20px; font-size:16px; text-align:right;"
>
<a
href="/privacy/consent/accept/"
style="background-color: #449d44; padding: 12px; font-weight: 12px; text-decoration: none; color: #fff; border-radius: 5px; font-size:16px;"
>
Accept
</a>
</td>
<td
style="padding:15px 20px 0px 20px; font-size:16px; text-align:left;"
>
<a
href="/privacy/consent/reject/"
style="background-color: #d9534f; padding: 12px; font-weight: 12px; text-decoration: none; color: #fff; border-radius: 5px; font-size:16px;"
>
Reject
</a>
</td>
</tr>
<tr>
<td
colspan="2"
style="padding:15px 20px 15px 20px; font-size:16px;"
>
<p>
If you need further information, please respond to this email and we will attend your request as soon as possible.
</p>
<p>
Thank you!
</p>
</td>
</tr>
</tbody>
</table>
<table style="width:600px;margin:0px auto;text-align:center;">
<tbody>
<tr>
<td style="padding-top:10px;font-size: 12px;">
<p>
Sent by
<a
href="/"
style="color:#717188;"
>${object.activity_id.controller_id.display_name|safe}</a>.
</p>
</td>
</tr>
</tbody>
</table>
</div>
</field>
</record>
<!-- Mail subtypes -->
<record id="mt_consent_consent_new" model="mail.message.subtype">
<field name="name">New Consent</field>
<field name="description">Privacy consent request created</field>
<field name="res_model">privacy.consent</field>
<field name="default" eval="False" />
<field name="hidden" eval="False" />
<field name="internal" eval="True" />
</record>
<record id="mt_consent_acceptance_changed" model="mail.message.subtype">
<field name="name">Acceptance Changed by Subject</field>
<field name="description">Acceptance status updated by subject</field>
<field name="res_model">privacy.consent</field>
<field name="default" eval="False" />
<field name="hidden" eval="False" />
<field name="internal" eval="True" />
</record>
<record id="mt_consent_state_changed" model="mail.message.subtype">
<field name="name">State Changed</field>
<field name="description">Privacy consent request state changed</field>
<field name="res_model">privacy.consent</field>
<field name="default" eval="False" />
<field name="hidden" eval="False" />
<field name="internal" eval="True" />
</record>
<record id="mt_activity_consent_new" model="mail.message.subtype">
<field name="name">New Consent</field>
<field name="description">Privacy consent request created</field>
<field name="res_model">privacy.activity</field>
<field name="default" eval="True" />
<field name="hidden" eval="False" />
<field name="internal" eval="True" />
<field name="parent_id" ref="mt_consent_consent_new" />
<field name="relation_field">activity_id</field>
</record>
<record id="mt_activity_acceptance_changed" model="mail.message.subtype">
<field name="name">Acceptance Changed</field>
<field
name="description"
>Privacy consent request acceptance status changed</field>
<field name="res_model">privacy.activity</field>
<field name="default" eval="True" />
<field name="hidden" eval="False" />
<field name="internal" eval="True" />
<field name="parent_id" ref="mt_consent_acceptance_changed" />
<field name="relation_field">activity_id</field>
</record>
<record id="mt_activity_state_changed" model="mail.message.subtype">
<field name="name">State Changed</field>
<field name="description">Privacy consent request state changed</field>
<field name="res_model">privacy.activity</field>
<field name="default" eval="False" />
<field name="hidden" eval="False" />
<field name="internal" eval="True" />
<field name="parent_id" ref="mt_consent_state_changed" />
<field name="relation_field">activity_id</field>
</record>
</data>

652
privacy_consent/i18n/de.po

@ -0,0 +1,652 @@
# 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: 2019-05-13 17:04+0000\n"
"PO-Revision-Date: 2019-04-11 11:16+0000\n"
"Last-Translator: dw3gn3r <denise.wegner@initos.com>\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 ""
"<?xml version=\"1.0\"?>\n"
"<div style=\"background:#F3F5F6;color:#515166;padding:25px 0px;font-family:"
"Arial,Helvetica,sans-serif;font-size:14px;\">\n"
" <table style=\"width:600px;margin:5px auto;\">\n"
" <tbody>\n"
" <tr>\n"
" <td>\n"
" <a href=\"/\">\n"
" <img src=\"/logo\" alt=\"${object."
"activity_id.controller_id.display_name|safe}\" style=\"vertical-align:"
"baseline;max-width:100px;\"/>\n"
" </a>\n"
" </td>\n"
" </tr>\n"
" </tbody>\n"
" </table>\n"
" <table style=\"width:600px;margin:0px auto;background:white;"
"border:1px solid #e1e1e1;\">\n"
" <tbody>\n"
" <tr>\n"
" <td colspan=\"2\" style=\"padding:15px 20px 0px "
"20px; font-size:16px;\">\n"
" <p>\n"
" Hello, ${object.partner_id.name|safe}\n"
" </p>\n"
" <p>\n"
" We contacted you to ask you to give us "
"your explicit consent to include your data in a data processing activity "
"called\n"
" <b>${object.activity_id.display_name|"
"safe}</b>, property of\n"
" <i>${object.activity_id.controller_id."
"display_name|safe}</i>\n"
" </p>\n"
" ${object.description or \"\"}\n"
" <p>\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"
" <b>accepted</b>\n"
" % else:\n"
" <b>rejected</b>\n"
" % endif\n"
" such data processing.\n"
" </p>\n"
" <p>\n"
" You can update your preferences below:\n"
" </p>\n"
" </td>\n"
" </tr>\n"
" <tr>\n"
" <td style=\"padding:15px 20px 0px 20px; font-"
"size:16px; text-align:right;\">\n"
" <a href=\"/privacy/consent/accept/\" style="
"\"background-color: #449d44; padding: 12px; font-weight: 12px; text-"
"decoration: none; color: #fff; border-radius: 5px; font-size:16px;\">\n"
" Accept\n"
" </a>\n"
" </td>\n"
" <td style=\"padding:15px 20px 0px 20px; font-"
"size:16px; text-align:left;\">\n"
" <a href=\"/privacy/consent/reject/\" style="
"\"background-color: #d9534f; padding: 12px; font-weight: 12px; text-"
"decoration: none; color: #fff; border-radius: 5px; font-size:16px;\">\n"
" Reject\n"
" </a>\n"
" </td>\n"
" </tr>\n"
" <tr>\n"
" <td colspan=\"2\" style=\"padding:15px 20px 15px "
"20px; font-size:16px;\">\n"
" <p>\n"
" If you need further information, please "
"respond to this email and we will attend your request as soon as possible.\n"
" </p>\n"
" <p>\n"
" Thank you!\n"
" </p>\n"
" </td>\n"
" </tr>\n"
" </tbody>\n"
" </table>\n"
" <table style=\"width:600px;margin:0px auto;text-align:center;"
"\">\n"
" <tbody>\n"
" <tr>\n"
" <td style=\"padding-top:10px;font-size: 12px;"
"\">\n"
" <p>\n"
" Sent by\n"
" <a href=\"/\" style=\"color:#717188;\">"
"${object.activity_id.controller_id.display_name|safe}</a>.\n"
" </p>\n"
" </td>\n"
" </tr>\n"
" </tbody>\n"
" </table>\n"
" </div>\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 "Zustimmung durch den Betroffenen geändert"
#. 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 "Akzeptiert"
#. 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 "Aktiv"
#. 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 "Aktivität"
#. module: privacy_consent
#: selection:privacy.consent,state:0
msgid "Answered"
msgstr "Beantwortet"
#. module: privacy_consent
#: model_terms:ir.ui.view,arch_db:privacy_consent.consent_search
msgid "Archived"
msgstr "Archiviert"
#. module: privacy_consent
#: model_terms:ir.ui.view,arch_db:privacy_consent.consent_form
msgid "Ask for consent"
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 "Einwilligung beim Betroffenen einholen"
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__message_attachment_count
msgid "Attachment Count"
msgstr ""
#. module: privacy_consent
#: selection:privacy.activity,consent_required:0
msgid "Automatically"
msgstr "Automatisch"
#. module: privacy_consent
#: selection:privacy.consent,state:0
msgid "Awaiting response"
msgstr "Warten auf Antwort"
#. module: privacy_consent
#: model_terms:ir.ui.view,arch_db:privacy_consent.activity_form
msgid "Consent"
msgstr "Einwilligung"
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity__consent_template_default_body_html
#, fuzzy
msgid "Consent Template Default Body Html"
msgstr "Einverständniserklärung Standardtext html"
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity__consent_template_default_subject
#, fuzzy
msgid "Consent Template Default Subject"
msgstr "Standardmäßige Einverständniserklärung Betroffener"
#. module: privacy_consent
#: model:ir.model,name:privacy_consent.model_privacy_consent
msgid "Consent of data processing"
msgstr "Einwilligung in die Datenverarbeitung"
#. 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 "Einwilligungen"
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity__consent_count
#, fuzzy
msgid "Consents count"
msgstr "Einwilligungen"
#. 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 "Erstellt von"
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__create_date
msgid "Created on"
msgstr "Erstellt am"
#. module: privacy_consent
#: model:ir.model,name:privacy_consent.model_privacy_activity
msgid "Data processing activities"
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 "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 "Anzeigename"
#. module: privacy_consent
#: selection:privacy.consent,state:0
msgid "Draft"
msgstr "Entwurf"
#. module: privacy_consent
#: sql_constraint:privacy.consent:0
msgid "Duplicated partner in this data processing activity"
msgstr "Doppelter Partner in dieser Verarbeitungsaktivität"
#. module: privacy_consent
#: model:ir.model,name:privacy_consent.model_mail_template
msgid "Email Templates"
msgstr "E-Mail-Vorlagen"
#. 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 ""
"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"
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_channel_ids
msgid "Followers (Channels)"
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
#, fuzzy
msgid "Generate and enqueue missing consent requests"
msgstr "Erstellung und Versand fehlender Einwilligungsanfragen"
#. module: privacy_consent
#: model_terms:ir.ui.view,arch_db:privacy_consent.activity_form
msgid "Generate missing draft consent requests"
msgstr "Fehlende Entwürfe von Einwilligungsanfragen erstellen"
#. module: privacy_consent
#: code:addons/privacy_consent/models/privacy_activity.py:139
#, python-format
msgid "Generated consents"
msgstr ""
#. module: privacy_consent
#: model_terms:ir.ui.view,arch_db:privacy_consent.consent_search
msgid "Group By"
msgstr "Gruppieren nach"
#. module: privacy_consent
#: model_terms:ir.ui.view,arch_db:privacy_consent.form
msgid "Hello,"
msgstr "Hallo"
#. module: privacy_consent
#: model_terms:ir.ui.view,arch_db:privacy_consent.form
msgid "I <b>accept</b> this processing of my data"
msgstr "Ich <b>akzeptiere</b> die Verarbeitung meiner Daten"
#. module: privacy_consent
#: model_terms:ir.ui.view,arch_db:privacy_consent.form
msgid "I <b>reject</b> this processing of my data"
msgstr "Ich <b>lehne</b> die Verarbeitung meiner Daten ab"
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__id
msgid "ID"
msgstr "Ausweis"
#. module: privacy_consent
#: model:ir.model.fields,help:privacy_consent.field_privacy_consent__message_unread
msgid "If checked new messages require your attention."
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 "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."
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__message_is_follower
msgid "Is Follower"
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__last_metadata
#, fuzzy
msgid "Last Metadata"
msgstr "Letzte Metadaten"
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent____last_update
msgid "Last Modified on"
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 "Zuletzt aktualisiert von"
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__write_date
msgid "Last Updated on"
msgstr "Zuletzt aktualisiert am"
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__message_main_attachment_id
msgid "Main Attachment"
msgstr ""
#. module: privacy_consent
#: selection:privacy.activity,consent_required:0
msgid "Manually"
msgstr "Manuell"
#. 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 "Metadaten aus der letzten Annahme oder Ablehnung durch den Betroffenen"
#. module: privacy_consent
#: 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"
"<a href=\"%s\">Accept</a>\n"
"<a href=\"%s\">Reject</a>"
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 "Neue Einwilligung"
#. 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 error"
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,help:privacy_consent.field_privacy_consent__message_needaction_counter
msgid "Number of messages which requires an 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.fields,help:privacy_consent.field_privacy_consent__message_unread_counter
msgid "Number of unread messages"
msgstr ""
#. module: privacy_consent
#: model:ir.model,name:privacy_consent.model_mail_mail
msgid "Outgoing Mails"
msgstr "Ausgehende Mails"
#. 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 "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 "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 "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 "Einwilligung zum Datenschutz"
#. module: privacy_consent
#: 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 ""
#. 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 "Server-Aktion"
#. 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,<br/>"
msgstr "Mit freundlichen Grüßen<br/>"
#. module: privacy_consent
#: code:addons/privacy_consent/models/privacy_activity.py:91
#, 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_terms:ir.ui.view,arch_db:privacy_consent.consent_search
msgid "State"
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 "Status geändert"
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__partner_id
msgid "Subject"
msgstr "Betroffener"
#. 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 "Vielen Dank."
#. module: privacy_consent
#: model_terms:ir.ui.view,arch_db:privacy_consent.form
msgid "Thanks for your response."
msgstr "Vielen Dank für Ihre Antwort."
#. module: privacy_consent
#: model_terms:ir.ui.view,arch_db:privacy_consent.activity_form
#, fuzzy
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?"
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__message_unread
msgid "Unread Messages"
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__message_unread_counter
msgid "Unread Messages Counter"
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 <b class=\"text-danger\">rejected</b> such processing."
msgstr ""
"Du hast diese Verarbeitungstätigkeit <b class=\"text-danger\">abgelehnt</b>."
#. module: privacy_consent
#: model_terms:ir.ui.view,arch_db:privacy_consent.form
msgid "You have <b class=\"text-success\">accepted</b> such processing."
msgstr ""
"Du hast dieser Verarbeitungstätigkeit <b class=\"text-success\">zugestimmt</"
"b>."
#~ msgid "Partner"
#~ msgstr "Partner"

779
privacy_consent/i18n/es.po

@ -0,0 +1,779 @@
# 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: 2019-05-13 17:04+0000\n"
"PO-Revision-Date: 2019-05-13 18:08+0100\n"
"Last-Translator: Jairo Llopis <yajo.sk8@gmail.com>\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.2.1\n"
#. module: privacy_consent
#: model:mail.template,body_html:privacy_consent.template_consent
msgid ""
"<?xml version=\"1.0\"?>\n"
"<div style=\"background:#F3F5F6;color:#515166;padding:25px 0px;font-family:"
"Arial,Helvetica,sans-serif;font-size:14px;\">\n"
" <table style=\"width:600px;margin:5px auto;\">\n"
" <tbody>\n"
" <tr>\n"
" <td>\n"
" <a href=\"/\">\n"
" <img src=\"/logo\" alt=\"${object."
"activity_id.controller_id.display_name|safe}\" style=\"vertical-align:"
"baseline;max-width:100px;\"/>\n"
" </a>\n"
" </td>\n"
" </tr>\n"
" </tbody>\n"
" </table>\n"
" <table style=\"width:600px;margin:0px auto;background:white;"
"border:1px solid #e1e1e1;\">\n"
" <tbody>\n"
" <tr>\n"
" <td colspan=\"2\" style=\"padding:15px 20px 0px "
"20px; font-size:16px;\">\n"
" <p>\n"
" Hello, ${object.partner_id.name|safe}\n"
" </p>\n"
" <p>\n"
" We contacted you to ask you to give us "
"your explicit consent to include your data in a data processing activity "
"called\n"
" <b>${object.activity_id.display_name|"
"safe}</b>, property of\n"
" <i>${object.activity_id.controller_id."
"display_name|safe}</i>\n"
" </p>\n"
" ${object.description or \"\"}\n"
" <p>\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"
" <b>accepted</b>\n"
" % else:\n"
" <b>rejected</b>\n"
" % endif\n"
" such data processing.\n"
" </p>\n"
" <p>\n"
" You can update your preferences below:\n"
" </p>\n"
" </td>\n"
" </tr>\n"
" <tr>\n"
" <td style=\"padding:15px 20px 0px 20px; font-"
"size:16px; text-align:right;\">\n"
" <a href=\"/privacy/consent/accept/\" style="
"\"background-color: #449d44; padding: 12px; font-weight: 12px; text-"
"decoration: none; color: #fff; border-radius: 5px; font-size:16px;\">\n"
" Accept\n"
" </a>\n"
" </td>\n"
" <td style=\"padding:15px 20px 0px 20px; font-"
"size:16px; text-align:left;\">\n"
" <a href=\"/privacy/consent/reject/\" style="
"\"background-color: #d9534f; padding: 12px; font-weight: 12px; text-"
"decoration: none; color: #fff; border-radius: 5px; font-size:16px;\">\n"
" Reject\n"
" </a>\n"
" </td>\n"
" </tr>\n"
" <tr>\n"
" <td colspan=\"2\" style=\"padding:15px 20px 15px "
"20px; font-size:16px;\">\n"
" <p>\n"
" If you need further information, please "
"respond to this email and we will attend your request as soon as possible.\n"
" </p>\n"
" <p>\n"
" Thank you!\n"
" </p>\n"
" </td>\n"
" </tr>\n"
" </tbody>\n"
" </table>\n"
" <table style=\"width:600px;margin:0px auto;text-align:center;"
"\">\n"
" <tbody>\n"
" <tr>\n"
" <td style=\"padding-top:10px;font-size: 12px;"
"\">\n"
" <p>\n"
" Sent by\n"
" <a href=\"/\" style=\"color:#717188;\">"
"${object.activity_id.controller_id.display_name|safe}</a>.\n"
" </p>\n"
" </td>\n"
" </tr>\n"
" </tbody>\n"
" </table>\n"
" </div>\n"
" "
msgstr ""
"<?xml version=\"1.0\"?>\n"
"<div style=\"background:#F3F5F6;color:#515166;padding:25px 0px;font-family:"
"Arial,Helvetica,sans-serif;font-size:14px;\">\n"
" <table style=\"width:600px;margin:5px auto;\">\n"
" <tbody>\n"
" <tr>\n"
" <td>\n"
" <a href=\"/\">\n"
" <img src=\"/logo\" alt=\"${object."
"activity_id.controller_id.display_name|safe}\" style=\"vertical-align:"
"baseline;max-width:100px;\"/>\n"
" </a>\n"
" </td>\n"
" </tr>\n"
" </tbody>\n"
" </table>\n"
" <table style=\"width:600px;margin:0px auto;background:white;"
"border:1px solid #e1e1e1;\">\n"
" <tbody>\n"
" <tr>\n"
" <td colspan=\"2\" style=\"padding:15px 20px 0px "
"20px; font-size:16px;\">\n"
" <p>\n"
" Hola, ${object.partner_id.name|safe}\n"
" </p>\n"
" <p>\n"
" Le hemos contactado para pedirle su "
"consentimiento explícito para incluir sus datos en una actividad de "
"tratamiento llamada\n"
" <b>${object.activity_id.display_name|"
"safe}</b>, propiedad de\n"
" <i>${object.activity_id.controller_id."
"display_name|safe}</i>\n"
" </p>\n"
" ${object.description or \"\"}\n"
" <p>\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"
" <b>ha aceptado</b>\n"
" % else:\n"
" <b>ha rechazado</b>\n"
" % endif\n"
" dicho procesamiento de datos.\n"
" </p>\n"
" <p>\n"
" Puede cambiar sus preferencias aquí "
"abajo:\n"
" </p>\n"
" </td>\n"
" </tr>\n"
" <tr>\n"
" <td style=\"padding:15px 20px 0px 20px; font-"
"size:16px; text-align:right;\">\n"
" <a href=\"/privacy/consent/accept/\" style="
"\"background-color: #449d44; padding: 12px; font-weight: 12px; text-"
"decoration: none; color: #fff; border-radius: 5px; font-size:16px;\">\n"
" Aceptar\n"
" </a>\n"
" </td>\n"
" <td style=\"padding:15px 20px 0px 20px; font-"
"size:16px; text-align:left;\">\n"
" <a href=\"/privacy/consent/reject/\" style="
"\"background-color: #d9534f; padding: 12px; font-weight: 12px; text-"
"decoration: none; color: #fff; border-radius: 5px; font-size:16px;\">\n"
" Rechazar\n"
" </a>\n"
" </td>\n"
" </tr>\n"
" <tr>\n"
" <td colspan=\"2\" style=\"padding:15px 20px 15px "
"20px; font-size:16px;\">\n"
" <p>\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"
" </p>\n"
" <p>\n"
" ¡Gracias!\n"
" </p>\n"
" </td>\n"
" </tr>\n"
" </tbody>\n"
" </table>\n"
" <table style=\"width:600px;margin:0px auto;text-align:center;"
"\">\n"
" <tbody>\n"
" <tr>\n"
" <td style=\"padding-top:10px;font-size: 12px;"
"\">\n"
" <p>\n"
" Enviado por\n"
" <a href=\"/\" style=\"color:#717188;\">"
"${object.activity_id.controller_id.display_name|safe}</a>.\n"
" </p>\n"
" </td>\n"
" </tr>\n"
" </tbody>\n"
" </table>\n"
" </div>\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_terms: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__message_needaction
msgid "Action Needed"
msgstr ""
#. 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_terms: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_terms:ir.ui.view,arch_db:privacy_consent.consent_search
msgid "Archived"
msgstr "Archivado"
#. module: privacy_consent
#: model_terms: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
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__message_attachment_count
msgid "Attachment Count"
msgstr ""
#. 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_terms:ir.ui.view,arch_db:privacy_consent.activity_form
msgid "Consent"
msgstr "Consentimiento"
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity__consent_template_default_body_html
#, fuzzy
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
#, fuzzy
msgid "Consent Template Default Subject"
msgstr "HTML por defecto para el asunto de la plantilla de 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.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 "Consents"
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity__consent_count
#, fuzzy
msgid "Consents count"
msgstr "Consents"
#. 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 "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.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.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_channel_ids
msgid "Followers (Channels)"
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 ""
"Generar y colocar en la bandeja de salida las solicitudes de consentimiento "
"que falten"
#. module: privacy_consent
#: model_terms: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:139
#, python-format
msgid "Generated consents"
msgstr "Consentimientos generados"
#. module: privacy_consent
#: model_terms:ir.ui.view,arch_db:privacy_consent.consent_search
msgid "Group By"
msgstr "Agrupar por"
#. module: privacy_consent
#: model_terms:ir.ui.view,arch_db:privacy_consent.form
msgid "Hello,"
msgstr "Hola,"
#. module: privacy_consent
#: model_terms:ir.ui.view,arch_db:privacy_consent.form
msgid "I <b>accept</b> this processing of my data"
msgstr "<b>Acepto</b> este tratamiento de mis datos"
#. module: privacy_consent
#: model_terms:ir.ui.view,arch_db:privacy_consent.form
msgid "I <b>reject</b> this processing of my data"
msgstr "<b>Rechazo</b> 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.model.fields,help:privacy_consent.field_privacy_consent__message_unread
msgid "If checked new messages require your attention."
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 "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__message_is_follower
msgid "Is Follower"
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__last_metadata
#, fuzzy
msgid "Last Metadata"
msgstr "Últimos metadatos"
#. 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__message_main_attachment_id
msgid "Main Attachment"
msgstr ""
#. module: privacy_consent
#: selection:privacy.activity,consent_required:0
msgid "Manually"
msgstr "Manualmente"
#. 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 ""
"Metadatos de la última aceptación o denegación por parte del interesado"
#. module: privacy_consent
#: 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"
"<a href=\"%s\">Accept</a>\n"
"<a href=\"%s\">Reject</a>"
msgstr ""
"Faltan los marcadores de posición de los enlaces para el consentimiento. "
"Necesita al menos estos dos enlaces:\n"
"<a href=\"%s\">Aceptar</a>\n"
"<a href=\"%s\">Rechazar</a>"
#. 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.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 error"
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,help:privacy_consent.field_privacy_consent__message_needaction_counter
msgid "Number of messages which requires an 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.fields,help:privacy_consent.field_privacy_consent__message_unread_counter
msgid "Number of unread messages"
msgstr ""
#. module: privacy_consent
#: model:ir.model,name:privacy_consent.model_mail_mail
msgid "Outgoing Mails"
msgstr "Correos electrónicos salientes"
#. 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
#: 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 ""
"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_terms:ir.ui.view,arch_db:privacy_consent.form
msgid "Sincerely,<br/>"
msgstr "Atentamente,<br/>"
#. module: privacy_consent
#: code:addons/privacy_consent/models/privacy_activity.py:91
#, 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_terms: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.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 "¡Gracias!"
#. module: privacy_consent
#: model_terms:ir.ui.view,arch_db:privacy_consent.form
msgid "Thanks for your response."
msgstr "Gracias por su respuesta."
#. 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 ""
"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.model.fields,field_description:privacy_consent.field_privacy_consent__message_unread
msgid "Unread Messages"
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__message_unread_counter
msgid "Unread Messages Counter"
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 ""
"Le hemos solicitado que nos autorice para procesar sus datos personales en "
"esta actividad de tratamiento:"
#. module: privacy_consent
#: model_terms: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_terms:ir.ui.view,arch_db:privacy_consent.form
msgid "You have <b class=\"text-danger\">rejected</b> such processing."
msgstr "Ha <b class=\"text-danger\">rechazado</b> dicho tratamiento."
#. module: privacy_consent
#: model_terms:ir.ui.view,arch_db:privacy_consent.form
msgid "You have <b class=\"text-success\">accepted</b> such processing."
msgstr "Ha <b class=\"text-success\">aceptado</b> dicho tratamiento."
#~ msgid "Email composition wizard"
#~ msgstr "Asistente de redacción de correo electrónico"
#~ msgid "Partner"
#~ msgstr "Contacto"
#~ msgid "Update partner's opt out"
#~ msgstr "Sincronizar la opción del contacto para recibir o no envíos masivos"

624
privacy_consent/i18n/fr.po

@ -0,0 +1,624 @@
# 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 ""
"<?xml version=\"1.0\"?>\n"
"<div style=\"background:#F3F5F6;color:#515166;padding:25px 0px;font-family:"
"Arial,Helvetica,sans-serif;font-size:14px;\">\n"
" <table style=\"width:600px;margin:5px auto;\">\n"
" <tbody>\n"
" <tr>\n"
" <td>\n"
" <a href=\"/\">\n"
" <img src=\"/logo\" alt=\"${object."
"activity_id.controller_id.display_name|safe}\" style=\"vertical-align:"
"baseline;max-width:100px;\"/>\n"
" </a>\n"
" </td>\n"
" </tr>\n"
" </tbody>\n"
" </table>\n"
" <table style=\"width:600px;margin:0px auto;background:white;"
"border:1px solid #e1e1e1;\">\n"
" <tbody>\n"
" <tr>\n"
" <td colspan=\"2\" style=\"padding:15px 20px 0px "
"20px; font-size:16px;\">\n"
" <p>\n"
" Hello, ${object.partner_id.name|safe}\n"
" </p>\n"
" <p>\n"
" We contacted you to ask you to give us "
"your explicit consent to include your data in a data processing activity "
"called\n"
" <b>${object.activity_id.display_name|"
"safe}</b>, property of\n"
" <i>${object.activity_id.controller_id."
"display_name|safe}</i>\n"
" </p>\n"
" ${object.description or \"\"}\n"
" <p>\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"
" <b>accepted</b>\n"
" % else:\n"
" <b>rejected</b>\n"
" % endif\n"
" such data processing.\n"
" </p>\n"
" <p>\n"
" You can update your preferences below:\n"
" </p>\n"
" </td>\n"
" </tr>\n"
" <tr>\n"
" <td style=\"padding:15px 20px 0px 20px; font-"
"size:16px; text-align:right;\">\n"
" <a href=\"/privacy/consent/accept/\" style="
"\"background-color: #449d44; padding: 12px; font-weight: 12px; text-"
"decoration: none; color: #fff; border-radius: 5px; font-size:16px;\">\n"
" Accept\n"
" </a>\n"
" </td>\n"
" <td style=\"padding:15px 20px 0px 20px; font-"
"size:16px; text-align:left;\">\n"
" <a href=\"/privacy/consent/reject/\" style="
"\"background-color: #d9534f; padding: 12px; font-weight: 12px; text-"
"decoration: none; color: #fff; border-radius: 5px; font-size:16px;\">\n"
" Reject\n"
" </a>\n"
" </td>\n"
" </tr>\n"
" <tr>\n"
" <td colspan=\"2\" style=\"padding:15px 20px 15px "
"20px; font-size:16px;\">\n"
" <p>\n"
" If you need further information, please "
"respond to this email and we will attend your request as soon as possible.\n"
" </p>\n"
" <p>\n"
" Thank you!\n"
" </p>\n"
" </td>\n"
" </tr>\n"
" </tbody>\n"
" </table>\n"
" <table style=\"width:600px;margin:0px auto;text-align:center;"
"\">\n"
" <tbody>\n"
" <tr>\n"
" <td style=\"padding-top:10px;font-size: 12px;"
"\">\n"
" <p>\n"
" Sent by\n"
" <a href=\"/\" style=\"color:#717188;\">"
"${object.activity_id.controller_id.display_name|safe}</a>.\n"
" </p>\n"
" </td>\n"
" </tr>\n"
" </tbody>\n"
" </table>\n"
" </div>\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
#: selection:privacy.consent,state:0
msgid "Answered"
msgstr ""
#. module: privacy_consent
#: 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
#: 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_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|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.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_channel_ids
msgid "Followers (Channels)"
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
#: code:addons/privacy_consent/models/privacy_activity.py:139
#, python-format
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_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 <b>accept</b> this processing of my data"
msgstr ""
#. module: privacy_consent
#: model_terms:ir.ui.view,arch_db:privacy_consent.form
msgid "I <b>reject</b> 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_unread
msgid "If checked new messages require your attention."
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____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__message_main_attachment_id
msgid "Main Attachment"
msgstr ""
#. module: privacy_consent
#: selection:privacy.activity,consent_required:0
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
#: 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"
"<a href=\"%s\">Accept</a>\n"
"<a href=\"%s\">Reject</a>"
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 error"
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,help:privacy_consent.field_privacy_consent__message_needaction_counter
msgid "Number of messages which requires an 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.fields,help:privacy_consent.field_privacy_consent__message_unread_counter
msgid "Number of unread messages"
msgstr ""
#. module: privacy_consent
#: model:ir.model,name:privacy_consent.model_mail_mail
msgid "Outgoing Mails"
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
#: 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 ""
#. 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,<br/>"
msgstr ""
#. module: privacy_consent
#: code:addons/privacy_consent/models/privacy_activity.py:91
#, 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_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:ir.model.fields,field_description:privacy_consent.field_privacy_consent__message_unread
msgid "Unread Messages"
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__message_unread_counter
msgid "Unread Messages Counter"
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 <b class=\"text-danger\">rejected</b> such processing."
msgstr ""
#. module: privacy_consent
#: model_terms:ir.ui.view,arch_db:privacy_consent.form
msgid "You have <b class=\"text-success\">accepted</b> such processing."
msgstr ""

588
privacy_consent/i18n/privacy_consent.pot

@ -0,0 +1,588 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * privacy_consent
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 12.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 "<?xml version=\"1.0\"?>\n"
"<div style=\"background:#F3F5F6;color:#515166;padding:25px 0px;font-family:Arial,Helvetica,sans-serif;font-size:14px;\">\n"
" <table style=\"width:600px;margin:5px auto;\">\n"
" <tbody>\n"
" <tr>\n"
" <td>\n"
" <a href=\"/\">\n"
" <img src=\"/logo\" alt=\"${object.activity_id.controller_id.display_name|safe}\" style=\"vertical-align:baseline;max-width:100px;\"/>\n"
" </a>\n"
" </td>\n"
" </tr>\n"
" </tbody>\n"
" </table>\n"
" <table style=\"width:600px;margin:0px auto;background:white;border:1px solid #e1e1e1;\">\n"
" <tbody>\n"
" <tr>\n"
" <td colspan=\"2\" style=\"padding:15px 20px 0px 20px; font-size:16px;\">\n"
" <p>\n"
" Hello, ${object.partner_id.name|safe}\n"
" </p>\n"
" <p>\n"
" We contacted you to ask you to give us your explicit consent to include your data in a data processing activity called\n"
" <b>${object.activity_id.display_name|safe}</b>, property of\n"
" <i>${object.activity_id.controller_id.display_name|safe}</i>\n"
" </p>\n"
" ${object.description or \"\"}\n"
" <p>\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"
" <b>accepted</b>\n"
" % else:\n"
" <b>rejected</b>\n"
" % endif\n"
" such data processing.\n"
" </p>\n"
" <p>\n"
" You can update your preferences below:\n"
" </p>\n"
" </td>\n"
" </tr>\n"
" <tr>\n"
" <td style=\"padding:15px 20px 0px 20px; font-size:16px; text-align:right;\">\n"
" <a href=\"/privacy/consent/accept/\" style=\"background-color: #449d44; padding: 12px; font-weight: 12px; text-decoration: none; color: #fff; border-radius: 5px; font-size:16px;\">\n"
" Accept\n"
" </a>\n"
" </td>\n"
" <td style=\"padding:15px 20px 0px 20px; font-size:16px; text-align:left;\">\n"
" <a href=\"/privacy/consent/reject/\" style=\"background-color: #d9534f; padding: 12px; font-weight: 12px; text-decoration: none; color: #fff; border-radius: 5px; font-size:16px;\">\n"
" Reject\n"
" </a>\n"
" </td>\n"
" </tr>\n"
" <tr>\n"
" <td colspan=\"2\" style=\"padding:15px 20px 15px 20px; font-size:16px;\">\n"
" <p>\n"
" If you need further information, please respond to this email and we will attend your request as soon as possible.\n"
" </p>\n"
" <p>\n"
" Thank you!\n"
" </p>\n"
" </td>\n"
" </tr>\n"
" </tbody>\n"
" </table>\n"
" <table style=\"width:600px;margin:0px auto;text-align:center;\">\n"
" <tbody>\n"
" <tr>\n"
" <td style=\"padding-top:10px;font-size: 12px;\">\n"
" <p>\n"
" Sent by\n"
" <a href=\"/\" style=\"color:#717188;\">${object.activity_id.controller_id.display_name|safe}</a>.\n"
" </p>\n"
" </td>\n"
" </tr>\n"
" </tbody>\n"
" </table>\n"
" </div>\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
#: selection:privacy.consent,state:0
msgid "Answered"
msgstr ""
#. module: privacy_consent
#: 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
#: 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_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|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.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_channel_ids
msgid "Followers (Channels)"
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
#: code:addons/privacy_consent/models/privacy_activity.py:139
#, python-format
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_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 <b>accept</b> this processing of my data"
msgstr ""
#. module: privacy_consent
#: model_terms:ir.ui.view,arch_db:privacy_consent.form
msgid "I <b>reject</b> 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_unread
msgid "If checked new messages require your attention."
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____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__message_main_attachment_id
msgid "Main Attachment"
msgstr ""
#. module: privacy_consent
#: selection:privacy.activity,consent_required:0
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
#: 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"
"<a href=\"%s\">Accept</a>\n"
"<a href=\"%s\">Reject</a>"
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 error"
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,help:privacy_consent.field_privacy_consent__message_needaction_counter
msgid "Number of messages which requires an 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.fields,help:privacy_consent.field_privacy_consent__message_unread_counter
msgid "Number of unread messages"
msgstr ""
#. module: privacy_consent
#: model:ir.model,name:privacy_consent.model_mail_mail
msgid "Outgoing Mails"
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
#: 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 ""
#. 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,<br/>"
msgstr ""
#. module: privacy_consent
#: code:addons/privacy_consent/models/privacy_activity.py:91
#, 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_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:ir.model.fields,field_description:privacy_consent.field_privacy_consent__message_unread
msgid "Unread Messages"
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__message_unread_counter
msgid "Unread Messages Counter"
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 <b class=\"text-danger\">rejected</b> such processing."
msgstr ""
#. module: privacy_consent
#: model_terms:ir.ui.view,arch_db:privacy_consent.form
msgid "You have <b class=\"text-success\">accepted</b> such processing."
msgstr ""

768
privacy_consent/i18n/pt.po

@ -0,0 +1,768 @@
msgid ""
msgstr ""
"Project-Id-Version: Portuguese (data-protection-10.0)\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2018-12-15 21:58+0000\n"
"Last-Translator: alvarorib <alvaro.ribeiro@exo.pt>\n"
"Language-Team: Portuguese <https://translation.odoo-community.org/projects/"
"data-protection-10-0/data-protection-10-0-privacy_consent/pt/>\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.3\n"
#. module: privacy_consent
#: model:mail.template,body_html:privacy_consent.template_consent
msgid ""
"<?xml version=\"1.0\"?>\n"
"<div style=\"background:#F3F5F6;color:#515166;padding:25px 0px;font-family:"
"Arial,Helvetica,sans-serif;font-size:14px;\">\n"
" <table style=\"width:600px;margin:5px auto;\">\n"
" <tbody>\n"
" <tr>\n"
" <td>\n"
" <a href=\"/\">\n"
" <img src=\"/logo\" alt=\"${object."
"activity_id.controller_id.display_name|safe}\" style=\"vertical-align:"
"baseline;max-width:100px;\"/>\n"
" </a>\n"
" </td>\n"
" </tr>\n"
" </tbody>\n"
" </table>\n"
" <table style=\"width:600px;margin:0px auto;background:white;"
"border:1px solid #e1e1e1;\">\n"
" <tbody>\n"
" <tr>\n"
" <td colspan=\"2\" style=\"padding:15px 20px 0px "
"20px; font-size:16px;\">\n"
" <p>\n"
" Hello, ${object.partner_id.name|safe}\n"
" </p>\n"
" <p>\n"
" We contacted you to ask you to give us "
"your explicit consent to include your data in a data processing activity "
"called\n"
" <b>${object.activity_id.display_name|"
"safe}</b>, property of\n"
" <i>${object.activity_id.controller_id."
"display_name|safe}</i>\n"
" </p>\n"
" ${object.description or \"\"}\n"
" <p>\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"
" <b>accepted</b>\n"
" % else:\n"
" <b>rejected</b>\n"
" % endif\n"
" such data processing.\n"
" </p>\n"
" <p>\n"
" You can update your preferences below:\n"
" </p>\n"
" </td>\n"
" </tr>\n"
" <tr>\n"
" <td style=\"padding:15px 20px 0px 20px; font-"
"size:16px; text-align:right;\">\n"
" <a href=\"/privacy/consent/accept/\" style="
"\"background-color: #449d44; padding: 12px; font-weight: 12px; text-"
"decoration: none; color: #fff; border-radius: 5px; font-size:16px;\">\n"
" Accept\n"
" </a>\n"
" </td>\n"
" <td style=\"padding:15px 20px 0px 20px; font-"
"size:16px; text-align:left;\">\n"
" <a href=\"/privacy/consent/reject/\" style="
"\"background-color: #d9534f; padding: 12px; font-weight: 12px; text-"
"decoration: none; color: #fff; border-radius: 5px; font-size:16px;\">\n"
" Reject\n"
" </a>\n"
" </td>\n"
" </tr>\n"
" <tr>\n"
" <td colspan=\"2\" style=\"padding:15px 20px 15px "
"20px; font-size:16px;\">\n"
" <p>\n"
" If you need further information, please "
"respond to this email and we will attend your request as soon as possible.\n"
" </p>\n"
" <p>\n"
" Thank you!\n"
" </p>\n"
" </td>\n"
" </tr>\n"
" </tbody>\n"
" </table>\n"
" <table style=\"width:600px;margin:0px auto;text-align:center;"
"\">\n"
" <tbody>\n"
" <tr>\n"
" <td style=\"padding-top:10px;font-size: 12px;"
"\">\n"
" <p>\n"
" Sent by\n"
" <a href=\"/\" style=\"color:#717188;\">"
"${object.activity_id.controller_id.display_name|safe}</a>.\n"
" </p>\n"
" </td>\n"
" </tr>\n"
" </tbody>\n"
" </table>\n"
" </div>\n"
" "
msgstr ""
"<?xml version=\"1.0\"?>\n"
"<div style=\"background:#F3F5F6;color:#515166;padding:25px 0px;font-family:"
"Arial,Helvetica,sans-serif;font-size:14px;\">\n"
" <table style=\"width:600px;margin:5px auto;\">\n"
" <tbody>\n"
" <tr>\n"
" <td>\n"
" <a href=\"/\">\n"
" <img src=\"/logo\" alt=\"${object."
"activity_id.controller_id.display_name|safe}\" style=\"vertical-align:"
"baseline;max-width:100px;\"/>\n"
" </a>\n"
" </td>\n"
" </tr>\n"
" </tbody>\n"
" </table>\n"
" <table style=\"width:600px;margin:0px auto;background:white;"
"border:1px solid #e1e1e1;\">\n"
" <tbody>\n"
" <tr>\n"
" <td colspan=\"2\" style=\"padding:15px 20px 0px "
"20px; font-size:16px;\">\n"
" <p>\n"
" Olá, ${object.partner_id.name|safe}\n"
" </p>\n"
" <p>\n"
" Contactámos, para solicitar o seu "
"consentimento explícito, à inclusão dos seus dados numa atividade de "
"processamento de dados, chamada\n"
" <b>${object.activity_id.display_name|"
"safe}</b>, propriedade de\n"
" <i>${object.activity_id.controller_id."
"display_name|safe}</i>\n"
" </p>\n"
" ${object.description or \"\"}\n"
" <p>\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"
" <b>aceitou</b>\n"
" % else:\n"
" <b>rejeitou</b>\n"
" % endif\n"
" esse processamento de dados.\n"
" </p>\n"
" <p>\n"
" Pode atualizar as suas preferências "
"abaixo:\n"
" </p>\n"
" </td>\n"
" </tr>\n"
" <tr>\n"
" <td style=\"padding:15px 20px 0px 20px; font-"
"size:16px; text-align:right;\">\n"
" <a href=\"/privacy/consent/accept/\" style="
"\"background-color: #449d44; padding: 12px; font-weight: 12px; text-"
"decoration: none; color: #fff; border-radius: 5px; font-size:16px;\">\n"
" Aceito\n"
" </a>\n"
" </td>\n"
" <td style=\"padding:15px 20px 0px 20px; font-"
"size:16px; text-align:left;\">\n"
" <a href=\"/privacy/consent/reject/\" style="
"\"background-color: #d9534f; padding: 12px; font-weight: 12px; text-"
"decoration: none; color: #fff; border-radius: 5px; font-size:16px;\">\n"
" Rejeito\n"
" </a>\n"
" </td>\n"
" </tr>\n"
" <tr>\n"
" <td colspan=\"2\" style=\"padding:15px 20px 15px "
"20px; font-size:16px;\">\n"
" <p>\n"
" Se necessitar de mais informação, por "
"favor responda a este email e nós trataremos de esclarecer assim que "
"possível.\n"
" </p>\n"
" <p>\n"
" Obrigado!\n"
" </p>\n"
" </td>\n"
" </tr>\n"
" </tbody>\n"
" </table>\n"
" <table style=\"width:600px;margin:0px auto;text-align:center;"
"\">\n"
" <tbody>\n"
" <tr>\n"
" <td style=\"padding-top:10px;font-size: 12px;"
"\">\n"
" <p>\n"
" Enviado por\n"
" <a href=\"/\" style=\"color:#717188;\">"
"${object.activity_id.controller_id.display_name|safe}</a>.\n"
" </p>\n"
" </td>\n"
" </tr>\n"
" </tbody>\n"
" </table>\n"
" </div>\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_terms: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__message_needaction
msgid "Action Needed"
msgstr ""
#. 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_terms: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_terms:ir.ui.view,arch_db:privacy_consent.consent_search
msgid "Archived"
msgstr "Arquivado"
#. module: privacy_consent
#: model_terms: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
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__message_attachment_count
msgid "Attachment Count"
msgstr ""
#. 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_terms:ir.ui.view,arch_db:privacy_consent.activity_form
msgid "Consent"
msgstr "Consentimento"
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity__consent_template_default_body_html
#, fuzzy
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
#, fuzzy
msgid "Consent Template Default Subject"
msgstr "Modelo predefinido de consentimento do titular"
#. 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.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 "Consentimentos"
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity__consent_count
#, fuzzy
msgid "Consents count"
msgstr "Consentimentos"
#. 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 "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.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.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_channel_ids
msgid "Followers (Channels)"
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
#, fuzzy
msgid "Generate and enqueue missing consent requests"
msgstr "Gerar e enviar pedidos de consentimento em falta"
#. module: privacy_consent
#: model_terms: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:139
#, python-format
msgid "Generated consents"
msgstr "Consentimentos gerados"
#. module: privacy_consent
#: model_terms:ir.ui.view,arch_db:privacy_consent.consent_search
msgid "Group By"
msgstr "Agrupar Por"
#. module: privacy_consent
#: model_terms:ir.ui.view,arch_db:privacy_consent.form
msgid "Hello,"
msgstr "Olá"
#. module: privacy_consent
#: model_terms:ir.ui.view,arch_db:privacy_consent.form
msgid "I <b>accept</b> this processing of my data"
msgstr "Eu <b>aceito</b> este processamento dos meus dados"
#. module: privacy_consent
#: model_terms:ir.ui.view,arch_db:privacy_consent.form
msgid "I <b>reject</b> this processing of my data"
msgstr "Eu <b>rejeito</b> este processamento dos meus dados"
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__id
msgid "ID"
msgstr "ID"
#. module: privacy_consent
#: model:ir.model.fields,help:privacy_consent.field_privacy_consent__message_unread
msgid "If checked new messages require your attention."
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 "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__message_is_follower
msgid "Is Follower"
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__last_metadata
#, fuzzy
msgid "Last Metadata"
msgstr "Últimos Metadados"
#. 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__message_main_attachment_id
msgid "Main Attachment"
msgstr ""
#. module: privacy_consent
#: selection:privacy.activity,consent_required:0
msgid "Manually"
msgstr "Manualmente"
#. 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 "Metadados da última aceitação ou rejeição pelo titular"
#. module: privacy_consent
#: 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"
"<a href=\"%s\">Accept</a>\n"
"<a href=\"%s\">Reject</a>"
msgstr ""
"Espaços reservados aos links de consentimento de privacidade em falta. "
"Necessita pelo menos destes dois links:\n"
"<a href=\"%s\">Aceito</a>\n"
"<a href=\"%s\">Rejeito</a>"
#. 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.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 error"
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,help:privacy_consent.field_privacy_consent__message_needaction_counter
msgid "Number of messages which requires an 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.fields,help:privacy_consent.field_privacy_consent__message_unread_counter
msgid "Number of unread messages"
msgstr ""
#. module: privacy_consent
#: model:ir.model,name:privacy_consent.model_mail_mail
msgid "Outgoing Mails"
msgstr "Mensagens a Enviar"
#. 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
#: 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 ""
"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_terms:ir.ui.view,arch_db:privacy_consent.form
msgid "Sincerely,<br/>"
msgstr "Cumprimentos,<br />"
#. module: privacy_consent
#: code:addons/privacy_consent/models/privacy_activity.py:91
#, 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_terms: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.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 "Obrigado!"
#. module: privacy_consent
#: model_terms:ir.ui.view,arch_db:privacy_consent.form
msgid "Thanks for your response."
msgstr "Obrigado pela sua resposta."
#. module: privacy_consent
#: model_terms:ir.ui.view,arch_db:privacy_consent.activity_form
#, fuzzy
msgid "This could enqueue 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.model.fields,field_description:privacy_consent.field_privacy_consent__message_unread
msgid "Unread Messages"
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent__message_unread_counter
msgid "Unread Messages Counter"
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 ""
"Pedimos-lhe que nos desse autorização para processarmos os seus dados nesta "
"atividade de processamento:"
#. module: privacy_consent
#: model_terms: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_terms:ir.ui.view,arch_db:privacy_consent.form
msgid "You have <b class=\"text-danger\">rejected</b> such processing."
msgstr "Você <b class=\"text-danger\">rejeitou</b> este processamento."
#. module: privacy_consent
#: model_terms:ir.ui.view,arch_db:privacy_consent.form
msgid "You have <b class=\"text-success\">accepted</b> such processing."
msgstr "Você <b class=\"text-success\">aceitou</b> este processamento."
#~ msgid "Partner"
#~ msgstr "Parceiro"
#~ msgid "Update partner's opt out"
#~ msgstr "Atualizar a Auto Exclusão do parceiro"
#~ msgid "Email composition wizard"
#~ msgstr "Assistente de criação de email"

5
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

62
privacy_consent/models/mail_mail.py

@ -0,0 +1,62 @@
# 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, success_pids, failure_reason=False, failure_type=None
):
"""Write consent status after sending message."""
# Know if mail was successfully sent to a privacy consent
res_ids = []
for mail in self:
if (
mail.mail_message_id.model == "privacy.consent"
and mail.state == "sent"
and success_pids
and not failure_reason
and not failure_type
):
res_ids.append(mail.mail_message_id.res_id)
consents = self.env["privacy.consent"].search(
[
("id", "in", res_ids),
("state", "=", "draft"),
("partner_id", "in", [par.id for par in success_pids]),
]
)
consents.write({"state": "sent"})
return super()._postprocess_sent_message(
success_pids=success_pids,
failure_reason=failure_reason,
failure_type=failure_type,
)
def _send_prepare_body(self):
"""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_prepare_body()
# Avoid polluting other model mails
if self.model != "privacy.consent":
return result
# Tokenize consent links
consent = self.env["privacy.consent"].browse(self.mail_message_id.res_id)
result = result.replace(
"/privacy/consent/accept/",
consent._url(True),
)
result = result.replace(
"/privacy/consent/reject/",
consent._url(False),
)
return result

37
privacy_consent/models/mail_template.py

@ -0,0 +1,37 @@
# 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 = [
"//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"
'<a href="%s">Accept</a>\n'
'<a href="%s">Reject</a>'
)
% (
"/privacy/consent/accept/",
"/privacy/consent/reject/",
)
)

145
privacy_consent/models/privacy_activity.py

@ -0,0 +1,145 @@
# 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 count",
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):
self.consent_count = 0
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]).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_vals = []
# Skip activitys where consent is not required
for one in self.with_context(active_test=False).filtered("consent_required"):
domain = [
("id", "not in", one.mapped("consent_ids.partner_id").ids),
("email", "!=", False),
] + safe_eval(one.subject_domain)
# Store values for creating missing consent requests
for missing in self.env["res.partner"].search(domain):
consents_vals.append(
{
"partner_id": missing.id,
"accepted": one.default_consent,
"activity_id": one.id,
}
)
# Create and send consent request emails for automatic activitys
consents = self.env["privacy.consent"].create(consents_vals)
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",
}

186
privacy_consent/models/privacy_consent.py

@ -0,0 +1,186 @@
# 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 _creation_subtype(self):
return self.env.ref("privacy_consent.mt_consent_consent_new")
def _track_subtype(self, init_values):
"""Return specific subtypes."""
if self.env.context.get("subject_answering"):
return self.env.ref("privacy_consent.mt_consent_acceptance_changed")
if "state" in init_values:
return self.env.ref("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."""
for one in self.with_context(
tpl_force_default_to=True,
mail_notify_user_signature=False,
mail_auto_subscribe_no_notify=True,
):
one.activity_id.consent_template_id.send_mail(one.id)
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_create_multi
def create(self, vals_list):
"""Run server action on create."""
results = super().create(vals_list)
# Sync the default acceptance status
results._run_action()
return results
def write(self, vals):
"""Run server action on update."""
result = super().write(vals)
self._run_action()
return result
def message_get_suggested_recipients(self):
result = super().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": "comment",
"default_model": self._name,
"default_res_id": self.id,
"default_template_id": self.activity_id.consent_template_id.id,
"default_use_template": 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})

33
privacy_consent/models/res_partner.py

@ -0,0 +1,33 @@
# 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."""
self.privacy_consent_count = 0
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]).privacy_consent_count = group[
"partner_id_count"
]

7
privacy_consent/readme/CONTRIBUTORS.rst

@ -0,0 +1,7 @@
* `Tecnativa <https://www.tecnativa.com>`_:
* Jairo Llopis
* `initOS GmbH <https://www.initos.com>`_:
* Florian Kantelberg

7
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.

15
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

69
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 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.
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.

3
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

BIN
privacy_consent/static/description/icon.png

After

Width: 128  |  Height: 128  |  Size: 9.2 KiB

525
privacy_consent/static/description/index.html

@ -0,0 +1,525 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.15.1: http://docutils.sourceforge.net/" />
<title>Privacy - Consent</title>
<style type="text/css">
/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 7952 2016-07-26 18:15:59Z milde $
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/
/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
border: 0 }
table.borderless td, table.borderless th {
/* Override padding for "table.docutils td" with "! important".
The right padding separates the table cells. */
padding: 0 0.5em 0 0 ! important }
.first {
/* Override more specific margin styles with "! important". */
margin-top: 0 ! important }
.last, .with-subtitle {
margin-bottom: 0 ! important }
.hidden {
display: none }
.subscript {
vertical-align: sub;
font-size: smaller }
.superscript {
vertical-align: super;
font-size: smaller }
a.toc-backref {
text-decoration: none ;
color: black }
blockquote.epigraph {
margin: 2em 5em ; }
dl.docutils dd {
margin-bottom: 0.5em }
object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
overflow: hidden;
}
/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
font-weight: bold }
*/
div.abstract {
margin: 2em 5em }
div.abstract p.topic-title {
font-weight: bold ;
text-align: center }
div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
margin: 2em ;
border: medium outset ;
padding: 1em }
div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
font-weight: bold ;
font-family: sans-serif }
div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title, .code .error {
color: red ;
font-weight: bold ;
font-family: sans-serif }
/* Uncomment (and remove this text!) to get reduced vertical space in
compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
margin-bottom: 0.5em }
div.compound .compound-last, div.compound .compound-middle {
margin-top: 0.5em }
*/
div.dedication {
margin: 2em 5em ;
text-align: center ;
font-style: italic }
div.dedication p.topic-title {
font-weight: bold ;
font-style: normal }
div.figure {
margin-left: 2em ;
margin-right: 2em }
div.footer, div.header {
clear: both;
font-size: smaller }
div.line-block {
display: block ;
margin-top: 1em ;
margin-bottom: 1em }
div.line-block div.line-block {
margin-top: 0 ;
margin-bottom: 0 ;
margin-left: 1.5em }
div.sidebar {
margin: 0 0 0.5em 1em ;
border: medium outset ;
padding: 1em ;
background-color: #ffffee ;
width: 40% ;
float: right ;
clear: right }
div.sidebar p.rubric {
font-family: sans-serif ;
font-size: medium }
div.system-messages {
margin: 5em }
div.system-messages h1 {
color: red }
div.system-message {
border: medium outset ;
padding: 1em }
div.system-message p.system-message-title {
color: red ;
font-weight: bold }
div.topic {
margin: 2em }
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
margin-top: 0.4em }
h1.title {
text-align: center }
h2.subtitle {
text-align: center }
hr.docutils {
width: 75% }
img.align-left, .figure.align-left, object.align-left, table.align-left {
clear: left ;
float: left ;
margin-right: 1em }
img.align-right, .figure.align-right, object.align-right, table.align-right {
clear: right ;
float: right ;
margin-left: 1em }
img.align-center, .figure.align-center, object.align-center {
display: block;
margin-left: auto;
margin-right: auto;
}
table.align-center {
margin-left: auto;
margin-right: auto;
}
.align-left {
text-align: left }
.align-center {
clear: both ;
text-align: center }
.align-right {
text-align: right }
/* reset inner alignment in figures */
div.align-right {
text-align: inherit }
/* div.align-center * { */
/* text-align: left } */
.align-top {
vertical-align: top }
.align-middle {
vertical-align: middle }
.align-bottom {
vertical-align: bottom }
ol.simple, ul.simple {
margin-bottom: 1em }
ol.arabic {
list-style: decimal }
ol.loweralpha {
list-style: lower-alpha }
ol.upperalpha {
list-style: upper-alpha }
ol.lowerroman {
list-style: lower-roman }
ol.upperroman {
list-style: upper-roman }
p.attribution {
text-align: right ;
margin-left: 50% }
p.caption {
font-style: italic }
p.credits {
font-style: italic ;
font-size: smaller }
p.label {
white-space: nowrap }
p.rubric {
font-weight: bold ;
font-size: larger ;
color: maroon ;
text-align: center }
p.sidebar-title {
font-family: sans-serif ;
font-weight: bold ;
font-size: larger }
p.sidebar-subtitle {
font-family: sans-serif ;
font-weight: bold }
p.topic-title {
font-weight: bold }
pre.address {
margin-bottom: 0 ;
margin-top: 0 ;
font: inherit }
pre.literal-block, pre.doctest-block, pre.math, pre.code {
margin-left: 2em ;
margin-right: 2em }
pre.code .ln { color: grey; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
pre.code .literal.string, code .literal.string { color: #0C5404 }
pre.code .name.builtin, code .name.builtin { color: #352B84 }
pre.code .deleted, code .deleted { background-color: #DEB0A1}
pre.code .inserted, code .inserted { background-color: #A3D289}
span.classifier {
font-family: sans-serif ;
font-style: oblique }
span.classifier-delimiter {
font-family: sans-serif ;
font-weight: bold }
span.interpreted {
font-family: sans-serif }
span.option {
white-space: nowrap }
span.pre {
white-space: pre }
span.problematic {
color: red }
span.section-subtitle {
/* font-size relative to parent (h1..h6 element) */
font-size: 80% }
table.citation {
border-left: solid 1px gray;
margin-left: 1px }
table.docinfo {
margin: 2em 4em }
table.docutils {
margin-top: 0.5em ;
margin-bottom: 0.5em }
table.footnote {
border-left: solid 1px black;
margin-left: 1px }
table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
padding-left: 0.5em ;
padding-right: 0.5em ;
vertical-align: top }
table.docutils th.field-name, table.docinfo th.docinfo-name {
font-weight: bold ;
text-align: left ;
white-space: nowrap ;
padding-left: 0 }
/* "booktabs" style (no vertical lines) */
table.docutils.booktabs {
border: 0px;
border-top: 2px solid;
border-bottom: 2px solid;
border-collapse: collapse;
}
table.docutils.booktabs * {
border: 0px;
}
table.docutils.booktabs th {
border-bottom: thin solid;
text-align: left;
}
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
font-size: 100% }
ul.auto-toc {
list-style-type: none }
</style>
</head>
<body>
<div class="document" id="privacy-consent">
<h1 class="title">Privacy - Consent</h1>
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external" href="https://odoo-community.org/page/development-status"><img alt="Production/Stable" src="https://img.shields.io/badge/maturity-Production%2FStable-green.png" /></a> <a class="reference external" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/OCA/data-protection/tree/13.0/privacy_consent"><img alt="OCA/data-protection" src="https://img.shields.io/badge/github-OCA%2Fdata--protection-lightgray.png?logo=github" /></a> <a class="reference external" href="https://translation.odoo-community.org/projects/data-protection-13-0/data-protection-13-0-privacy_consent"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external" href="https://runbot.odoo-community.org/runbot/263/13.0"><img alt="Try me on Runbot" src="https://img.shields.io/badge/runbot-Try%20me-875A7B.png" /></a></p>
<p>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.</p>
<p>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.</p>
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
<ul class="simple">
<li><a class="reference internal" href="#installation" id="id1">Installation</a><ul>
<li><a class="reference internal" href="#multi-database-instances" id="id2">Multi-database instances</a></li>
</ul>
</li>
<li><a class="reference internal" href="#usage" id="id3">Usage</a></li>
<li><a class="reference internal" href="#bug-tracker" id="id4">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="id5">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="id6">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="id7">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="id8">Maintainers</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="installation">
<h1><a class="toc-backref" href="#id1">Installation</a></h1>
<p>You may want to install, along with this module, one of OCA’s
<tt class="docutils literal">mail_tracking</tt> module collection, such as <tt class="docutils literal">mail_tracking_mailgun</tt>, so
you can provide more undeniable proof that some consent request was sent, and
to whom.</p>
<p>However, the most important proof to provide is the answer itself (more than
the question), and this addon provides enough tooling for that.</p>
<div class="section" id="multi-database-instances">
<h2><a class="toc-backref" href="#id2">Multi-database instances</a></h2>
<p>To enable multi-database support, you must load this addon as a server-wide
addon. Example command to boot Odoo:</p>
<pre class="literal-block">
odoo-bin --load=web,privacy_consent
</pre>
</div>
</div>
<div class="section" id="usage">
<h1><a class="toc-backref" href="#id3">Usage</a></h1>
<p>New options for data processing activities:</p>
<ol class="arabic">
<li><p class="first">Go to <em>Privacy &gt; Master Data &gt; Activities</em> and create one.</p>
</li>
<li><p class="first">Give it a name, such as <em>Sending mass mailings to customers</em>.</p>
</li>
<li><p class="first">Go to tab <em>Consent</em> and choose one option in <em>Ask subjects for consent</em>:</p>
<ul class="simple">
<li><em>Manual</em> 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.</li>
<li><em>Automatic</em> enables this module’s full power: send all consent requests
to selected partners automatically, every day and under your demand.</li>
</ul>
</li>
<li><p class="first">When you do this, all the consent-related options appear. Configure them:</p>
<ul>
<li><p class="first">A smart button tells you how many consents have been generated, and lets you
access them.</p>
</li>
<li><p class="first">Choose one <em>Email template</em> 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.</p>
</li>
<li><p class="first"><em>Subjects filter</em> defines what partners will be elegible for inclusion in
this data processing activity.</p>
</li>
<li><p class="first">You can enable <em>Accepted by default</em> if you want to assume subjects
accepted their data processing. You should possibly consult your
lawyer to use this.</p>
</li>
<li><p class="first">You can choose a <em>Server action</em> (developer mode only) that will
be executed whenever a new non-draft consent request is created,
or when its acceptance status changes.</p>
<p>This module supplies a server action by default, called
<em>Update partner’s opt out</em>, that syncs the acceptance status with the
partner’s <em>Elegible for mass mailings</em> option.</p>
</li>
</ul>
</li>
<li><p class="first">Click on <em>Generate consent requests</em> link to create new consent requests.</p>
<ul class="simple">
<li>If you chose <em>Manual</em> mode, all missing consent request are created as
drafts, and nothing else is done now.</li>
<li>If you chose <em>Automatic</em> mode, also those request e-mails are enqueued
and, when the mail queue is cleared, they will be set as <em>Sent</em>.</li>
</ul>
</li>
<li><p class="first">You will be presented with the list of just-created consent requests.
See below.</p>
</li>
</ol>
<p>New options for consent requests:</p>
<ol class="arabic simple">
<li>Access the consent requests by either:<ul>
<li>Generating new consent requests from a data processing activity.</li>
<li>Pressing the <em>Consents</em> smart button in a data processing activity.</li>
<li>Going to <em>Privacy &gt; Privacy &gt; Consents</em>.</li>
</ul>
</li>
<li>A consent will include the partner, the activity, the acceptance status,
and the request state.</li>
<li>You can manually ask for consent by pressing the button labeled as
<em>Ask for consent</em>.</li>
<li>All consent requests and responses are recorded in the mail thread below.</li>
</ol>
</div>
<div class="section" id="bug-tracker">
<h1><a class="toc-backref" href="#id4">Bug Tracker</a></h1>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/data-protection/issues">GitHub Issues</a>.
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
<a class="reference external" href="https://github.com/OCA/data-protection/issues/new?body=module:%20privacy_consent%0Aversion:%2013.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<p>Do not contact contributors directly about support or help with technical issues.</p>
</div>
<div class="section" id="credits">
<h1><a class="toc-backref" href="#id5">Credits</a></h1>
<div class="section" id="authors">
<h2><a class="toc-backref" href="#id6">Authors</a></h2>
<ul class="simple">
<li>Tecnativa</li>
<li>initOS GmbH</li>
</ul>
</div>
<div class="section" id="contributors">
<h2><a class="toc-backref" href="#id7">Contributors</a></h2>
<ul class="simple">
<li><a class="reference external" href="https://www.tecnativa.com">Tecnativa</a>:<ul>
<li>Jairo Llopis</li>
</ul>
</li>
<li><a class="reference external" href="https://www.initos.com">initOS GmbH</a>:<ul>
<li>Florian Kantelberg</li>
</ul>
</li>
</ul>
</div>
<div class="section" id="maintainers">
<h2><a class="toc-backref" href="#id8">Maintainers</a></h2>
<p>This module is maintained by the OCA.</p>
<a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a>
<p>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.</p>
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/data-protection/tree/13.0/privacy_consent">OCA/data-protection</a> project on GitHub.</p>
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
</div>
</div>
</div>
</body>
</html>

7
privacy_consent/static/src/css/privacy_consent.scss

@ -0,0 +1,7 @@
/* Copyright 2020 Tecnativa - Jairo Llopis
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). */
.o_consent_form {
// Need !important to override an inline style of max-width: 300px
max-width: 100% !important;
}

13
privacy_consent/templates/assets.xml

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2020 Tecnativa - Jairo Llopis
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
<data>
<template id="assets_frontend" inherit_id="web.assets_frontend">
<xpath expr=".">
<link
rel="stylesheet"
href="/privacy_consent/static/src/css/privacy_consent.scss"
/>
</xpath>
</template>
</data>

63
privacy_consent/templates/form.xml

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2018 Tecnativa - Jairo Llopis
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
<data>
<template id="form" name="Consent response processed">
<!-- Use web.login_layout because it gets automatically wrapped
by website layout if website is installed, and otherwise includes
all possibly needed assets -->
<t t-call="web.login_layout">
<t t-set="login_card_classes" t-value="'o_consent_form'" />
<div class="container readable">
<div class="jumbotron">
<h1>Thank you!</h1>
<p>
Hello, <b t-esc="consent.partner_id.display_name" />
</p>
<p>
We asked you to authorize us to process your data in this data processing activity:
<b t-esc="consent.activity_id.display_name" />
</p>
<t t-raw="consent.activity_id.description or ''" />
<p t-if="consent.accepted">
You have <b class="text-success">accepted</b> such processing.
</p>
<p t-else="">
You have <b class="text-danger">rejected</b> such processing.
</p>
<p>
We have recorded this action on your side.
</p>
<p>
If it was a mistake, you can undo it here:
<div class="text-center">
<a
t-if="consent.accepted"
t-att-href="consent._url(False)"
class="btn btn-danger btn-lg"
>
I <b>reject</b> this processing of my data
</a>
<a
t-else=""
t-att-href="consent._url(True)"
class="btn btn-success btn-lg"
>
I <b>accept</b> this processing of my data
</a>
</div>
</p>
<p>
Thanks for your response.
</p>
<p class="text-muted">
Sincerely,<br />
<i
t-raw="consent.activity_id.controller_id.with_context(show_address=True, html_format=True).name_get()[0][1]"
/>
</p>
</div>
</div>
</t>
</template>
</data>

1
privacy_consent/tests/__init__.py

@ -0,0 +1 @@
from . import test_consent

291
privacy_consent/tests/test_consent.py

@ -0,0 +1,291 @@
# 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 Form, HttpCase
class ActivityCase(HttpCase):
def setUp(self):
super(ActivityCase, self).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(
"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"}
)
self.partners += self.partners.create(
{"name": "consent-partner-1", "email": "partner1@example.com"}
)
self.partners += self.partners.create(
{"name": "consent-partner-2", "email": "partner2@example.com"}
)
# Partner without email, on purpose
self.partners += self.partners.create({"name": "consent-partner-3"})
# Partner with wrong email, on purpose
self.partners += self.partners.create(
{"name": "consent-partner-4", "email": "wrong-mail"}
)
# Blacklist some partners
self.blacklists = self.env["mail.blacklist"]
self.blacklists += self.blacklists._add("partner1@example.com")
# 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.sync_blacklist.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.sync_blacklist.id,
}
)
@contextmanager
def _patch_build(self):
self._built_messages = []
IMS = self.env["ir.mail_server"]
def _build_email(_self, email_from, email_to, subject, body, *args, **kwargs):
self._built_messages.append(body)
return _build_email.origin(
_self,
email_from,
email_to,
subject,
body,
*args,
**kwargs,
)
try:
IMS._patch_method("build_email", _build_email)
yield
finally:
IMS._revert_method("build_email")
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 pending mails
for consent in consents:
self.assertEqual(consent.state, "draft")
messages = consent.message_ids
self.assertEqual(len(messages), 2)
# Check sent mails
with self._patch_build():
self.cron_mail_queue.method_direct_trigger()
for consent in consents:
good_email = "@" in (consent.partner_id.email or "")
expected_messages = 3 if good_email else 2
self.assertEqual(
consent.state,
"sent" if good_email else "draft",
)
messages = consent.message_ids
self.assertEqual(len(messages), expected_messages)
# 2nd message notifies creation
self.assertEqual(
messages[expected_messages - 1].subtype_id,
self.mt_consent_consent_new,
)
# 3rd message notifies subject
# Placeholder links should be logged
self.assertIn(
"/privacy/consent/accept/", messages[expected_messages - 2].body
)
self.assertIn(
"/privacy/consent/reject/", messages[expected_messages - 2].body
)
# Tokenized links shouldn't be logged
self.assertNotIn(consent._url(True), messages[expected_messages - 2].body)
self.assertNotIn(consent._url(False), messages[expected_messages - 2].body)
# 4th message contains the state change
if good_email:
self.assertEqual(
messages[0].subtype_id,
self.mt_consent_state_changed,
)
# Partner's is_blacklisted should be synced with default consent
self.assertFalse(consent.partner_id.is_blacklisted)
# Check the sent message was built properly tokenized
accept_url, reject_url = map(consent._url, (True, False))
for body in self._built_messages:
if accept_url in body and reject_url in body:
self._built_messages.remove(body)
break
else:
raise AssertionError("Some message body should have these urls")
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."""
for partner in self.partners:
if "@" in (partner.email or ""):
self.blacklists._remove(partner.email)
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"] * 3)
self.assertEqual(
consents.mapped("partner_id.is_blacklisted"),
[False] * 3,
)
self.assertEqual(consents.mapped("accepted"), [False] * 3)
self.assertEqual(consents.mapped("last_metadata"), [False] * 3)
# Check sent mails
messages = consents.mapped("message_ids")
self.assertEqual(len(messages), 3)
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"],
)
composer_wizard = Form(Composer)
self.assertIn(consents[0].partner_id.name, composer_wizard.body)
composer_record = composer_wizard.save()
with self._patch_build():
composer_record.send_mail()
# Check the sent message was built properly tokenized
body = self._built_messages[0]
self.assertIn(consents[0]._url(True), body)
self.assertIn(consents[0]._url(False), body)
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", "draft"])
self.assertEqual(
consents.mapped("partner_id.is_blacklisted"),
[True, False, 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
result = self.url_open(accept_url).text
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, False])
self.assertTrue(consents[0].last_metadata)
self.assertFalse(consents[0].partner_id.is_blacklisted)
self.assertEqual(consents.mapped("state"), ["answered", "draft", "draft"])
self.assertEqual(
consents[0].message_ids[0].subtype_id,
self.mt_consent_acceptance_changed,
)
# Visit tokenized reject URL
result = self.url_open(reject_url).text
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, False])
self.assertTrue(consents[0].last_metadata)
self.assertTrue(consents[0].partner_id.is_blacklisted)
self.assertEqual(consents.mapped("state"), ["answered", "draft", "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 :("

76
privacy_consent/views/privacy_activity.xml

@ -0,0 +1,76 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2018 Tecnativa - Jairo Llopis
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
<data>
<record id="activity_form" model="ir.ui.view">
<field name="name">Add consent fields</field>
<field name="model">privacy.activity</field>
<field name="inherit_id" ref="privacy.activity_form" />
<field name="arch" type="xml">
<div name="button_box" position="inside">
<button
attrs='{"invisible": [("consent_required", "=", False)]}'
class="oe_stat_button"
context='{"search_default_activity_id": active_id}'
icon="fa-handshake-o"
name="%(consent_action)d"
type="action"
>
<field name="consent_count" widget="statinfo" />
</button>
</div>
<notebook name="advanced" position="inside">
<page string="Consent" name="consent">
<group>
<label for="consent_required" />
<div>
<field name="consent_required" class="oe_inline" />
<button
attrs='{"invisible": [("consent_required", "!=", "manual")]}'
class="btn-link"
icon="fa-user-plus"
name="action_new_consents"
type="object"
string="Generate missing draft consent requests"
/>
<button
attrs='{"invisible": [("consent_required", "!=", "auto")]}'
class="btn-link"
icon="fa-user-plus"
name="action_new_consents"
type="object"
string="Generate and enqueue missing consent requests"
confirm="This could enqueue many consent emails, are you sure to proceed?"
/>
</div>
</group>
<group attrs='{"invisible": [("consent_required", "=", False)]}'>
<group>
<field name="default_consent" />
<field name="server_action_id" groups="base.group_no_one" />
</group>
<group>
<field
name="consent_template_default_body_html"
invisible="1"
/>
<field
name="consent_template_default_subject"
invisible="1"
/>
<field
name="consent_template_id"
attrs='{"required": [("consent_required", "=", "auto")]}'
context='{
"default_model": "privacy.consent",
"default_body_html": consent_template_default_body_html,
"default_subject": consent_template_default_subject,
}'
/>
</group>
</group>
</page>
</notebook>
</field>
</record>
</data>

97
privacy_consent/views/privacy_consent.xml

@ -0,0 +1,97 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2018 Tecnativa - Jairo Llopis
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
<data>
<record model="ir.ui.view" id="consent_form">
<field name="name">Privacy Consent Form</field>
<field name="model">privacy.consent</field>
<field name="arch" type="xml">
<form>
<header>
<button
type="object"
name="action_manual_ask"
class="oe_highlight"
string="Ask for consent"
/>
<field name="state" widget="statusbar" />
</header>
<sheet>
<div class="oe_button_box" name="button_box">
<field name="active" invisible="1" />
<widget
name="web_ribbon"
title="Archived"
bg_color="bg-danger"
attrs="{'invisible': [('active', '=', True)]}"
/>
</div>
<group>
<field name="partner_id" />
<field name="activity_id" />
<field name="accepted" />
<field name="last_metadata" />
</group>
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers" />
<field name="message_ids" widget="mail_thread" />
</div>
</form>
</field>
</record>
<record model="ir.ui.view" id="consent_tree">
<field name="name">Privacy Consent Tree</field>
<field name="model">privacy.consent</field>
<field name="arch" type="xml">
<tree>
<field name="activity_id" />
<field name="partner_id" />
<field name="state" />
<field name="accepted" />
</tree>
</field>
</record>
<record model="ir.ui.view" id="consent_search">
<field name="name">Privacy Consent Search</field>
<field name="model">privacy.consent</field>
<field name="arch" type="xml">
<search>
<field name="activity_id" />
<field name="partner_id" />
<field name="state" />
<field name="accepted" />
<separator />
<filter
string="Archived"
name="inactive"
domain="[('active', '=', False)]"
/>
<separator />
<group string="Group By" name="groupby">
<filter
name="activity_id_groupby"
string="Activity"
context="{'group_by': 'activity_id'}"
/>
<filter
name="state_groupby"
string="State"
context="{'group_by': 'state'}"
/>
<filter
name="accepted_groupby"
string="Accepted"
context="{'group_by': 'accepted'}"
/>
</group>
</search>
</field>
</record>
<act_window id="consent_action" name="Consents" res_model="privacy.consent" />
<menuitem
action="consent_action"
id="menu_privacy_consent"
parent="privacy.menu_data_protection_master_data"
/>
</data>

28
privacy_consent/views/res_partner.xml

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2018 Tecnativa - Jairo Llopis
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
<data>
<record id="view_partner_form" model="ir.ui.view">
<field name="name">Add consent smart button</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_form" />
<field
name="groups_id"
eval="[(4, ref('privacy.group_data_protection_user'))]"
/>
<field name="arch" type="xml">
<div name="button_box" position="inside">
<button
attrs='{"invisible": [("privacy_consent_count", "=", 0)]}'
class="oe_stat_button"
context='{"search_default_partner_id": active_id}'
icon="fa-handshake-o"
name="%(consent_action)d"
type="action"
>
<field name="privacy_consent_count" widget="statinfo" />
</button>
</div>
</field>
</record>
</data>

1
setup/privacy_consent/odoo/addons/privacy_consent

@ -0,0 +1 @@
../../../../privacy_consent

6
setup/privacy_consent/setup.py

@ -0,0 +1,6 @@
import setuptools
setuptools.setup(
setup_requires=['setuptools-odoo'],
odoo_addon=True,
)
Loading…
Cancel
Save