Compare commits

...

76 Commits
11.0 ... 10.0

Author SHA1 Message Date
OCA-git-bot 18edede76f [ADD] setup.py 3 years ago
OCA-git-bot 5af65e086a [UPD] addons table in README.md 3 years ago
OCA Transbot 18353cba29 Update translation files 4 years ago
OCA-git-bot 8247e0e58d Merge PR #41 into 10.0 4 years ago
Denis Roussel 9a371bc5e3 [10.0][IMP] Update travis to latest template 4 years ago
OCA-git-bot 36d31b6683
[ADD] .editorconfig [ci skip] 5 years ago
OCA-git-bot 689baf6ba3 [UPD] README.rst 5 years ago
OCA Transbot 9be3b11d39 Update translation files 5 years ago
oca-travis 27ceaf5e01 [UPD] Update privacy_consent.pot 5 years ago
OCA Transbot e590fe0cc5 Update translation files 5 years ago
Pedro M. Baeza 3217750bc1
Merge pull request #30 from Tecnativa/10.0-privacy_consent-fix_locked_transaction 5 years ago
Jairo Llopis a4927a162e
[FIX] privacy_consent: Separate automated emails send process 5 years ago
OCA Transbot d49113128d Update translation files 5 years ago
oca-travis b829d7e21a [UPD] Update privacy_consent.pot 5 years ago
dw3gn3r e30dca7841 Translated using Weblate (German) 5 years ago
dw3gn3r 3ccd411079 Translated using Weblate (German) 5 years ago
Pedro M. Baeza 030d5f6906
Merge pull request #29 from Tecnativa/10.0-privacy_consent-avoid_race_sending_emails 5 years ago
Jairo Llopis 069185e83a
[FIX] privacy_consent: Avoid race condition when sending emails 5 years ago
dw3gn3r 873bd09a1d Added translation using Weblate (German) 5 years ago
dw3gn3r 79e39a6e40 Translated using Weblate (German) 5 years ago
dw3gn3r 1e32f83da2 Translated using Weblate (German) 5 years ago
dw3gn3r 821e9f4eff Translated using Weblate (German) 5 years ago
Malin Kienke 58597e2594 Translated using Weblate (German) 5 years ago
Malin Kienke 9c523facef Added translation using Weblate (German) 5 years ago
Malin Kienke 8ad98f15f5 Added translation using Weblate (German) 5 years ago
OCA Transbot 8258d0c0ac Update translation files 5 years ago
oca-travis 5fd62ea2bb [UPD] Update privacy_consent.pot 5 years ago
Pedro M. Baeza 43f1c4f2cb
Merge pull request #26 from Tecnativa/10.0-privacy_consent-fix_race_with_mail_queue 5 years ago
Jairo Llopis 09efb813a3
[FIX] privacy_consent: Avoid race condition with mail queue cron 5 years ago
João Carvalhido 8b33305851 Translated using Weblate (Portuguese) 5 years ago
Pedro M. Baeza c60a95198a
Merge pull request #25 from Tecnativa/10.0-upd-privacy_consent 5 years ago
Cristina Martin 14b614cdc2 [10.0][UPD] privacy_consent: set partner lang on mail template 5 years ago
Pedro M. Baeza 23649f17c8
Merge pull request #20 from Tecnativa/10-privacy_consent-test_at_install 5 years ago
Jairo Llopis 1eb21c6d29
[FIX] privacy_consent: Test at install 5 years ago
alvarorib 0bb3037102 Translated using Weblate (Portuguese) 5 years ago
alvarorib 3dbc87568d Translated using Weblate (Portuguese) 5 years ago
alvarorib f73f9992f4 Added translation using Weblate (Portuguese) 5 years ago
Alexandre Fayolle e0f0febecf Added translation using Weblate (French) 5 years ago
Alexandre Fayolle 74ab269ef8 Added translation using Weblate (French) 5 years ago
Alexandre Fayolle a364cf8779 Added translation using Weblate (French) 5 years ago
OCA Transbot 31b68323e7 Update translation files 5 years ago
oca-travis 2af1c4340b [UPD] Update privacy_partner_report.pot 6 years ago
OCA-git-bot 9f78ff381b [ADD] setup.py 6 years ago
OCA-git-bot 7394c18c98 [UPD] addons table in README.md [ci skip] 6 years ago
Pedro M. Baeza 341e915007
Merge pull request #12 from Eficent/10.0-mig-partner-report 6 years ago
Pedro Castro Silva 7c52985c11 Translated using Weblate (Portuguese) 6 years ago
Pedro Castro Silva d9f6fe7372 Translated using Weblate (Portuguese) 6 years ago
Pedro Castro Silva 276e6de3b7 Translated using Weblate (Portuguese) 6 years ago
Pedro Castro Silva e0f272a3e3 Translated using Weblate (Portuguese) 6 years ago
Pedro Castro Silva a2f4fcc315 Translated using Weblate (Portuguese) 6 years ago
Pedro Castro Silva 25ff979051 Added translation using Weblate (Portuguese) 6 years ago
Pedro Castro Silva 918b7958f6 Added translation using Weblate (Portuguese) 6 years ago
OCA Git Bot 24c6218b49 [UPD] README.rst 6 years ago
OCA Git Bot 1659ecb9c8 [ADD] setup.py 6 years ago
OCA Git Bot a9fb365886 [UPD] README.rst 6 years ago
OCA Git Bot b3e73edfe3 [UPD] addons table in README.md [ci skip] 6 years ago
oca-travis af01aa9cb0 [UPD] Update privacy_consent.pot 6 years ago
oca-travis c8091a5070 [UPD] Update privacy.pot 6 years ago
Pedro M. Baeza 18910b879d
[FIX] README.md: Change version 6 years ago
Jairo Llopis 522953438d [ADD] privacy_consent: Privacy explicit consent tracking tools (#11) 6 years ago
mreficent a0457dfccf [MIG] privacy_partner_report: Migration to 10.0 6 years ago
mreficent 11db044a51 [FIX] Admin should be data_protetion_manager by default 6 years ago
mreficent 5ff3c421f3 [ADD] privacy_partner_report 6 years ago
oca-travis ce6e54bc76 [UPD] Update privacy.pot 6 years ago
OCA Git Bot 63b9c06237 [ADD] setup.py 6 years ago
OCA Git Bot 1641bc35aa [UPD] README.rst 6 years ago
OCA Git Bot fde7d7d3ef [UPD] addons table in README.md [ci skip] 6 years ago
Pedro M. Baeza 231f45465d
Merge pull request #6 from dreispt/10.0-add-base 6 years ago
Daniel Reis 42992965d2 Port to 10.0 6 years ago
Daniel Reis ab109974d4
Merge pull request #9 from bealdav/patch-1 6 years ago
Pedro M. Baeza af4dcc1c15 [IMP] privacy: Icon 6 years ago
OCA Git Bot 003e136a56 [UPD] addons table in README.md [ci skip] 6 years ago
David Beal 31a9cb5b3f
Update top menu name 6 years ago
Daniel Reis 9e42732ee5 Change menu item sequence 6 years ago
Daniel Reis d30921228d Structure the privacy_base app module 6 years ago
mreficent d03c6ec02e [ADD] gdpr_partner_report 6 years ago
  1. 20
      .editorconfig
  2. 36
      .gitignore
  3. 69
      .travis.yml
  4. 13
      README.md
  5. 13
      oca_dependencies.txt
  6. 86
      privacy/README.rst
  7. 2
      privacy/__init__.py
  8. 29
      privacy/__manifest__.py
  9. 10
      privacy/demo/res_users.xml
  10. 201
      privacy/i18n/de.po
  11. 205
      privacy/i18n/es.po
  12. 195
      privacy/i18n/fr.po
  13. 195
      privacy/i18n/privacy.pot
  14. 196
      privacy/i18n/pt.po
  15. 1
      privacy/models/__init__.py
  16. 53
      privacy/models/privacy_activity.py
  17. 2
      privacy/readme/CONFIGURATION.rst
  18. 2
      privacy/readme/CONTRIBUTORS.rst
  19. 2
      privacy/readme/DESCRIPTION.rst
  20. 6
      privacy/readme/USAGE.rst
  21. 30
      privacy/security/data_protection.xml
  22. 3
      privacy/security/ir.model.access.csv
  23. BIN
      privacy/static/description/icon.png
  24. 115
      privacy/static/description/icon.svg
  25. 432
      privacy/static/description/index.html
  26. 51
      privacy/views/data_protection_menu_view.xml
  27. 127
      privacy/views/privacy_activity_view.xml
  28. 173
      privacy_consent/README.rst
  29. 2
      privacy_consent/__init__.py
  30. 29
      privacy_consent/__manifest__.py
  31. 1
      privacy_consent/controllers/__init__.py
  32. 47
      privacy_consent/controllers/main.py
  33. 23
      privacy_consent/data/ir_actions_server.xml
  34. 16
      privacy_consent/data/ir_cron.xml
  35. 158
      privacy_consent/data/mail.xml
  36. 539
      privacy_consent/i18n/de.po
  37. 663
      privacy_consent/i18n/es.po
  38. 519
      privacy_consent/i18n/fr.po
  39. 482
      privacy_consent/i18n/privacy_consent.pot
  40. 653
      privacy_consent/i18n/pt.po
  41. 5
      privacy_consent/models/__init__.py
  42. 54
      privacy_consent/models/mail_mail.py
  43. 33
      privacy_consent/models/mail_template.py
  44. 143
      privacy_consent/models/privacy_activity.py
  45. 187
      privacy_consent/models/privacy_consent.py
  46. 32
      privacy_consent/models/res_partner.py
  47. 3
      privacy_consent/readme/CONTRIBUTORS.rst
  48. 7
      privacy_consent/readme/DESCRIPTION.rst
  49. 15
      privacy_consent/readme/INSTALL.rst
  50. 69
      privacy_consent/readme/USAGE.rst
  51. 3
      privacy_consent/security/ir.model.access.csv
  52. BIN
      privacy_consent/static/description/icon.png
  53. 520
      privacy_consent/static/description/index.html
  54. 63
      privacy_consent/templates/form.xml
  55. 1
      privacy_consent/tests/__init__.py
  56. 253
      privacy_consent/tests/test_consent.py
  57. 89
      privacy_consent/views/privacy_activity.xml
  58. 113
      privacy_consent/views/privacy_consent.xml
  59. 35
      privacy_consent/views/res_partner.xml
  60. 67
      privacy_partner_report/README.rst
  61. 4
      privacy_partner_report/__init__.py
  62. 21
      privacy_partner_report/__manifest__.py
  63. 2
      privacy_partner_report/controllers/__init__.py
  64. 21
      privacy_partner_report/controllers/main.py
  65. 159
      privacy_partner_report/i18n/de.po
  66. 157
      privacy_partner_report/i18n/fr.po
  67. 157
      privacy_partner_report/i18n/privacy_partner_report.pot
  68. 159
      privacy_partner_report/i18n/pt.po
  69. 2
      privacy_partner_report/report/__init__.py
  70. 94
      privacy_partner_report/report/privacy_partner_xlsx.py
  71. BIN
      privacy_partner_report/static/description/icon.png
  72. 14
      privacy_partner_report/views/privacy_menu_view.xml
  73. 11
      privacy_partner_report/views/privacy_report.xml
  74. 2
      privacy_partner_report/wizard/__init__.py
  75. 226
      privacy_partner_report/wizard/privacy_report_partner.py
  76. 51
      privacy_partner_report/wizard/privacy_report_partner_wizard.xml
  77. 1
      setup/_metapackage/VERSION.txt
  78. 20
      setup/_metapackage/setup.py
  79. 1
      setup/privacy/odoo/__init__.py
  80. 1
      setup/privacy/odoo/addons/__init__.py
  81. 1
      setup/privacy/odoo/addons/privacy
  82. 6
      setup/privacy/setup.py
  83. 1
      setup/privacy_consent/odoo/__init__.py
  84. 1
      setup/privacy_consent/odoo/addons/__init__.py
  85. 1
      setup/privacy_consent/odoo/addons/privacy_consent
  86. 6
      setup/privacy_consent/setup.py
  87. 1
      setup/privacy_partner_report/odoo/__init__.py
  88. 1
      setup/privacy_partner_report/odoo/addons/__init__.py
  89. 1
      setup/privacy_partner_report/odoo/addons/privacy_partner_report
  90. 6
      setup/privacy_partner_report/setup.py

20
.editorconfig

@ -0,0 +1,20 @@
# Configuration for known file extensions
[*.{css,js,json,less,md,py,rst,sass,scss,xml,yaml,yml}]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
[.eslintrc,*.{json,yml,yaml,rst,md}]
indent_size = 2
# Do not configure editor for libs and autogenerated content
[*/static/{lib,src/lib}/**,*/static/description/index.html,*/readme/../README.rst]
charset = unset
end_of_line = unset
indent_size = unset
indent_style = unset
insert_final_newline = false
trim_trailing_whitespace = false

36
.gitignore

@ -5,6 +5,24 @@ __pycache__/
# C extensions
*.so
# Distribution / packaging
.Python
env/
bin/
build/
develop-eggs/
dist/
eggs/
# Project specific
oca.cfg
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
# C extensions
*.so
# Distribution / packaging
.Python
env/
@ -21,6 +39,7 @@ var/
*.egg-info/
.installed.cfg
*.egg
*.eggs
# Installer logs
pip-log.txt
@ -36,10 +55,23 @@ coverage.xml
# Translations
*.mo
*.pot
# Pycharm
.idea
# Eclipse
.settings
# Visual Studio cache/options directory
.vs/
# OSX Files
.DS_Store
# Django stuff:
*.log
# Mr Developer
.mr.developer.cfg
.project
@ -55,5 +87,5 @@ docs/_build/
*~
*.swp
# OSX Files
*.DS_Store
# OCA rules
!static/lib/

69
.travis.yml

@ -1,83 +1,30 @@
language: python
sudo: false
cache:
apt: true
directories:
- $HOME/.cache/pip
cache: pip
python:
- "2.7"
# For branches <= 10.0, put `- "2.7.13"`
- "2.7.13"
addons:
postgresql: "9.6"
apt:
# sources:
# Search your sources alias here:
# https://github.com/travis-ci/apt-source-whitelist/blob/master/ubuntu.json
packages:
- expect-dev # provides unbuffer utility
- python-lxml # because pip installation is slow
- expect-dev
- python-lxml
- python-simplejson
- python-serial
- python-yaml
# Search your packages here:
# https://github.com/travis-ci/apt-package-whitelist/blob/master/ubuntu-precise
# For wkhtmltopdf, see the env section below
# Sometimes complicated website repos need Compass & SaSS:
#before_install:
# - rvm install ruby --latest
# - gem install bootstrap-sass
# - gem install compass --pre
env:
global:
- VERSION="10.0" TESTS="0" LINT_CHECK="0" TRANSIFEX="0"
# Set this variable to some version existing as linux-generic build on
# https://github.com/wkhtmltopdf/wkhtmltopdf/releases
# if you need to install wkhtmltopdf
# - WKHTMLTOPDF_VERSION="0.12.4"
# Set the above to install a `wkhtmltopdf` version that is not the one provided
# by the `pov-wkhtmltopdf` repo.
- VERSION="10.0" TESTS="0" LINT_CHECK="0" MAKEPOT="0"
- PHANTOMJS_VERSION="latest"
# The above line controls the PhantomJS version that is used for JS testing.
# It is not necessary to include this value unless you are altering the default.
# Use `OS` to skip the PhantomJS upgrade & use the system version instead.
- WEBSITE_REPO="1"
# Use the above line to install dependencies that are required for website repos:
# * SASS & Bootstrap-SASS
# * Compass
- TRANSIFEX_USER='transbot@odoo-community.org'
# This line contains the encrypted transifex password
# To encrypt transifex password, install travis ruby utils with:
# $ gem install travis --user-install
# and use:
# $ travis encrypt TRANSIFEX_PASSWORD=your-password -r owner/project
# Secure list for current OCA projects is in https://github.com/OCA/maintainer-quality-tools/issues/194
- secure: yHr0UC45NBliMtTpZCYhNc2BdRgiHtXSQKBejHHWw2MXvOogZ+JqdwuqCPbHeP3NIKJYruUpYzXNdqCGP4Vll4xueSsA8CzeFp+gdJqxK6Z+gZiUZJ4W+vqckt2Q6YfdfqIGV8csNEUITCdidarGFSI/3EmDV1xl7Kkq8IMaIhUgd29MQ/R4CzCVcXfdZiN/mXZG7Ta1mLilcZwO7wlVed5IDsOJzXXglkQIYUbp73IraZsp9euXnO7pu+OQz19FuAJWOcPFV7Mgg0cPq+6fU+7lqyAdoj6d5NFrUpjKYbuT88L8wFrto4k0AHXLtL7cl+KNYahXNtnIvfnKNIwJ2lDN61I024mx4f8TQ7PNvSfv+nEdy0KVVk7rlw/JgudWEZFNIjlLYSGn6xdQVgiTrY53GEr9ASd4e/ELdfrNmHUw2JdOM1sg7GA4uwjAoNsF2IMfuvQJyhJRqEXowt9PKEL0ww4uVpxrwZLNWfV+oVvw3iV+QtV9dO18/LMBOXRj/DnfjZ3HVLim4WqjbpsgP5biiCRxKOqeBv+8D3jRcDTK56G8KX9+HnJAhLct/r+DragLufE2yoMCnMHH9AbhyI2omOVM7RoQ9+7PJhsR9ipsifGD+5Xi14sRxOCLPy5yV27FuzwwLkiBowkqeuUaS57DqrRlBjIJK8+Ea53xr14=
# Use the following lines if you need to manually change the transifex project slug or/and the transifex organization.
# The default project slug is owner-repo_name-version (with dash in the version string).
# The default organization is the owner of the repo.
# The default fill up resources (TM) is True.
# The default team is 23907. https://www.transifex.com/organization/oca/team/23907/
# - TRANSIFEX_PROJECT_SLUG=
# - TRANSIFEX_ORGANIZATION=
# - TRANSIFEX_FILL_UP_RESOURCES=
# - TRANSIFEX_TEAM=
matrix:
- LINT_CHECK="1"
- TRANSIFEX="1"
- TESTS="1" ODOO_REPO="odoo/odoo"
- TESTS="1" ODOO_REPO="odoo/odoo" MAKEPOT="1"
- TESTS="1" ODOO_REPO="OCA/OCB"
# either use the two lines above or the two below. Don't change the default if
# it's not necessary (it is only necessary if modules in your repository can't
# be installed in the same database. And you get a huge speed penalty in your
# tests)
# - TESTS="1.0" ODOO_REPO="odoo/odoo" UNIT_TEST="1"
# - TESTS="1.0" ODOO_REPO="OCA/OCB" UNIT_TEST="1"
virtualenv:
system_site_packages: true
install:
- git clone --depth=1 https://github.com/OCA/maintainer-quality-tools.git ${HOME}/maintainer-quality-tools

13
README.md

@ -1,11 +1,20 @@
[![Runbot Status](https://runbot.odoo-community.org/runbot/badge/flat/263/11.0.svg)](https://runbot.odoo-community.org/runbot/repo/github-com-oca-data-protection-263)
[![Build Status](https://travis-ci.org/OCA/data-protection.svg?branch=11.0)](https://travis-ci.org/OCA/data-protection)
[![Runbot Status](https://runbot.odoo-community.org/runbot/badge/flat/263/10.0.svg)](https://runbot.odoo-community.org/runbot/repo/github-com-oca-data-protection-263)
[![Build Status](https://travis-ci.org/OCA/data-protection.svg?branch=10.0)](https://travis-ci.org/OCA/data-protection)
# Data Protection
Odoo modules for data protection (like GDPR).
[//]: # (addons)
Available addons
----------------
addon | version | maintainers | summary
--- | --- | --- | ---
[privacy](privacy/) | 10.0.2.0.0 | | Provides data privacy and protection features to comply to regulations, such as GDPR.
[privacy_consent](privacy_consent/) | 10.0.1.0.0 | | Allow people to explicitly accept or reject inclusion in some activity, GDPR compliant
[privacy_partner_report](privacy_partner_report/) | 10.0.1.0.0 | [![mreficent](https://github.com/mreficent.png?size=30px)](https://github.com/mreficent) | Show the transactions that a specific partner is involved in.
[//]: # (end addons)
----

13
oca_dependencies.txt

@ -1,15 +1,4 @@
# List the OCA project dependencies, one per line
# Add a repository url and branch if you need a forked version
#
# Examples
# ========
#
# To depend on the standard version of sale-workflow, use:
# sale-workflow
#
# To explicitely give the URL of a fork, and still use the version specified in
# .travis.yml, use:
# sale-workflow https://github.com/OCA/sale-workflow
#
# To provide both the URL and a branch, use:
# sale-workflow https://github.com/OCA/sale-workflow branchname
reporting-engine

86
privacy/README.rst

@ -0,0 +1,86 @@
===========================
Data Privacy and Protection
===========================
.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
:target: https://odoo-community.org/page/development-status
:alt: Beta
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fdata--protection-lightgray.png?logo=github
:target: https://github.com/OCA/data-protection/tree/10.0/privacy
:alt: OCA/data-protection
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/data-protection-10-0/data-protection-10-0-privacy
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
:target: https://runbot.odoo-community.org/runbot/263/10.0
:alt: Try me on Runbot
|badge1| |badge2| |badge3| |badge4| |badge5|
This application provides data protection and privacy feature,
to comply with regulations such as GDPR.
**Table of contents**
.. contents::
:local:
Usage
=====
To define data processing activities:
#. Go to *Privacy > Master Data > Activities* and create one.
#. Define the data processing activity using the provided tools.
Consult your lawyer!
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%0Aversion:%2010.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
~~~~~~~
* Eficent
* Tecnativa
Contributors
~~~~~~~~~~~~
* Miquel Raïch <miquel.raich@eficent.com>
* Daniel Reis <dreis.pt@hotmail.com>
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/10.0/privacy>`_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

2
privacy/__init__.py

@ -0,0 +1,2 @@
# -*- coding: utf-8 -*-
from . import models

29
privacy/__manifest__.py

@ -0,0 +1,29 @@
# -*- coding: utf-8 -*-
# Copyright 2018 Eficent Business and IT Consulting Services S.L.
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
{
'name': 'Data Privacy and Protection',
'version': '10.0.2.0.0',
'category': 'Data Protection',
'summary': 'Provides data privacy and protection features '
'to comply to regulations, such as GDPR.',
'author': "Eficent, "
"Tecnativa, "
"Odoo Community Association (OCA)",
'website': 'http://www.github.com/OCA/data-protection',
'license': 'AGPL-3',
'data': [
'security/data_protection.xml',
'security/ir.model.access.csv',
'views/data_protection_menu_view.xml',
'views/privacy_activity_view.xml',
],
'demo': [
'demo/res_users.xml',
],
'depends': [
'mail',
],
'installable': True,
'application': True,
}

10
privacy/demo/res_users.xml

@ -0,0 +1,10 @@
<?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="base.user_demo" model="res.users">
<field name="groups_id" eval="[(4, ref('group_data_protection_user'))]"/>
</record>
</data>

201
privacy/i18n/de.po

@ -0,0 +1,201 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * privacy
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 10.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2019-03-28 17:14+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.1\n"
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_active
msgid "Active"
msgstr "Aktiv"
#. module: privacy
#: model:ir.actions.act_window,name:privacy.activity_action
#: model:ir.ui.menu,name:privacy.menu_privacy_activity
msgid "Activities"
msgstr "Tätigkeiten"
#. module: privacy
#: model:ir.ui.view,arch_db:privacy.activity_search
msgid "Archived"
msgstr "Archiviert"
#. module: privacy
#: model:ir.model.fields,help:privacy.field_privacy_activity_subject_find
msgid "Are affected subjects present in this database?"
msgstr "Sind betroffene Personen in der Datenbank enthalten?"
#. module: privacy
#: model:ir.actions.act_window,help:privacy.activity_action
msgid "Click to add a data processing activity."
msgstr "Klicken Sie hier, um eine Verarbeitungstätigkeit hinzuzufügen."
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_controller_id
#: model:ir.ui.view,arch_db:privacy.activity_search
msgid "Controller"
msgstr "Verantwortlicher"
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_create_uid
msgid "Created by"
msgstr "Erstellt von"
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_create_date
msgid "Created on"
msgstr "Erstellt am"
#. module: privacy
#: model:ir.module.category,name:privacy.module_category_data_protection
msgid "Data Protection"
msgstr "Datenschutz"
#. module: privacy
#: model:res.groups,name:privacy.group_data_protection_manager
msgid "Data Protection Manager"
msgstr "Datenschutzbeauftragter"
#. module: privacy
#: model:res.groups,name:privacy.group_data_protection_user
msgid "Data Protection User"
msgstr ""
#. module: privacy
#: model:ir.model,name:privacy.model_privacy_activity
msgid "Data processing activities"
msgstr "Verarbeitungstätigkeiten"
#. module: privacy
#: model:ir.actions.act_window,help:privacy.activity_action
msgid "Data processing activities define why, how and what you do\n"
" with subjects' personal data."
msgstr ""
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_subject_find
msgid "Define subjects"
msgstr ""
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_description
#: model:ir.ui.view,arch_db:privacy.activity_form
msgid "Description"
msgstr "Beschreibung"
#. module: privacy
#: model:ir.ui.view,arch_db:privacy.activity_form
msgid "Details"
msgstr "Details"
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_display_name
msgid "Display Name"
msgstr "Anzeigename"
#. module: privacy
#: model:ir.ui.view,arch_db:privacy.activity_search
msgid "Group By"
msgstr "Gruppieren nach"
#. module: privacy
#: model:ir.model.fields,help:privacy.field_privacy_activity_description
msgid "How is personal data used here? Why? Etc."
msgstr "Wie werden hier personenbezogene Daten verwendet? Warum? Etc."
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_id
msgid "ID"
msgstr ""
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity___last_update
msgid "Last Modified on"
msgstr "Letzte Änderung am"
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_write_uid
msgid "Last Updated by"
msgstr "Zuletzt aktualisiert von"
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_write_date
msgid "Last Updated on"
msgstr "Zuletzt aktualisiert am"
#. module: privacy
#: model:ir.ui.menu,name:privacy.menu_data_protection_master_data
msgid "Master Data"
msgstr ""
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_name
msgid "Name"
msgstr "Bezeichnung"
#. module: privacy
#: model:ir.actions.act_window,name:privacy.action_data_protection_partner_form
#: model:ir.ui.menu,name:privacy.menu_data_protection_partner
msgid "Partners"
msgstr ""
#. module: privacy
#: model:ir.ui.menu,name:privacy.parent_menu_data_protection
msgid "Privacy"
msgstr ""
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_processor_ids
msgid "Processors"
msgstr "Auftragsverarbeiter"
#. module: privacy
#: model:ir.ui.menu,name:privacy.menu_data_protection_report
msgid "Reports"
msgstr "Berichte"
#. module: privacy
#: model:ir.model.fields,help:privacy.field_privacy_activity_subject_domain
msgid "Selection filter to find specific subjects included."
msgstr "Auswahlfilter, um bestimmte betroffene Personen auszuwählen."
#. module: privacy
#: model:ir.ui.menu,name:privacy.menu_data_protection_setting
msgid "Settings"
msgstr "Einstellungen"
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_subject_domain
msgid "Subjects filter"
msgstr ""
#. module: privacy
#: model:ir.ui.menu,name:privacy.menu_data_protection_transaction
msgid "Transactions"
msgstr ""
#. module: privacy
#: model:ir.model.fields,help:privacy.field_privacy_activity_controller_id
msgid "Whoever determines the purposes and means of the processing of personal data."
msgstr ""
"Die Stelle, welche über die Zwecke und Mittel der Verarbeitung von "
"personenbezogenen Daten entscheidet."
#. module: privacy
#: model:ir.model.fields,help:privacy.field_privacy_activity_processor_ids
msgid "Whoever processes personal data on behalf of the controller."
msgstr ""
"Die Stelle, die personenbezogene Daten im Auftrag des Verantwortlichen "
"verarbeitet."

205
privacy/i18n/es.po

@ -0,0 +1,205 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * privacy
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 10.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-07-11 08:39+0000\n"
"PO-Revision-Date: 2018-07-11 10:46+0200\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.0.8\n"
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_active
msgid "Active"
msgstr "Activa"
#. module: privacy
#: model:ir.actions.act_window,name:privacy.activity_action
#: model:ir.ui.menu,name:privacy.menu_privacy_activity
msgid "Activities"
msgstr "Actividades"
#. module: privacy
#: model:ir.ui.view,arch_db:privacy.activity_search
msgid "Archived"
msgstr "Archivada"
#. module: privacy
#: model:ir.model.fields,help:privacy.field_privacy_activity_subject_find
msgid "Are affected subjects present in this database?"
msgstr "¿Los sujetos interesados se encuentran en esta base de datos?"
#. module: privacy
#: model:ir.actions.act_window,help:privacy.activity_action
msgid "Click to add a data processing activity."
msgstr "Pulse para añadir una actividad de tratamiento de datos."
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_controller_id
#: model:ir.ui.view,arch_db:privacy.activity_search
msgid "Controller"
msgstr "Responsable"
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_create_uid
msgid "Created by"
msgstr "Creado por"
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_create_date
msgid "Created on"
msgstr "Creado el"
#. module: privacy
#: model:ir.module.category,name:privacy.module_category_data_protection
msgid "Data Protection"
msgstr "Protección de datos"
#. module: privacy
#: model:res.groups,name:privacy.group_data_protection_manager
msgid "Data Protection Manager"
msgstr "Gestor de protección de datos"
#. module: privacy
#: model:res.groups,name:privacy.group_data_protection_user
msgid "Data Protection User"
msgstr "Usuario de protección de datos"
#. module: privacy
#: model:ir.model,name:privacy.model_privacy_activity
msgid "Data processing activities"
msgstr "Actividades de tratamiento de datos"
#. module: privacy
#: model:ir.actions.act_window,help:privacy.activity_action
msgid ""
"Data processing activities define why, how and what you do\n"
" with subjects' personal data."
msgstr ""
"Las actividades de tratamiento definen por qué, cómo y qué se hace\n"
"\t\tcon los datos personales de los interesados."
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_subject_find
msgid "Define subjects"
msgstr "Definir interesados"
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_description
#: model:ir.ui.view,arch_db:privacy.activity_form
msgid "Description"
msgstr "Descripción"
#. module: privacy
#: model:ir.ui.view,arch_db:privacy.activity_form
msgid "Details"
msgstr "Detalles"
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_display_name
msgid "Display Name"
msgstr "Nombre a mostrar"
#. module: privacy
#: model:ir.ui.view,arch_db:privacy.activity_search
msgid "Group By"
msgstr "Agrupar por"
#. module: privacy
#: model:ir.model.fields,help:privacy.field_privacy_activity_description
msgid "How is personal data used here? Why? Etc."
msgstr "¿Cómo se usan los datos personales aquí? ¿Por qué? Etc."
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_id
msgid "ID"
msgstr "ID"
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity___last_update
msgid "Last Modified on"
msgstr "Última modificación en"
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_write_uid
msgid "Last Updated by"
msgstr "Última actualización por"
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_write_date
msgid "Last Updated on"
msgstr "Última actualización el"
#. module: privacy
#: model:ir.ui.menu,name:privacy.menu_data_protection_master_data
msgid "Master Data"
msgstr "Datos maestros"
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_name
msgid "Name"
msgstr "Nombre"
#. module: privacy
#: model:ir.actions.act_window,name:privacy.action_data_protection_partner_form
#: model:ir.ui.menu,name:privacy.menu_data_protection_partner
msgid "Partners"
msgstr "Contactos"
#. module: privacy
#: model:ir.ui.menu,name:privacy.parent_menu_data_protection
msgid "Privacy"
msgstr "Privacidad"
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_processor_ids
msgid "Processors"
msgstr "Encargados del tratamiento"
#. module: privacy
#: model:ir.ui.menu,name:privacy.menu_data_protection_report
msgid "Reports"
msgstr "Informes"
#. module: privacy
#: model:ir.model.fields,help:privacy.field_privacy_activity_subject_domain
msgid "Selection filter to find specific subjects included."
msgstr ""
"Filtro de selección para encontrar los interesados específicos incluidos."
#. module: privacy
#: model:ir.ui.menu,name:privacy.menu_data_protection_setting
msgid "Settings"
msgstr "Configuración"
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_subject_domain
msgid "Subjects filter"
msgstr "Filtro de interesados"
#. module: privacy
#: model:ir.ui.menu,name:privacy.menu_data_protection_transaction
msgid "Transactions"
msgstr "Transacciones"
#. module: privacy
#: model:ir.model.fields,help:privacy.field_privacy_activity_controller_id
msgid ""
"Whoever determines the purposes and means of the processing of personal data."
msgstr ""
"Quien determina los propósitos y medios del procesamiento de datos "
"personales."
#. module: privacy
#: model:ir.model.fields,help:privacy.field_privacy_activity_processor_ids
msgid "Whoever processes personal data on behalf of the controller."
msgstr "Quien procesa los datos personales en nombre del responsable."

195
privacy/i18n/fr.po

@ -0,0 +1,195 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * privacy
#
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
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_active
msgid "Active"
msgstr ""
#. module: privacy
#: model:ir.actions.act_window,name:privacy.activity_action
#: model:ir.ui.menu,name:privacy.menu_privacy_activity
msgid "Activities"
msgstr ""
#. module: privacy
#: model:ir.ui.view,arch_db:privacy.activity_search
msgid "Archived"
msgstr ""
#. module: privacy
#: model:ir.model.fields,help:privacy.field_privacy_activity_subject_find
msgid "Are affected subjects present in this database?"
msgstr ""
#. module: privacy
#: model:ir.actions.act_window,help:privacy.activity_action
msgid "Click to add a data processing activity."
msgstr ""
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_controller_id
#: model:ir.ui.view,arch_db:privacy.activity_search
msgid "Controller"
msgstr ""
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_create_uid
msgid "Created by"
msgstr ""
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_create_date
msgid "Created on"
msgstr ""
#. module: privacy
#: model:ir.module.category,name:privacy.module_category_data_protection
msgid "Data Protection"
msgstr ""
#. module: privacy
#: model:res.groups,name:privacy.group_data_protection_manager
msgid "Data Protection Manager"
msgstr ""
#. module: privacy
#: model:res.groups,name:privacy.group_data_protection_user
msgid "Data Protection User"
msgstr ""
#. module: privacy
#: model:ir.model,name:privacy.model_privacy_activity
msgid "Data processing activities"
msgstr ""
#. module: privacy
#: model:ir.actions.act_window,help:privacy.activity_action
msgid "Data processing activities define why, how and what you do\n"
" with subjects' personal data."
msgstr ""
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_subject_find
msgid "Define subjects"
msgstr ""
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_description
#: model:ir.ui.view,arch_db:privacy.activity_form
msgid "Description"
msgstr ""
#. module: privacy
#: model:ir.ui.view,arch_db:privacy.activity_form
msgid "Details"
msgstr ""
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_display_name
msgid "Display Name"
msgstr ""
#. module: privacy
#: model:ir.ui.view,arch_db:privacy.activity_search
msgid "Group By"
msgstr ""
#. module: privacy
#: model:ir.model.fields,help:privacy.field_privacy_activity_description
msgid "How is personal data used here? Why? Etc."
msgstr ""
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_id
msgid "ID"
msgstr ""
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity___last_update
msgid "Last Modified on"
msgstr ""
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_write_uid
msgid "Last Updated by"
msgstr ""
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_write_date
msgid "Last Updated on"
msgstr ""
#. module: privacy
#: model:ir.ui.menu,name:privacy.menu_data_protection_master_data
msgid "Master Data"
msgstr ""
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_name
msgid "Name"
msgstr ""
#. module: privacy
#: model:ir.actions.act_window,name:privacy.action_data_protection_partner_form
#: model:ir.ui.menu,name:privacy.menu_data_protection_partner
msgid "Partners"
msgstr ""
#. module: privacy
#: model:ir.ui.menu,name:privacy.parent_menu_data_protection
msgid "Privacy"
msgstr ""
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_processor_ids
msgid "Processors"
msgstr ""
#. module: privacy
#: model:ir.ui.menu,name:privacy.menu_data_protection_report
msgid "Reports"
msgstr ""
#. module: privacy
#: model:ir.model.fields,help:privacy.field_privacy_activity_subject_domain
msgid "Selection filter to find specific subjects included."
msgstr ""
#. module: privacy
#: model:ir.ui.menu,name:privacy.menu_data_protection_setting
msgid "Settings"
msgstr ""
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_subject_domain
msgid "Subjects filter"
msgstr ""
#. module: privacy
#: model:ir.ui.menu,name:privacy.menu_data_protection_transaction
msgid "Transactions"
msgstr ""
#. module: privacy
#: model:ir.model.fields,help:privacy.field_privacy_activity_controller_id
msgid "Whoever determines the purposes and means of the processing of personal data."
msgstr ""
#. module: privacy
#: model:ir.model.fields,help:privacy.field_privacy_activity_processor_ids
msgid "Whoever processes personal data on behalf of the controller."
msgstr ""

195
privacy/i18n/privacy.pot

@ -0,0 +1,195 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * privacy
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 10.0\n"
"Report-Msgid-Bugs-To: \n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_active
msgid "Active"
msgstr ""
#. module: privacy
#: model:ir.actions.act_window,name:privacy.activity_action
#: model:ir.ui.menu,name:privacy.menu_privacy_activity
msgid "Activities"
msgstr ""
#. module: privacy
#: model:ir.ui.view,arch_db:privacy.activity_search
msgid "Archived"
msgstr ""
#. module: privacy
#: model:ir.model.fields,help:privacy.field_privacy_activity_subject_find
msgid "Are affected subjects present in this database?"
msgstr ""
#. module: privacy
#: model:ir.actions.act_window,help:privacy.activity_action
msgid "Click to add a data processing activity."
msgstr ""
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_controller_id
#: model:ir.ui.view,arch_db:privacy.activity_search
msgid "Controller"
msgstr ""
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_create_uid
msgid "Created by"
msgstr ""
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_create_date
msgid "Created on"
msgstr ""
#. module: privacy
#: model:ir.module.category,name:privacy.module_category_data_protection
msgid "Data Protection"
msgstr ""
#. module: privacy
#: model:res.groups,name:privacy.group_data_protection_manager
msgid "Data Protection Manager"
msgstr ""
#. module: privacy
#: model:res.groups,name:privacy.group_data_protection_user
msgid "Data Protection User"
msgstr ""
#. module: privacy
#: model:ir.model,name:privacy.model_privacy_activity
msgid "Data processing activities"
msgstr ""
#. module: privacy
#: model:ir.actions.act_window,help:privacy.activity_action
msgid "Data processing activities define why, how and what you do\n"
" with subjects' personal data."
msgstr ""
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_subject_find
msgid "Define subjects"
msgstr ""
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_description
#: model:ir.ui.view,arch_db:privacy.activity_form
msgid "Description"
msgstr ""
#. module: privacy
#: model:ir.ui.view,arch_db:privacy.activity_form
msgid "Details"
msgstr ""
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_display_name
msgid "Display Name"
msgstr ""
#. module: privacy
#: model:ir.ui.view,arch_db:privacy.activity_search
msgid "Group By"
msgstr ""
#. module: privacy
#: model:ir.model.fields,help:privacy.field_privacy_activity_description
msgid "How is personal data used here? Why? Etc."
msgstr ""
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_id
msgid "ID"
msgstr ""
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity___last_update
msgid "Last Modified on"
msgstr ""
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_write_uid
msgid "Last Updated by"
msgstr ""
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_write_date
msgid "Last Updated on"
msgstr ""
#. module: privacy
#: model:ir.ui.menu,name:privacy.menu_data_protection_master_data
msgid "Master Data"
msgstr ""
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_name
msgid "Name"
msgstr ""
#. module: privacy
#: model:ir.actions.act_window,name:privacy.action_data_protection_partner_form
#: model:ir.ui.menu,name:privacy.menu_data_protection_partner
msgid "Partners"
msgstr ""
#. module: privacy
#: model:ir.ui.menu,name:privacy.parent_menu_data_protection
msgid "Privacy"
msgstr ""
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_processor_ids
msgid "Processors"
msgstr ""
#. module: privacy
#: model:ir.ui.menu,name:privacy.menu_data_protection_report
msgid "Reports"
msgstr ""
#. module: privacy
#: model:ir.model.fields,help:privacy.field_privacy_activity_subject_domain
msgid "Selection filter to find specific subjects included."
msgstr ""
#. module: privacy
#: model:ir.ui.menu,name:privacy.menu_data_protection_setting
msgid "Settings"
msgstr ""
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_subject_domain
msgid "Subjects filter"
msgstr ""
#. module: privacy
#: model:ir.ui.menu,name:privacy.menu_data_protection_transaction
msgid "Transactions"
msgstr ""
#. module: privacy
#: model:ir.model.fields,help:privacy.field_privacy_activity_controller_id
msgid "Whoever determines the purposes and means of the processing of personal data."
msgstr ""
#. module: privacy
#: model:ir.model.fields,help:privacy.field_privacy_activity_processor_ids
msgid "Whoever processes personal data on behalf of the controller."
msgstr ""

196
privacy/i18n/pt.po

@ -0,0 +1,196 @@
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/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
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_active
msgid "Active"
msgstr "Ativo"
#. module: privacy
#: model:ir.actions.act_window,name:privacy.activity_action
#: model:ir.ui.menu,name:privacy.menu_privacy_activity
msgid "Activities"
msgstr "Atividades"
#. module: privacy
#: model:ir.ui.view,arch_db:privacy.activity_search
msgid "Archived"
msgstr "Arquivado"
#. module: privacy
#: model:ir.model.fields,help:privacy.field_privacy_activity_subject_find
msgid "Are affected subjects present in this database?"
msgstr "Os titulares afetados estão presentes nesta base de dados?"
#. module: privacy
#: model:ir.actions.act_window,help:privacy.activity_action
msgid "Click to add a data processing activity."
msgstr "Clique para adicionar uma atividade de processamento de dados."
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_controller_id
#: model:ir.ui.view,arch_db:privacy.activity_search
msgid "Controller"
msgstr "Controlador"
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_create_uid
msgid "Created by"
msgstr "Criado por"
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_create_date
msgid "Created on"
msgstr "Criado em"
#. module: privacy
#: model:ir.module.category,name:privacy.module_category_data_protection
msgid "Data Protection"
msgstr "Proteção de Dados"
#. module: privacy
#: model:res.groups,name:privacy.group_data_protection_manager
msgid "Data Protection Manager"
msgstr "Gestor de Proteção de Dados"
#. module: privacy
#: model:res.groups,name:privacy.group_data_protection_user
msgid "Data Protection User"
msgstr "Utilizador de Proteção de Dados"
#. module: privacy
#: model:ir.model,name:privacy.model_privacy_activity
msgid "Data processing activities"
msgstr "Atividades de processamento de dados"
#. module: privacy
#: model:ir.actions.act_window,help:privacy.activity_action
msgid "Data processing activities define why, how and what you do\n"
" with subjects' personal data."
msgstr ""
"As atividades de processamento de dados definem porquê, como e o que faz com "
"os dados pessoais dos titulares."
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_subject_find
msgid "Define subjects"
msgstr "Definir titulares"
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_description
#: model:ir.ui.view,arch_db:privacy.activity_form
msgid "Description"
msgstr "Descrição"
#. module: privacy
#: model:ir.ui.view,arch_db:privacy.activity_form
msgid "Details"
msgstr "Detalhes"
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_display_name
msgid "Display Name"
msgstr "Nome a Exibir"
#. module: privacy
#: model:ir.ui.view,arch_db:privacy.activity_search
msgid "Group By"
msgstr "Agrupar Por"
#. module: privacy
#: model:ir.model.fields,help:privacy.field_privacy_activity_description
msgid "How is personal data used here? Why? Etc."
msgstr "Como são usados os dados pessoais aqui? Porquê? Etc."
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_id
msgid "ID"
msgstr "ID"
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity___last_update
msgid "Last Modified on"
msgstr "Última Modificação em"
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_write_uid
msgid "Last Updated by"
msgstr "Última Atualização por"
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_write_date
msgid "Last Updated on"
msgstr "Última Atualização em"
#. module: privacy
#: model:ir.ui.menu,name:privacy.menu_data_protection_master_data
msgid "Master Data"
msgstr "Dados Principais"
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_name
msgid "Name"
msgstr "Nome"
#. module: privacy
#: model:ir.actions.act_window,name:privacy.action_data_protection_partner_form
#: model:ir.ui.menu,name:privacy.menu_data_protection_partner
msgid "Partners"
msgstr "Parceiros"
#. module: privacy
#: model:ir.ui.menu,name:privacy.parent_menu_data_protection
msgid "Privacy"
msgstr "Privacidade"
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_processor_ids
msgid "Processors"
msgstr "Processadores"
#. module: privacy
#: model:ir.ui.menu,name:privacy.menu_data_protection_report
msgid "Reports"
msgstr "Relatórios"
#. module: privacy
#: model:ir.model.fields,help:privacy.field_privacy_activity_subject_domain
msgid "Selection filter to find specific subjects included."
msgstr "Filtro de seleção para procurar titulares específicos incluídos."
#. module: privacy
#: model:ir.ui.menu,name:privacy.menu_data_protection_setting
msgid "Settings"
msgstr "Configurações"
#. module: privacy
#: model:ir.model.fields,field_description:privacy.field_privacy_activity_subject_domain
msgid "Subjects filter"
msgstr "Filtro de titulares"
#. module: privacy
#: model:ir.ui.menu,name:privacy.menu_data_protection_transaction
msgid "Transactions"
msgstr "Transações"
#. module: privacy
#: model:ir.model.fields,help:privacy.field_privacy_activity_controller_id
msgid "Whoever determines the purposes and means of the processing of personal data."
msgstr "Quem determina os fins e meios do processamento de dados pessoais."
#. module: privacy
#: model:ir.model.fields,help:privacy.field_privacy_activity_processor_ids
msgid "Whoever processes personal data on behalf of the controller."
msgstr "Quem processa dados pessoais em nome do controlador."

1
privacy/models/__init__.py

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

53
privacy/models/privacy_activity.py

@ -0,0 +1,53 @@
# -*- coding: utf-8 -*-
# Copyright 2018 Tecnativa - Jairo Llopis
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import api, fields, models
class PrivacyActivity(models.Model):
_name = "privacy.activity"
_description = "Data processing activities"
_inherit = "mail.thread"
active = fields.Boolean(
default=True,
index=True,
)
name = fields.Char(
index=True,
required=True,
translate=True,
)
description = fields.Html(
translate=True,
help="How is personal data used here? Why? Etc."
)
controller_id = fields.Many2one(
"res.partner",
string="Controller",
required=True,
default=lambda self: self._default_controller_id(),
help="Whoever determines the purposes and means of the processing "
"of personal data.",
)
processor_ids = fields.Many2many(
"res.partner",
"privacy_activity_res_partner_processor_ids",
string="Processors",
help="Whoever processes personal data on behalf of the controller.",
)
subject_find = fields.Boolean(
"Define subjects",
help="Are affected subjects present in this database?",
)
subject_domain = fields.Char(
"Subjects filter",
default="[]",
help="Selection filter to find specific subjects included.",
)
@api.model
def _default_controller_id(self):
"""By default it should be the current user's company."""
return self.env.user.company_id

2
privacy/readme/CONFIGURATION.rst

@ -0,0 +1,2 @@
In the "Privacy", open the "Settings" menu to find and enable
the main features available.

2
privacy/readme/CONTRIBUTORS.rst

@ -0,0 +1,2 @@
* Miquel Raïch <miquel.raich@eficent.com>
* Daniel Reis <dreis.pt@hotmail.com>

2
privacy/readme/DESCRIPTION.rst

@ -0,0 +1,2 @@
This application provides data protection and privacy feature,
to comply with regulations such as GDPR.

6
privacy/readme/USAGE.rst

@ -0,0 +1,6 @@
To define data processing activities:
#. Go to *Privacy > Master Data > Activities* and create one.
#. Define the data processing activity using the provided tools.
Consult your lawyer!

30
privacy/security/data_protection.xml

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2018 Eficent Business and IT Consulting Services S.L.
License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl-3.0) -->
<odoo>
<data noupdate="0">
<record model="ir.module.category" id="module_category_data_protection">
<field name="name">Data Protection</field>
<field name="sequence">30</field>
</record>
<record id="group_data_protection_user" model="res.groups">
<field name="name">Data Protection User</field>
<field name="implied_ids" eval="[(4, ref('base.group_user'))]"/>
<field name="category_id" ref="module_category_data_protection"/>
</record>
<record id="group_data_protection_manager" model="res.groups">
<field name="name">Data Protection Manager</field>
<field name="implied_ids" eval="[(4, ref('privacy.group_data_protection_user'))]"/>
<field name="category_id" ref="module_category_data_protection"/>
<field name="users" eval="[(4, ref('base.user_root'))]"/>
</record>
<record id="base.user_root" model="res.users">
<field name="groups_id" eval="[(4, ref('group_data_protection_manager'))]"/>
</record>
</data>
</odoo>

3
privacy/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
read,Permission to read activities,model_privacy_activity,group_data_protection_user,1,0,0,0
write,Permission to write activities,model_privacy_activity,group_data_protection_manager,1,1,1,1

BIN
privacy/static/description/icon.png

Before

Width: 128  |  Height: 128  |  Size: 2.1 KiB

After

Width: 128  |  Height: 128  |  Size: 2.1 KiB

115
privacy/static/description/icon.svg

@ -0,0 +1,115 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
id="svg2"
version="1.1"
inkscape:version="0.92.3 (2405546, 2018-03-11)"
width="60"
height="60"
viewBox="0 0 60 60"
sodipodi:docname="icon.svg"
inkscape:export-filename="icon.png"
inkscape:export-xdpi="204.8"
inkscape:export-ydpi="204.8">
<metadata
id="metadata8">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs6" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1853"
inkscape:window-height="1018"
id="namedview4"
showgrid="false"
inkscape:zoom="5.6568542"
inkscape:cx="-13.498037"
inkscape:cy="27.319233"
inkscape:window-x="67"
inkscape:window-y="34"
inkscape:window-maximized="1"
inkscape:current-layer="svg2"
showguides="true"
inkscape:guide-bbox="true">
<sodipodi:guide
position="0,41.75"
orientation="1,0"
id="guide3360"
inkscape:locked="false" />
<sodipodi:guide
position="60,60.074219"
orientation="1,0"
id="guide3362"
inkscape:locked="false" />
<sodipodi:guide
position="0.17578125,60"
orientation="0,1"
id="guide3364"
inkscape:locked="false" />
<sodipodi:guide
position="58.71196,-0.0055242717"
orientation="0,1"
id="guide3366"
inkscape:locked="false" />
<sodipodi:guide
position="47.0625,10.9375"
orientation="-0.70710678,0.70710678"
id="guide3347"
inkscape:locked="false" />
<sodipodi:guide
position="21.743534,47.376154"
orientation="-0.70710678,0.70710678"
id="guide23"
inkscape:locked="false" />
</sodipodi:namedview>
<rect
style="opacity:1;fill:#0092d7;fill-opacity:1"
id="rect4147"
width="60"
height="60"
x="0"
y="0" />
<path
style="opacity:1;fill:#000000;fill-opacity:0.39215686"
d="M 0.0078125,34.359568 0,60 36.1162,60.0088 47.0625,49.0625 37.871757,16.233181 21.743534,12.623846 Z"
id="rect4171"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccc" />
<g
id="g4169"
transform="matrix(0.3061173,0,0,0.3061173,-1.0360053,-1.0457906)"
style="fill:#ffffff;stroke:none" />
<g
aria-label=""
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:9.38242626px;line-height:0%;font-family:FontAwesome;-inkscape-font-specification:FontAwesome;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.78186888px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="text3352">
<path
d="m 44.064502,27.442816 c 1.038855,0 1.917886,0.399559 2.717006,1.118767 0.719207,0.799119 1.118767,1.67815 1.118767,2.717006 v 15.343092 c 0,1.118767 -0.39956,1.997799 -1.118767,2.717006 -0.79912,0.799119 -1.678151,1.118767 -2.717006,1.118767 H 15.935499 c -1.118767,0 -1.997799,-0.319648 -2.717006,-1.118767 -0.79912,-0.719207 -1.118767,-1.598239 -1.118767,-2.717006 V 31.278589 c 0,-1.038856 0.319647,-1.917887 1.118767,-2.717006 0.719207,-0.719208 1.598239,-1.118767 2.717006,-1.118767 h 1.917886 v -5.75366 c 0,-2.157622 0.479472,-4.155421 1.598239,-6.073308 1.118767,-1.837974 2.557182,-3.276389 4.475069,-4.395156 C 25.764667,10.101925 27.762466,9.542541 30,9.542541 c 2.157623,0 4.155421,0.559384 6.073308,1.678151 1.837974,1.118767 3.276389,2.557182 4.395156,4.395156 1.118768,1.917887 1.678151,3.915686 1.678151,6.073308 v 5.75366 z m -8.310842,0 v -5.75366 c 0,-1.598239 -0.559384,-2.956742 -1.678151,-4.075509 C 32.956742,16.49488 31.598239,15.935496 30,15.935496 c -1.598239,0 -2.956742,0.559384 -4.075509,1.678151 -1.118767,1.118767 -1.67815,2.47727 -1.67815,4.075509 v 5.75366 z"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:40.91491318px;line-height:1.25;font-family:'Font Awesome 5 Free';-inkscape-font-specification:'Font Awesome 5 Free';stroke-width:0.78186888px"
id="path25" />
</g>
</svg>

432
privacy/static/description/index.html

@ -0,0 +1,432 @@
<?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>Data Privacy and Protection</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="data-privacy-and-protection">
<h1 class="title">Data Privacy and Protection</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="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.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/10.0/privacy"><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-10-0/data-protection-10-0-privacy"><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/10.0"><img alt="Try me on Runbot" src="https://img.shields.io/badge/runbot-Try%20me-875A7B.png" /></a></p>
<p>This application provides data protection and privacy feature,
to comply with regulations such as GDPR.</p>
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
<ul class="simple">
<li><a class="reference internal" href="#usage" id="id1">Usage</a></li>
<li><a class="reference internal" href="#bug-tracker" id="id2">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="id3">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="id4">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="id5">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="id6">Maintainers</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="usage">
<h1><a class="toc-backref" href="#id1">Usage</a></h1>
<p>To define data processing activities:</p>
<ol class="arabic simple">
<li>Go to <em>Privacy &gt; Master Data &gt; Activities</em> and create one.</li>
<li>Define the data processing activity using the provided tools.</li>
</ol>
<p>Consult your lawyer!</p>
</div>
<div class="section" id="bug-tracker">
<h1><a class="toc-backref" href="#id2">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%0Aversion:%2010.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="#id3">Credits</a></h1>
<div class="section" id="authors">
<h2><a class="toc-backref" href="#id4">Authors</a></h2>
<ul class="simple">
<li>Eficent</li>
<li>Tecnativa</li>
</ul>
</div>
<div class="section" id="contributors">
<h2><a class="toc-backref" href="#id5">Contributors</a></h2>
<ul class="simple">
<li>Miquel Raïch &lt;<a class="reference external" href="mailto:miquel.raich&#64;eficent.com">miquel.raich&#64;eficent.com</a>&gt;</li>
<li>Daniel Reis &lt;<a class="reference external" href="mailto:dreis.pt&#64;hotmail.com">dreis.pt&#64;hotmail.com</a>&gt;</li>
</ul>
</div>
<div class="section" id="maintainers">
<h2><a class="toc-backref" href="#id6">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/10.0/privacy">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>

51
privacy/views/data_protection_menu_view.xml

@ -0,0 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2018 Eficent Business and IT Consulting Services S.L.
License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl-3.0) -->
<data>
<record id="action_data_protection_partner_form" model="ir.actions.act_window">
<field name="name">Partners</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">res.partner</field>
<field name="view_type">form</field>
<field name="view_mode">kanban,tree,form</field>
</record>
<menuitem id="parent_menu_data_protection"
name="Privacy"
groups="group_data_protection_user"
web_icon="privacy,static/description/icon.png"
/>
<menuitem id="menu_data_protection_master_data"
name="Master Data"
parent="parent_menu_data_protection"
groups="group_data_protection_user"
sequence="10"
/>
<menuitem id="menu_data_protection_partner"
name="Partners"
parent="menu_data_protection_master_data"
action="action_data_protection_partner_form"
sequence="1010"
/>
<menuitem id="menu_data_protection_transaction"
name="Transactions"
parent="parent_menu_data_protection"
groups="group_data_protection_user"
sequence="20"
/>
<menuitem id="menu_data_protection_report"
name="Reports"
parent="parent_menu_data_protection"
groups="group_data_protection_user"
sequence="30"
/>
<menuitem id="menu_data_protection_setting"
name="Settings"
parent="parent_menu_data_protection"
groups="group_data_protection_manager"
sequence="90"
/>
</data>

127
privacy/views/privacy_activity_view.xml

@ -0,0 +1,127 @@
<?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="activity_form">
<field name="name">Privacy Activity Form</field>
<field name="model">privacy.activity</field>
<field name="arch" type="xml">
<form>
<header>
<!-- Placeholder for submodules -->
</header>
<sheet>
<div class="oe_button_box" name="button_box">
<button
class="oe_stat_button"
icon="fa-archive"
name="toggle_active"
type="object"
>
<field
name="active"
options='{"terminology": "archive"}'
widget="boolean_button"
/>
</button>
</div>
<div class="oe_title">
<label for="name" class="oe_edit_only"/>
<h1><field name="name"/></h1>
</div>
<group name="basic">
<group name="owners">
<field name="controller_id"/>
<field
name="processor_ids"
widget="many2many_tags"
/>
</group>
<group name="subjects">
<field name="subject_find"/>
<field
name="subject_domain"
widget="char_domain"
options='{"model": "res.partner"}'
attrs='{"required": [("subject_find", "=", True)],
"invisible": [("subject_find", "=", False)]}'
/>
</group>
</group>
<notebook string="Details" name="advanced">
<page string="Description">
<group>
<field name="description" nolabel="1"/>
</group>
</page>
</notebook>
</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="activity_tree">
<field name="name">Privacy Activity Tree</field>
<field name="model">privacy.activity</field>
<field name="arch" type="xml">
<tree>
<field name="name"/>
<field name="controller_id"/>
<field name="processor_ids"/>
</tree>
</field>
</record>
<record model="ir.ui.view" id="activity_search">
<field name="name">Privacy Activity Search</field>
<field name="model">privacy.activity</field>
<field name="arch" type="xml">
<search>
<field name="name"/>
<field name="controller_id"/>
<field name="processor_ids"/>
<separator/>
<filter
string="Archived"
name="inactive"
domain="[('active', '=', False)]"
/>
<separator/>
<group string="Group By" name="groupby">
<filter
name="controller_id_groupby"
string="Controller"
context="{'group_by': 'controller_id'}"
/>
</group>
</search>
</field>
</record>
<record id="activity_action" model="ir.actions.act_window">
<field name="name">Activities</field>
<field name="res_model">privacy.activity</field>
<field name="view_mode">tree,form</field>
<field name="help" type="html">
<p class="oe_view_nocontent_create">
Click to add a data processing activity.
</p><p>
Data processing activities define why, how and what you do
with subjects' personal data.
</p>
</field>
</record>
<menuitem
action="activity_action"
groups="group_data_protection_user"
id="menu_privacy_activity"
parent="menu_data_protection_master_data"
/>
</data>

173
privacy_consent/README.rst

@ -0,0 +1,173 @@
=================
Privacy - Consent
=================
.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |badge1| image:: https://img.shields.io/badge/maturity-Production%2FStable-green.png
:target: https://odoo-community.org/page/development-status
:alt: Production/Stable
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fdata--protection-lightgray.png?logo=github
:target: https://github.com/OCA/data-protection/tree/10.0/privacy_consent
:alt: OCA/data-protection
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/data-protection-10-0/data-protection-10-0-privacy_consent
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
:target: https://runbot.odoo-community.org/runbot/263/10.0
:alt: Try me on Runbot
|badge1| |badge2| |badge3| |badge4| |badge5|
This module allows the user to define a set of subjects (partners)
affected by any data processing activity, and establish
a process to ask them for consent to include them in that activity.
For those that need explicit consent as a lawfulness base for personal data
processing, as required by GDPR (article 6.1.a), this module provides the
needed tools to automate it.
**Table of contents**
.. contents::
:local:
Installation
============
You may want to install, along with this module, one of OCA's
``mail_tracking`` module collection, such as ``mail_tracking_mailgun``, so
you can provide more undeniable proof that some consent request was sent, and
to whom.
However, the most important proof to provide is the answer itself (more than
the question), and this addon provides enough tooling for that.
Multi-database instances
~~~~~~~~~~~~~~~~~~~~~~~~
To enable multi-database support, you must load this addon as a server-wide
addon. Example command to boot Odoo::
odoo-bin --load=web,privacy_consent
Usage
=====
New options for data processing activities:
#. Go to *Privacy > Master Data > Activities* and create one.
#. Give it a name, such as *Sending mass mailings to customers*.
#. Go to tab *Consent* and choose one option in *Ask subjects for consent*:
* *Manual* tells the activity that you will want to create and send the
consent requests manually, and only provides some helpers for you to
be able to batch-generate them.
* *Automatic* enables this module's full power: send all consent requests
to selected partners automatically, every day and under your demand.
#. When you do this, all the consent-related options appear. Configure them:
* A smart button tells you how many consents have been generated, and lets you
access them.
* Choose one *Email template* to send to subjects. This email itself is what
asks for consent, and it gets recorded, to serve as a proof that it was sent.
The module provides a default template that should be good for most usage
cases; and if you create one directly from that field, some good defaults
are provided for your comfortability.
* *Subjects filter* defines what partners will be elegible for inclusion in
this data processing activity.
* You can enable *Accepted by default* if you want to assume subjects
accepted their data processing. You should possibly consult your
lawyer to use this.
* You can choose a *Server action* (developer mode only) that will
be executed whenever a new non-draft consent request is created,
or when its acceptance status changes.
This module supplies a server action by default, called
*Update partner's opt out*, that syncs the acceptance status with the
partner's *Elegible for mass mailings* option.
#. Click on *Generate consent requests* link to create new consent requests.
* If you chose *Manual* mode, all missing consent request are created as
drafts, and nothing else is done now.
* If you chose *Automatic* mode, also those 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:%2010.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
Contributors
~~~~~~~~~~~~
* `Tecnativa <https://www.tecnativa.com>`_:
* Jairo Llopis
Maintainers
~~~~~~~~~~~
This module is maintained by the OCA.
.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org
OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.
This module is part of the `OCA/data-protection <https://github.com/OCA/data-protection/tree/10.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

29
privacy_consent/__manifest__.py

@ -0,0 +1,29 @@
# -*- coding: utf-8 -*-
# Copyright 2018 Tecnativa - Jairo Llopis
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
{
"name": "Privacy - Consent",
"summary": "Allow people to explicitly accept or reject inclusion "
"in some activity, GDPR compliant",
"version": "10.0.1.0.0",
"development_status": "Production/Stable",
"category": "Privacy",
"website": "https://github.com/OCA/management-activity",
"author": "Tecnativa, Odoo Community Association (OCA)",
"license": "AGPL-3",
"application": False,
"installable": True,
"depends": [
"privacy",
],
"data": [
"security/ir.model.access.csv",
"data/ir_actions_server.xml",
"data/ir_cron.xml",
"data/mail.xml",
"templates/form.xml",
"views/privacy_consent.xml",
"views/privacy_activity.xml",
"views/res_partner.xml",
],
}

1
privacy_consent/controllers/__init__.py

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

47
privacy_consent/controllers/main.py

@ -0,0 +1,47 @@
# -*- coding: utf-8 -*-
# Copyright 2018 Tecnativa - Jairo Llopis
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from datetime import datetime
from werkzeug.exceptions import NotFound
from odoo.http import Controller, request, route
from odoo.addons.web.controllers.main import ensure_db
class ConsentController(Controller):
@route("/privacy/consent/<any(accept,reject):choice>/"
"<int:consent_id>/<token>",
type="http", auth="none", website=True)
def consent(self, choice, consent_id, token, *args, **kwargs):
"""Process user's consent acceptance or rejection."""
ensure_db()
try:
# If there's a website, we need a user to render the template
request.uid = request.website.user_id.id
except AttributeError:
# If there's no website, the default is OK
pass
consent = request.env["privacy.consent"] \
.with_context(subject_answering=True) \
.sudo().browse(consent_id)
if not (consent.exists() and consent._token() == token):
raise NotFound
if consent.partner_id.lang:
consent = consent.with_context(lang=consent.partner_id.lang)
request.context = consent.env.context
consent.action_answer(choice == "accept", self._metadata())
return request.render("privacy_consent.form", {
"consent": consent,
})
def _metadata(self):
return (u"User agent: {}\n"
u"Remote IP: {}\n"
u"Date and time: {:%Y-%m-%d %H:%M:%S}").format(
request.httprequest.environ.get("HTTP_USER_AGENT"),
request.httprequest.environ.get("REMOTE_ADDRESS"),
datetime.now(),
)

23
privacy_consent/data/ir_actions_server.xml

@ -0,0 +1,23 @@
<?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="update_opt_out" model="ir.actions.server">
<field name="name">Update partner's opt out</field>
<field name="model_id" ref="model_privacy_consent"/>
<field name="crud_model_id" ref="base.model_res_partner"/>
<field name="state">object_write</field>
<field name="use_write">expression</field>
<field name="write_expression">record.partner_id</field>
</record>
<record id="update_opt_out_line_1" model="ir.server.object.lines">
<field name="server_id" ref="update_opt_out"/>
<field name="col1" ref="mail.field_res_partner_opt_out"/>
<field name="type">equation</field>
<field name="value">not record.accepted</field>
</record>
</data>

16
privacy_consent/data/ir_cron.xml

@ -0,0 +1,16 @@
<?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="cron_auto_consent" model="ir.cron">
<field name="name">Request automatic data processing consents</field>
<field name="model">privacy.activity</field>
<field name="function">_cron_new_consents</field>
<field name="interval_number">1</field>
<field name="interval_type">work_days</field>
<field name="numbercall">-1</field>
</record>
</data>

158
privacy_consent/data/mail.xml

@ -0,0 +1,158 @@
<?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>

539
privacy_consent/i18n/de.po

@ -0,0 +1,539 @@
# 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: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_active
msgid "Active"
msgstr "Aktiv"
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_activity_id
#: model:ir.ui.view,arch_db:privacy_consent.consent_search
msgid "Activity"
msgstr "Aktivität"
#. module: privacy_consent
#: selection:privacy.consent,state:0
msgid "Answered"
msgstr "Beantwortet"
#. module: privacy_consent
#: model:ir.ui.view,arch_db:privacy_consent.consent_search
msgid "Archived"
msgstr "Archiviert"
#. module: privacy_consent
#: model: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
#: 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:ir.ui.view,arch_db:privacy_consent.activity_form
msgid "Consent"
msgstr "Einwilligung"
#. 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.model.fields,field_description:privacy_consent.field_privacy_activity_consent_template_default_body_html
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
msgid "Consent template default subject"
msgstr "Standardmäßige Einverständniserklärung Betroffener"
#. module: privacy_consent
#: model:ir.actions.act_window,name:privacy_consent.consent_action
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_count
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_ids
#: model:ir.model.fields,field_description:privacy_consent.field_res_partner_privacy_consent_count
#: model:ir.model.fields,field_description:privacy_consent.field_res_users_privacy_consent_count
#: model:ir.ui.menu,name:privacy_consent.menu_privacy_consent
msgid "Consents"
msgstr "Einwilligungen"
#. 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.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: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:ir.ui.view,arch_db:privacy_consent.consent_search
msgid "Group By"
msgstr "Gruppieren nach"
#. module: privacy_consent
#: model:ir.ui.view,arch_db:privacy_consent.form
msgid "Hello,"
msgstr "Hallo"
#. module: privacy_consent
#: model: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: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.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___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_last_metadata
msgid "Last metadata"
msgstr "Letzte Metadaten"
#. module: privacy_consent
#: selection:privacy.activity,consent_required:0
msgid "Manually"
msgstr "Manuell"
#. module: privacy_consent
#: model:ir.model.fields,help:privacy_consent.field_privacy_consent_last_metadata
msgid "Metadata from the last acceptance or rejection by the subject"
msgstr "Metadaten aus der letzten Annahme oder Ablehnung durch den Betroffenen"
#. module: privacy_consent
#: code:addons/privacy_consent/models/mail_template.py:25
#, python-format
msgid ""
"Missing privacy consent link placeholders. You need at least these two "
"links:\n"
"<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,name:privacy_consent.model_mail_mail
msgid "Outgoing Mails"
msgstr "Ausgehende Mails"
#. module: privacy_consent
#: model:ir.model,name:privacy_consent.model_res_partner
msgid "Partner"
msgstr "Partner"
#. module: privacy_consent
#: model:mail.message.subtype,description:privacy_consent.mt_activity_acceptance_changed
msgid "Privacy consent request acceptance status changed"
msgstr ""
"Der Akzeptanzstatus der Anfrage 'Einwilligung zum Datenschutz' wurde "
"geändert."
#. module: privacy_consent
#: model:mail.message.subtype,description:privacy_consent.mt_activity_consent_new
#: model:mail.message.subtype,description:privacy_consent.mt_consent_consent_new
msgid "Privacy consent request created"
msgstr "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
#: code:addons/privacy_consent/models/privacy_activity.py:100
#, python-format
msgid "Require consent is available only for subjects in current database."
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,help:privacy_consent.field_privacy_activity_server_action_id
msgid ""
"Run this action when a new consent request is created or its acceptance "
"status is updated."
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_server_action_id
msgid "Server action"
msgstr "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: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:92
#, python-format
msgid "Specify a mail template to ask automated consent."
msgstr ""
"Wählen Sie eine E-Mail-Vorlage aus, um eine automatische Einwilligung "
"einzuholen."
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_state
#: model:ir.ui.view,arch_db:privacy_consent.consent_search
msgid "State"
msgstr "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.ui.view,arch_db:privacy_consent.form
msgid "Thank you!"
msgstr "Vielen Dank."
#. module: privacy_consent
#: model:ir.ui.view,arch_db:privacy_consent.form
msgid "Thanks for your response."
msgstr "Vielen Dank für Ihre Antwort."
#. module: privacy_consent
#: model: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.actions.server,name:privacy_consent.update_opt_out
msgid "Update partner's opt out"
msgstr ""
#. module: privacy_consent
#: model:ir.ui.view,arch_db:privacy_consent.form
msgid ""
"We asked you to authorize us to process your data in this data processing "
"activity:"
msgstr ""
#. module: privacy_consent
#: model:ir.ui.view,arch_db:privacy_consent.form
msgid "We have recorded this action on your side."
msgstr ""
#. module: privacy_consent
#: model:ir.ui.view,arch_db:privacy_consent.form
msgid "You have <b class=\"text-danger\">rejected</b> such processing."
msgstr ""
"Du hast diese Verarbeitungstätigkeit <b class=\"text-danger\">abgelehnt</b>."
#. module: privacy_consent
#: model: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>."

663
privacy_consent/i18n/es.po

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

519
privacy_consent/i18n/fr.po

@ -0,0 +1,519 @@
# 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"
"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:ir.ui.view,arch_db:privacy_consent.consent_search
msgid "Accepted"
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_default_consent
msgid "Accepted by default"
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_active
msgid "Active"
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_activity_id
#: model:ir.ui.view,arch_db:privacy_consent.consent_search
msgid "Activity"
msgstr ""
#. module: privacy_consent
#: selection:privacy.consent,state:0
msgid "Answered"
msgstr ""
#. module: privacy_consent
#: model:ir.ui.view,arch_db:privacy_consent.consent_search
msgid "Archived"
msgstr ""
#. module: privacy_consent
#: model:ir.ui.view,arch_db:privacy_consent.consent_form
msgid "Ask for consent"
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_required
msgid "Ask subjects for consent"
msgstr ""
#. module: privacy_consent
#: selection:privacy.activity,consent_required:0
msgid "Automatically"
msgstr ""
#. module: privacy_consent
#: selection:privacy.consent,state:0
msgid "Awaiting response"
msgstr ""
#. module: privacy_consent
#: model:ir.ui.view,arch_db:privacy_consent.activity_form
msgid "Consent"
msgstr ""
#. module: privacy_consent
#: model:ir.model,name:privacy_consent.model_privacy_consent
msgid "Consent of data processing"
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_template_default_body_html
msgid "Consent template default body html"
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_template_default_subject
msgid "Consent template default subject"
msgstr ""
#. module: privacy_consent
#: model:ir.actions.act_window,name:privacy_consent.consent_action
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_count
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_ids
#: model:ir.model.fields,field_description:privacy_consent.field_res_partner_privacy_consent_count
#: model:ir.model.fields,field_description:privacy_consent.field_res_users_privacy_consent_count
#: model:ir.ui.menu,name:privacy_consent.menu_privacy_consent
msgid "Consents"
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_create_uid
msgid "Created by"
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_create_date
msgid "Created on"
msgstr ""
#. module: privacy_consent
#: model:ir.model,name:privacy_consent.model_privacy_activity
msgid "Data processing activities"
msgstr ""
#. module: privacy_consent
#: model:mail.template,subject:privacy_consent.template_consent
msgid ""
"Data processing consent request for ${object.activity_id.display_name|safe}"
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_display_name
msgid "Display Name"
msgstr ""
#. module: privacy_consent
#: selection:privacy.consent,state:0
msgid "Draft"
msgstr ""
#. module: privacy_consent
#: sql_constraint:privacy.consent:0
msgid "Duplicated partner in this data processing activity"
msgstr ""
#. module: privacy_consent
#: model:ir.model,name:privacy_consent.model_mail_template
msgid "Email Templates"
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_template_id
msgid "Email template"
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,help:privacy_consent.field_privacy_activity_consent_template_id
msgid ""
"Email to be sent to subjects to ask for consent. A good template should "
"include details about the current consent request status, how to change it, "
"and where to get more information."
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,help:privacy_consent.field_privacy_activity_consent_required
msgid ""
"Enable if you need to track any kind of consent from the affected subjects"
msgstr ""
#. module: privacy_consent
#: model:ir.ui.view,arch_db:privacy_consent.activity_form
msgid "Generate and enqueue missing consent requests"
msgstr ""
#. module: privacy_consent
#: model:ir.ui.view,arch_db:privacy_consent.activity_form
msgid "Generate missing draft consent requests"
msgstr ""
#. module: privacy_consent
#: code:addons/privacy_consent/models/privacy_activity.py:139
#, python-format
msgid "Generated consents"
msgstr ""
#. module: privacy_consent
#: model:ir.ui.view,arch_db:privacy_consent.consent_search
msgid "Group By"
msgstr ""
#. module: privacy_consent
#: model:ir.ui.view,arch_db:privacy_consent.form
msgid "Hello,"
msgstr ""
#. module: privacy_consent
#: model:ir.ui.view,arch_db:privacy_consent.form
msgid "I <b>accept</b> this processing of my data"
msgstr ""
#. module: privacy_consent
#: model: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.ui.view,arch_db:privacy_consent.form
msgid "If it was a mistake, you can undo it here:"
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,help:privacy_consent.field_privacy_consent_accepted
msgid ""
"Indicates current acceptance status, which can come from subject's last "
"answer, or from the default specified in the related data processing "
"activity."
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent___last_update
msgid "Last Modified on"
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_write_uid
msgid "Last Updated by"
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_write_date
msgid "Last Updated on"
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_last_metadata
msgid "Last metadata"
msgstr ""
#. module: privacy_consent
#: selection:privacy.activity,consent_required:0
msgid "Manually"
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,help:privacy_consent.field_privacy_consent_last_metadata
msgid "Metadata from the last acceptance or rejection by the subject"
msgstr ""
#. module: privacy_consent
#: code:addons/privacy_consent/models/mail_template.py:25
#, python-format
msgid ""
"Missing privacy consent link placeholders. You need at least these two "
"links:\n"
"<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,name:privacy_consent.model_mail_mail
msgid "Outgoing Mails"
msgstr ""
#. module: privacy_consent
#: model:ir.model,name:privacy_consent.model_res_partner
msgid "Partner"
msgstr ""
#. module: privacy_consent
#: model:mail.message.subtype,description:privacy_consent.mt_activity_acceptance_changed
msgid "Privacy consent request acceptance status changed"
msgstr ""
#. module: privacy_consent
#: model:mail.message.subtype,description:privacy_consent.mt_activity_consent_new
#: model:mail.message.subtype,description:privacy_consent.mt_consent_consent_new
msgid "Privacy consent request created"
msgstr ""
#. module: privacy_consent
#: model:mail.message.subtype,description:privacy_consent.mt_activity_state_changed
#: model:mail.message.subtype,description:privacy_consent.mt_consent_state_changed
msgid "Privacy consent request state changed"
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,help:privacy_consent.field_res_partner_privacy_consent_count
#: model:ir.model.fields,help:privacy_consent.field_res_users_privacy_consent_count
msgid "Privacy consent requests amount"
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_res_partner_privacy_consent_ids
#: model:ir.model.fields,field_description:privacy_consent.field_res_users_privacy_consent_ids
msgid "Privacy consents"
msgstr ""
#. module: privacy_consent
#: code:addons/privacy_consent/models/privacy_activity.py:100
#, python-format
msgid "Require consent is available only for subjects in current database."
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,help:privacy_consent.field_privacy_activity_server_action_id
msgid ""
"Run this action when a new consent request is created or its acceptance "
"status is updated."
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_server_action_id
msgid "Server action"
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,help:privacy_consent.field_privacy_activity_default_consent
msgid "Should we assume the subject has accepted if we receive no response?"
msgstr ""
#. module: privacy_consent
#: model:ir.ui.view,arch_db:privacy_consent.form
msgid "Sincerely,<br/>"
msgstr ""
#. module: privacy_consent
#: code:addons/privacy_consent/models/privacy_activity.py:92
#, python-format
msgid "Specify a mail template to ask automated consent."
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_state
#: model:ir.ui.view,arch_db:privacy_consent.consent_search
msgid "State"
msgstr ""
#. module: privacy_consent
#: model:mail.message.subtype,name:privacy_consent.mt_activity_state_changed
#: model:mail.message.subtype,name:privacy_consent.mt_consent_state_changed
msgid "State Changed"
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_partner_id
msgid "Subject"
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,help:privacy_consent.field_privacy_consent_partner_id
msgid "Subject asked for consent."
msgstr ""
#. module: privacy_consent
#: model:ir.ui.view,arch_db:privacy_consent.form
msgid "Thank you!"
msgstr ""
#. module: privacy_consent
#: model:ir.ui.view,arch_db:privacy_consent.form
msgid "Thanks for your response."
msgstr ""
#. module: privacy_consent
#: model:ir.ui.view,arch_db:privacy_consent.activity_form
msgid "This could enqueue many consent emails, are you sure to proceed?"
msgstr ""
#. module: privacy_consent
#: model:ir.actions.server,name:privacy_consent.update_opt_out
msgid "Update partner's opt out"
msgstr ""
#. module: privacy_consent
#: model:ir.ui.view,arch_db:privacy_consent.form
msgid ""
"We asked you to authorize us to process your data in this data processing "
"activity:"
msgstr ""
#. module: privacy_consent
#: model:ir.ui.view,arch_db:privacy_consent.form
msgid "We have recorded this action on your side."
msgstr ""
#. module: privacy_consent
#: model:ir.ui.view,arch_db:privacy_consent.form
msgid "You have <b class=\"text-danger\">rejected</b> such processing."
msgstr ""
#. module: privacy_consent
#: model:ir.ui.view,arch_db:privacy_consent.form
msgid "You have <b class=\"text-success\">accepted</b> such processing."
msgstr ""

482
privacy_consent/i18n/privacy_consent.pot

@ -0,0 +1,482 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * privacy_consent
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 10.0\n"
"Report-Msgid-Bugs-To: \n"
"Last-Translator: <>\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:ir.ui.view,arch_db:privacy_consent.consent_search
msgid "Accepted"
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_default_consent
msgid "Accepted by default"
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_active
msgid "Active"
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_activity_id
#: model:ir.ui.view,arch_db:privacy_consent.consent_search
msgid "Activity"
msgstr ""
#. module: privacy_consent
#: selection:privacy.consent,state:0
msgid "Answered"
msgstr ""
#. module: privacy_consent
#: model:ir.ui.view,arch_db:privacy_consent.consent_search
msgid "Archived"
msgstr ""
#. module: privacy_consent
#: model:ir.ui.view,arch_db:privacy_consent.consent_form
msgid "Ask for consent"
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_required
msgid "Ask subjects for consent"
msgstr ""
#. module: privacy_consent
#: selection:privacy.activity,consent_required:0
msgid "Automatically"
msgstr ""
#. module: privacy_consent
#: selection:privacy.consent,state:0
msgid "Awaiting response"
msgstr ""
#. module: privacy_consent
#: model:ir.ui.view,arch_db:privacy_consent.activity_form
msgid "Consent"
msgstr ""
#. module: privacy_consent
#: model:ir.model,name:privacy_consent.model_privacy_consent
msgid "Consent of data processing"
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_template_default_body_html
msgid "Consent template default body html"
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_template_default_subject
msgid "Consent template default subject"
msgstr ""
#. module: privacy_consent
#: model:ir.actions.act_window,name:privacy_consent.consent_action
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_count
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_ids
#: model:ir.model.fields,field_description:privacy_consent.field_res_partner_privacy_consent_count
#: model:ir.model.fields,field_description:privacy_consent.field_res_users_privacy_consent_count
#: model:ir.ui.menu,name:privacy_consent.menu_privacy_consent
msgid "Consents"
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_create_uid
msgid "Created by"
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_create_date
msgid "Created on"
msgstr ""
#. module: privacy_consent
#: model:ir.model,name:privacy_consent.model_privacy_activity
msgid "Data processing activities"
msgstr ""
#. module: privacy_consent
#: model:mail.template,subject:privacy_consent.template_consent
msgid "Data processing consent request for ${object.activity_id.display_name|safe}"
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_display_name
msgid "Display Name"
msgstr ""
#. module: privacy_consent
#: selection:privacy.consent,state:0
msgid "Draft"
msgstr ""
#. module: privacy_consent
#: sql_constraint:privacy.consent:0
msgid "Duplicated partner in this data processing activity"
msgstr ""
#. module: privacy_consent
#: model:ir.model,name:privacy_consent.model_mail_template
msgid "Email Templates"
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_template_id
msgid "Email template"
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,help:privacy_consent.field_privacy_activity_consent_template_id
msgid "Email to be sent to subjects to ask for consent. A good template should include details about the current consent request status, how to change it, and where to get more information."
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,help:privacy_consent.field_privacy_activity_consent_required
msgid "Enable if you need to track any kind of consent from the affected subjects"
msgstr ""
#. module: privacy_consent
#: model:ir.ui.view,arch_db:privacy_consent.activity_form
msgid "Generate and enqueue missing consent requests"
msgstr ""
#. module: privacy_consent
#: model:ir.ui.view,arch_db:privacy_consent.activity_form
msgid "Generate missing draft consent requests"
msgstr ""
#. module: privacy_consent
#: code:addons/privacy_consent/models/privacy_activity.py:139
#, python-format
msgid "Generated consents"
msgstr ""
#. module: privacy_consent
#: model:ir.ui.view,arch_db:privacy_consent.consent_search
msgid "Group By"
msgstr ""
#. module: privacy_consent
#: model:ir.ui.view,arch_db:privacy_consent.form
msgid "Hello,"
msgstr ""
#. module: privacy_consent
#: model:ir.ui.view,arch_db:privacy_consent.form
msgid "I <b>accept</b> this processing of my data"
msgstr ""
#. module: privacy_consent
#: model: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.ui.view,arch_db:privacy_consent.form
msgid "If it was a mistake, you can undo it here:"
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,help:privacy_consent.field_privacy_consent_accepted
msgid "Indicates current acceptance status, which can come from subject's last answer, or from the default specified in the related data processing activity."
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent___last_update
msgid "Last Modified on"
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_write_uid
msgid "Last Updated by"
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_write_date
msgid "Last Updated on"
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_last_metadata
msgid "Last metadata"
msgstr ""
#. module: privacy_consent
#: selection:privacy.activity,consent_required:0
msgid "Manually"
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,help:privacy_consent.field_privacy_consent_last_metadata
msgid "Metadata from the last acceptance or rejection by the subject"
msgstr ""
#. module: privacy_consent
#: code:addons/privacy_consent/models/mail_template.py:25
#, python-format
msgid "Missing privacy consent link placeholders. You need at least these two links:\n"
"<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,name:privacy_consent.model_mail_mail
msgid "Outgoing Mails"
msgstr ""
#. module: privacy_consent
#: model:ir.model,name:privacy_consent.model_res_partner
msgid "Partner"
msgstr ""
#. module: privacy_consent
#: model:mail.message.subtype,description:privacy_consent.mt_activity_acceptance_changed
msgid "Privacy consent request acceptance status changed"
msgstr ""
#. module: privacy_consent
#: model:mail.message.subtype,description:privacy_consent.mt_activity_consent_new
#: model:mail.message.subtype,description:privacy_consent.mt_consent_consent_new
msgid "Privacy consent request created"
msgstr ""
#. module: privacy_consent
#: model:mail.message.subtype,description:privacy_consent.mt_activity_state_changed
#: model:mail.message.subtype,description:privacy_consent.mt_consent_state_changed
msgid "Privacy consent request state changed"
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,help:privacy_consent.field_res_partner_privacy_consent_count
#: model:ir.model.fields,help:privacy_consent.field_res_users_privacy_consent_count
msgid "Privacy consent requests amount"
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_res_partner_privacy_consent_ids
#: model:ir.model.fields,field_description:privacy_consent.field_res_users_privacy_consent_ids
msgid "Privacy consents"
msgstr ""
#. module: privacy_consent
#: code:addons/privacy_consent/models/privacy_activity.py:100
#, python-format
msgid "Require consent is available only for subjects in current database."
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,help:privacy_consent.field_privacy_activity_server_action_id
msgid "Run this action when a new consent request is created or its acceptance status is updated."
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_server_action_id
msgid "Server action"
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,help:privacy_consent.field_privacy_activity_default_consent
msgid "Should we assume the subject has accepted if we receive no response?"
msgstr ""
#. module: privacy_consent
#: model:ir.ui.view,arch_db:privacy_consent.form
msgid "Sincerely,<br/>"
msgstr ""
#. module: privacy_consent
#: code:addons/privacy_consent/models/privacy_activity.py:92
#, python-format
msgid "Specify a mail template to ask automated consent."
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_state
#: model:ir.ui.view,arch_db:privacy_consent.consent_search
msgid "State"
msgstr ""
#. module: privacy_consent
#: model:mail.message.subtype,name:privacy_consent.mt_activity_state_changed
#: model:mail.message.subtype,name:privacy_consent.mt_consent_state_changed
msgid "State Changed"
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_partner_id
msgid "Subject"
msgstr ""
#. module: privacy_consent
#: model:ir.model.fields,help:privacy_consent.field_privacy_consent_partner_id
msgid "Subject asked for consent."
msgstr ""
#. module: privacy_consent
#: model:ir.ui.view,arch_db:privacy_consent.form
msgid "Thank you!"
msgstr ""
#. module: privacy_consent
#: model:ir.ui.view,arch_db:privacy_consent.form
msgid "Thanks for your response."
msgstr ""
#. module: privacy_consent
#: model:ir.ui.view,arch_db:privacy_consent.activity_form
msgid "This could enqueue many consent emails, are you sure to proceed?"
msgstr ""
#. module: privacy_consent
#: model:ir.actions.server,name:privacy_consent.update_opt_out
msgid "Update partner's opt out"
msgstr ""
#. module: privacy_consent
#: model:ir.ui.view,arch_db:privacy_consent.form
msgid "We asked you to authorize us to process your data in this data processing activity:"
msgstr ""
#. module: privacy_consent
#: model:ir.ui.view,arch_db:privacy_consent.form
msgid "We have recorded this action on your side."
msgstr ""
#. module: privacy_consent
#: model:ir.ui.view,arch_db:privacy_consent.form
msgid "You have <b class=\"text-danger\">rejected</b> such processing."
msgstr ""
#. module: privacy_consent
#: model:ir.ui.view,arch_db:privacy_consent.form
msgid "You have <b class=\"text-success\">accepted</b> such processing."
msgstr ""

653
privacy_consent/i18n/pt.po

@ -0,0 +1,653 @@
msgid ""
msgstr ""
"Project-Id-Version: Portuguese (data-protection-10.0)\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-05-13 17:04+0000\n"
"PO-Revision-Date: 2018-12-15 21:58+0000\n"
"Last-Translator: alvarorib <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:ir.ui.view,arch_db:privacy_consent.consent_search
msgid "Accepted"
msgstr "Aceite"
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_default_consent
msgid "Accepted by default"
msgstr "Aceite por defeito"
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_active
msgid "Active"
msgstr "Ativo"
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_activity_id
#: model:ir.ui.view,arch_db:privacy_consent.consent_search
msgid "Activity"
msgstr "Atividade"
#. module: privacy_consent
#: selection:privacy.consent,state:0
msgid "Answered"
msgstr "Respondido"
#. module: privacy_consent
#: model:ir.ui.view,arch_db:privacy_consent.consent_search
msgid "Archived"
msgstr "Arquivado"
#. module: privacy_consent
#: model:ir.ui.view,arch_db:privacy_consent.consent_form
msgid "Ask for consent"
msgstr "Pedir consentimento"
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_required
msgid "Ask subjects for consent"
msgstr "Solicitar consentimento aos titulares"
#. module: privacy_consent
#: selection:privacy.activity,consent_required:0
msgid "Automatically"
msgstr "Automaticamente"
#. module: privacy_consent
#: selection:privacy.consent,state:0
msgid "Awaiting response"
msgstr "À espera de resposta"
#. module: privacy_consent
#: model:ir.ui.view,arch_db:privacy_consent.activity_form
msgid "Consent"
msgstr "Consentimento"
#. module: privacy_consent
#: model:ir.model,name:privacy_consent.model_privacy_consent
msgid "Consent of data processing"
msgstr "Consentimento de processamento de dados"
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_template_default_body_html
msgid "Consent template default body html"
msgstr "Corpo predefinido HTML do modelo de consentimento"
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_template_default_subject
msgid "Consent template default subject"
msgstr "Modelo predefinido de consentimento do titular"
#. module: privacy_consent
#: model:ir.actions.act_window,name:privacy_consent.consent_action
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_count
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_ids
#: model:ir.model.fields,field_description:privacy_consent.field_res_partner_privacy_consent_count
#: model:ir.model.fields,field_description:privacy_consent.field_res_users_privacy_consent_count
#: model:ir.ui.menu,name:privacy_consent.menu_privacy_consent
msgid "Consents"
msgstr "Consentimentos"
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_create_uid
msgid "Created by"
msgstr "Criado por"
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_create_date
msgid "Created on"
msgstr "Criado em"
#. module: privacy_consent
#: model:ir.model,name:privacy_consent.model_privacy_activity
msgid "Data processing activities"
msgstr "Atividades de processamento de dados"
#. module: privacy_consent
#: model:mail.template,subject:privacy_consent.template_consent
msgid ""
"Data processing consent request for ${object.activity_id.display_name|safe}"
msgstr ""
"Processamento de dados de pedidos de consentimento para ${object.activity_id."
"display_name|safe}"
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_display_name
msgid "Display Name"
msgstr "Nome a Exibir"
#. module: privacy_consent
#: selection:privacy.consent,state:0
msgid "Draft"
msgstr "Rascunho"
#. module: privacy_consent
#: sql_constraint:privacy.consent:0
msgid "Duplicated partner in this data processing activity"
msgstr "Parceiro duplicado nesta atividade de processamento de dados"
#. module: privacy_consent
#: model:ir.model,name:privacy_consent.model_mail_template
msgid "Email Templates"
msgstr "Modelos de E-mail"
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_consent_template_id
msgid "Email template"
msgstr "Modelo de Email"
#. module: privacy_consent
#: model:ir.model.fields,help:privacy_consent.field_privacy_activity_consent_template_id
msgid ""
"Email to be sent to subjects to ask for consent. A good template should "
"include details about the current consent request status, how to change it, "
"and where to get more information."
msgstr ""
"Email a ser enviado para os titulares a pedir o consentimento. Um bom modelo "
"deve incluir detalhes sobre o estado atual do pedido de consentimento, como "
"alterá-lo, e onde obter ais informação."
#. module: privacy_consent
#: model:ir.model.fields,help:privacy_consent.field_privacy_activity_consent_required
msgid ""
"Enable if you need to track any kind of consent from the affected subjects"
msgstr ""
"Ativar se necessita seguir qualquer espécie de consentimento dos titulares "
"afetados"
#. module: privacy_consent
#: model:ir.ui.view,arch_db:privacy_consent.activity_form
#, fuzzy
msgid "Generate and enqueue missing consent requests"
msgstr "Gerar e enviar pedidos de consentimento em falta"
#. module: privacy_consent
#: model:ir.ui.view,arch_db:privacy_consent.activity_form
msgid "Generate missing draft consent requests"
msgstr "Gerar pedidos de consentimento em rascunho em falta"
#. module: privacy_consent
#: code:addons/privacy_consent/models/privacy_activity.py:139
#, python-format
msgid "Generated consents"
msgstr "Consentimentos gerados"
#. module: privacy_consent
#: model:ir.ui.view,arch_db:privacy_consent.consent_search
msgid "Group By"
msgstr "Agrupar Por"
#. module: privacy_consent
#: model:ir.ui.view,arch_db:privacy_consent.form
msgid "Hello,"
msgstr "Olá"
#. module: privacy_consent
#: model:ir.ui.view,arch_db:privacy_consent.form
msgid "I <b>accept</b> this processing of my data"
msgstr "Eu <b>aceito</b> este processamento dos meus dados"
#. module: privacy_consent
#: model: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.ui.view,arch_db:privacy_consent.form
msgid "If it was a mistake, you can undo it here:"
msgstr "Se foi um lapso, pode revertê-lo aqui:"
#. module: privacy_consent
#: model:ir.model.fields,help:privacy_consent.field_privacy_consent_accepted
msgid ""
"Indicates current acceptance status, which can come from subject's last "
"answer, or from the default specified in the related data processing "
"activity."
msgstr ""
"Indica o estado atual da aceitação, que pode derivar da última resposta do "
"titular, ou estar predefinida nos dados relacionados contidos na atividade "
"em processamento."
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent___last_update
msgid "Last Modified on"
msgstr "Última Modificação em"
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_write_uid
msgid "Last Updated by"
msgstr "Última Atualização por"
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_write_date
msgid "Last Updated on"
msgstr "Última Atualização em"
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_last_metadata
msgid "Last metadata"
msgstr "Últimos Metadados"
#. module: privacy_consent
#: selection:privacy.activity,consent_required:0
msgid "Manually"
msgstr "Manualmente"
#. module: privacy_consent
#: model:ir.model.fields,help:privacy_consent.field_privacy_consent_last_metadata
msgid "Metadata from the last acceptance or rejection by the subject"
msgstr "Metadados da última aceitação ou rejeição pelo titular"
#. module: privacy_consent
#: code:addons/privacy_consent/models/mail_template.py:25
#, python-format
msgid ""
"Missing privacy consent link placeholders. You need at least these two "
"links:\n"
"<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,name:privacy_consent.model_mail_mail
msgid "Outgoing Mails"
msgstr "Mensagens a Enviar"
#. module: privacy_consent
#: model:ir.model,name:privacy_consent.model_res_partner
msgid "Partner"
msgstr "Parceiro"
#. module: privacy_consent
#: model:mail.message.subtype,description:privacy_consent.mt_activity_acceptance_changed
msgid "Privacy consent request acceptance status changed"
msgstr "Estado de aceitação do pedido de consentimento de privacidade alterado"
#. module: privacy_consent
#: model:mail.message.subtype,description:privacy_consent.mt_activity_consent_new
#: model:mail.message.subtype,description:privacy_consent.mt_consent_consent_new
msgid "Privacy consent request created"
msgstr "Pedido de consentimento de privacidade criado"
#. module: privacy_consent
#: model:mail.message.subtype,description:privacy_consent.mt_activity_state_changed
#: model:mail.message.subtype,description:privacy_consent.mt_consent_state_changed
msgid "Privacy consent request state changed"
msgstr "Estado do pedido de consentimento de privacidade alterado"
#. module: privacy_consent
#: model:ir.model.fields,help:privacy_consent.field_res_partner_privacy_consent_count
#: model:ir.model.fields,help:privacy_consent.field_res_users_privacy_consent_count
msgid "Privacy consent requests amount"
msgstr "Número de pedidos de consentimento de privacidade"
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_res_partner_privacy_consent_ids
#: model:ir.model.fields,field_description:privacy_consent.field_res_users_privacy_consent_ids
msgid "Privacy consents"
msgstr "Consentimentos de privacidade"
#. module: privacy_consent
#: code:addons/privacy_consent/models/privacy_activity.py:100
#, python-format
msgid "Require consent is available only for subjects in current database."
msgstr ""
"Requerer consentimento, só está disponível para titulares da base de dados "
"atual."
#. module: privacy_consent
#: model:ir.model.fields,help:privacy_consent.field_privacy_activity_server_action_id
msgid ""
"Run this action when a new consent request is created or its acceptance "
"status is updated."
msgstr ""
"Execute esta ação quando um novo pedido de consentimento for criado ou seu "
"estado de aceitação for atualizado."
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_activity_server_action_id
msgid "Server action"
msgstr "Ação do servidor"
#. module: privacy_consent
#: model:ir.model.fields,help:privacy_consent.field_privacy_activity_default_consent
msgid "Should we assume the subject has accepted if we receive no response?"
msgstr ""
"Devemos assumir que o titular dos dados aceitou, se não houver resposta?"
#. module: privacy_consent
#: model:ir.ui.view,arch_db:privacy_consent.form
msgid "Sincerely,<br/>"
msgstr "Cumprimentos,<br />"
#. module: privacy_consent
#: code:addons/privacy_consent/models/privacy_activity.py:92
#, python-format
msgid "Specify a mail template to ask automated consent."
msgstr ""
"Especifique um modelo de email para pedido automático de consentimento."
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_state
#: model:ir.ui.view,arch_db:privacy_consent.consent_search
msgid "State"
msgstr "Estado"
#. module: privacy_consent
#: model:mail.message.subtype,name:privacy_consent.mt_activity_state_changed
#: model:mail.message.subtype,name:privacy_consent.mt_consent_state_changed
msgid "State Changed"
msgstr "Estado Alterado"
#. module: privacy_consent
#: model:ir.model.fields,field_description:privacy_consent.field_privacy_consent_partner_id
msgid "Subject"
msgstr "Titular dos dados"
#. module: privacy_consent
#: model:ir.model.fields,help:privacy_consent.field_privacy_consent_partner_id
msgid "Subject asked for consent."
msgstr "Foi pedido consentimento ao titular."
#. module: privacy_consent
#: model:ir.ui.view,arch_db:privacy_consent.form
msgid "Thank you!"
msgstr "Obrigado!"
#. module: privacy_consent
#: model:ir.ui.view,arch_db:privacy_consent.form
msgid "Thanks for your response."
msgstr "Obrigado pela sua resposta."
#. module: privacy_consent
#: model:ir.ui.view,arch_db:privacy_consent.activity_form
#, 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.actions.server,name:privacy_consent.update_opt_out
msgid "Update partner's opt out"
msgstr "Atualizar a Auto Exclusão do parceiro"
#. module: privacy_consent
#: model:ir.ui.view,arch_db:privacy_consent.form
msgid ""
"We asked you to authorize us to process your data in this data processing "
"activity:"
msgstr ""
"Pedimos-lhe que nos desse autorização para processarmos os seus dados nesta "
"atividade de processamento:"
#. module: privacy_consent
#: model:ir.ui.view,arch_db:privacy_consent.form
msgid "We have recorded this action on your side."
msgstr "Registámos esta ação com seu conhecimento."
#. module: privacy_consent
#: model:ir.ui.view,arch_db:privacy_consent.form
msgid "You have <b class=\"text-danger\">rejected</b> such processing."
msgstr "Você <b class=\"text-danger\">rejeitou</b> este processamento."
#. module: privacy_consent
#: model: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 "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

54
privacy_consent/models/mail_mail.py

@ -0,0 +1,54 @@
# -*- coding: utf-8 -*-
# Copyright 2018 Tecnativa - Jairo Llopis
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import models
class MailMail(models.Model):
_inherit = "mail.mail"
def _postprocess_sent_message(self, mail_sent=True):
"""Write consent status after sending message."""
if mail_sent:
# Get all mails sent to consents
consent_mails = self.filtered(
lambda one: one.mail_message_id.model == "privacy.consent"
)
# Get related draft consents
consents = self.env["privacy.consent"].browse(
consent_mails.mapped("mail_message_id.res_id"),
self._prefetch
).filtered(lambda one: one.state == "draft")
# Set as sent
consents.write({
"state": "sent",
})
return super(MailMail, self)._postprocess_sent_message(mail_sent)
def send_get_mail_body(self, partner=None):
"""Replace privacy consent magic links.
This replacement is done here instead of directly writing it into
the ``mail.template`` to avoid writing the tokeinzed URL
in the mail thread for the ``privacy.consent`` record,
which would enable any reader of such thread to impersonate the
subject and choose in its behalf.
"""
result = super(MailMail, self).send_get_mail_body(partner=partner)
# Avoid polluting other model mails
if self.model != "privacy.consent":
return result
# Tokenize consent links
consent = self.env["privacy.consent"] \
.browse(self.mail_message_id.res_id) \
.with_prefetch(self._prefetch)
result = result.replace(
"/privacy/consent/accept/",
consent._url(True),
)
result = result.replace(
"/privacy/consent/reject/",
consent._url(False),
)
return result

33
privacy_consent/models/mail_template.py

@ -0,0 +1,33 @@
# -*- coding: utf-8 -*-
# Copyright 2018 Tecnativa - Jairo Llopis
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from lxml import html
from odoo import _, api, models
from odoo.exceptions import ValidationError
class MailTemplate(models.Model):
_inherit = "mail.template"
@api.constrains("body_html", "model")
def _check_consent_links_in_body_html(self):
"""Body for ``privacy.consent`` templates needs placeholder links."""
links = [u"//a[@href='/privacy/consent/{}/']".format(action)
for action in ("accept", "reject")]
for one in self:
if one.model != "privacy.consent":
continue
doc = html.document_fromstring(one.body_html)
for link in links:
if not doc.xpath(link):
raise ValidationError(_(
"Missing privacy consent link placeholders. "
"You need at least these two links:\n"
'<a href="%s">Accept</a>\n'
'<a href="%s">Reject</a>'
) % (
"/privacy/consent/accept/",
"/privacy/consent/reject/",
))

143
privacy_consent/models/privacy_activity.py

@ -0,0 +1,143 @@
# -*- coding: utf-8 -*-
# Copyright 2018 Tecnativa - Jairo Llopis
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import _, api, fields, models
from odoo.exceptions import ValidationError
from odoo.tools.safe_eval import safe_eval
class PrivacyActivity(models.Model):
_inherit = 'privacy.activity'
server_action_id = fields.Many2one(
"ir.actions.server",
"Server action",
domain=[
("model_id.model", "=", "privacy.consent"),
],
help="Run this action when a new consent request is created or its "
"acceptance status is updated.",
)
consent_ids = fields.One2many(
"privacy.consent",
"activity_id",
"Consents",
)
consent_count = fields.Integer(
"Consents",
compute="_compute_consent_count",
)
consent_required = fields.Selection(
[("auto", "Automatically"), ("manual", "Manually")],
"Ask subjects for consent",
help="Enable if you need to track any kind of consent "
"from the affected subjects",
)
consent_template_id = fields.Many2one(
"mail.template",
"Email template",
default=lambda self: self._default_consent_template_id(),
domain=[
("model", "=", "privacy.consent"),
],
help="Email to be sent to subjects to ask for consent. "
"A good template should include details about the current "
"consent request status, how to change it, and where to "
"get more information.",
)
default_consent = fields.Boolean(
"Accepted by default",
help="Should we assume the subject has accepted if we receive no "
"response?",
)
# Hidden helpers help user design new templates
consent_template_default_body_html = fields.Text(
compute="_compute_consent_template_defaults",
)
consent_template_default_subject = fields.Char(
compute="_compute_consent_template_defaults",
)
@api.model
def _default_consent_template_id(self):
return self.env.ref("privacy_consent.template_consent", False)
@api.depends("consent_ids")
def _compute_consent_count(self):
groups = self.env["privacy.consent"].read_group(
[("activity_id", "in", self.ids)],
["activity_id"],
["activity_id"],
)
for group in groups:
self.browse(group["activity_id"][0], self._prefetch) \
.consent_count = group["activity_id_count"]
def _compute_consent_template_defaults(self):
"""Used in context values, to help users design new templates."""
template = self._default_consent_template_id()
if template:
self.update({
"consent_template_default_body_html": template.body_html,
"consent_template_default_subject": template.subject,
})
@api.constrains("consent_required", "consent_template_id")
def _check_auto_consent_has_template(self):
"""Require a mail template to automate consent requests."""
for one in self:
if one.consent_required == "auto" and not one.consent_template_id:
raise ValidationError(_(
"Specify a mail template to ask automated consent."
))
@api.constrains("consent_required", "subject_find")
def _check_consent_required_subject_find(self):
for one in self:
if one.consent_required and not one.subject_find:
raise ValidationError(_(
"Require consent is available only for subjects "
"in current database."
))
@api.model
def _cron_new_consents(self):
"""Ask all missing automatic consent requests."""
automatic = self.search([("consent_required", "=", "auto")])
automatic.action_new_consents()
@api.onchange("consent_required")
def _onchange_consent_required_subject_find(self):
"""Find subjects automatically if we require their consent."""
if self.consent_required:
self.subject_find = True
def action_new_consents(self):
"""Generate new consent requests."""
consents = self.env["privacy.consent"]
# Skip activitys where consent is not required
for one in self.with_context(active_test=False) \
.filtered("consent_required"):
domain = [
("id", "not in", one.mapped("consent_ids.partner_id").ids),
("email", "!=", False),
] + safe_eval(one.subject_domain)
# Create missing consent requests
for missing in self.env["res.partner"].search(domain):
consents |= consents.create({
"partner_id": missing.id,
"accepted": one.default_consent,
"activity_id": one.id,
})
# Send consent request emails for automatic activitys
consents.action_auto_ask()
# Redirect user to new consent requests generated
return {
"domain": [("id", "in", consents.ids)],
"name": _("Generated consents"),
"res_model": consents._name,
"type": "ir.actions.act_window",
"view_mode": "tree,form",
}

187
privacy_consent/models/privacy_consent.py

@ -0,0 +1,187 @@
# -*- coding: utf-8 -*-
# Copyright 2018 Tecnativa - Jairo Llopis
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
import hashlib
import hmac
from odoo import api, fields, models
class PrivacyConsent(models.Model):
_name = 'privacy.consent'
_description = "Consent of data processing"
_inherit = "mail.thread"
_rec_name = "partner_id"
_sql_constraints = [
("unique_partner_activity", "UNIQUE(partner_id, activity_id)",
"Duplicated partner in this data processing activity"),
]
active = fields.Boolean(
default=True,
index=True,
)
accepted = fields.Boolean(
track_visibility="onchange",
help="Indicates current acceptance status, which can come from "
"subject's last answer, or from the default specified in the "
"related data processing activity.",
)
last_metadata = fields.Text(
readonly=True,
track_visibility="onchange",
help="Metadata from the last acceptance or rejection by the subject",
)
partner_id = fields.Many2one(
"res.partner",
"Subject",
required=True,
readonly=True,
track_visibility="onchange",
help="Subject asked for consent.",
)
activity_id = fields.Many2one(
"privacy.activity",
"Activity",
readonly=True,
required=True,
track_visibility="onchange",
)
state = fields.Selection(
selection=[
("draft", "Draft"),
("sent", "Awaiting response"),
("answered", "Answered"),
],
default="draft",
readonly=True,
required=True,
track_visibility="onchange",
)
def _track_subtype(self, init_values):
"""Return specific subtypes."""
if self.env.context.get("subject_answering"):
return "privacy_consent.mt_consent_acceptance_changed"
if "activity_id" in init_values or "partner_id" in init_values:
return "privacy_consent.mt_consent_consent_new"
if "state" in init_values:
return "privacy_consent.mt_consent_state_changed"
return super(PrivacyConsent, self)._track_subtype(init_values)
def _token(self):
"""Secret token to publicly authenticate this record."""
secret = self.env["ir.config_parameter"].sudo().get_param(
"database.secret")
params = "{}-{}-{}-{}".format(
self.env.cr.dbname,
self.id,
self.partner_id.id,
self.activity_id.id,
)
return hmac.new(
secret.encode('utf-8'),
params.encode('utf-8'),
hashlib.sha512,
).hexdigest()
def _url(self, accept):
"""Tokenized URL to let subject decide consent.
:param bool accept:
Indicates if you want the acceptance URL, or the rejection one.
"""
return "/privacy/consent/{}/{}/{}?db={}".format(
"accept" if accept else "reject",
self.id,
self._token(),
self.env.cr.dbname,
)
def _send_consent_notification(self):
"""Send email notification to subject."""
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
def create(self, vals):
"""Run server action on create."""
result = super(PrivacyConsent,
self.with_context(mail_create_nolog=True)).create(vals)
# Sync the default acceptance status
result.sudo()._run_action()
return result
def write(self, vals):
"""Run server action on update."""
result = super(PrivacyConsent, self).write(vals)
self._run_action()
return result
def message_get_suggested_recipients(self):
result = super(PrivacyConsent, self) \
.message_get_suggested_recipients()
reason = self._fields["partner_id"].string
for one in self:
one._message_add_suggested_recipient(
result,
partner=one.partner_id,
reason=reason,
)
return result
def action_manual_ask(self):
"""Let user manually ask for consent."""
return {
"context": {
"default_composition_mode": "mass_mail",
"default_model": self._name,
"default_res_id": self.id,
"default_template_id": self.activity_id.consent_template_id.id,
"default_use_template": True,
"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,
})

32
privacy_consent/models/res_partner.py

@ -0,0 +1,32 @@
# -*- coding: utf-8 -*-
# Copyright 2018 Tecnativa - Jairo Llopis
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import api, fields, models
class ResPartner(models.Model):
_inherit = "res.partner"
privacy_consent_ids = fields.One2many(
"privacy.consent",
"partner_id",
"Privacy consents",
)
privacy_consent_count = fields.Integer(
"Consents",
compute="_compute_privacy_consent_count",
help="Privacy consent requests amount",
)
@api.depends("privacy_consent_ids")
def _compute_privacy_consent_count(self):
"""Count consent requests."""
groups = self.env["privacy.consent"].read_group(
[("partner_id", "in", self.ids)],
["partner_id"],
["partner_id"],
)
for group in groups:
self.browse(group["partner_id"][0], self._prefetch) \
.privacy_consent_count = group["partner_id_count"]

3
privacy_consent/readme/CONTRIBUTORS.rst

@ -0,0 +1,3 @@
* `Tecnativa <https://www.tecnativa.com>`_:
* Jairo Llopis

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

Before

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

After

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

520
privacy_consent/static/description/index.html

@ -0,0 +1,520 @@
<?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/10.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-10-0/data-protection-10-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/10.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:%2010.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>
</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>
</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/10.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>

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

253
privacy_consent/tests/test_consent.py

@ -0,0 +1,253 @@
# -*- coding: utf-8 -*-
# Copyright 2018 Tecnativa - Jairo Llopis
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from contextlib import contextmanager
from odoo.exceptions import ValidationError
from odoo.tests.common import HttpCase
class ActivityCase(HttpCase):
def setUp(self):
super(ActivityCase, self).setUp()
# HACK https://github.com/odoo/odoo/issues/12237
# TODO Remove hack in v12
self._oldenv = self.env
self.env = self._oldenv(self.cursor())
# HACK end
self.cron = self.env.ref("privacy_consent.cron_auto_consent")
self.cron_mail_queue = self.env.ref(
"mail.ir_cron_mail_scheduler_action")
self.update_opt_out = self.env.ref("privacy_consent.update_opt_out")
self.mt_consent_consent_new = self.env.ref(
"privacy_consent.mt_consent_consent_new")
self.mt_consent_acceptance_changed = self.env.ref(
"privacy_consent.mt_consent_acceptance_changed")
self.mt_consent_state_changed = self.env.ref(
"privacy_consent.mt_consent_state_changed")
# Some partners to ask for consent
self.partners = self.env["res.partner"]
self.partners += self.partners.create({
"name": "consent-partner-0",
"email": "partner0@example.com",
"notify_email": "none",
"opt_out": False,
})
self.partners += self.partners.create({
"name": "consent-partner-1",
"email": "partner1@example.com",
"notify_email": "always",
"opt_out": True,
})
self.partners += self.partners.create({
"name": "consent-partner-2",
"email": "partner2@example.com",
"opt_out": False,
})
# Partner without email, on purpose
self.partners += self.partners.create({
"name": "consent-partner-3",
"opt_out": True,
})
# Activity without consent
self.activity_noconsent = self.env["privacy.activity"].create({
"name": "activity_noconsent",
"description": "I'm activity 1",
})
# Activity with auto consent, for all partners
self.activity_auto = self.env["privacy.activity"].create({
"name": "activity_auto",
"description": "I'm activity auto",
"subject_find": True,
"subject_domain": repr([("id", "in", self.partners.ids)]),
"consent_required": "auto",
"default_consent": True,
"server_action_id": self.update_opt_out.id,
})
# Activity with manual consent, skipping partner 0
self.activity_manual = self.env["privacy.activity"].create({
"name": "activity_manual",
"description": "I'm activity 3",
"subject_find": True,
"subject_domain": repr([("id", "in", self.partners[1:].ids)]),
"consent_required": "manual",
"default_consent": False,
"server_action_id": self.update_opt_out.id,
})
# HACK https://github.com/odoo/odoo/issues/12237
# TODO Remove hack in v12
def tearDown(self):
self.env = self._oldenv
super(ActivityCase, self).tearDown()
# HACK https://github.com/odoo/odoo/issues/12237
# TODO Remove hack in v12
@contextmanager
def release_cr(self):
self.env.cr.release()
yield
self.env.cr.acquire()
def check_activity_auto_properly_sent(self):
"""Check emails sent by ``self.activity_auto``."""
consents = self.env["privacy.consent"].search([
("activity_id", "=", self.activity_auto.id),
])
# Check pending mails
for consent in consents:
self.assertEqual(consent.state, "draft")
messages = consent.message_ids
self.assertEqual(len(messages), 2)
# Check sent mails
self.cron_mail_queue.method_direct_trigger()
for consent in consents:
self.assertEqual(consent.state, "sent")
messages = consent.message_ids
self.assertEqual(len(messages), 3)
# 2nd message notifies creation
self.assertEqual(
messages[2].subtype_id,
self.mt_consent_consent_new,
)
# 3rd message notifies subject
# Placeholder links should be logged
self.assertTrue("/privacy/consent/accept/" in messages[1].body)
self.assertTrue("/privacy/consent/reject/" in messages[1].body)
# Tokenized links shouldn't be logged
self.assertFalse(consent._url(True) in messages[1].body)
self.assertFalse(consent._url(False) in messages[1].body)
# 4th message contains the state change
self.assertEqual(
messages[0].subtype_id,
self.mt_consent_state_changed,
)
# Partner's opt_out should be synced with default consent
self.assertFalse(consent.partner_id.opt_out)
def test_default_template(self):
"""We have a good mail template by default."""
good = self.env.ref("privacy_consent.template_consent")
self.assertEqual(
self.activity_noconsent.consent_template_id,
good,
)
self.assertEqual(
self.activity_noconsent.consent_template_default_body_html,
good.body_html,
)
self.assertEqual(
self.activity_noconsent.consent_template_default_subject,
good.subject,
)
def test_find_subject_if_consent_required(self):
"""If user wants to require consent, it needs subjects."""
# Test the onchange helper
onchange_activity1 = self.env["privacy.activity"].new(
self.activity_noconsent.copy_data()[0])
self.assertFalse(onchange_activity1.subject_find)
onchange_activity1.consent_required = "auto"
onchange_activity1._onchange_consent_required_subject_find()
self.assertTrue(onchange_activity1.subject_find)
# Test very dumb user that forces an error
with self.assertRaises(ValidationError):
self.activity_noconsent.consent_required = "manual"
def test_template_required_auto(self):
"""Automatic consent activities need a template."""
self.activity_noconsent.subject_find = True
self.activity_noconsent.consent_template_id = False
self.activity_noconsent.consent_required = "manual"
with self.assertRaises(ValidationError):
self.activity_noconsent.consent_required = "auto"
def test_generate_manually(self):
"""Manually-generated consents work as expected."""
self.partners.write({"opt_out": False})
result = self.activity_manual.action_new_consents()
self.assertEqual(result["res_model"], "privacy.consent")
consents = self.env[result["res_model"]].search(result["domain"])
self.assertEqual(consents.mapped("state"), ["draft"] * 2)
self.assertEqual(consents.mapped("partner_id.opt_out"), [False] * 2)
self.assertEqual(consents.mapped("accepted"), [False] * 2)
self.assertEqual(consents.mapped("last_metadata"), [False] * 2)
# Check sent mails
messages = consents.mapped("message_ids")
self.assertEqual(len(messages), 2)
subtypes = messages.mapped("subtype_id")
self.assertTrue(subtypes & self.mt_consent_consent_new)
self.assertFalse(subtypes & self.mt_consent_acceptance_changed)
self.assertFalse(subtypes & self.mt_consent_state_changed)
# Send one manual request
action = consents[0].action_manual_ask()
self.assertEqual(action["res_model"], "mail.compose.message")
composer = self.env[action["res_model"]] \
.with_context(active_ids=consents[0].ids,
active_model=consents._name,
**action["context"]).create({})
composer.onchange_template_id_wrapper()
composer.send_mail()
messages = consents.mapped("message_ids") - messages
self.assertEqual(len(messages), 2)
self.assertEqual(messages[0].subtype_id, self.mt_consent_state_changed)
self.assertEqual(consents.mapped("state"), ["sent", "draft"])
self.assertEqual(consents.mapped("partner_id.opt_out"), [True, False])
# Placeholder links should be logged
self.assertTrue("/privacy/consent/accept/" in messages[1].body)
self.assertTrue("/privacy/consent/reject/" in messages[1].body)
# Tokenized links shouldn't be logged
accept_url = consents[0]._url(True)
reject_url = consents[0]._url(False)
self.assertNotIn(accept_url, messages[1].body)
self.assertNotIn(reject_url, messages[1].body)
# Visit tokenized accept URL
with self.release_cr():
result = self.url_open(accept_url).read()
self.assertIn("accepted", result)
self.assertIn(reject_url, result)
self.assertIn(self.activity_manual.name, result)
self.assertIn(self.activity_manual.description, result)
consents.invalidate_cache()
self.assertEqual(consents.mapped("accepted"), [True, False])
self.assertTrue(consents[0].last_metadata)
self.assertFalse(consents[0].partner_id.opt_out)
self.assertEqual(consents.mapped("state"), ["answered", "draft"])
self.assertEqual(
consents[0].message_ids[0].subtype_id,
self.mt_consent_acceptance_changed,
)
# Visit tokenized reject URL
with self.release_cr():
result = self.url_open(reject_url).read()
self.assertIn("rejected", result)
self.assertIn(accept_url, result)
self.assertIn(self.activity_manual.name, result)
self.assertIn(self.activity_manual.description, result)
consents.invalidate_cache()
self.assertEqual(consents.mapped("accepted"), [False, False])
self.assertTrue(consents[0].last_metadata)
self.assertTrue(consents[0].partner_id.opt_out)
self.assertEqual(consents.mapped("state"), ["answered", "draft"])
self.assertEqual(
consents[0].message_ids[0].subtype_id,
self.mt_consent_acceptance_changed,
)
self.assertFalse(consents[1].last_metadata)
def test_generate_automatically(self):
"""Automatically-generated consents work as expected."""
result = self.activity_auto.action_new_consents()
self.assertEqual(result["res_model"], "privacy.consent")
self.check_activity_auto_properly_sent()
def test_generate_cron(self):
"""Cron-generated consents work as expected."""
self.cron.method_direct_trigger()
self.check_activity_auto_properly_sent()
def test_mail_template_without_links(self):
"""Cannot create mail template without needed links."""
with self.assertRaises(ValidationError):
self.activity_manual.consent_template_id.body_html = "No links :("

89
privacy_consent/views/privacy_activity.xml

@ -0,0 +1,89 @@
<?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">
<!-- TODO Change icon to fa-handshake-o in Odoo 11 -->
<button
attrs='{"invisible": [("consent_required", "=", False)]}'
class="oe_stat_button"
context='{"search_default_activity_id": active_id}'
icon="fa-gavel"
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>

113
privacy_consent/views/privacy_consent.xml

@ -0,0 +1,113 @@
<?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">
<button
class="oe_stat_button"
icon="fa-archive"
name="toggle_active"
type="object"
>
<field
name="active"
options='{"terminology": "archive"}'
widget="boolean_button"
/>
</button>
</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>

35
privacy_consent/views/res_partner.xml

@ -0,0 +1,35 @@
<?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">
<!-- TODO Change icon to fa-handshake-o in Odoo 11 -->
<button
attrs='{"invisible": [("privacy_consent_count", "=", 0)]}'
class="oe_stat_button"
context='{"search_default_partner_id": active_id}'
icon="fa-gavel"
name="%(consent_action)d"
type="action"
>
<field
name="privacy_consent_count"
widget="statinfo"
/>
</button>
</div>
</field>
</record>
</data>

67
privacy_partner_report/README.rst

@ -0,0 +1,67 @@
.. image:: https://img.shields.io/badge/license-AGPL--3-blue.png
:target: https://www.gnu.org/licenses/agpl
:alt: License: AGPL-3
======================
Privacy Partner Report
======================
This module helps a company to identify all the transactions that a specific
partner is involved in, with the possibility to export the associated data.
Usage
=====
To use this module, you need to:
#. Go to menu of ``Privacy > Reports > Partner Report``.
#. Select a partner, and then wait some seconds until a list of models appear.
#. Click on ``Export XLSX``.
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas
:alt: Try me on Runbot
:target: https://runbot.odoo-community.org/runbot/263/10.0
Known issues / Roadmap
======================
* Remove controller workaround if https://github.com/odoo/odoo/pull/24964 is merged.
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 smash it by providing detailed and welcomed feedback.
Credits
=======
Images
------
* Odoo Community Association: `Icon <https://odoo-community.org/logo.png>`_.
Contributors
------------
* Miquel Raïch <miquel.raich@eficent.com>
Do not contact contributors directly about support or help with technical issues.
Maintainer
----------
.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org
This module is maintained by the OCA.
OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.
To contribute to this module, please visit https://odoo-community.org.

4
privacy_partner_report/__init__.py

@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
from . import controllers
from . import report
from . import wizard

21
privacy_partner_report/__manifest__.py

@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
# Copyright 2018 Eficent Business and IT Consulting Services S.L.
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
{
'name': 'Privacy Partner Report',
'version': '10.0.1.0.0',
'category': 'GDPR',
'summary': 'Show the transactions that a specific partner is involved in.',
'author': "Eficent, "
"Odoo Community Association (OCA)",
'website': 'https://github.com/OCA/data-protection/',
'license': 'AGPL-3',
'depends': ['privacy', 'report_xlsx'],
'data': [
'wizard/privacy_report_partner_wizard.xml',
'views/privacy_report.xml',
'views/privacy_menu_view.xml',
],
'installable': True,
'maintainers': ['mreficent'],
}

2
privacy_partner_report/controllers/__init__.py

@ -0,0 +1,2 @@
# -*- coding: utf-8 -*-
from . import main

21
privacy_partner_report/controllers/main.py

@ -0,0 +1,21 @@
# Copyright 2018 Eficent Business and IT Consulting Services, S.L.
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl).
import json
from odoo import http
from odoo.addons.web.controllers.main import serialize_exception
from odoo.addons.web.controllers.main import Reports
class ReportsExtended(Reports):
# HACK of https://github.com/odoo/odoo/pull/24964
@http.route()
@serialize_exception
def index(self, action, token):
action = json.loads(action)
if "data" in action.keys() and action["data"]:
action["datas"] = action["data"]
action = json.dumps(action)
return super(ReportsExtended, self).index(action, token)

159
privacy_partner_report/i18n/de.po

@ -0,0 +1,159 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * privacy_partner_report
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 10.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2019-04-01 14:14+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.1\n"
#. module: privacy_partner_report
#: model:ir.ui.view,arch_db:privacy_partner_report.privacy_partner_report_wizard
msgid "<span>Select a company</span><br/>"
msgstr "<span>Wählen Sie eine Firma</span><br/>"
#. module: privacy_partner_report
#: model:ir.ui.view,arch_db:privacy_partner_report.privacy_partner_report_wizard
msgid "<span>Select a partner</span><br/>"
msgstr "<span>Wählen Sie einen Partner</span><br/>"
#. module: privacy_partner_report
#: model:ir.ui.view,arch_db:privacy_partner_report.privacy_partner_report_wizard
msgid "Cancel"
msgstr "Abbrechen"
#. module: privacy_partner_report
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_report_company_id
msgid "Company"
msgstr "Unternehmen"
#. module: privacy_partner_report
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_data_create_uid
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_report_create_uid
msgid "Created by"
msgstr "Erstellt von"
#. module: privacy_partner_report
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_data_create_date
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_report_create_date
msgid "Created on"
msgstr "Erstellt am"
#. module: privacy_partner_report
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_data_name
msgid "Database Table"
msgstr "Datenbanktabelle"
#. module: privacy_partner_report
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_data_display_name
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_report_display_name
msgid "Display Name"
msgstr "Anzeigename"
#. module: privacy_partner_report
#: model:ir.ui.view,arch_db:privacy_partner_report.privacy_partner_report_wizard
msgid "Export XLSX"
msgstr "XLSX exportieren"
#. module: privacy_partner_report
#: code:addons/privacy_partner_report/wizard/privacy_report_partner.py:110
#, python-format
msgid "Form content is missing, this report cannot be printed."
msgstr "Formularinhalt fehlt, dieser Bericht kann nicht gedruckt werden."
#. module: privacy_partner_report
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_data_id
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_report_id
msgid "ID"
msgstr "Kennung"
#. module: privacy_partner_report
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_data___last_update
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_report___last_update
msgid "Last Modified on"
msgstr "Letzte Änderung am"
#. module: privacy_partner_report
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_data_write_uid
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_report_write_uid
msgid "Last Updated by"
msgstr "Zuletzt aktualisiert von"
#. module: privacy_partner_report
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_data_write_date
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_report_write_date
msgid "Last Updated on"
msgstr "Zuletzt aktualisiert am"
#. module: privacy_partner_report
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_data_model_id
msgid "Models"
msgstr "Vorlagen"
#. module: privacy_partner_report
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_report_table_ids
msgid "Models with related partner data"
msgstr "Vorlagen mit zugehörigen Partnerdaten"
#. module: privacy_partner_report
#: code:addons/privacy_partner_report/wizard/privacy_report_partner.py:114
#, python-format
msgid "No provided partner."
msgstr "Kein unterstützter Partner."
#. module: privacy_partner_report
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_data_count_rows
msgid "Number of lines"
msgstr "Anzahl der Zeilen"
#. module: privacy_partner_report
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_report_partner_id
msgid "Partner"
msgstr "Partner"
#. module: privacy_partner_report
#: code:addons/privacy_partner_report/report/privacy_partner_xlsx.py:37
#, python-format
msgid "Partner Data"
msgstr "Partnerdaten"
#. module: privacy_partner_report
#: model:ir.actions.act_window,name:privacy_partner_report.action_privacy_partner_menu
#: model:ir.ui.menu,name:privacy_partner_report.menu_privacy_report_privacy_report
msgid "Partner Report"
msgstr "Partnerbericht"
#. module: privacy_partner_report
#: model:ir.actions.report.xml,name:privacy_partner_report.action_report_partner_data_xlsx
#: model:ir.model,name:privacy_partner_report.model_privacy_partner_data
msgid "Privacy Partner Data"
msgstr "Datenschutz Partnerdaten"
#. module: privacy_partner_report
#: model:ir.model,name:privacy_partner_report.model_privacy_partner_report
msgid "Privacy Partner Report"
msgstr "Datenschutz Partnerbericht"
#. module: privacy_partner_report
#: model:ir.ui.view,arch_db:privacy_partner_report.privacy_partner_report_wizard
msgid "Report Options"
msgstr "Berichtsoptionen"
#. module: privacy_partner_report
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_data_type
msgid "Type"
msgstr "Typ"
#. module: privacy_partner_report
#: model:ir.ui.view,arch_db:privacy_partner_report.privacy_partner_report_wizard
msgid "or"
msgstr "oder"

157
privacy_partner_report/i18n/fr.po

@ -0,0 +1,157 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * privacy_partner_report
#
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_partner_report
#: model:ir.ui.view,arch_db:privacy_partner_report.privacy_partner_report_wizard
msgid "<span>Select a company</span><br/>"
msgstr ""
#. module: privacy_partner_report
#: model:ir.ui.view,arch_db:privacy_partner_report.privacy_partner_report_wizard
msgid "<span>Select a partner</span><br/>"
msgstr ""
#. module: privacy_partner_report
#: model:ir.ui.view,arch_db:privacy_partner_report.privacy_partner_report_wizard
msgid "Cancel"
msgstr ""
#. module: privacy_partner_report
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_report_company_id
msgid "Company"
msgstr ""
#. module: privacy_partner_report
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_data_create_uid
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_report_create_uid
msgid "Created by"
msgstr ""
#. module: privacy_partner_report
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_data_create_date
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_report_create_date
msgid "Created on"
msgstr ""
#. module: privacy_partner_report
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_data_name
msgid "Database Table"
msgstr ""
#. module: privacy_partner_report
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_data_display_name
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_report_display_name
msgid "Display Name"
msgstr ""
#. module: privacy_partner_report
#: model:ir.ui.view,arch_db:privacy_partner_report.privacy_partner_report_wizard
msgid "Export XLSX"
msgstr ""
#. module: privacy_partner_report
#: code:addons/privacy_partner_report/wizard/privacy_report_partner.py:110
#, python-format
msgid "Form content is missing, this report cannot be printed."
msgstr ""
#. module: privacy_partner_report
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_data_id
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_report_id
msgid "ID"
msgstr ""
#. module: privacy_partner_report
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_data___last_update
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_report___last_update
msgid "Last Modified on"
msgstr ""
#. module: privacy_partner_report
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_data_write_uid
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_report_write_uid
msgid "Last Updated by"
msgstr ""
#. module: privacy_partner_report
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_data_write_date
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_report_write_date
msgid "Last Updated on"
msgstr ""
#. module: privacy_partner_report
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_data_model_id
msgid "Models"
msgstr ""
#. module: privacy_partner_report
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_report_table_ids
msgid "Models with related partner data"
msgstr ""
#. module: privacy_partner_report
#: code:addons/privacy_partner_report/wizard/privacy_report_partner.py:114
#, python-format
msgid "No provided partner."
msgstr ""
#. module: privacy_partner_report
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_data_count_rows
msgid "Number of lines"
msgstr ""
#. module: privacy_partner_report
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_report_partner_id
msgid "Partner"
msgstr ""
#. module: privacy_partner_report
#: code:addons/privacy_partner_report/report/privacy_partner_xlsx.py:37
#, python-format
msgid "Partner Data"
msgstr ""
#. module: privacy_partner_report
#: model:ir.actions.act_window,name:privacy_partner_report.action_privacy_partner_menu
#: model:ir.ui.menu,name:privacy_partner_report.menu_privacy_report_privacy_report
msgid "Partner Report"
msgstr ""
#. module: privacy_partner_report
#: model:ir.actions.report.xml,name:privacy_partner_report.action_report_partner_data_xlsx
#: model:ir.model,name:privacy_partner_report.model_privacy_partner_data
msgid "Privacy Partner Data"
msgstr ""
#. module: privacy_partner_report
#: model:ir.model,name:privacy_partner_report.model_privacy_partner_report
msgid "Privacy Partner Report"
msgstr ""
#. module: privacy_partner_report
#: model:ir.ui.view,arch_db:privacy_partner_report.privacy_partner_report_wizard
msgid "Report Options"
msgstr ""
#. module: privacy_partner_report
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_data_type
msgid "Type"
msgstr ""
#. module: privacy_partner_report
#: model:ir.ui.view,arch_db:privacy_partner_report.privacy_partner_report_wizard
msgid "or"
msgstr ""

157
privacy_partner_report/i18n/privacy_partner_report.pot

@ -0,0 +1,157 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * privacy_partner_report
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 10.0\n"
"Report-Msgid-Bugs-To: \n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: privacy_partner_report
#: model:ir.ui.view,arch_db:privacy_partner_report.privacy_partner_report_wizard
msgid "<span>Select a company</span><br/>"
msgstr ""
#. module: privacy_partner_report
#: model:ir.ui.view,arch_db:privacy_partner_report.privacy_partner_report_wizard
msgid "<span>Select a partner</span><br/>"
msgstr ""
#. module: privacy_partner_report
#: model:ir.ui.view,arch_db:privacy_partner_report.privacy_partner_report_wizard
msgid "Cancel"
msgstr ""
#. module: privacy_partner_report
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_report_company_id
msgid "Company"
msgstr ""
#. module: privacy_partner_report
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_data_create_uid
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_report_create_uid
msgid "Created by"
msgstr ""
#. module: privacy_partner_report
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_data_create_date
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_report_create_date
msgid "Created on"
msgstr ""
#. module: privacy_partner_report
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_data_name
msgid "Database Table"
msgstr ""
#. module: privacy_partner_report
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_data_display_name
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_report_display_name
msgid "Display Name"
msgstr ""
#. module: privacy_partner_report
#: model:ir.ui.view,arch_db:privacy_partner_report.privacy_partner_report_wizard
msgid "Export XLSX"
msgstr ""
#. module: privacy_partner_report
#: code:addons/privacy_partner_report/wizard/privacy_report_partner.py:110
#, python-format
msgid "Form content is missing, this report cannot be printed."
msgstr ""
#. module: privacy_partner_report
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_data_id
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_report_id
msgid "ID"
msgstr ""
#. module: privacy_partner_report
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_data___last_update
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_report___last_update
msgid "Last Modified on"
msgstr ""
#. module: privacy_partner_report
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_data_write_uid
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_report_write_uid
msgid "Last Updated by"
msgstr ""
#. module: privacy_partner_report
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_data_write_date
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_report_write_date
msgid "Last Updated on"
msgstr ""
#. module: privacy_partner_report
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_data_model_id
msgid "Models"
msgstr ""
#. module: privacy_partner_report
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_report_table_ids
msgid "Models with related partner data"
msgstr ""
#. module: privacy_partner_report
#: code:addons/privacy_partner_report/wizard/privacy_report_partner.py:114
#, python-format
msgid "No provided partner."
msgstr ""
#. module: privacy_partner_report
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_data_count_rows
msgid "Number of lines"
msgstr ""
#. module: privacy_partner_report
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_report_partner_id
msgid "Partner"
msgstr ""
#. module: privacy_partner_report
#: code:addons/privacy_partner_report/report/privacy_partner_xlsx.py:37
#, python-format
msgid "Partner Data"
msgstr ""
#. module: privacy_partner_report
#: model:ir.actions.act_window,name:privacy_partner_report.action_privacy_partner_menu
#: model:ir.ui.menu,name:privacy_partner_report.menu_privacy_report_privacy_report
msgid "Partner Report"
msgstr ""
#. module: privacy_partner_report
#: model:ir.actions.report.xml,name:privacy_partner_report.action_report_partner_data_xlsx
#: model:ir.model,name:privacy_partner_report.model_privacy_partner_data
msgid "Privacy Partner Data"
msgstr ""
#. module: privacy_partner_report
#: model:ir.model,name:privacy_partner_report.model_privacy_partner_report
msgid "Privacy Partner Report"
msgstr ""
#. module: privacy_partner_report
#: model:ir.ui.view,arch_db:privacy_partner_report.privacy_partner_report_wizard
msgid "Report Options"
msgstr ""
#. module: privacy_partner_report
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_data_type
msgid "Type"
msgstr ""
#. module: privacy_partner_report
#: model:ir.ui.view,arch_db:privacy_partner_report.privacy_partner_report_wizard
msgid "or"
msgstr ""

159
privacy_partner_report/i18n/pt.po

@ -0,0 +1,159 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * privacy_partner_report
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 10.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2019-02-08 18:50+0000\n"
"Last-Translator: João Carvalhido <joao.carvalhido@exo.pt>\n"
"Language-Team: none\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.4\n"
#. module: privacy_partner_report
#: model:ir.ui.view,arch_db:privacy_partner_report.privacy_partner_report_wizard
msgid "<span>Select a company</span><br/>"
msgstr "<span>Seleccione uma empresa</span><br/>"
#. module: privacy_partner_report
#: model:ir.ui.view,arch_db:privacy_partner_report.privacy_partner_report_wizard
msgid "<span>Select a partner</span><br/>"
msgstr "<span>Seleccione um parceiro</span><br/>"
#. module: privacy_partner_report
#: model:ir.ui.view,arch_db:privacy_partner_report.privacy_partner_report_wizard
msgid "Cancel"
msgstr "Cancelar"
#. module: privacy_partner_report
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_report_company_id
msgid "Company"
msgstr "Empresa"
#. module: privacy_partner_report
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_data_create_uid
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_report_create_uid
msgid "Created by"
msgstr "Criado por"
#. module: privacy_partner_report
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_data_create_date
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_report_create_date
msgid "Created on"
msgstr "Criado em"
#. module: privacy_partner_report
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_data_name
msgid "Database Table"
msgstr "Tabela da Base de Dados"
#. module: privacy_partner_report
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_data_display_name
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_report_display_name
msgid "Display Name"
msgstr "Nome a Apresentar"
#. module: privacy_partner_report
#: model:ir.ui.view,arch_db:privacy_partner_report.privacy_partner_report_wizard
msgid "Export XLSX"
msgstr "Exportar XLSX"
#. module: privacy_partner_report
#: code:addons/privacy_partner_report/wizard/privacy_report_partner.py:110
#, python-format
msgid "Form content is missing, this report cannot be printed."
msgstr "O formulário não tem conteúdo, este relatório não se pode imprimir."
#. module: privacy_partner_report
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_data_id
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_report_id
msgid "ID"
msgstr "ID"
#. module: privacy_partner_report
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_data___last_update
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_report___last_update
msgid "Last Modified on"
msgstr "Última Alteração em"
#. module: privacy_partner_report
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_data_write_uid
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_report_write_uid
msgid "Last Updated by"
msgstr "Última Atualização por"
#. module: privacy_partner_report
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_data_write_date
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_report_write_date
msgid "Last Updated on"
msgstr "Última Atualização em"
#. module: privacy_partner_report
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_data_model_id
msgid "Models"
msgstr "Modelos"
#. module: privacy_partner_report
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_report_table_ids
msgid "Models with related partner data"
msgstr "Modelos com dados relacionados de parceiro"
#. module: privacy_partner_report
#: code:addons/privacy_partner_report/wizard/privacy_report_partner.py:114
#, python-format
msgid "No provided partner."
msgstr "Nenhum parceiro fornecido."
#. module: privacy_partner_report
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_data_count_rows
msgid "Number of lines"
msgstr "Número de linhas"
#. module: privacy_partner_report
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_report_partner_id
msgid "Partner"
msgstr "Parceiro"
#. module: privacy_partner_report
#: code:addons/privacy_partner_report/report/privacy_partner_xlsx.py:37
#, python-format
msgid "Partner Data"
msgstr "Dados do Parceiro"
#. module: privacy_partner_report
#: model:ir.actions.act_window,name:privacy_partner_report.action_privacy_partner_menu
#: model:ir.ui.menu,name:privacy_partner_report.menu_privacy_report_privacy_report
msgid "Partner Report"
msgstr "Relatório do Parceiro"
#. module: privacy_partner_report
#: model:ir.actions.report.xml,name:privacy_partner_report.action_report_partner_data_xlsx
#: model:ir.model,name:privacy_partner_report.model_privacy_partner_data
msgid "Privacy Partner Data"
msgstr "Privacidade dos Dados do Parceiro"
#. module: privacy_partner_report
#: model:ir.model,name:privacy_partner_report.model_privacy_partner_report
msgid "Privacy Partner Report"
msgstr "Privacidade do Relatório do Parceiro"
#. module: privacy_partner_report
#: model:ir.ui.view,arch_db:privacy_partner_report.privacy_partner_report_wizard
msgid "Report Options"
msgstr "Opções do Relatório"
#. module: privacy_partner_report
#: model:ir.model.fields,field_description:privacy_partner_report.field_privacy_partner_data_type
msgid "Type"
msgstr "Tipo"
#. module: privacy_partner_report
#: model:ir.ui.view,arch_db:privacy_partner_report.privacy_partner_report_wizard
msgid "or"
msgstr "ou"

2
privacy_partner_report/report/__init__.py

@ -0,0 +1,2 @@
# -*- coding: utf-8 -*-
from . import privacy_partner_xlsx

94
privacy_partner_report/report/privacy_partner_xlsx.py

@ -0,0 +1,94 @@
# -*- coding: utf-8 -*-
# Copyright 2018 Eficent Business and IT Consulting Services S.L.
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
import logging
from odoo.report import report_sxw
from odoo.tools.translate import _
_logger = logging.getLogger(__name__)
try:
from openerp.addons.report_xlsx.report.report_xlsx import ReportXlsx
except ImportError:
_logger.debug("report_xlsx not installed, Excel export non functional")
class ReportXlsx(object):
def __init__(self, *args, **kwargs):
pass
class ReportPartnerXlsx(ReportXlsx):
def _search_longest_row(self, tables):
res = 0
for table in tables:
for model in tables[table]:
if len(tables[table][model]) > 0:
if len(tables[table][model][0]) > res:
res = len(tables[table][model][0])
return res
def generate_xlsx_report(self, workbook, data, objects):
partner = data['form'].get('partner_id', False)
partner = self.env['res.partner'].sudo().browse(partner[0])
workbook.set_properties({
'comments': 'Created with Python and XlsxWriter from Odoo'})
sheet = workbook.add_worksheet(_('Partner Data'))
sheet.set_landscape()
sheet.fit_to_pages(1, 0)
sheet.set_zoom(75)
sheet.set_column(0, self._search_longest_row(data['tables']), 25)
title_style = workbook.add_format(
{'bold': True, 'bg_color': '#FFFFCC', 'border': 2})
sheet.set_row(0, None, None, {'collapsed': 1})
sheet.write_row(1, 0, ["Partner: " + partner.display_name],
title_style)
i = 3
first_row = i+2
for table in sorted(data['tables'].keys()):
for model in sorted(data['tables'][table].keys()):
rows = len(data['tables'][table][model])
if rows:
style = workbook.add_format()
style.set_bold(True)
style.set_border(2)
sheet.write_row(i, 0, [model], style)
i += 1
j = 0
for column in data['tables'][table][model][0]:
style = workbook.add_format()
style.set_bold(True)
if j == 0:
style.set_left(1)
if j == len(data['tables'][table][model][0]) - 1:
style.set_right(1)
style.set_top(1)
style.set_bottom(1)
sheet.write_row(i, j, [column], style)
j += 1
for row in data['tables'][table][model]:
i += 1
j = 0
for column in row:
style = workbook.add_format()
if j == 0:
style.set_left(1)
if j == len(row) - 1:
style.set_right(1)
if i == rows + first_row - 1:
style.set_bottom(1)
if row[column]:
sheet.write_row(i, j, [row[column]], style)
else:
sheet.write_row(i, j, [''], style)
j += 1
i += 2
first_row = i+2
ReportPartnerXlsx(
'report.privacy.report_partner_xlsx',
'privacy.partner.report',
parser=report_sxw.rml_parse
)

BIN
privacy_partner_report/static/description/icon.png

Before

Width: 128  |  Height: 128  |  Size: 2.1 KiB

After

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

14
privacy_partner_report/views/privacy_menu_view.xml

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2018 Eficent Business and IT Consulting Services S.L.
License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl-3.0) -->
<odoo>
<menuitem id="menu_privacy_report_privacy_report"
name="Partner Report"
parent="privacy.menu_data_protection_report"
groups="privacy.group_data_protection_user"
sequence="10"
action="privacy_partner_report.action_privacy_partner_menu"
/>
</odoo>

11
privacy_partner_report/views/privacy_report.xml

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="action_report_partner_data_xlsx" model="ir.actions.report.xml">
<field name="name">Privacy Partner Data</field>
<field name="model">privacy.partner.report</field>
<field name="type">ir.actions.report.xml</field>
<field name="report_name">privacy.report_partner_xlsx</field>
<field name="report_type">xlsx</field>
<field name="auto" eval="False"/>
</record>
</odoo>

2
privacy_partner_report/wizard/__init__.py

@ -0,0 +1,2 @@
# -*- coding: utf-8 -*-
from . import privacy_report_partner

226
privacy_partner_report/wizard/privacy_report_partner.py

@ -0,0 +1,226 @@
# -*- coding: utf-8 -*-
# Copyright 2018 Eficent Business and IT Consulting Services S.L.
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
from odoo import api, fields, models, _
from odoo.exceptions import UserError
class PrivacyPartnerReport(models.TransientModel):
_name = "privacy.partner.report"
_description = "Privacy Partner Report"
company_id = fields.Many2one(
comodel_name='res.company',
string='Company',
required=True,
default=lambda self: self.env.user.company_id,
)
partner_id = fields.Many2one(
comodel_name='res.partner',
string='Partner',
required=True,
)
table_ids = fields.Many2many(
comodel_name='privacy.partner.data',
string='Models with related partner data',
)
@api.onchange('partner_id')
def _onchange_partner_id(self):
if self.partner_id:
data = self._get_tables_from_partner(self.partner_id)
names = self._get_table_names(data)
tables = self.env['privacy.partner.data']
for name in sorted(names):
vals = self._get_default_table(
name=name,
data=[t for t in data if t[0] == name and not t[5]],
)
if vals:
tables |= self.env['privacy.partner.data'].create(vals)
self.table_ids = tables
else:
self.table_ids = self.env['privacy.partner.data']
return {
'domain': {
'table_ids': [
('id', 'in', self.table_ids.ids)],
},
}
@api.onchange('company_id')
def _onchange_company_id(self):
if not self.company_id:
self.company_id = self.env.user.company_id
return {
'domain': {
'partner_id': [
('company_id', 'in', [self.company_id.id, False])],
},
}
@api.multi
def button_export_xlsx(self):
self.ensure_one()
return self.check_report(xlsx_report=True)
def _build_contexts(self, data):
result = {}
result['partner_id'] = data['form']['partner_id'][0] or False
result['company_id'] = data['form']['company_id'][0] or False
result['table_ids'] = 'table_ids' in data['form'] and \
data['form']['table_ids'] or False
return result
def _clean_data(self, model, rows):
cleaned_rows = []
for i, row in enumerate(rows):
cleaned_rows.append({})
for key, value in row.items():
label = self.env[model]._fields[key].string or key
if self.env[model]._fields[key].store:
if 'many2one' == self.env[model]._fields[key].type:
comodel = self.env[model]._fields[key].comodel_name
if value:
record = self.env[comodel].sudo().browse(value)
cleaned_rows[i][label] = \
record.display_name.encode('utf8')
else:
cleaned_rows[i][label] = rows[i][key]
elif '2many' not in self.env[model]._fields[key].type:
cleaned_rows[i][label] = rows[i][key]
return cleaned_rows
@api.multi
def check_report(self, xlsx_report=False):
self.ensure_one()
data = {}
data['ids'] = self.env.context.get('active_ids', [])
data['model'] = self.env.context.get('active_model', 'ir.ui.menu')
data['form'] = self.read(['partner_id', 'company_id', 'table_ids'])[0]
used_context = self._build_contexts(data)
data['form']['used_context'] = dict(
used_context, lang=self.env.context.get('lang', 'en_US'))
return self._print_report(data=data, xlsx_report=xlsx_report)
@api.multi
def compute_data_for_report(self, data):
if not data.get('form'):
raise UserError(
_("Form content is missing, this report cannot be printed."))
partner = data['form'].get('partner_id', False)
if not partner:
raise UserError(
_("No provided partner."))
partner = self.env['res.partner'].sudo().browse(partner[0])
tables = data['form'].get('table_ids', False)
if tables:
tables = self.env['privacy.partner.data'].browse(tables)
tables = self._get_rows_from_tables(tables, partner)
data.update({'tables': tables, })
return data
def _exclude_column(self, model, column):
# https://github.com/odoo/odoo/issues/24927
if model in ('mail.compose.message', 'survey.mail.compose.message'):
if column in ('needaction_partner_ids', 'starred_partner_ids'):
return True
# feel free to add more specific cases meanwhile the issue is not fixed
return False
def _get_default_table(self, name, data):
if data:
data_type = data[0][4]
res = self.env[data[0][1]]
for t in data:
res |= self.env[t[1]].sudo().browse(t[3])
if res:
values = {
'name': name,
'model_id': self.env['ir.model'].sudo().search(
[('model', '=', res._name)]).id,
'count_rows': len(res.ids),
'type': data_type,
}
return values
return {}
def _get_model_from_table(self, table, partner):
new_tables = {}
for model in table.model_id:
rows = self._get_rows_from_model(model, partner)
new_tables[model.display_name.encode('utf8')] = rows
return new_tables
def _get_rows_from_model(self, model, partner):
lines = self.env[model.model]
columns = [k for k, v in self.env[model.model]._fields.items()
if v.comodel_name == 'res.partner' and
v.store and not self._exclude_column(model.model, k)]
for column in columns:
lines |= self.env[model.model].sudo().search(
[(column, '=', partner.id)])
rows = lines.sudo().read(load=False)
rows = self._clean_data(model.model, rows)
return rows
def _get_rows_from_tables(self, tables, partner):
new_tables = {}
for table in tables:
data_table = self._get_model_from_table(table, partner)
new_tables[str(table.name)] = data_table
return new_tables
def _get_table_names(self, data):
names = []
for t in data:
if t[3] and not t[5] and t[0] not in names:
names.append(t[0])
return names
def _get_tables_from_partner(self, partner):
tables = [t[0] for t in [
[[self.env[m]._table, m, k, self.env[m].sudo().search(
[(k, '=', partner.id)]).ids, v.type, self.env[m]._transient]
for k, v in self.env[m]._fields.items()
if v.comodel_name == 'res.partner' and self.env[m]._auto and
v.store and not self._exclude_column(m, k)]
for m in [x for x in self.env.registry.keys()]] if t]
for i, t in enumerate(tables):
if t[4] == 'many2many':
if t[3]:
relation = self.env[t[1]]._fields[t[2]].relation
if relation:
tables[i][0] = relation
return tables
def _print_report(self, data, xlsx_report=False):
records = self.env[data['model']].sudo().browse(data.get('ids', []))
processed_data = self.compute_data_for_report(data)
if xlsx_report:
return self.env['report'].with_context(landscape=True).get_action(
records=records, report_name='privacy.report_partner_xlsx',
data=processed_data)
class PrivacyPartnerData(models.TransientModel):
_name = "privacy.partner.data"
_description = "Privacy Partner Data"
name = fields.Char(
string='Database Table',
)
model_id = fields.Many2one(
comodel_name='ir.model',
ondelete='cascade',
string='Models',
)
type = fields.Char(
string="Type",
)
count_rows = fields.Integer(
default=0,
string='Number of lines',
)

51
privacy_partner_report/wizard/privacy_report_partner_wizard.xml

@ -0,0 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2018 Eficent Business and IT Consulting Services S.L.
License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl-3.0) -->
<odoo>
<record id="privacy_partner_report_wizard" model="ir.ui.view">
<field name="name">Partner Report</field>
<field name="model">privacy.partner.report</field>
<field name="arch" type="xml">
<form string="Report Options">
<group groups="base.group_multi_company">
<group>
<span >Select a company</span><br/>
<field name="company_id" options="{'no_create': True}" nolabel="1" />
</group>
</group>
<group>
<group>
<span>Select a partner</span><br/>
<field name="partner_id" options="{'no_create': True}" nolabel="1" domain="[('company_id', 'in', [False, company_id])]"/>
</group>
</group>
<group attrs="{'invisible': [('partner_id', '=', False)]}" col="1">
<field name="table_ids" options="{'no_create': True}" editable="bottom">
<tree>
<field name="model_id"/>
<field name="count_rows" text-align="right"/>
</tree>
</field>
</group>
<footer>
<button name="button_export_xlsx" string="Export XLSX" type="object" default_focus="1" class="oe_highlight"/>
or
<button string="Cancel" class="oe_link" special="cancel" />
</footer>
</form>
</field>
</record>
<record id="action_privacy_partner_menu" model="ir.actions.act_window">
<field name="name">Partner Report</field>
<field name="res_model">privacy.partner.report</field>
<field name="type">ir.actions.act_window</field>
<field name="view_type">form</field>
<field name="view_mode">form</field>
<field name="view_id" ref="privacy_partner_report_wizard"/>
<field name="context">{}</field>
<field name="target">new</field>
</record>
</odoo>

1
setup/_metapackage/VERSION.txt

@ -0,0 +1 @@
10.0.20211016.0

20
setup/_metapackage/setup.py

@ -0,0 +1,20 @@
import setuptools
with open('VERSION.txt', 'r') as f:
version = f.read().strip()
setuptools.setup(
name="odoo10-addons-oca-data-protection",
description="Meta package for oca-data-protection Odoo addons",
version=version,
install_requires=[
'odoo10-addon-privacy',
'odoo10-addon-privacy_consent',
'odoo10-addon-privacy_partner_report',
],
classifiers=[
'Programming Language :: Python',
'Framework :: Odoo',
'Framework :: Odoo :: 10.0',
]
)

1
setup/privacy/odoo/__init__.py

@ -0,0 +1 @@
__import__('pkg_resources').declare_namespace(__name__)

1
setup/privacy/odoo/addons/__init__.py

@ -0,0 +1 @@
__import__('pkg_resources').declare_namespace(__name__)

1
setup/privacy/odoo/addons/privacy

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

6
setup/privacy/setup.py

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

1
setup/privacy_consent/odoo/__init__.py

@ -0,0 +1 @@
__import__('pkg_resources').declare_namespace(__name__)

1
setup/privacy_consent/odoo/addons/__init__.py

@ -0,0 +1 @@
__import__('pkg_resources').declare_namespace(__name__)

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,
)

1
setup/privacy_partner_report/odoo/__init__.py

@ -0,0 +1 @@
__import__('pkg_resources').declare_namespace(__name__)

1
setup/privacy_partner_report/odoo/addons/__init__.py

@ -0,0 +1 @@
__import__('pkg_resources').declare_namespace(__name__)

1
setup/privacy_partner_report/odoo/addons/privacy_partner_report

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

6
setup/privacy_partner_report/setup.py

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