├── .gitignore ├── README.md ├── gdpr_inventory ├── __init__.py ├── __openerp__.py ├── docs │ ├── CELEX_32016R0679_SV_TXT.pdf │ ├── GDPR-key-issues-explained.pdf │ ├── Tech-Vendor-Directory-1.4-electronic.pdf │ ├── etiska_regler_epost_b2b_2013.pdf │ ├── ny-dataskyddslag-sou-201739.pdf │ └── preparing-for-the-gdpr-12-steps.pdf ├── gdpr.py ├── gdpr_data.xml ├── gdpr_demo.xml ├── gdpr_report.xml ├── gdpr_view.xml ├── i18n │ ├── gdpr_inventory.pot │ └── sv.po ├── report │ ├── __init__.py │ ├── gdpr_report.py │ └── gdpr_report_view.xml ├── security │ ├── gdpr_security.xml │ └── ir.model.access.csv └── static │ └── src │ └── img │ └── contract.jpg ├── gdpr_mass_mailing ├── __init__.py ├── __openerp__.py ├── gdpr.py ├── gdpr_view.xml ├── security │ └── ir.model.access.csv ├── static │ ├── description │ │ ├── gdpr.png │ │ ├── icon.png │ │ ├── index.html │ │ └── mass_mailing.png │ └── src │ │ ├── css │ │ └── main.css │ │ └── js │ │ ├── main.js │ │ └── mass_mailing.js └── template.xml └── website_gdpr ├── __init__.py ├── __openerp__.py ├── gdpr.py ├── gdpr_demo.xml ├── gdpr_view.xml ├── i18n ├── sv.po └── website_gdpr.pot ├── static └── src │ └── css │ └── main.css └── templates.xml /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | 27 | # PyInstaller 28 | # Usually these files are written by a python script from a template 29 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 30 | *.manifest 31 | *.spec 32 | 33 | # Installer logs 34 | pip-log.txt 35 | pip-delete-this-directory.txt 36 | 37 | # Unit test / coverage reports 38 | htmlcov/ 39 | .tox/ 40 | .coverage 41 | .coverage.* 42 | .cache 43 | nosetests.xml 44 | coverage.xml 45 | *,cover 46 | .hypothesis/ 47 | 48 | # Translations 49 | *.mo 50 | 51 | # Django stuff: 52 | *.log 53 | local_settings.py 54 | 55 | # Flask stuff: 56 | instance/ 57 | .webassets-cache 58 | 59 | # Scrapy stuff: 60 | .scrapy 61 | 62 | # Sphinx documentation 63 | docs/_build/ 64 | 65 | # PyBuilder 66 | target/ 67 | 68 | # IPython Notebook 69 | .ipynb_checkpoints 70 | 71 | # pyenv 72 | .python-version 73 | 74 | # celery beat schedule file 75 | celerybeat-schedule 76 | 77 | # dotenv 78 | .env 79 | 80 | # virtualenv 81 | venv/ 82 | ENV/ 83 | 84 | # Spyder project settings 85 | .spyderproject 86 | 87 | # Rope project settings 88 | .ropeproject 89 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # odoo-gdpr 2 | Privacy program management solutions for General Data Protection Regulation complience 3 | 4 | These modules does: 5 | 6 | * Inventory of personal data and processing 7 | * Rules for automatic deletions 8 | * Website information 9 | * Consent database 10 | * Personal portal, displaying what personal data that is stored in your system, administration of consents 11 | 12 | 13 | The Modules for GDPR helps you to implement fully GDPR compliense 14 | 15 | The inventory may include both personal data in foreign systems and information in Odoo.The Odoo module provides support for mapping the organization's personal data processing and documenting them in a GDPR inventory. 16 | 17 | -------------------------------------------------------------------------------- /gdpr_inventory/__init__.py: -------------------------------------------------------------------------------- 1 | import gdpr 2 | # ~ import wizard 3 | -------------------------------------------------------------------------------- /gdpr_inventory/__openerp__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | ############################################################################## 3 | # 4 | # OpenERP, Open Source Management Solution, third party addon 5 | # Copyright (C) 2004-2017 Vertel AB (). 6 | # 7 | # This program is free software: you can redistribute it and/or modify 8 | # it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | # 20 | ############################################################################## 21 | 22 | { 23 | 'name': 'GDPR Inventory', 24 | 'version': '0.2', 25 | 'category': 'Other', 26 | 'summary': 'Inventory for GDPR', 27 | 'description': """ 28 | Basic tool to make your data handling GDPR compliant. 29 | 30 | Create inventories of all the private data you handle. 31 | 32 | Manage consents of data storage and handling. 33 | 34 | Set up rules to govern purpose and life span of inventoried data. Once data is no longer allowed to be stored, it can be automatically overwritten, deleted, hidden or flagged for manual processing. 35 | """, 36 | 'images': ['static/description/event_participant.jpg'], 37 | 'author': 'Vertel AB', 38 | 'website': 'http://www.vertel.se', 39 | 'depends': ['attachment_notebook', 'mail', 'knowledge', 'document'], 40 | 'data': [ 41 | 'security/gdpr_security.xml', 42 | 'security/ir.model.access.csv', 43 | 'gdpr_data.xml', 44 | 'gdpr_view.xml', 45 | # ~ 'wizard/consent_view.xml', 46 | #'report/gdpr_report.xml', 47 | ], 48 | 'demo': ['gdpr_demo.xml'], 49 | 'application': True, 50 | 'installable': True, 51 | } 52 | # vim:expandtab:smartindent:tabstop=4s:softtabstop=4:shiftwidth=4: 53 | -------------------------------------------------------------------------------- /gdpr_inventory/docs/CELEX_32016R0679_SV_TXT.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vertelab/odoo-gdpr/252aeca3c1b2dfc4827fa8f68b7221f54ec1a520/gdpr_inventory/docs/CELEX_32016R0679_SV_TXT.pdf -------------------------------------------------------------------------------- /gdpr_inventory/docs/GDPR-key-issues-explained.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vertelab/odoo-gdpr/252aeca3c1b2dfc4827fa8f68b7221f54ec1a520/gdpr_inventory/docs/GDPR-key-issues-explained.pdf -------------------------------------------------------------------------------- /gdpr_inventory/docs/Tech-Vendor-Directory-1.4-electronic.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vertelab/odoo-gdpr/252aeca3c1b2dfc4827fa8f68b7221f54ec1a520/gdpr_inventory/docs/Tech-Vendor-Directory-1.4-electronic.pdf -------------------------------------------------------------------------------- /gdpr_inventory/docs/etiska_regler_epost_b2b_2013.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vertelab/odoo-gdpr/252aeca3c1b2dfc4827fa8f68b7221f54ec1a520/gdpr_inventory/docs/etiska_regler_epost_b2b_2013.pdf -------------------------------------------------------------------------------- /gdpr_inventory/docs/ny-dataskyddslag-sou-201739.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vertelab/odoo-gdpr/252aeca3c1b2dfc4827fa8f68b7221f54ec1a520/gdpr_inventory/docs/ny-dataskyddslag-sou-201739.pdf -------------------------------------------------------------------------------- /gdpr_inventory/docs/preparing-for-the-gdpr-12-steps.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vertelab/odoo-gdpr/252aeca3c1b2dfc4827fa8f68b7221f54ec1a520/gdpr_inventory/docs/preparing-for-the-gdpr-12-steps.pdf -------------------------------------------------------------------------------- /gdpr_inventory/gdpr.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | ############################################################################## 3 | # 4 | # OpenERP, Open Source Management Solution, third party addon 5 | # Copyright (C) 2004-2017 Vertel AB (). 6 | # 7 | # This program is free software: you can redistribute it and/or modify 8 | # it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | # 20 | ############################################################################## 21 | from openerp import models, fields, api, _ 22 | from datetime import timedelta 23 | from random import choice 24 | from openerp.tools.safe_eval import safe_eval 25 | from openerp.exceptions import Warning 26 | 27 | import time 28 | import datetime 29 | import dateutil 30 | import pytz 31 | 32 | import logging 33 | _logger = logging.getLogger(__name__) 34 | 35 | #TODO: logg on restrict method (when its done by cron) 36 | 37 | 38 | class gdpr_inventory_state(models.Model): 39 | _name = 'gdpr.inventory.state' 40 | 41 | name = fields.Char(string='Name', required=True) 42 | technical_name = fields.Char(string='Technical Name', required=True) 43 | sequence = fields.Integer(string='Sequence') 44 | fold = fields.Boolean(string='Folded in Kanban View', help='This stage is folded in the kanban view when there are no records in that state to display.') 45 | 46 | common_eval_vars = """ 47 | Available variables: 48 | * env: Odoo environment. 49 | * time: time python module. 50 | * datetime: datetime python module. 51 | * dateutil: dateutil python module. 52 | * timezone: pytz.timezone python module.""" 53 | 54 | class gdpr_system(models.Model): 55 | _name = 'gdpr.system' 56 | _description = 'GDPR Data System' 57 | 58 | name = fields.Char(string='Name') 59 | description = fields.Text(string='Description') 60 | 61 | class gdpr_subject(models.Model): 62 | _name = 'gdpr.subject' 63 | _description = 'GDPR Data Subject' 64 | 65 | name = fields.Char(string='Name') 66 | 67 | class gdpr_data_type(models.Model): 68 | _name = 'gdpr.data_type' 69 | _description = 'GDPR Data Type' 70 | 71 | name = fields.Char(string='Name') 72 | 73 | class gdpr_role(models.Model): 74 | _name = 'gdpr.role' 75 | _description = 'GDPR Role' 76 | 77 | name = fields.Char(string='Name') 78 | 79 | class gdpr_category(models.Model): 80 | _name = 'gdpr.category' 81 | _description = 'GDPR Category' 82 | 83 | sequence = fields.Integer(string='Sequence') 84 | name = fields.Char(string='Name') 85 | description = fields.Text(string='Description') 86 | inventory_ids = fields.One2many(comodel_name='gdpr.inventory',inverse_name='category') 87 | 88 | 89 | class gdpr_bp(models.Model): 90 | _name = 'gdpr.bp' 91 | _description = 'GDPR Business Process' 92 | 93 | sequence = fields.Integer(string='Sequence') 94 | name = fields.Char(string='Name') 95 | 96 | # https://www.privacy-regulation.eu 97 | class gdpr_inventory(models.Model): 98 | _name = 'gdpr.inventory' 99 | _description = 'GDPR Inventory' 100 | _inherit = ['mail.thread'] 101 | 102 | @api.model 103 | def _default_system_id(self): 104 | return self.env['ir.model.data'].xmlid_to_object('gdpr_inventory.gdpr_system_odoo', False) 105 | 106 | @api.model 107 | def _default_state_id(self): 108 | return self.env['gdpr.inventory.state'].search([], order='sequence', limit=1) 109 | 110 | @api.model 111 | def _default_subject_ids(self): 112 | return self.env['ir.model.data'].xmlid_to_object('gdpr_inventory.gdpr_data_subject_customer', False) 113 | 114 | @api.model 115 | def _get_state_selection(self): 116 | states = self.env['gdpr.inventory.state'].search([], order='sequence') 117 | return [(state.technical_name, state.name) for state in states] 118 | 119 | @api.multi 120 | def consent_get(self, partner=None, object=None): 121 | return self.env['gdpr.consent'].get_consent(self, partner, object) 122 | 123 | name = fields.Char(string="Name", translate=True, required=True) 124 | color = fields.Integer(string='Color Index') 125 | state_id = fields.Many2one(comodel_name='gdpr.inventory.state', string='State', required=True, default=_default_state_id, track_visibility='onchange') 126 | state = fields.Selection(selection=_get_state_selection, compute='_compute_state') 127 | 128 | @api.one 129 | def _compute_state(self): 130 | self.state = self.state_id.technical_name 131 | 132 | type_of_personal_data = fields.Selection(selection=[('general', 'General'), ('special', 'Special Category'), ('child', 'Childs consent'), ('criminal', 'Criminal related')], string="Type", 133 | help="General: non sensitive personal data, Special: sensitive personal data, Child consent: personal data concerning under aged persons, Criminal relared: personal data relating to criminal convictions and offences") 134 | role = fields.Selection(selection=[('controller', 'Controller'), ('processor', 'Processor')], string='Our Role', default='controller', required=True, track_visibility='onchange') 135 | category = fields.Many2one(comodel_name="gdpr.category", string="Category", required=True,help="Divide inventories in several catories eg Customers, Resellers etc") 136 | business_process = fields.Many2one(comodel_name="gdpr.bp", string="Business Process", help="Attach the inventorie to a business process") 137 | user_id = fields.Many2one(comodel_name="res.users", string="Responsible", track_visibility='onchange', required=True) 138 | partner_fields_ids = fields.Many2many(comodel_name="ir.model.fields", string="Partner Fields", relation='gdpr_inventory_ir_model_rel_partner_fields_ids', help="Fields with personal link") 139 | partner_domain = fields.Text(string="Partner Domain", help="Domain for identification of partners connected to this personal data") 140 | @api.depends('object_ids.partner_id') 141 | @api.one 142 | def _partner_ids(self): 143 | self.partner_ids = self.object_ids.mapped('partner_id') 144 | self.partner_count = len(self.partner_ids) 145 | partner_ids = fields.Many2many(string='Partners', comodel_name='res.partner', compute='_partner_ids', store=True) 146 | #~ partner_ids = fields.Many2many(string='Partners', comodel_name='res.partner', relation='gdpr_inventory_rel_res_partner', column1='gdpr_id', column2='partner_id') 147 | partner_count = fields.Integer(string='Partner Count', compute='_partner_ids', store=True) 148 | object_ids = fields.One2many(string='Objects', comodel_name='gdpr.object', inverse_name='gdpr_id') 149 | @api.depends('object_ids') 150 | @api.one 151 | def _object_count(self): 152 | self.object_count = len(self.object_ids) 153 | object_count = fields.Integer(string='Object Count', compute='_object_count', store=True) 154 | security_of_processing_ids = fields.Many2many(comodel_name="gdpr.security", string="Security", help="Security of processing", track_visibility='onchange') 155 | 156 | # Identification 157 | identification_desc = fields.Text(string='Identification Description', track_visibility='onchange', translate=True, help="A description of how the data items covered by this inventory can be identified.") 158 | data_local = fields.Boolean(string='Data Is Local', help="The data is stored in this Odoo database and should be automatically inventoried.") 159 | inventory_model = fields.Many2one(comodel_name="ir.model", string="Inventory Model", help="Model (Class) for this Inventory") 160 | inventory_domain = fields.Text(string="Inventory Domain", help="Domain for identification of personal data of this type\n%s" % common_eval_vars, default='[]') 161 | inventory_domain_advanced = fields.Boolean(string='Advanced Domain') 162 | inventory_domain_code = fields.Text(string='Restrict Domain Code', help="Python code that will be executed before domain evaluation. Any variables defined here will be available during domain evaluation.\n%s\n* restrict_days: Restrict time of this inventory" % common_eval_vars) 163 | 164 | # Purpose 165 | purpose_limitation = fields.Text(track_visibility='onchange', translate=True, required=True) 166 | lawsection_desc = fields.Html(string="Law section Explanation", track_visibility='onchange',translate=True) 167 | lawsection_id = fields.Many2one(comodel_name="gdpr.lawsection", string="Law Section", required=True, track_visibility='onchange') 168 | lawsection_description = fields.Html(related='lawsection_id.description', readonly=True, track_visibility='onchange') 169 | consent = fields.Boolean(related='lawsection_id.consent', track_visibility='onchange') 170 | 171 | # Data description 172 | data_subject_ids = fields.Many2many(comodel_name='gdpr.subject', string='Data Subjects', default=_default_subject_ids, track_visibility='onchange') 173 | data_type_ids = fields.Many2many(comodel_name='gdpr.data_type', string='Data Types', help="A description of the types of data that are stored in this inventory.", track_visibility='onchange') 174 | data_collection_ids = fields.Many2many(comodel_name='gdpr.system', string='Data Collection', relation='gdpr_inventory_gdpr_system_collection_rel', column1='gdpr_id', column2='system_id', help="The system that is used to collect data for this inventory.", default=_default_system_id, track_visibility='onchange') 175 | data_storage_ids = fields.Many2many(comodel_name='gdpr.system', string='Data Storage', relation='gdpr_inventory_gdpr_system_storage_rel', column1='gdpr_id', column2='system_id', help="The system that is used to store data for this inventory.", default=_default_system_id, track_visibility='onchange') 176 | data_sharing_ids = fields.Many2many(comodel_name='res.partner', relation='gdpr_inventory_res_partner_sharing_rel', column1='gdpr_id', column2='partner_id', string='Data Sharing', help="Any partners that we share this data with.", track_visibility='onchange') 177 | 178 | # Consent 179 | consent_title = fields.Char(string="Title") 180 | consent_desc = fields.Text(string="Description") 181 | consent_ids = fields.One2many(comodel_name='gdpr.consent', inverse_name='gdpr_id', string='Consents') 182 | consent_count = fields.Integer(string='Consent Count', compute='_consent_count', store=True) 183 | 184 | @api.depends('consent_ids') 185 | @api.one 186 | def _consent_count(self): 187 | self.consent_count = len(self.consent_ids) 188 | 189 | # Restrictions 190 | restrict_desc = fields.Text(string='Restriction Description', track_visibility='onchange', translate=True, help="A description of how the data items covered by this inventory can be identified.") 191 | restrict_time_days = fields.Integer(string='Restrict time', help="Number of days before this data will be restricted", track_visibility='onchange') 192 | restrict_method_id = fields.Many2one(comodel_name="gdpr.restrict_method", string="Restrict Method", track_visibility='onchange') 193 | restrict_domain = fields.Text(string='Restrict Domain', help="Domain for identifying records that should be restricted.\n%s\n* restrict_days: Restrict time of this inventory" % common_eval_vars, default='[]') 194 | restrict_domain_advanced = fields.Boolean(string='Advanced Domain') 195 | restrict_domain_code = fields.Text(string='Restrict Domain Code', help="Python code that will be executed before domain evaluation. Any variables defined here will be available during domain evaluation.\n%s" % common_eval_vars) 196 | restrict_code = fields.Text(string='Restriction Code', help="""Python code to run when restricting records. 197 | %s 198 | * inventory: This inventory record. 199 | * objects: The gdpr objects to be restricted (gdpr.object). Actual records to be processed can be accessed through objects.mapped('object_id').""" % common_eval_vars, default = '{}') 200 | pseudo_values = fields.Text(string='Pseudonymisation Values', help="Custom values used to anonymize fields. Any fields not specified in this dict will be set to False.", default = '{}') 201 | restrict_type = fields.Selection(string='Restriction Type', related='restrict_method_id.type') 202 | manual_count = fields.Integer(string='Manual Count', compute='_manual_count', default=0) 203 | @api.one 204 | def _manual_count(self): 205 | self.manual_count = self.env['gdpr.object'].search_count([('manual', '=', True), ('restricted', '=', False), ('gdpr_id', '=', self.id)]) 206 | fields_ids = fields.Many2many(comodel_name="ir.model.fields", string="Fields", relation='gdpr_inventory_ir_model_rel_fields_ids', help="Fields with (potential) personal data") 207 | 208 | @api.onchange('restrict_method_id') 209 | def onchange_restrict_method_id(self): 210 | if self.restrict_method_id: 211 | self.restrict_code = self.restrict_method_id.code 212 | 213 | @api.onchange('restrict_method_id', 'inventory_model') 214 | def onchange_verify_hide(self): 215 | if self.restrict_method_id and self.restrict_method_id.type == 'hide' and self.inventory_model: 216 | if not self.env['ir.model.fields'].search_count([('model_id', '=', self.inventory_model.id), ('name', '=', 'active')]): 217 | raise Warning("Model %s (%s) can not be hidden because it does not have an 'active' field." % (self.inventory_model.name, self.inventory_model.model)) 218 | 219 | #~ @api.one 220 | #~ def _partner_ids(self): 221 | #~ self.partner_ids = self.env['res.partner'].search(self.inventory_domain) 222 | #~ partner_ids = fields.Many2many(comodel_name="res.partner", compute="_partner_ids") 223 | 224 | @api.one 225 | def create_random_objects(self, count=1): 226 | records = self.env[self.inventory_model.model].search([]) 227 | partners = self.env['res.partner'].search([]) 228 | while count > 0: 229 | self.env['gdpr.object'].create({ 230 | 'object_id': '%s,%s' % (records._name, choice(records).id), 231 | 'partner_id': choice(partners).id, 232 | 'gdpr_id': self.id, 233 | }) 234 | count -= 1 235 | 236 | @api.one 237 | def log(self, subject, body): 238 | id = self.env['mail.message'].create({ 239 | 'body': body, 240 | 'subject': subject, 241 | 'author_id': self.env['res.users'].browse(self.env.uid).partner_id.id, 242 | 'res_id': self.id, 243 | 'model': self._name, 244 | 'type': 'notification', 245 | }) 246 | 247 | @api.multi 248 | def action_view_objects(self): 249 | object_ids = [r['object_res_id'] for r in self.env['gdpr.object'].search_read([('gdpr_id', '=', self.id)], ['object_res_id'])] 250 | return { 251 | 'type': u'ir.actions.act_window', 252 | 'target': u'current', 253 | 'res_model': self.inventory_model.model, 254 | 'view_mode': u'tree,form', 255 | 'domain': [('id', 'in', object_ids)], 256 | 'context': {}, 257 | } 258 | 259 | @api.multi 260 | def action_view_manual_objects(self): 261 | return { 262 | 'type': u'ir.actions.act_window', 263 | 'target': u'current', 264 | 'res_model': 'gdpr.object', 265 | 'view_mode': u'tree,form', 266 | 'domain': [('gdpr_id', '=', self.id)], 267 | 'context': {'search_default_manual': 1, 'search_default_unrestricted': 1}, 268 | } 269 | 270 | @api.model 271 | def cron_restrictions(self): 272 | for gdpr in self.env['gdpr.inventory'].search([('state', '=', 'active')]): 273 | gdpr.resrict_objects() 274 | 275 | @api.one 276 | def update_partner_ids(self): 277 | """Update partner_ids field.""" 278 | pass 279 | 280 | @api.model 281 | def cron_partner_ids(self): 282 | """Update all connections between inventories and partners.""" 283 | pass 284 | 285 | @api.one 286 | def update_object_ids(self): 287 | if not self.data_local: 288 | return 289 | # Remove non-existing objects 290 | model = self.env[self.inventory_model.model] 291 | if model.fields_get('active'): 292 | object_ids = [d['id'] for d in model.search_read([('active', 'in', (True, False))], ['id'])] 293 | else: 294 | object_ids = [d['id'] for d in model.search_read([], ['id'])] 295 | self.env['gdpr.object'].search([('gdpr_id', '=', self.id), ('object_res_id', 'not in', object_ids)]).unlink() 296 | 297 | # Update all matching objects 298 | global_vars = self.env['gdpr.restrict_method'].get_eval_context() 299 | if self.inventory_domain_advanced: 300 | eval(compile(self.inventory_domain_code, __name__, 'exec'), global_vars) 301 | _logger.warn(global_vars) 302 | objects = model.search(safe_eval(self.inventory_domain, global_vars)) 303 | if self.object_ids: 304 | objects |= self.object_ids.mapped('object_id') 305 | _logger.warn(objects) 306 | for o in objects: 307 | partners = self.env['res.partner'].browse([]) 308 | for p in self.partner_fields_ids: 309 | if p.ttype == 'integer' and getattr(o, p.name): 310 | # Assume that this is the ID of a partner 311 | partners |= self.env['res.partner'].browse(getattr(o, p.name)) 312 | else: 313 | partners |= getattr(o, p.name) 314 | _logger.warn(partners) 315 | for partner in partners: 316 | if not self.env['gdpr.object'].search([('gdpr_id', '=', self.id), ('object_id', '=', '%s,%s' %(self.inventory_model.model, o.id)), ('partner_id', '=', partner.id)]): 317 | self.env['gdpr.object'].create({ 318 | 'gdpr_id': self.id, 319 | 'object_id': '%s,%s' %(o._name, o.id), 320 | 'partner_id': partner.id, 321 | }) 322 | 323 | @api.one 324 | def restrict_objects(self): 325 | """ 326 | Check if any records meet the restrict critera and perform restriction according to the chosen restrict method. 327 | """ 328 | if self.data_local and self.restrict_method_id: 329 | model = self.inventory_model.model 330 | global_vars = self.env['gdpr.restrict_method'].get_eval_context(restrict_days=self.restrict_time_days) 331 | if self.restrict_domain_advanced: 332 | eval(compile(self.restrict_domain_code, __name__, 'exec'), global_vars) 333 | domain = safe_eval(self.restrict_domain, global_vars) 334 | object_ids = [o['id'] for o in self.env[model].search_read(domain, ['id'])] 335 | _logger.debug('restrict_objects object_ids: %s' % object_ids) 336 | domain = [('restricted', '!=', True), ('gdpr_id', '=', self.id), ('object_res_id', 'in', object_ids)] 337 | if self.lawsection_id.consent: 338 | gdpr_o_ids = [o['gdpr_object_id'][0] for o in self.env['gdpr.consent'].search_read([('state', '=', 'withdrawn'), ('record_id', 'in', [('%s,%s' % (model, id)) for id in object_ids]), ('gdpr_id', '=', self.id)], ['gdpr_object_id'])] 339 | domain.append(('id', 'in', gdpr_o_ids)) 340 | _logger.debug('restrict_objects domain: %s' % domain) 341 | objects = self.env['gdpr.object'].search(domain) 342 | if objects: 343 | self.restrict_method_id.restrict_objects(self, objects) 344 | 345 | @api.multi 346 | def cron_object_ids(self): 347 | self.search([]).update_object_ids() 348 | 349 | @api.multi 350 | def act_gdpr_inventory_2_gdpr_res_partner(self): 351 | return { 352 | 'name': 'Res Partner 2 GDPR Inventory Partner', 353 | 'res_model': 'res.partner', 354 | 'type': 'ir.actions.act_window', 355 | 'view_mode': 'kanban,tree,form', 356 | 'view_type': 'kanban', 357 | 'domain': [('id', 'in', self.partner_ids.mapped('id'))], 358 | 'context': {}, 359 | } 360 | 361 | @api.model 362 | def _read_state_id(self, present_ids, domain, **kwargs): 363 | states = self.env['gdpr.inventory.state'].search([], order='sequence').name_get() 364 | return states, None 365 | @api.model 366 | def _read_lawsection_id(self, present_ids, domain, **kwargs): 367 | return self.env['gdpr.lawsection'].search([], order='sequence').name_get(), None 368 | @api.model 369 | def _read_business_process(self, present_ids, domain, **kwargs): 370 | return self.env['gdpr.bp'].search([], order='sequence').name_get(), None 371 | @api.model 372 | def _read_role(self, present_ids, domain, **kwargs): 373 | return self.env['gdpr.role'].search([], ).name_get(), None 374 | @api.model 375 | def _read_category(self, present_ids, domain, **kwargs): 376 | return self.env['gdpr.category'].search([], order='sequence').name_get(), None 377 | @api.model 378 | def _read_user_id(self, present_ids, domain, **kwargs): 379 | return self.env['gdpr.inventory'].search([], ).mapped('user_id').name_get(), None 380 | @api.model 381 | def _read_restrict_method_id(self, present_ids, domain, **kwargs): 382 | return self.env['gdpr.restrict_method'].search([], ).name_get(), None 383 | @api.model 384 | def _read_type(self, present_ids, domain, **kwargs): 385 | return [('general', 'General'), ('special', 'Special Category'), ('child', 'Childs consent'), ('criminal', 'Criminal related')], None 386 | _group_by_full = { 387 | 'state_id': _read_state_id, 388 | 'lawsection_id': _read_lawsection_id, 389 | 'business_process': _read_business_process, 390 | 'role': _read_role, 391 | 'category': _read_category, 392 | 'user_id': _read_user_id, 393 | 'restrict_method_id': _read_restrict_method_id, 394 | #~ 'type_of_personal_data': _read_type, 395 | } 396 | 397 | class gdpr_lawsection(models.Model): 398 | """ 399 | 1. Processing shall be lawful only if and to the extent that at least one of the following applies: 400 | => Article: 9 401 | (a) the data subject has given consent to the processing of his or her personal data for one or more specific purposes; 402 | => Article: 7 403 | => Recital: 42, 171 404 | (b) processing is necessary for the performance of a contract to which the data subject is party or in order to take steps at the request of the data subject prior to entering into a contract; 405 | (c) processing is necessary for compliance with a legal obligation to which the controller is subject; 406 | (d) processing is necessary in order to protect the vital interests of the data subject or of another natural person; 407 | (e) processing is necessary for the performance of a task carried out in the public interest or in the exercise of official authority vested in the controller; 408 | (f) processing is necessary for the purposes of the legitimate interests pursued by the controller or by a third party, except where such interests are overridden by the interests or fundamental rights and freedoms of the data subject which require protection of personal data, in particular where the data subject is a child. 409 | => Article: 13, 21 410 | => Recital: 113, 47 411 | """ 412 | _name = 'gdpr.lawsection' 413 | _description = "Lawfullness of processing" 414 | 415 | sequence = fields.Integer(string='Sequence') 416 | name = fields.Char(string='Name',translate=True) 417 | description = fields.Html(string='Description',translate=True) 418 | consent = fields.Boolean(string='Consent') 419 | 420 | 421 | class gdpr_consent(models.Model): 422 | """ 423 | 1. Where processing is based on consent, the controller shall be able to demonstrate that the data subject has consented to processing of his or her personal data. 424 | 2. If the data subject's consent is given in the context of a written declaration which also concerns other matters, the request for consent shall be presented in a manner which is clearly distinguishable from the other matters, in an intelligible and easily accessible form, using clear and plain language. Any part of such a declaration which constitutes an infringement of this Regulation shall not be binding. 425 | 3. The data subject shall have the right to withdraw his or her consent at any time. The withdrawal of consent shall not affect the lawfulness of processing based on consent before its withdrawal. Prior to giving consent, the data subject shall be informed thereof. It shall be as easy to withdraw as to give consent. 426 | 4. When assessing whether consent is freely given, utmost account shall be taken of whether, inter alia, the performance of a contract, including the provision of a service, is conditional on consent to the processing of personal data that is not necessary for the performance of that contract. 427 | """ 428 | _name = 'gdpr.consent' 429 | _description = "Given consents" 430 | _inherit = ['mail.thread'] 431 | 432 | name = fields.Char(string='Name') 433 | gdpr_object_id = fields.Many2one(comodel_name='gdpr.object', string='GDPR Object') 434 | record_id = fields.Reference(related='gdpr_object_id.object_id', string="Object", help="Object that is consented for processing of personal data") 435 | partner_id = fields.Many2one(comodel_name="res.partner") 436 | gdpr_id = fields.Many2one(comodel_name='gdpr.inventory', help="Description of consent") 437 | date = fields.Date(string="Date", help="Date when consent first given") 438 | state = fields.Selection(selection=[('given', 'Given'), ('withdrawn', 'Withdrawn'), ('missing', 'Missing')], string="State", track_visibility='onchange') # transaction log 439 | 440 | #~ object_id = fields.Reference(string='Object', selection='_reference_models', compute='_get_object_id', inverse='_set_object_id', search='_search_object_id') 441 | #~ object_model = fields.Char(string='Object Model') 442 | #~ object_res_id = fields.Integer(string='Object ID') 443 | 444 | 445 | #~ @api.one 446 | #~ def _get_object_id(self): 447 | #~ if self.object_model and self.object_res_id: 448 | #~ self.object_id = self.env[self.object_model].search([('id', '=', self.object_res_id)]) 449 | @api.one 450 | def remove(self, msg): 451 | self.state = 'withdrawn' 452 | self.env['mail.message'].create({ 453 | 'body': msg.replace('\n', '
'), 454 | 'subject': 'Consent withdrawn', 455 | 'author_id': self.env.user.partner_id.id, 456 | 'res_id': self.id, 457 | 'model': self._name, 458 | 'type': 'notification',}) 459 | 460 | @api.model 461 | def add(self, gdpr_id, object, email=None, partner=None, name=None, msg=''): 462 | partner = partner or self.env['res.partner'].search([('email', '=', email)], limit=1) 463 | if email and not partner: 464 | partner = self.env['res.partner'].sudo().create({'name': name or email, 'email': email}) 465 | if object._name != 'gdpr.object': 466 | object_id = self.env['gdpr.object'].sudo().search([ 467 | ('gdpr_id', '=', gdpr_id.id), 468 | ('object_id', '=', '%s,%s' %(object._name, object.id)), 469 | ('partner_id', '=', partner.id), 470 | ]) 471 | if not object_id: 472 | object_id = self.env['gdpr.object'].sudo().create({ 473 | 'gdpr_id': gdpr_id.id, 474 | 'object_id': '%s,%s' %(object._name, object.id), 475 | 'partner_id': partner.id, 476 | }) 477 | else: 478 | object_id = object 479 | consent = self.get_consent(gdpr_id, partner, object_id) 480 | if not consent: 481 | consent = self.env['gdpr.consent'].sudo().create({ 482 | 'name': _('Consent %s') %partner.name, 483 | 'gdpr_id': gdpr_id.id, 484 | 'partner_id': partner.id, 485 | 'gdpr_object_id': object_id.id, 486 | }) 487 | consent.state = 'given' 488 | self.env['mail.message'].create({ 489 | 'body': msg.replace('\n', '
'), 490 | 'subject': 'Consent given', 491 | 'author_id': self.env.user.partner_id.id, 492 | 'res_id': consent.id, 493 | 'model': consent._name, 494 | 'type': 'notification',}) 495 | return consent 496 | 497 | @api.model 498 | def get_consent(self, gdpr_id, partner_id, object_id): 499 | if object_id._name != 'gdpr.object': 500 | object_id = self.env['gdpr.object'].sudo().search([('gdpr_id', '=', gdpr_id.id), ('partner_id', '=', partner_id.id), ('object_id', '=', '%s,%s' % (object_id._name, object_id.id))], limit=1) 501 | return self.env['gdpr.consent'].sudo().search([('gdpr_id', '=', gdpr_id.id), ('partner_id', '=', partner_id.id), ('gdpr_object_id', '=', object_id.id)], limit=1) 502 | 503 | class gdpr_security(models.Model): 504 | """ 505 | 506 | 1. Taking into account the state of the art, the costs of implementation and the nature, scope, context and purposes of processing as well as the risk of varying likelihood and severity for the rights and freedoms of natural persons, the controller and the processor shall implement appropriate technical and organisational measures to ensure a level of security appropriate to the risk, including inter alia as appropriate: 507 | (a) the pseudonymisation and encryption of personal data; 508 | => Article: 4 509 | (b) the ability to ensure the ongoing confidentiality, integrity, availability and resilience of processing systems and services; 510 | (c) the ability to restore the availability and access to personal data in a timely manner in the event of a physical or technical incident; 511 | (d) a process for regularly testing, assessing and evaluating the effectiveness of technical and organisational measures for ensuring the security of the processing. 512 | 2. In assessing the appropriate level of security account shall be taken in particular of the risks that are presented by processing, in particular from accidental or unlawful destruction, loss, alteration, unauthorised disclosure of, or access to personal data transmitted, stored or otherwise processed. 513 | => Recital: 75 514 | 3. Adherence to an approved code of conduct as referred to in Article 40 or an approved certification mechanism as referred to in Article 42 may be used as an element by which to demonstrate compliance with the requirements set out in paragraph 1 of this Article. 515 | 4. The controller and processor shall take steps to ensure that any natural person acting under the authority of the controller or the processor who has access to personal data does not process them except on instructions from the controller, unless he or she is required to do so by Union or Member State law. 516 | 517 | 518 | 1. Med beaktande av den senaste utvecklingen, genomförandekostnaderna och behandlingens art, omfattning, sammanhang och ändamål samt riskerna, av varierande sannolikhetsgrad och allvar, för fysiska personers rättigheter och friheter ska den personuppgiftsansvarige och personuppgiftsbiträdet vidta lämpliga tekniska och organisatoriska åtgärder för att säkerställa en säkerhetsnivå som är lämplig i förhållande till risken, inbegripet, när det är lämpligt 519 | a) pseudonymisering och kryptering av personuppgifter, 520 | => Artikel: 4 521 | b) förmågan att fortlöpande säkerställa konfidentialitet, integritet, tillgänglighet och motståndskraft hos behandlingssystemen och -tjänsterna, 522 | c) förmågan att återställa tillgängligheten och tillgången till personuppgifter i rimlig tid vid en fysisk eller teknisk incident, 523 | d) ett förfarande för att regelbundet testa, undersöka och utvärdera effektiviteten hos de tekniska och organisatoriska åtgärder som ska säkerställa behandlingens säkerhet. 524 | 2. Vid bedömningen av lämplig säkerhetsnivå ska särskild hänsyn tas till de risker som behandling medför, i synnerhet från oavsiktlig eller olaglig förstöring, förlust eller ändring eller till obehörigt röjande av eller obehörig åtkomst till de personuppgifter som överförts, lagrats eller på annat sätt behandlats. 525 | => Grundläggande: 75 526 | 3. Anslutning till en godkänd uppförandekod som avses i artikel 40 eller en godkänd certifieringsmekanism som avses i artikel 42 får användas för att visa att kraven i punkt 1 i den här artikeln följs. 527 | 4. Den personuppgiftsansvarige och personuppgiftsbiträdet ska vidta åtgärder för att säkerställa att varje fysisk person som utför arbete under den personuppgiftsansvariges eller personuppgiftsbiträdets överinseende, och som får tillgång till personuppgifter, endast behandlar dessa på instruktion från den personuppgiftsansvarige, om inte unionsrätten eller medlemsstaternas nationella rätt ålägger honom eller henne att göra det. 528 | 529 | """ 530 | _name = 'gdpr.security' 531 | _description = "Security of processing" 532 | 533 | name = fields.Char() 534 | description = fields.Text() 535 | 536 | class gdpr_restrict_method(models.Model): 537 | _name = 'gdpr.restrict_method' 538 | _description = "Restrict Method" 539 | _inherit = ['mail.thread'] 540 | 541 | name = fields.Char() 542 | description = fields.Text() 543 | type = fields.Selection(selection=[('erase', 'Erase'), ('hide', 'Hide'), ('encrypt', 'Encrypt'), ('pseudo', 'Pseudonymisation'), ('manual', 'Manual'), ('code', 'Code')]) 544 | code = fields.Text() 545 | 546 | @api.one 547 | def restrict_erase(self, gdpr): 548 | models = self.env[gdpr.model].search(gdpr.domain) 549 | self.env[gdpr.model].search(gdpr.domain).unlink() 550 | gdpr.log(_('Restrict Erase'), ', '.join(models.mapped('name'))) 551 | 552 | @api.one 553 | def restrict_hide(self, gdpr): 554 | fields.Datetime.to_string(intervals[0][0]) 555 | restrict_date = fields.Date.to_string(fields.Date.today()) - datetime.timedelta(days=gdpr.restrict_time_days) 556 | models = self.env[gdpr.model].search(gdpr.domain.format({ 557 | 'restrict_date': fields.Date.tostring(fields.Date.today() - datetime.timedelta(days=gdpr.restrict_time_days)) 558 | })) 559 | self.env[gdpr.model].search(gdpr.domain).write({'active': False}) 560 | gdpr.log(_('Restrict Hide'), models) 561 | 562 | @api.one 563 | def restrict_encrypt(self, gdpr): 564 | models = self.env[gdpr.model].search(gdpr.domain) 565 | self.env[gdpr.model].search(gdpr.domain).write({'active': False}) 566 | gdpr.log(_('Restrict Hide'), models) 567 | 568 | @api.one 569 | def restrict_log(self, gdpr): 570 | models = self.env[gdpr.model].search(gdpr.domain) 571 | self.env[gdpr.model].search(gdpr.domain).write({'active': False}) 572 | gdpr.log(_('Restrict Hide'), models) 573 | 574 | @api.one 575 | def cron(self, gdpr): 576 | models = self.env[gdpr.model].search(gdpr.domain) 577 | self.env[gdpr.model].search(gdpr.domain).write({'active': False}) 578 | gdpr.log(_('Restrict Hide'), models) 579 | 580 | @api.one 581 | def restrict_objects(self, inventory, objects): 582 | """ 583 | Perform restriction. 584 | :param inventory: The inventory that the objects belong to. 585 | :param objects: The GDPR objects (gdpr.object) that should be restricted. 586 | """ 587 | if self.type == 'erase': 588 | objects.mapped('object_id').unlink() 589 | objects.unlink() 590 | elif self.type == 'hide': 591 | if hasattr(objects, 'active'): 592 | objects.mapped('object_id').write({'active': False}) 593 | objects.write({'restricted': True}) 594 | elif self.type == 'encrypt': 595 | pass 596 | elif self.type == 'pseudo': 597 | values = safe_eval(inventory.pseudo_values, self.get_eval_context()) 598 | for field in inventory.fields_ids: 599 | if field.name not in values: 600 | values[field.name] = False 601 | objects.mapped('object_id').write(values) 602 | objects.write({'restricted': True}) 603 | elif self.type == 'manual': 604 | objects.write({'manual': True}) 605 | # TODO: Button to list expired records. 606 | pass 607 | elif self.type == 'code': 608 | safe_eval(inventory.restrict_code, self.get_eval_context(inventory=inventory, objects=objects), mode='exec') 609 | 610 | @api.model 611 | def get_eval_context(self, **kw): 612 | context = { 613 | # python libs 614 | 'time': time, 615 | 'datetime': datetime, 616 | 'dateutil': dateutil, 617 | # NOTE: only `timezone` function. Do not provide the whole `pytz` module as users 618 | # will have access to `pytz.os` and `pytz.sys` to do nasty things... 619 | 'timezone': pytz.timezone, 620 | # orm 621 | 'env': self.env, 622 | } 623 | context.update(kw) 624 | return context 625 | 626 | class gdpr_object(models.Model): 627 | _name = 'gdpr.object' 628 | 629 | @api.one 630 | def _get_name(self): 631 | if self.object_id and hasattr(self.object_id, 'name'): 632 | self.name = self.object_id.name 633 | elif self.object_id: 634 | self.name = '%s, %s' % (self.object_id._name, self.object_id.id) 635 | else: 636 | self.name = 'gdpr.object, %s' % self.id 637 | 638 | name = fields.Char(string='Name', compute='_get_name') 639 | gdpr_id = fields.Many2one(string='Inventory', comodel_name='gdpr.inventory') 640 | object_id = fields.Reference(string='Object', selection='_reference_models', compute='_get_object_id', inverse='_set_object_id', search='_search_object_id') 641 | object_model = fields.Char(string='Object Model') 642 | object_res_id = fields.Integer(string='Object ID') 643 | partner_id = fields.Many2one(string='Partners', comodel_name='res.partner') 644 | restricted = fields.Boolean(string='Restricted', help="This record has been restricted.") 645 | manual = fields.Boolean(string='Manual Action Required', help="This record needs attention.") 646 | 647 | @api.one 648 | def _get_object_id(self): 649 | if self.object_model and self.object_res_id: 650 | self.object_id = self.env[self.object_model].search([('id', '=', self.object_res_id)]) 651 | 652 | @api.one 653 | def _set_object_id(self): 654 | if self.object_id: 655 | self.object_res_id = self.object_id.id 656 | self.object_model = self.object_id._name 657 | else: 658 | self.object_res_id = False 659 | self.object_model = False 660 | 661 | @api.model 662 | def _search_object_id(self, operator, value): 663 | _logger.debug('_search_object_id; operator: %s, value: %s' % (operator, value)) 664 | if operator in ('in', 'not in'): 665 | if operator == 'in': 666 | op_m = '=' 667 | ao1 = '&' 668 | ao2 = '|' 669 | else: 670 | op_m = '!=' 671 | ao1 = '|' 672 | ao2 = '&' 673 | ids = {} 674 | for v in value: 675 | m, id = v.split(',') 676 | if m not in ids: 677 | ids[m] = [] 678 | ids[m].append(int(id)) 679 | res = [] 680 | for model in ids: 681 | if res: 682 | res = [ao2] + res 683 | res += [ao1, ('object_model', op_m, model), ('object_res_id', operator, ids[model])] 684 | elif value: 685 | res = ['&', ('object_model', operator, value.split(',')[0]), ('object_res_id', operator, int(value.split(',')[1]))] 686 | else: 687 | res = ['&', ('object_model', operator, value), ('object_res_id', operator, value)] 688 | _logger.debug(res) 689 | return res 690 | 691 | @api.model 692 | def _reference_models(self): 693 | models = self.env['ir.model'].search([('state', '!=', 'manual')]) 694 | return [(model.model, model.name) for model in models] 695 | 696 | class res_partner(models.Model): 697 | _inherit = 'res.partner' 698 | 699 | """ 700 | 1) search for non inventoried res.partner 701 | 2) button: consents 702 | 3) button: list related gdpr.inventorie (other law sections) 703 | 4) for each gdpr.inventory list document related to res.partner and gdpr.inventory 704 | 5) list res.partber for each gdpr.inventory 705 | 706 | """ 707 | @api.one 708 | def _gdpr_ids(self): 709 | self.gdpr_ids = self.env['gdpr.object'].search([('partner_id', '=', self.id)]).mapped('gdpr_id') 710 | gdpr_ids = fields.Many2many(string='GDPRs', comodel_name='gdpr.inventory', compute='_gdpr_ids') 711 | #~ gdpr_ids = fields.Many2many(string='GDPRs', comodel_name='gdpr.inventory', relation='gdpr_inventory_rel_res_partner', column1='partner_id', column2='gdpr_id', compute='_gdpr_ids', store=True) 712 | @api.one 713 | def _get_gdpr_count(self): 714 | self.gdpr_count = len(self.gdpr_ids) 715 | gdpr_count = fields.Integer(string='# Inventories', compute='_get_gdpr_count') 716 | 717 | consent_ids = fields.One2many(string='Consents', comodel_name='gdpr.consent', inverse_name='partner_id') 718 | @api.one 719 | def _get_consent_count(self): 720 | self.consent_count = len(self.consent_ids) 721 | consent_count = fields.Integer(string='# Consents', compute='_get_consent_count') 722 | 723 | gdpr_object_ids = fields.One2many(comodel_name='gdpr.object', inverse_name='partner_id', string='GDPR Objects') 724 | @api.one 725 | def _get_gdpr_object_count(self): 726 | self.gdpr_object_count = len(self.gdpr_object_ids) 727 | gdpr_object_count = fields.Integer(string='# Objects', compute='_get_gdpr_object_count') 728 | 729 | @api.multi 730 | def action_gdpr_inventory(self): 731 | action = self.env['ir.actions.act_window'].for_xml_id('gdpr_inventory', 'action_gdpr_inventory') 732 | action['domain'] = [('partner_ids', '=', self.id)] 733 | return action 734 | 735 | @api.multi 736 | def action_gdpr_objects(self): 737 | action = self.env['ir.actions.act_window'].for_xml_id('gdpr_inventory', 'action_gdpr_object') 738 | action['domain'] = [('partner_ids', '=', self.id)] 739 | return action 740 | 741 | @api.multi 742 | def act_res_partner_2_gdpr_inventory(self): 743 | return { 744 | 'name': 'Res Partner 2 GDPR Inventory', 745 | 'res_model': 'gdpr.inventory', 746 | 'type': 'ir.actions.act_window', 747 | 'view_mode': 'kanban,tree,form', 748 | 'view_type': 'kanban', 749 | 'domain': [('id', 'in', self.gdpr_ids.mapped('id'))], 750 | 'context': {}, 751 | } 752 | 753 | """ 754 | write: if gdpr.gdpr_method_id.type in (encrypt) 755 | read: decrypt fields 756 | """ 757 | 758 | class ir_attachment(models.Model): 759 | _inherit = 'ir.attachment' 760 | 761 | @api.one 762 | def _consent_ids(self): 763 | if type(self.id) == int: 764 | self.consent_ids = self.env['gdpr.consent'].search([('gdpr_object_id.object_id', '=', '%s,%s' % (self._name, self.id),)]) 765 | consent_ids = fields.One2many(comodel_name='gdpr.consent', compute='_consent_ids') 766 | -------------------------------------------------------------------------------- /gdpr_inventory/gdpr_data.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | consent 6 | 7 |

Processing are beeing lawful on the ground that the data subject 8 | has given consent to the processing of his or her personal data for one or more specific purposes. 9 |

=> Article: 7, 8, 9 10 |
=> Recital: 32, 42, 43, 171 11 |
=> Dossier: Consent, Permission

12 |
13 | 14 |
15 | 16 | 17 | Contract 18 |

Processing are beeing lawful on the ground that processing is 19 | necessary for the performance of a contract to which the data subject is party or in order to 20 | take steps at the request of the data subject prior to entering into a contract 21 |

=> Article: 20 22 |
=> Dossier: Permission 23 |

24 | 25 |
26 | 27 | 28 | Legal Obligation 29 | 30 |

Processing are beeing lawful on the ground that processing is 31 | necessary for compliance with a legal obligation to which the controller is subject 32 |

=> Dossier: Permission

33 |
34 | 35 |
36 | 37 | 38 | 39 | Vital Interest 40 | Processing are beeing lawful on the ground that processing is 41 | necessary in order to protect the vital interests of the data subject or of another natural person 42 | => Dossier: Permission 43 | 44 | 45 | 46 | 47 | 48 | Public Interest 49 | Processing are beeing lawful on the ground that processing is 50 | necessary for the performance of a task carried out in the public interest or in 51 | the exercise of official authority vested in the controller 52 | => Dossier: Task in Public Interest, Permission 53 | 54 | 55 | 56 | 57 | Legitimate Interest 58 | Processing are beeing lawful on the ground that processing is 59 | necessary for the purposes of the legitimate interests pursued by the controller or by a third 60 | party, except where such interests are overridden by the interests or fundamental rights and 61 | freedoms of the data subject which require protection of personal data, in particular where 62 | the data subject is a child. 63 | 64 | => Article: 13, 21 65 | => Recital: 113, 47, 48 66 | 67 | 68 | 69 | 70 | 71 | 72 | Erase 73 | erase 74 | All records will be erased 75 | 76 | 77 | 78 | Hide 79 | hide 80 | Will hide the records by setting active to False. 81 | 82 | 83 | 90 | 91 | 92 | Pseudonymisation 93 | pseudo 94 | Will overwrite the listed fields on the record. 95 | 96 | 97 | 98 | Manual 99 | manual 100 | No action will be taken on restriction. Records to restrict can be listed. 101 | 102 | 103 | 104 | Code 105 | code 106 | Restriction will be handled by executing customizable python code. 107 | # Will do the same as Erase (erase all records and their gdpr.objects) 108 | objects.mapped('object_id').unlink() 109 | objects.unlink() 110 | 111 | 112 |
113 | 114 | 115 | 116 | Draft 117 | draft 118 | 10 119 | 120 | 121 | Active 122 | active 123 | 20 124 | 125 | 126 | To be ceased 127 | to_be_ceased 128 | 30 129 | 130 | 131 | Ceased 132 | ceased 133 | 40 134 | 135 | 136 | 137 | Create GDRP Object 138 | code 139 | 140 | 141 | object.cron_object_ids() 142 | 143 | 144 | 145 | Create GDRP Object 146 | gdpr.inventory 147 | client_action_multi 148 | 149 | 150 | 151 | 152 | Odoo 153 | 154 | 155 | 156 | Customers 157 | 158 | 159 | 160 | Employees 161 | 162 | 163 | 164 | Name 165 | 166 | 167 | 168 | Address 169 | 170 | 171 | 172 | Email Address 173 | 174 | 175 | 176 | Bank Details 177 | 178 | 179 | 180 |
181 | 182 | 183 | -------------------------------------------------------------------------------- /gdpr_inventory/gdpr_demo.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Contract 7 | directory 8 | 9 | 10 | Agrolait Contract 11 | url 12 | /gdpr_inventory/static/src/img/library/contract.jpg 13 | 14 | 15 | 16 | 17 | 18 | Customer Contracts 19 | general 20 | 21 | Personal data processing in connection with execution of customer contracts 22 |

Processing are beeing lawful on the ground that processing is 23 | necessary for the performance of a contract to which the data subject is party or in order to 24 | take steps at the request of the data subject prior to entering into a contract 25 |

=> Article: 20 26 |
=> Dossier: Permission 27 |

28 | 29 | 30 | 31 | 32 | 33 | 34 | [('create_date', '<', (datetime.date.today() - datetime.timedelta(days=restrict_days + 365)).strftime('%Y-%m-%d'))] 35 | 36 |
37 | 38 | 39 | 40 | Business Hands 41 | url 42 | /website/static/src/img/library/business_hands.jpg 43 | 44 | 45 | Pictures for marketing 46 | general 47 | 48 | Personal data processing in connection with marketing of the company 49 | Processing are beeing lawful on the ground that the data subject has given consent to the processing of his or her personal data for one or more specific purposes. 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | Consent Mark Davis 69 | 70 | 71 | 72 | given 73 | 74 | 75 | Consent Roger Scott 76 | 77 | 78 | 79 | given 80 | 81 |
82 |
83 | 84 | 85 | -------------------------------------------------------------------------------- /gdpr_inventory/gdpr_report.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /gdpr_inventory/i18n/gdpr_inventory.pot: -------------------------------------------------------------------------------- 1 | # Translation of Odoo Server. 2 | # This file contains the translation of the following modules: 3 | # * gdpr_inventory 4 | # 5 | msgid "" 6 | msgstr "" 7 | "Project-Id-Version: Odoo Server 8.0-20171009\n" 8 | "Report-Msgid-Bugs-To: \n" 9 | "POT-Creation-Date: 2018-05-16 09:28+0000\n" 10 | "PO-Revision-Date: 2018-05-16 09:28+0000\n" 11 | "Last-Translator: <>\n" 12 | "Language-Team: \n" 13 | "MIME-Version: 1.0\n" 14 | "Content-Type: text/plain; charset=UTF-8\n" 15 | "Content-Transfer-Encoding: \n" 16 | "Plural-Forms: \n" 17 | 18 | #. module: gdpr_inventory 19 | #: field:res.partner,consent_count:0 20 | msgid "# Consents" 21 | msgstr "" 22 | 23 | #. module: gdpr_inventory 24 | #: field:res.partner,gdpr_count:0 25 | msgid "# Inventories" 26 | msgstr "" 27 | 28 | #. module: gdpr_inventory 29 | #: field:res.partner,gdpr_object_count:0 30 | msgid "# Objects" 31 | msgstr "" 32 | 33 | #. module: gdpr_inventory 34 | #: model:gdpr.lawsection,description:gdpr_inventory.lawfullness_obligation 35 | msgid "

Processing are beeing lawful on the ground that processing is\n" 36 | "necessary for compliance with a legal obligation to which the controller is subject\n" 37 | "

=> Dossier: Permission

\n" 38 | "" 39 | msgstr "" 40 | 41 | #. module: gdpr_inventory 42 | #: model:gdpr.lawsection,description:gdpr_inventory.lawfullness_contract 43 | msgid "

Processing are beeing lawful on the ground that processing is\n" 44 | "necessary for the performance of a contract to which the data subject is party or in order to\n" 45 | "take steps at the request of the data subject prior to entering into a contract\n" 46 | "

=> Article: 20\n" 47 | "
=> Dossier: Permission\n" 48 | "

" 49 | msgstr "" 50 | 51 | #. module: gdpr_inventory 52 | #: model:gdpr.lawsection,description:gdpr_inventory.lawfullness_public_interest 53 | msgid "

Processing are beeing lawful on the ground that processing is\n" 54 | "necessary for the performance of a task carried out in the public interest or in\n" 55 | "the exercise of official authority vested in the controller\n" 56 | "=> Dossier: Task in Public Interest, Permission

" 57 | msgstr "" 58 | 59 | #. module: gdpr_inventory 60 | #: model:gdpr.lawsection,description:gdpr_inventory.lawfullness_legitimate_interest 61 | msgid "

Processing are beeing lawful on the ground that processing is\n" 62 | "necessary for the purposes of the legitimate interests pursued by the controller or by a third\n" 63 | "party, except where such interests are overridden by the interests or fundamental rights and\n" 64 | "freedoms of the data subject which require protection of personal data, in particular where\n" 65 | "the data subject is a child.\n" 66 | "\n" 67 | "=> Article: 13, 21\n" 68 | "=> Recital: 113, 47, 48\n" 69 | "\n" 70 | "

" 71 | msgstr "" 72 | 73 | #. module: gdpr_inventory 74 | #: model:gdpr.lawsection,description:gdpr_inventory.lawfullness_vital_interest 75 | msgid "

Processing are beeing lawful on the ground that processing is\n" 76 | "necessary in order to protect the vital interests of the data subject or of another natural person\n" 77 | "=> Dossier: Permission

" 78 | msgstr "" 79 | 80 | #. module: gdpr_inventory 81 | #: model:gdpr.lawsection,description:gdpr_inventory.lawfullness_consent 82 | msgid "

Processing are beeing lawful on the ground that the data subject\n" 83 | "has given consent to the processing of his or her personal data for one or more specific purposes.\n" 84 | "

=> Article: 7, 8, 9\n" 85 | "
=> Recital: 32, 42, 43, 171\n" 86 | "
=> Dossier: Consent, Permission

\n" 87 | " " 88 | msgstr "" 89 | 90 | #. module: gdpr_inventory 91 | #: help:gdpr.inventory,identification_desc:0 92 | #: help:gdpr.inventory,restrict_desc:0 93 | msgid "A description of how the data items covered by this inventory can be identified." 94 | msgstr "" 95 | 96 | #. module: gdpr_inventory 97 | #: help:gdpr.inventory,data_type_ids:0 98 | msgid "A description of the types of data that are stored in this inventory." 99 | msgstr "" 100 | 101 | #. module: gdpr_inventory 102 | #: view:gdpr.inventory:gdpr_inventory.view_gdpr_inventory_form 103 | msgid "Action Req." 104 | msgstr "" 105 | 106 | #. module: gdpr_inventory 107 | #: field:gdpr.inventory,inventory_domain_advanced:0 108 | #: field:gdpr.inventory,restrict_domain_advanced:0 109 | msgid "Advanced Domain" 110 | msgstr "" 111 | 112 | #. module: gdpr_inventory 113 | #: help:gdpr.inventory,data_sharing_ids:0 114 | msgid "Any partners that we share this data with." 115 | msgstr "" 116 | 117 | #. module: gdpr_inventory 118 | #: help:gdpr.inventory,business_process:0 119 | msgid "Attach the inventorie to a business process" 120 | msgstr "" 121 | 122 | #. module: gdpr_inventory 123 | #: view:gdpr.inventory:gdpr_inventory.view_gdpr_inventory_filter 124 | #: field:gdpr.inventory,business_process:0 125 | msgid "Business Process" 126 | msgstr "" 127 | 128 | #. module: gdpr_inventory 129 | #: view:gdpr.inventory:gdpr_inventory.view_gdpr_inventory_filter 130 | #: field:gdpr.inventory,category:0 131 | msgid "Category" 132 | msgstr "" 133 | 134 | #. module: gdpr_inventory 135 | #: selection:gdpr.inventory,type_of_personal_data:0 136 | msgid "Childs consent" 137 | msgstr "" 138 | 139 | #. module: gdpr_inventory 140 | #: view:gdpr.restrict_method:gdpr_inventory.view_gdpr_restrict_method_filter 141 | #: field:gdpr.restrict_method,code:0 142 | #: selection:gdpr.restrict_method,type:0 143 | msgid "Code" 144 | msgstr "" 145 | 146 | #. module: gdpr_inventory 147 | #: help:gdpr.inventory,consent_add:0 148 | msgid "Code for consent add" 149 | msgstr "" 150 | 151 | #. module: gdpr_inventory 152 | #: help:gdpr.inventory,consent_remove:0 153 | msgid "Code for consent remove" 154 | msgstr "" 155 | 156 | #. module: gdpr_inventory 157 | #: field:gdpr.inventory,color:0 158 | msgid "Color Index" 159 | msgstr "" 160 | 161 | #. module: gdpr_inventory 162 | #: view:gdpr.inventory:gdpr_inventory.view_gdpr_inventory_form 163 | #: field:gdpr.inventory,consent:0 164 | #: field:gdpr.lawsection,consent:0 165 | msgid "Consent" 166 | msgstr "" 167 | 168 | #. module: gdpr_inventory 169 | #: code:addons/gdpr_inventory/gdpr.py:470 170 | #, python-format 171 | msgid "Consent %s" 172 | msgstr "" 173 | 174 | #. module: gdpr_inventory 175 | #: field:gdpr.inventory,consent_count:0 176 | msgid "Consent Count" 177 | msgstr "" 178 | 179 | #. module: gdpr_inventory 180 | #: view:gdpr.consent:gdpr_inventory.view_gdpr_consent_filter 181 | msgid "Consent Given" 182 | msgstr "" 183 | 184 | #. module: gdpr_inventory 185 | #: view:gdpr.consent:gdpr_inventory.view_gdpr_consent_filter 186 | msgid "Consent Missing" 187 | msgstr "" 188 | 189 | #. module: gdpr_inventory 190 | #: view:gdpr.consent:gdpr_inventory.view_gdpr_consent_filter 191 | msgid "Consent Withdrawn" 192 | msgstr "" 193 | 194 | #. module: gdpr_inventory 195 | #: field:ir.attachment,consent_ids:0 196 | msgid "Consent ids" 197 | msgstr "" 198 | 199 | #. module: gdpr_inventory 200 | #: view:gdpr.inventory:gdpr_inventory.view_gdpr_inventory_form 201 | #: view:gdpr.inventory:gdpr_inventory.view_gdpr_inventory_kanban 202 | #: field:gdpr.inventory,consent_ids:0 203 | #: view:res.partner:gdpr_inventory.view_partner_form 204 | #: field:res.partner,consent_ids:0 205 | msgid "Consents" 206 | msgstr "" 207 | 208 | #. module: gdpr_inventory 209 | #: model:gdpr.lawsection,name:gdpr_inventory.lawfullness_contract 210 | msgid "Contract" 211 | msgstr "" 212 | 213 | #. module: gdpr_inventory 214 | #: selection:gdpr.inventory,role:0 215 | msgid "Controller" 216 | msgstr "" 217 | 218 | #. module: gdpr_inventory 219 | #: model:ir.actions.server,name:gdpr_inventory.action_create_gdrp_object 220 | msgid "Create GDRP Object" 221 | msgstr "" 222 | 223 | #. module: gdpr_inventory 224 | #: field:gdpr.bp,create_uid:0 225 | #: field:gdpr.category,create_uid:0 226 | #: field:gdpr.consent,create_uid:0 227 | #: field:gdpr.data_type,create_uid:0 228 | #: field:gdpr.inventory,create_uid:0 229 | #: field:gdpr.inventory.state,create_uid:0 230 | #: field:gdpr.lawsection,create_uid:0 231 | #: field:gdpr.object,create_uid:0 232 | #: field:gdpr.restrict_method,create_uid:0 233 | #: field:gdpr.role,create_uid:0 234 | #: field:gdpr.security,create_uid:0 235 | #: field:gdpr.subject,create_uid:0 236 | #: field:gdpr.system,create_uid:0 237 | msgid "Created by" 238 | msgstr "" 239 | 240 | #. module: gdpr_inventory 241 | #: field:gdpr.bp,create_date:0 242 | #: field:gdpr.category,create_date:0 243 | #: field:gdpr.consent,create_date:0 244 | #: field:gdpr.data_type,create_date:0 245 | #: field:gdpr.inventory,create_date:0 246 | #: field:gdpr.inventory.state,create_date:0 247 | #: field:gdpr.lawsection,create_date:0 248 | #: field:gdpr.object,create_date:0 249 | #: field:gdpr.restrict_method,create_date:0 250 | #: field:gdpr.role,create_date:0 251 | #: field:gdpr.security,create_date:0 252 | #: field:gdpr.subject,create_date:0 253 | #: field:gdpr.system,create_date:0 254 | msgid "Created on" 255 | msgstr "" 256 | 257 | #. module: gdpr_inventory 258 | #: selection:gdpr.inventory,type_of_personal_data:0 259 | msgid "Criminal related" 260 | msgstr "" 261 | 262 | #. module: gdpr_inventory 263 | #: help:gdpr.inventory,pseudo_values:0 264 | msgid "Custom values used to anonymize fields. Any fields not specified in this dict will be set to False." 265 | msgstr "" 266 | 267 | #. module: gdpr_inventory 268 | #: field:gdpr.inventory,data_collection_ids:0 269 | msgid "Data Collection" 270 | msgstr "" 271 | 272 | #. module: gdpr_inventory 273 | #: view:gdpr.inventory:gdpr_inventory.view_gdpr_inventory_form 274 | msgid "Data Description" 275 | msgstr "" 276 | 277 | #. module: gdpr_inventory 278 | #: field:gdpr.inventory,data_local:0 279 | msgid "Data Is Local" 280 | msgstr "" 281 | 282 | #. module: gdpr_inventory 283 | #: field:gdpr.inventory,data_sharing_ids:0 284 | msgid "Data Sharing" 285 | msgstr "" 286 | 287 | #. module: gdpr_inventory 288 | #: field:gdpr.inventory,data_storage_ids:0 289 | msgid "Data Storage" 290 | msgstr "" 291 | 292 | #. module: gdpr_inventory 293 | #: field:gdpr.inventory,data_subject_ids:0 294 | msgid "Data Subjects" 295 | msgstr "" 296 | 297 | #. module: gdpr_inventory 298 | #: field:gdpr.inventory,data_type_ids:0 299 | msgid "Data Types" 300 | msgstr "" 301 | 302 | #. module: gdpr_inventory 303 | #: view:gdpr.consent:gdpr_inventory.view_gdpr_consent_filter 304 | #: field:gdpr.consent,date:0 305 | msgid "Date" 306 | msgstr "" 307 | 308 | #. module: gdpr_inventory 309 | #: help:gdpr.consent,message_last_post:0 310 | #: help:gdpr.inventory,message_last_post:0 311 | #: help:gdpr.restrict_method,message_last_post:0 312 | msgid "Date of the last message posted on the record." 313 | msgstr "" 314 | 315 | #. module: gdpr_inventory 316 | #: help:gdpr.consent,date:0 317 | msgid "Date when consent first given" 318 | msgstr "" 319 | 320 | #. module: gdpr_inventory 321 | #: view:gdpr.inventory:gdpr_inventory.view_gdpr_inventory_kanban 322 | msgid "Delete" 323 | msgstr "" 324 | 325 | #. module: gdpr_inventory 326 | #: view:gdpr.inventory:gdpr_inventory.view_gdpr_inventory_form 327 | msgid "Describe the item..." 328 | msgstr "" 329 | 330 | #. module: gdpr_inventory 331 | #: view:gdpr.category:gdpr_inventory.view_gdpr_category_filter 332 | #: field:gdpr.category,description:0 333 | #: field:gdpr.inventory,lawsection_description:0 334 | #: field:gdpr.lawsection,description:0 335 | #: view:gdpr.restrict_method:gdpr_inventory.view_gdpr_restrict_method_filter 336 | #: field:gdpr.restrict_method,description:0 337 | #: view:gdpr.security:gdpr_inventory.view_gdpr_security_filter 338 | #: field:gdpr.security,description:0 339 | #: field:gdpr.system,description:0 340 | msgid "Description" 341 | msgstr "" 342 | 343 | #. module: gdpr_inventory 344 | #: help:gdpr.consent,gdpr_id:0 345 | msgid "Description of consent" 346 | msgstr "" 347 | 348 | #. module: gdpr_inventory 349 | #: field:gdpr.bp,display_name:0 350 | #: field:gdpr.category,display_name:0 351 | #: field:gdpr.consent,display_name:0 352 | #: field:gdpr.data_type,display_name:0 353 | #: field:gdpr.inventory,display_name:0 354 | #: field:gdpr.inventory.state,display_name:0 355 | #: field:gdpr.lawsection,display_name:0 356 | #: field:gdpr.object,display_name:0 357 | #: field:gdpr.restrict_method,display_name:0 358 | #: field:gdpr.role,display_name:0 359 | #: field:gdpr.security,display_name:0 360 | #: field:gdpr.subject,display_name:0 361 | #: field:gdpr.system,display_name:0 362 | msgid "Display Name" 363 | msgstr "" 364 | 365 | #. module: gdpr_inventory 366 | #: help:gdpr.inventory,category:0 367 | msgid "Divide inventories in several catories eg Customers, Resellers etc" 368 | msgstr "" 369 | 370 | #. module: gdpr_inventory 371 | #: help:gdpr.inventory,partner_domain:0 372 | msgid "Domain for identification of partners connected to this personal data" 373 | msgstr "" 374 | 375 | #. module: gdpr_inventory 376 | #: help:gdpr.inventory,inventory_domain:0 377 | msgid "Domain for identification of personal data of this type\n" 378 | "\n" 379 | "Available variables:\n" 380 | "* env: Odoo environment.\n" 381 | "* time: time python module.\n" 382 | "* datetime: datetime python module.\n" 383 | "* dateutil: dateutil python module.\n" 384 | "* timezone: pytz.timezone python module." 385 | msgstr "" 386 | 387 | #. module: gdpr_inventory 388 | #: help:gdpr.inventory,restrict_domain:0 389 | msgid "Domain for identifying records that should be restricted.\n" 390 | "\n" 391 | "Available variables:\n" 392 | "* env: Odoo environment.\n" 393 | "* time: time python module.\n" 394 | "* datetime: datetime python module.\n" 395 | "* dateutil: dateutil python module.\n" 396 | "* timezone: pytz.timezone python module.\n" 397 | "* restrict_days: Restrict time of this inventory" 398 | msgstr "" 399 | 400 | #. module: gdpr_inventory 401 | #: view:gdpr.inventory:gdpr_inventory.view_gdpr_inventory_filter 402 | msgid "Draft" 403 | msgstr "" 404 | 405 | #. module: gdpr_inventory 406 | #: selection:gdpr.restrict_method,type:0 407 | msgid "Encrypt" 408 | msgstr "" 409 | 410 | #. module: gdpr_inventory 411 | #: selection:gdpr.restrict_method,type:0 412 | msgid "Erase" 413 | msgstr "" 414 | 415 | #. module: gdpr_inventory 416 | #: field:gdpr.inventory,fields_ids:0 417 | msgid "Fields" 418 | msgstr "" 419 | 420 | #. module: gdpr_inventory 421 | #: help:gdpr.inventory,fields_ids:0 422 | msgid "Fields with (potential) personal data" 423 | msgstr "" 424 | 425 | #. module: gdpr_inventory 426 | #: help:gdpr.inventory,partner_fields_ids:0 427 | msgid "Fields with personal link" 428 | msgstr "" 429 | 430 | #. module: gdpr_inventory 431 | #: field:gdpr.inventory.state,fold:0 432 | msgid "Folded in Kanban View" 433 | msgstr "" 434 | 435 | #. module: gdpr_inventory 436 | #: field:gdpr.consent,message_follower_ids:0 437 | #: field:gdpr.inventory,message_follower_ids:0 438 | #: field:gdpr.restrict_method,message_follower_ids:0 439 | msgid "Followers" 440 | msgstr "" 441 | 442 | #. module: gdpr_inventory 443 | #: model:ir.module.category,name:gdpr_inventory.module_category_gdpr 444 | #: model:ir.ui.menu,name:gdpr_inventory.menu_gdpr 445 | #: model:ir.ui.menu,name:gdpr_inventory.menu_gdpr_config 446 | msgid "GDPR" 447 | msgstr "" 448 | 449 | #. module: gdpr_inventory 450 | #: model:ir.model,name:gdpr_inventory.model_gdpr_bp 451 | msgid "GDPR Business Process" 452 | msgstr "" 453 | 454 | #. module: gdpr_inventory 455 | #: view:gdpr.category:gdpr_inventory.view_gdpr_category_form 456 | #: view:gdpr.category:gdpr_inventory.view_gdpr_category_tree 457 | #: model:ir.actions.act_window,name:gdpr_inventory.action_gdpr_category 458 | #: model:ir.model,name:gdpr_inventory.model_gdpr_category 459 | #: model:ir.ui.menu,name:gdpr_inventory.menu_gdpr_category 460 | msgid "GDPR Category" 461 | msgstr "" 462 | 463 | #. module: gdpr_inventory 464 | #: view:gdpr.consent:gdpr_inventory.view_gdpr_consent_form 465 | #: view:gdpr.consent:gdpr_inventory.view_gdpr_consent_tree 466 | #: model:ir.actions.act_window,name:gdpr_inventory.action_gdpr_consent 467 | #: model:ir.ui.menu,name:gdpr_inventory.menu_gdpr_consent 468 | msgid "GDPR Consent" 469 | msgstr "" 470 | 471 | #. module: gdpr_inventory 472 | #: view:ir.attachment:gdpr_inventory.view_attachment_form 473 | msgid "GDPR Consents" 474 | msgstr "" 475 | 476 | #. module: gdpr_inventory 477 | #: model:ir.model,name:gdpr_inventory.model_gdpr_subject 478 | msgid "GDPR Data Subject" 479 | msgstr "" 480 | 481 | #. module: gdpr_inventory 482 | #: model:ir.model,name:gdpr_inventory.model_gdpr_system 483 | msgid "GDPR Data System" 484 | msgstr "" 485 | 486 | #. module: gdpr_inventory 487 | #: model:ir.model,name:gdpr_inventory.model_gdpr_data_type 488 | msgid "GDPR Data Type" 489 | msgstr "" 490 | 491 | #. module: gdpr_inventory 492 | #: view:gdpr.inventory:gdpr_inventory.view_gdpr_inventory_form 493 | #: view:gdpr.inventory:gdpr_inventory.view_gdpr_inventory_tree 494 | #: model:ir.actions.act_window,name:gdpr_inventory.action_gdpr_inventory 495 | #: model:ir.model,name:gdpr_inventory.model_gdpr_inventory 496 | #: model:ir.ui.menu,name:gdpr_inventory.menu_gdpr_inventory 497 | msgid "GDPR Inventory" 498 | msgstr "" 499 | 500 | #. module: gdpr_inventory 501 | #: model:ir.actions.act_window,name:gdpr_inventory.act_gdpr_inventory_2_gdpr_consent 502 | msgid "GDPR Inventory 2 GDPR Consent" 503 | msgstr "" 504 | 505 | #. module: gdpr_inventory 506 | #: view:gdpr.inventory.state:gdpr_inventory.view_gdpr_inventory_state_form 507 | #: view:gdpr.inventory.state:gdpr_inventory.view_gdpr_inventory_state_tree 508 | #: model:ir.actions.act_window,name:gdpr_inventory.action_gdpr_inventory_state 509 | #: model:ir.ui.menu,name:gdpr_inventory.menu_inventory_state 510 | msgid "GDPR Inventory State" 511 | msgstr "" 512 | 513 | #. module: gdpr_inventory 514 | #: view:gdpr.lawsection:gdpr_inventory.view_gdpr_lawsection_form 515 | #: view:gdpr.lawsection:gdpr_inventory.view_gdpr_lawsection_tree 516 | #: model:ir.actions.act_window,name:gdpr_inventory.action_gdpr_lawsection 517 | #: model:ir.ui.menu,name:gdpr_inventory.menu_gdpr_lawsection 518 | msgid "GDPR Lawsection" 519 | msgstr "" 520 | 521 | #. module: gdpr_inventory 522 | #: field:gdpr.consent,gdpr_object_id:0 523 | #: view:gdpr.object:gdpr_inventory.view_gdpr_object_form 524 | #: view:gdpr.object:gdpr_inventory.view_gdpr_object_tree 525 | #: model:ir.actions.act_window,name:gdpr_inventory.action_gdpr_object 526 | msgid "GDPR Object" 527 | msgstr "" 528 | 529 | #. module: gdpr_inventory 530 | #: field:res.partner,gdpr_object_ids:0 531 | msgid "GDPR Objects" 532 | msgstr "" 533 | 534 | #. module: gdpr_inventory 535 | #: view:gdpr.restrict_method:gdpr_inventory.view_gdpr_restrict_method_form 536 | #: view:gdpr.restrict_method:gdpr_inventory.view_gdpr_restrict_method_tree 537 | #: model:ir.actions.act_window,name:gdpr_inventory.action_gdpr_restrict_method 538 | #: model:ir.ui.menu,name:gdpr_inventory.menu_gdpr_restrict_method 539 | msgid "GDPR Restrict Method" 540 | msgstr "" 541 | 542 | #. module: gdpr_inventory 543 | #: model:ir.model,name:gdpr_inventory.model_gdpr_role 544 | msgid "GDPR Role" 545 | msgstr "" 546 | 547 | #. module: gdpr_inventory 548 | #: view:gdpr.security:gdpr_inventory.view_gdpr_security_tree 549 | #: model:ir.actions.act_window,name:gdpr_inventory.action_gdpr_security 550 | #: model:ir.ui.menu,name:gdpr_inventory.menu_gdpr_security 551 | msgid "GDPR Security" 552 | msgstr "" 553 | 554 | #. module: gdpr_inventory 555 | #: view:gdpr.security:gdpr_inventory.view_gdpr_security_form 556 | msgid "GDPR security" 557 | msgstr "" 558 | 559 | #. module: gdpr_inventory 560 | #: field:res.partner,gdpr_ids:0 561 | msgid "GDPRs" 562 | msgstr "" 563 | 564 | #. module: gdpr_inventory 565 | #: field:gdpr.consent,gdpr_id:0 566 | msgid "Gdpr id" 567 | msgstr "" 568 | 569 | #. module: gdpr_inventory 570 | #: selection:gdpr.inventory,type_of_personal_data:0 571 | msgid "General" 572 | msgstr "" 573 | 574 | #. module: gdpr_inventory 575 | #: help:gdpr.inventory,type_of_personal_data:0 576 | msgid "General: non sensitive personal data, Special: sensitive personal data, Child consent: personal data concerning under aged persons, Criminal relared: personal data relating to criminal convictions and offences" 577 | msgstr "" 578 | 579 | #. module: gdpr_inventory 580 | #: selection:gdpr.consent,state:0 581 | msgid "Given" 582 | msgstr "" 583 | 584 | #. module: gdpr_inventory 585 | #: model:ir.model,name:gdpr_inventory.model_gdpr_consent 586 | msgid "Given consents" 587 | msgstr "" 588 | 589 | #. module: gdpr_inventory 590 | #: view:gdpr.consent:gdpr_inventory.view_gdpr_consent_filter 591 | #: view:gdpr.inventory:gdpr_inventory.view_gdpr_inventory_filter 592 | #: view:gdpr.object:gdpr_inventory.view_gdpr_object_filter 593 | #: view:gdpr.restrict_method:gdpr_inventory.view_gdpr_restrict_method_filter 594 | msgid "Group By" 595 | msgstr "" 596 | 597 | #. module: gdpr_inventory 598 | #: model:ir.module.category,description:gdpr_inventory.module_category_gdpr 599 | msgid "Helps you to manage GDPR inventory" 600 | msgstr "" 601 | 602 | #. module: gdpr_inventory 603 | #: selection:gdpr.restrict_method,type:0 604 | msgid "Hide" 605 | msgstr "" 606 | 607 | #. module: gdpr_inventory 608 | #: help:gdpr.consent,message_summary:0 609 | #: help:gdpr.inventory,message_summary:0 610 | #: help:gdpr.restrict_method,message_summary:0 611 | msgid "Holds the Chatter summary (number of messages, ...). This summary is directly in html format in order to be inserted in kanban views." 612 | msgstr "" 613 | 614 | #. module: gdpr_inventory 615 | #: field:gdpr.bp,id:0 616 | #: field:gdpr.category,id:0 617 | #: field:gdpr.consent,id:0 618 | #: field:gdpr.data_type,id:0 619 | #: field:gdpr.inventory,id:0 620 | #: field:gdpr.inventory.state,id:0 621 | #: field:gdpr.lawsection,id:0 622 | #: field:gdpr.object,id:0 623 | #: field:gdpr.restrict_method,id:0 624 | #: field:gdpr.role,id:0 625 | #: field:gdpr.security,id:0 626 | #: field:gdpr.subject,id:0 627 | #: field:gdpr.system,id:0 628 | msgid "ID" 629 | msgstr "" 630 | 631 | #. module: gdpr_inventory 632 | #: view:gdpr.inventory:gdpr_inventory.view_gdpr_inventory_form 633 | msgid "Identification" 634 | msgstr "" 635 | 636 | #. module: gdpr_inventory 637 | #: field:gdpr.inventory,identification_desc:0 638 | msgid "Identification Description" 639 | msgstr "" 640 | 641 | #. module: gdpr_inventory 642 | #: help:gdpr.consent,message_unread:0 643 | #: help:gdpr.inventory,message_unread:0 644 | #: help:gdpr.restrict_method,message_unread:0 645 | msgid "If checked new messages require your attention." 646 | msgstr "" 647 | 648 | #. module: gdpr_inventory 649 | #: view:gdpr.object:gdpr_inventory.view_gdpr_object_filter 650 | #: view:res.partner:gdpr_inventory.view_partner_form 651 | msgid "Inventories" 652 | msgstr "" 653 | 654 | #. module: gdpr_inventory 655 | #: view:gdpr.consent:gdpr_inventory.view_gdpr_consent_filter 656 | #: field:gdpr.object,gdpr_id:0 657 | msgid "Inventory" 658 | msgstr "" 659 | 660 | #. module: gdpr_inventory 661 | #: field:gdpr.inventory,inventory_domain:0 662 | msgid "Inventory Domain" 663 | msgstr "" 664 | 665 | #. module: gdpr_inventory 666 | #: field:gdpr.inventory,inventory_model:0 667 | msgid "Inventory Model" 668 | msgstr "" 669 | 670 | #. module: gdpr_inventory 671 | #: view:gdpr.inventory:gdpr_inventory.view_gdpr_inventory_kanban 672 | msgid "Inventory Settings" 673 | msgstr "" 674 | 675 | #. module: gdpr_inventory 676 | #: field:gdpr.consent,message_is_follower:0 677 | #: field:gdpr.inventory,message_is_follower:0 678 | #: field:gdpr.restrict_method,message_is_follower:0 679 | msgid "Is a Follower" 680 | msgstr "" 681 | 682 | #. module: gdpr_inventory 683 | #: field:gdpr.consent,message_last_post:0 684 | #: field:gdpr.inventory,message_last_post:0 685 | #: field:gdpr.restrict_method,message_last_post:0 686 | msgid "Last Message Date" 687 | msgstr "" 688 | 689 | #. module: gdpr_inventory 690 | #: field:gdpr.bp,__last_update:0 691 | #: field:gdpr.category,__last_update:0 692 | #: field:gdpr.consent,__last_update:0 693 | #: field:gdpr.data_type,__last_update:0 694 | #: field:gdpr.inventory,__last_update:0 695 | #: field:gdpr.inventory.state,__last_update:0 696 | #: field:gdpr.lawsection,__last_update:0 697 | #: field:gdpr.object,__last_update:0 698 | #: field:gdpr.restrict_method,__last_update:0 699 | #: field:gdpr.role,__last_update:0 700 | #: field:gdpr.security,__last_update:0 701 | #: field:gdpr.subject,__last_update:0 702 | #: field:gdpr.system,__last_update:0 703 | msgid "Last Modified on" 704 | msgstr "" 705 | 706 | #. module: gdpr_inventory 707 | #: field:gdpr.bp,write_uid:0 708 | #: field:gdpr.category,write_uid:0 709 | #: field:gdpr.consent,write_uid:0 710 | #: field:gdpr.data_type,write_uid:0 711 | #: field:gdpr.inventory,write_uid:0 712 | #: field:gdpr.inventory.state,write_uid:0 713 | #: field:gdpr.lawsection,write_uid:0 714 | #: field:gdpr.object,write_uid:0 715 | #: field:gdpr.restrict_method,write_uid:0 716 | #: field:gdpr.role,write_uid:0 717 | #: field:gdpr.security,write_uid:0 718 | #: field:gdpr.subject,write_uid:0 719 | #: field:gdpr.system,write_uid:0 720 | msgid "Last Updated by" 721 | msgstr "" 722 | 723 | #. module: gdpr_inventory 724 | #: field:gdpr.bp,write_date:0 725 | #: field:gdpr.category,write_date:0 726 | #: field:gdpr.consent,write_date:0 727 | #: field:gdpr.data_type,write_date:0 728 | #: field:gdpr.inventory,write_date:0 729 | #: field:gdpr.inventory.state,write_date:0 730 | #: field:gdpr.lawsection,write_date:0 731 | #: field:gdpr.object,write_date:0 732 | #: field:gdpr.restrict_method,write_date:0 733 | #: field:gdpr.role,write_date:0 734 | #: field:gdpr.security,write_date:0 735 | #: field:gdpr.subject,write_date:0 736 | #: field:gdpr.system,write_date:0 737 | msgid "Last Updated on" 738 | msgstr "" 739 | 740 | #. module: gdpr_inventory 741 | #: field:gdpr.inventory,lawsection_id:0 742 | msgid "Law Section" 743 | msgstr "" 744 | 745 | #. module: gdpr_inventory 746 | #: field:gdpr.inventory,lawsection_desc:0 747 | msgid "Law section Explanation" 748 | msgstr "" 749 | 750 | #. module: gdpr_inventory 751 | #: model:ir.model,name:gdpr_inventory.model_gdpr_lawsection 752 | msgid "Lawfullness of processing" 753 | msgstr "" 754 | 755 | #. module: gdpr_inventory 756 | #: view:gdpr.inventory:gdpr_inventory.view_gdpr_inventory_filter 757 | #: view:gdpr.inventory:gdpr_inventory.view_gdpr_inventory_form 758 | msgid "Lawsection" 759 | msgstr "" 760 | 761 | #. module: gdpr_inventory 762 | #: view:gdpr.inventory:gdpr_inventory.view_gdpr_inventory_form 763 | msgid "Lawsection description" 764 | msgstr "" 765 | 766 | #. module: gdpr_inventory 767 | #: model:gdpr.lawsection,name:gdpr_inventory.lawfullness_obligation 768 | msgid "Legal Obligation" 769 | msgstr "" 770 | 771 | #. module: gdpr_inventory 772 | #: model:gdpr.lawsection,name:gdpr_inventory.lawfullness_legitimate_interest 773 | msgid "Legitimate Interest" 774 | msgstr "" 775 | 776 | #. module: gdpr_inventory 777 | #: selection:gdpr.restrict_method,type:0 778 | msgid "Manual" 779 | msgstr "" 780 | 781 | #. module: gdpr_inventory 782 | #: view:gdpr.object:gdpr_inventory.view_gdpr_object_filter 783 | #: field:gdpr.object,manual:0 784 | msgid "Manual Action Required" 785 | msgstr "" 786 | 787 | #. module: gdpr_inventory 788 | #: field:gdpr.inventory,manual_count:0 789 | msgid "Manual Count" 790 | msgstr "" 791 | 792 | #. module: gdpr_inventory 793 | #: field:gdpr.consent,message_ids:0 794 | #: field:gdpr.inventory,message_ids:0 795 | #: field:gdpr.restrict_method,message_ids:0 796 | msgid "Messages" 797 | msgstr "" 798 | 799 | #. module: gdpr_inventory 800 | #: help:gdpr.consent,message_ids:0 801 | #: help:gdpr.inventory,message_ids:0 802 | #: help:gdpr.restrict_method,message_ids:0 803 | msgid "Messages and communication history" 804 | msgstr "" 805 | 806 | #. module: gdpr_inventory 807 | #: selection:gdpr.consent,state:0 808 | msgid "Missing" 809 | msgstr "" 810 | 811 | #. module: gdpr_inventory 812 | #: help:gdpr.inventory,inventory_model:0 813 | msgid "Model (Class) for this Inventory" 814 | msgstr "" 815 | 816 | #. module: gdpr_inventory 817 | #: field:gdpr.bp,name:0 818 | #: view:gdpr.category:gdpr_inventory.view_gdpr_category_filter 819 | #: field:gdpr.category,name:0 820 | #: view:gdpr.consent:gdpr_inventory.view_gdpr_consent_filter 821 | #: field:gdpr.consent,name:0 822 | #: field:gdpr.data_type,name:0 823 | #: field:gdpr.inventory,name:0 824 | #: view:gdpr.inventory.state:gdpr_inventory.view_gdpr_inventory_state_filter 825 | #: field:gdpr.inventory.state,name:0 826 | #: view:gdpr.lawsection:gdpr_inventory.view_gdpr_lawsection_filter 827 | #: field:gdpr.lawsection,name:0 828 | #: field:gdpr.object,name:0 829 | #: view:gdpr.restrict_method:gdpr_inventory.view_gdpr_restrict_method_filter 830 | #: field:gdpr.restrict_method,name:0 831 | #: field:gdpr.role,name:0 832 | #: view:gdpr.security:gdpr_inventory.view_gdpr_security_filter 833 | #: field:gdpr.security,name:0 834 | #: field:gdpr.subject,name:0 835 | #: field:gdpr.system,name:0 836 | msgid "Name" 837 | msgstr "" 838 | 839 | #. module: gdpr_inventory 840 | #: view:gdpr.inventory:gdpr_inventory.view_gdpr_inventory_filter 841 | msgid "Not Ceased" 842 | msgstr "" 843 | 844 | #. module: gdpr_inventory 845 | #: help:gdpr.inventory,restrict_time_days:0 846 | msgid "Number of days before this data will be restricted" 847 | msgstr "" 848 | 849 | #. module: gdpr_inventory 850 | #: field:gdpr.consent,record_id:0 851 | #: field:gdpr.object,object_id:0 852 | msgid "Object" 853 | msgstr "" 854 | 855 | #. module: gdpr_inventory 856 | #: field:gdpr.inventory,object_count:0 857 | msgid "Object Count" 858 | msgstr "" 859 | 860 | #. module: gdpr_inventory 861 | #: field:gdpr.object,object_res_id:0 862 | msgid "Object ID" 863 | msgstr "" 864 | 865 | #. module: gdpr_inventory 866 | #: field:gdpr.object,object_model:0 867 | msgid "Object Model" 868 | msgstr "" 869 | 870 | #. module: gdpr_inventory 871 | #: help:gdpr.consent,record_id:0 872 | msgid "Object that is consented for processing of personal data" 873 | msgstr "" 874 | 875 | #. module: gdpr_inventory 876 | #: view:gdpr.inventory:gdpr_inventory.view_gdpr_inventory_form 877 | #: view:gdpr.inventory:gdpr_inventory.view_gdpr_inventory_kanban 878 | #: field:gdpr.inventory,object_ids:0 879 | #: view:res.partner:gdpr_inventory.view_partner_form 880 | msgid "Objects" 881 | msgstr "" 882 | 883 | #. module: gdpr_inventory 884 | #: field:gdpr.inventory,role:0 885 | msgid "Our Role" 886 | msgstr "" 887 | 888 | #. module: gdpr_inventory 889 | #: view:gdpr.inventory:gdpr_inventory.view_gdpr_inventory_filter 890 | msgid "Parent" 891 | msgstr "" 892 | 893 | #. module: gdpr_inventory 894 | #: view:gdpr.consent:gdpr_inventory.view_gdpr_consent_filter 895 | #: view:gdpr.object:gdpr_inventory.view_gdpr_object_filter 896 | #: model:ir.model,name:gdpr_inventory.model_res_partner 897 | msgid "Partner" 898 | msgstr "" 899 | 900 | #. module: gdpr_inventory 901 | #: field:gdpr.inventory,partner_count:0 902 | msgid "Partner Count" 903 | msgstr "" 904 | 905 | #. module: gdpr_inventory 906 | #: field:gdpr.inventory,partner_domain:0 907 | msgid "Partner Domain" 908 | msgstr "" 909 | 910 | #. module: gdpr_inventory 911 | #: field:gdpr.inventory,partner_fields_ids:0 912 | msgid "Partner Fields" 913 | msgstr "" 914 | 915 | #. module: gdpr_inventory 916 | #: field:gdpr.consent,partner_id:0 917 | msgid "Partner id" 918 | msgstr "" 919 | 920 | #. module: gdpr_inventory 921 | #: view:gdpr.inventory:gdpr_inventory.view_gdpr_inventory_form 922 | #: view:gdpr.inventory:gdpr_inventory.view_gdpr_inventory_kanban 923 | #: field:gdpr.inventory,partner_ids:0 924 | #: field:gdpr.object,partner_id:0 925 | msgid "Partners" 926 | msgstr "" 927 | 928 | #. module: gdpr_inventory 929 | #: selection:gdpr.inventory,role:0 930 | msgid "Processor" 931 | msgstr "" 932 | 933 | #. module: gdpr_inventory 934 | #: selection:gdpr.restrict_method,type:0 935 | msgid "Pseudonymisation" 936 | msgstr "" 937 | 938 | #. module: gdpr_inventory 939 | #: field:gdpr.inventory,pseudo_values:0 940 | msgid "Pseudonymisation Values" 941 | msgstr "" 942 | 943 | #. module: gdpr_inventory 944 | #: model:gdpr.lawsection,name:gdpr_inventory.lawfullness_public_interest 945 | msgid "Public Interest" 946 | msgstr "" 947 | 948 | #. module: gdpr_inventory 949 | #: view:gdpr.inventory:gdpr_inventory.view_gdpr_inventory_form 950 | msgid "Purpose" 951 | msgstr "" 952 | 953 | #. module: gdpr_inventory 954 | #: view:gdpr.inventory:gdpr_inventory.view_gdpr_inventory_form 955 | msgid "Purpose Limitation" 956 | msgstr "" 957 | 958 | #. module: gdpr_inventory 959 | #: field:gdpr.inventory,purpose_limitation:0 960 | msgid "Purpose limitation" 961 | msgstr "" 962 | 963 | #. module: gdpr_inventory 964 | #: help:gdpr.inventory,restrict_domain_code:0 965 | msgid "Python code that will be executed before domain evaluation. Any variables defined here will be available during domain evaluation.\n" 966 | "\n" 967 | "Available variables:\n" 968 | "* env: Odoo environment.\n" 969 | "* time: time python module.\n" 970 | "* datetime: datetime python module.\n" 971 | "* dateutil: dateutil python module.\n" 972 | "* timezone: pytz.timezone python module." 973 | msgstr "" 974 | 975 | #. module: gdpr_inventory 976 | #: help:gdpr.inventory,inventory_domain_code:0 977 | msgid "Python code that will be executed before domain evaluation. Any variables defined here will be available during domain evaluation.\n" 978 | "\n" 979 | "Available variables:\n" 980 | "* env: Odoo environment.\n" 981 | "* time: time python module.\n" 982 | "* datetime: datetime python module.\n" 983 | "* dateutil: dateutil python module.\n" 984 | "* timezone: pytz.timezone python module.\n" 985 | "* restrict_days: Restrict time of this inventory" 986 | msgstr "" 987 | 988 | #. module: gdpr_inventory 989 | #: help:gdpr.inventory,restrict_code:0 990 | msgid "Python code to run when restricting records.\n" 991 | "\n" 992 | "Available variables:\n" 993 | "* env: Odoo environment.\n" 994 | "* time: time python module.\n" 995 | "* datetime: datetime python module.\n" 996 | "* dateutil: dateutil python module.\n" 997 | "* timezone: pytz.timezone python module.\n" 998 | "* inventory: This inventory record.\n" 999 | "* objects: The gdpr objects to be restricted (gdpr.object). Actual records to be processed can be accessed through objects.mapped('object_id')." 1000 | msgstr "" 1001 | 1002 | #. module: gdpr_inventory 1003 | #: model:ir.actions.act_window,name:gdpr_inventory.act_res_partner_2_gdpr_consent 1004 | msgid "Res Partner 2 GDPR Consents" 1005 | msgstr "" 1006 | 1007 | #. module: gdpr_inventory 1008 | #: model:ir.actions.act_window,name:gdpr_inventory.act_res_partner_2_gdpr_object 1009 | msgid "Res Partner 2 GDPR Objects" 1010 | msgstr "" 1011 | 1012 | #. module: gdpr_inventory 1013 | #: view:gdpr.inventory:gdpr_inventory.view_gdpr_inventory_filter 1014 | #: field:gdpr.inventory,user_id:0 1015 | msgid "Responsible" 1016 | msgstr "" 1017 | 1018 | #. module: gdpr_inventory 1019 | #: field:gdpr.inventory,restrict_domain:0 1020 | msgid "Restrict Domain" 1021 | msgstr "" 1022 | 1023 | #. module: gdpr_inventory 1024 | #: field:gdpr.inventory,inventory_domain_code:0 1025 | #: field:gdpr.inventory,restrict_domain_code:0 1026 | msgid "Restrict Domain Code" 1027 | msgstr "" 1028 | 1029 | #. module: gdpr_inventory 1030 | #: code:addons/gdpr_inventory/gdpr.py:538 1031 | #, python-format 1032 | msgid "Restrict Erase" 1033 | msgstr "" 1034 | 1035 | #. module: gdpr_inventory 1036 | #: code:addons/gdpr_inventory/gdpr.py:548 1037 | #: code:addons/gdpr_inventory/gdpr.py:554 1038 | #: code:addons/gdpr_inventory/gdpr.py:560 1039 | #: code:addons/gdpr_inventory/gdpr.py:566 1040 | #, python-format 1041 | msgid "Restrict Hide" 1042 | msgstr "" 1043 | 1044 | #. module: gdpr_inventory 1045 | #: view:gdpr.inventory:gdpr_inventory.view_gdpr_inventory_filter 1046 | #: field:gdpr.inventory,restrict_method_id:0 1047 | #: model:ir.model,name:gdpr_inventory.model_gdpr_restrict_method 1048 | msgid "Restrict Method" 1049 | msgstr "" 1050 | 1051 | #. module: gdpr_inventory 1052 | #: view:gdpr.inventory:gdpr_inventory.view_gdpr_inventory_form 1053 | msgid "Restrict Objects" 1054 | msgstr "" 1055 | 1056 | #. module: gdpr_inventory 1057 | #: field:gdpr.inventory,restrict_time_days:0 1058 | msgid "Restrict time" 1059 | msgstr "" 1060 | 1061 | #. module: gdpr_inventory 1062 | #: view:gdpr.object:gdpr_inventory.view_gdpr_object_filter 1063 | #: field:gdpr.object,restricted:0 1064 | msgid "Restricted" 1065 | msgstr "" 1066 | 1067 | #. module: gdpr_inventory 1068 | #: field:gdpr.inventory,restrict_code:0 1069 | msgid "Restriction Code" 1070 | msgstr "" 1071 | 1072 | #. module: gdpr_inventory 1073 | #: field:gdpr.inventory,restrict_desc:0 1074 | msgid "Restriction Description" 1075 | msgstr "" 1076 | 1077 | #. module: gdpr_inventory 1078 | #: field:gdpr.inventory,restrict_type:0 1079 | msgid "Restriction Type" 1080 | msgstr "" 1081 | 1082 | #. module: gdpr_inventory 1083 | #: view:gdpr.inventory:gdpr_inventory.view_gdpr_inventory_form 1084 | msgid "Restrictions" 1085 | msgstr "" 1086 | 1087 | #. module: gdpr_inventory 1088 | #: view:gdpr.inventory:gdpr_inventory.view_gdpr_inventory_filter 1089 | msgid "Role" 1090 | msgstr "" 1091 | 1092 | #. module: gdpr_inventory 1093 | #: view:gdpr.category:gdpr_inventory.view_gdpr_category_filter 1094 | msgid "Search GDPR Category" 1095 | msgstr "" 1096 | 1097 | #. module: gdpr_inventory 1098 | #: view:gdpr.consent:gdpr_inventory.view_gdpr_consent_filter 1099 | msgid "Search GDPR Consent" 1100 | msgstr "" 1101 | 1102 | #. module: gdpr_inventory 1103 | #: view:gdpr.inventory:gdpr_inventory.view_gdpr_inventory_filter 1104 | msgid "Search GDPR Inventory" 1105 | msgstr "" 1106 | 1107 | #. module: gdpr_inventory 1108 | #: view:gdpr.inventory.state:gdpr_inventory.view_gdpr_inventory_state_filter 1109 | msgid "Search GDPR Inventory State" 1110 | msgstr "" 1111 | 1112 | #. module: gdpr_inventory 1113 | #: view:gdpr.lawsection:gdpr_inventory.view_gdpr_lawsection_filter 1114 | msgid "Search GDPR Lawsection" 1115 | msgstr "" 1116 | 1117 | #. module: gdpr_inventory 1118 | #: view:gdpr.object:gdpr_inventory.view_gdpr_object_filter 1119 | msgid "Search GDPR Object" 1120 | msgstr "" 1121 | 1122 | #. module: gdpr_inventory 1123 | #: view:gdpr.restrict_method:gdpr_inventory.view_gdpr_restrict_method_filter 1124 | msgid "Search GDPR Restrict Method" 1125 | msgstr "" 1126 | 1127 | #. module: gdpr_inventory 1128 | #: view:gdpr.security:gdpr_inventory.view_gdpr_security_filter 1129 | msgid "Search GDPR Security" 1130 | msgstr "" 1131 | 1132 | #. module: gdpr_inventory 1133 | #: field:gdpr.inventory,security_of_processing_ids:0 1134 | msgid "Security" 1135 | msgstr "" 1136 | 1137 | #. module: gdpr_inventory 1138 | #: help:gdpr.inventory,security_of_processing_ids:0 1139 | #: model:ir.model,name:gdpr_inventory.model_gdpr_security 1140 | msgid "Security of processing" 1141 | msgstr "" 1142 | 1143 | #. module: gdpr_inventory 1144 | #: field:gdpr.bp,sequence:0 1145 | #: field:gdpr.category,sequence:0 1146 | #: field:gdpr.inventory.state,sequence:0 1147 | #: field:gdpr.lawsection,sequence:0 1148 | msgid "Sequence" 1149 | msgstr "" 1150 | 1151 | #. module: gdpr_inventory 1152 | #: selection:gdpr.inventory,type_of_personal_data:0 1153 | msgid "Special Category" 1154 | msgstr "" 1155 | 1156 | #. module: gdpr_inventory 1157 | #: view:gdpr.consent:gdpr_inventory.view_gdpr_consent_filter 1158 | #: field:gdpr.consent,state:0 1159 | #: view:gdpr.inventory:gdpr_inventory.view_gdpr_inventory_filter 1160 | #: field:gdpr.inventory,state:0 1161 | #: field:gdpr.inventory,state_id:0 1162 | msgid "State" 1163 | msgstr "" 1164 | 1165 | #. module: gdpr_inventory 1166 | #: field:gdpr.consent,message_summary:0 1167 | #: field:gdpr.inventory,message_summary:0 1168 | #: field:gdpr.restrict_method,message_summary:0 1169 | msgid "Summary" 1170 | msgstr "" 1171 | 1172 | #. module: gdpr_inventory 1173 | #: field:gdpr.inventory.state,technical_name:0 1174 | msgid "Technical Name" 1175 | msgstr "" 1176 | 1177 | #. module: gdpr_inventory 1178 | #: help:gdpr.inventory,data_local:0 1179 | msgid "The data is stored in this Odoo database and should be automatically inventoried." 1180 | msgstr "" 1181 | 1182 | #. module: gdpr_inventory 1183 | #: help:gdpr.inventory,data_collection_ids:0 1184 | msgid "The system that is used to collect data for this inventory." 1185 | msgstr "" 1186 | 1187 | #. module: gdpr_inventory 1188 | #: help:gdpr.inventory,data_storage_ids:0 1189 | msgid "The system that is used to store data for this inventory." 1190 | msgstr "" 1191 | 1192 | #. module: gdpr_inventory 1193 | #: help:gdpr.object,restricted:0 1194 | msgid "This record has been restricted." 1195 | msgstr "" 1196 | 1197 | #. module: gdpr_inventory 1198 | #: help:gdpr.object,manual:0 1199 | msgid "This record needs attention." 1200 | msgstr "" 1201 | 1202 | #. module: gdpr_inventory 1203 | #: help:gdpr.inventory.state,fold:0 1204 | msgid "This stage is folded in the kanban view when there are no records in that state to display." 1205 | msgstr "" 1206 | 1207 | #. module: gdpr_inventory 1208 | #: field:gdpr.inventory,type_of_personal_data:0 1209 | #: view:gdpr.restrict_method:gdpr_inventory.view_gdpr_restrict_method_filter 1210 | #: field:gdpr.restrict_method,type:0 1211 | msgid "Type" 1212 | msgstr "" 1213 | 1214 | #. module: gdpr_inventory 1215 | #: field:gdpr.consent,message_unread:0 1216 | #: field:gdpr.inventory,message_unread:0 1217 | #: field:gdpr.restrict_method,message_unread:0 1218 | msgid "Unread Messages" 1219 | msgstr "" 1220 | 1221 | #. module: gdpr_inventory 1222 | #: view:gdpr.object:gdpr_inventory.view_gdpr_object_filter 1223 | msgid "Unrestricted" 1224 | msgstr "" 1225 | 1226 | #. module: gdpr_inventory 1227 | #: view:gdpr.inventory:gdpr_inventory.view_gdpr_inventory_form 1228 | msgid "Update Objects" 1229 | msgstr "" 1230 | 1231 | #. module: gdpr_inventory 1232 | #: model:ir.actions.act_window,name:gdpr_inventory.act_gdpr_inventory_2_gdpr_object 1233 | msgid "View GDPR Objects" 1234 | msgstr "" 1235 | 1236 | #. module: gdpr_inventory 1237 | #: model:gdpr.lawsection,name:gdpr_inventory.lawfullness_vital_interest 1238 | msgid "Vital Interest" 1239 | msgstr "" 1240 | 1241 | #. module: gdpr_inventory 1242 | #: selection:gdpr.consent,state:0 1243 | msgid "Withdrawn" 1244 | msgstr "" 1245 | 1246 | #. module: gdpr_inventory 1247 | #: model:gdpr.lawsection,name:gdpr_inventory.lawfullness_consent 1248 | msgid "consent" 1249 | msgstr "" 1250 | 1251 | #. module: gdpr_inventory 1252 | #: field:gdpr.inventory,consent_add:0 1253 | msgid "consent Add" 1254 | msgstr "" 1255 | 1256 | #. module: gdpr_inventory 1257 | #: field:gdpr.inventory,consent_desc:0 1258 | msgid "consent Explanation" 1259 | msgstr "" 1260 | 1261 | #. module: gdpr_inventory 1262 | #: field:gdpr.inventory,consent_remove:0 1263 | msgid "consent Remove" 1264 | msgstr "" 1265 | 1266 | #. module: gdpr_inventory 1267 | #: view:gdpr.inventory:gdpr_inventory.view_gdpr_inventory_form 1268 | msgid "foobar gazonk" 1269 | msgstr "" 1270 | 1271 | -------------------------------------------------------------------------------- /gdpr_inventory/report/__init__.py: -------------------------------------------------------------------------------- 1 | #import gdpr_report 2 | -------------------------------------------------------------------------------- /gdpr_inventory/report/gdpr_report.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | ############################################################################## 3 | # 4 | # OpenERP, Open Source Management Solution, third party addon 5 | # Copyright (C) 2004-2018 Vertel AB (). 6 | # 7 | # This program is free software: you can redistribute it and/or modify 8 | # it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | # 20 | ############################################################################## 21 | from openerp import models, fields, api, _ 22 | from datetime import timedelta 23 | from openerp.exceptions import Warning 24 | from openerp import tools 25 | 26 | class gdpr_report_inventory(models.Model): 27 | _name = 'gdpr.report.inventory' 28 | _description = 'GDPR Inventory Statistics' 29 | _auto = False 30 | _rec_name = 'color' 31 | 32 | 33 | color = fields.Integer(string='Color Index') 34 | name = fields.Char(string="Name", translate=True, required=True) 35 | state_id = fields.Many2one(comodel_name='gdpr.inventory.state', string='State', track_visibility='onchange') 36 | type_of_personal_data = fields.Selection(selection=[('general', 'General'), ('special', 'Special Category'), ('child', 'Childs consent'), ('criminal', 'Criminal related')], string="Type", 37 | help="General: non sensitive personal data, Special: sensitive personal data, Child consent: personal data concerning under aged persons, Criminal relared: personal data relating to criminal convictions and offences") 38 | purpose_limitation = fields.Text(track_visibility='onchange', translate=True, required=True) 39 | user_id = fields.Many2one(comodel_name="res.users", string="Responsible", track_visibility='onchange', required=True) 40 | lawsection_id = fields.Many2one(comodel_name="gdpr.lawsection", string="Law Section", required=True) 41 | consent = fields.Boolean(related='lawsection_id.consent') 42 | consent_ids = fields.One2many(comodel_name='gdpr.consent', inverse_name='gdpr_id', string='Consents') 43 | @api.depends('consent_ids') 44 | @api.one 45 | def _consent_count(self): 46 | self.consent_count = len(self.consent_ids) 47 | consent_count = fields.Integer(string='Consent Count', compute='_consent_count', store=True) 48 | restrict_time_days = fields.Integer(string='Restrict time', help="Number of days before this data will be restricted", track_visibility='onchange') 49 | restrict_method_id = fields.Many2one(comodel_name="gdpr.restrict_method", string="Restrict Method", track_visibility='onchange') 50 | restrict_type = fields.Selection(string='Restriction Type', related='restrict_method_id.type') 51 | inventory_model = fields.Many2one(comodel_name="ir.model", string="Inventory Model", help="Model (Class) for this Inventory") 52 | @api.depends('object_ids.partner_id') 53 | @api.one 54 | def _partner_ids(self): 55 | self.partner_ids = self.object_ids.mapped('partner_id') 56 | self.partner_count = len(self.partner_ids) 57 | partner_ids = fields.Many2many(string='Partners', comodel_name='res.partner', compute='_partner_ids', store=True) 58 | partner_count = fields.Integer(string='Partner Count', compute='_partner_ids', store=True) 59 | object_ids = fields.One2many(string='Objects', comodel_name='gdpr.object', inverse_name='gdpr_id') 60 | @api.depends('object_ids') 61 | @api.one 62 | def _object_count(self): 63 | self.object_count = len(self.object_ids) 64 | object_count = fields.Integer(string='Object Count', compute='_object_count', store=True) 65 | 66 | 67 | 68 | def _select(self): 69 | select_str = """ 70 | SELECT min(id), 71 | color, 72 | name, 73 | state_id, 74 | type_of_personal_data, 75 | purpose_limitation, 76 | user_id, 77 | lawsection_id, 78 | consent_count, 79 | restrict_time_days, 80 | restrict_method_id, 81 | restrict_type, 82 | inventory_model, 83 | partner_count 84 | """ 85 | return select_str 86 | 87 | def _from(self): 88 | from_str = """ 89 | gdpr_inventory 90 | """ 91 | return from_str 92 | 93 | def _group_by(self): 94 | group_by_str = """ 95 | GROUP BY ( 96 | color, 97 | state_id, 98 | type_of_personal_data, 99 | user_id, 100 | lawsection_id, 101 | restrict_method_id, 102 | restrict_type, 103 | inventory_model 104 | """ 105 | return group_by_str 106 | 107 | def init(self, cr): 108 | # self._table = sale_report 109 | tools.drop_view_if_exists(cr, self._table) 110 | cr.execute("""CREATE or REPLACE VIEW %s as ( 111 | %s 112 | FROM %s 113 | %s 114 | )""" % (self._table, self._select(), self._from(), self._group_by())) 115 | 116 | # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: -------------------------------------------------------------------------------- /gdpr_inventory/report/gdpr_report_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | gdpr.report.inventory.graph 7 | gdpr.inventory 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | Without responsibe 20 | gdpr.inventory 21 | 24 | 25 | {'group_by': ['state_id'], 'measures': ['partner_count']} 26 | 27 | 28 | 48 | 49 | 50 | gdpr.inventory.search 51 | gdpr.inventory 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 62 | 63 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | GDPR Analysis 89 | gdpr.inventory.report 90 | form 91 | graph 92 | 93 | 94 | {'search_default_Sales':1, 'group_by_no_leaf':1,'group_by':[]} 95 | This report performs analysis on your GDPR inventorier. 96 | 97 | 98 | 99 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /gdpr_inventory/security/gdpr_security.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | GDPR 7 | Helps you to manage GDPR inventory 8 | 6 9 | 10 | 11 | 12 | User 13 | 14 | 15 | the user will have access to his own data in GDPR inventory. 16 | 17 | 18 | Officer 19 | 20 | 21 | the user will have full control to own data in GDPR inventory. 22 | 23 | 24 | Manager 25 | 26 | 27 | 28 | the user will have full control to all data in GDPR inventory. 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /gdpr_inventory/security/ir.model.access.csv: -------------------------------------------------------------------------------- 1 | id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink 2 | access_gdpr_inventory_user,gdpr.inventory.user,model_gdpr_inventory,base.group_gdpr_user,1,0,0,0 3 | access_gdpr_inventory_officer,gdpr.inventory.officer,model_gdpr_inventory,base.group_gdpr_officer,1,1,1,1 4 | access_gdpr_inventory_manager,gdpr.inventory.manager,model_gdpr_inventory,base.group_gdpr_manager,1,1,1,1 5 | access_gdpr_object_user,gdpr.object.user,model_gdpr_object,base.group_gdpr_user,1,0,0,0 6 | access_gdpr_object_officer,gdpr.object.officer,model_gdpr_object,base.group_gdpr_officer,1,1,1,1 7 | access_gdpr_object_manager,gdpr.object.manager,model_gdpr_object,base.group_gdpr_manager,1,1,1,1 8 | access_gdpr_consent_user,gdpr.consent.user,model_gdpr_consent,base.group_gdpr_user,1,0,0,0 9 | access_gdpr_consent_officer,gdpr.consent.officer,model_gdpr_consent,base.group_gdpr_officer,1,1,1,1 10 | access_gdpr_consent_manager,gdpr.consent.manager,model_gdpr_consent,base.group_gdpr_manager,1,1,1,1 11 | access_gdpr_inventory_state_user,gdpr.inventory.state.user,model_gdpr_inventory_state,base.group_gdpr_user,1,0,0,0 12 | access_gdpr_inventory_state_officer,gdpr.inventory.state.officer,model_gdpr_inventory_state,base.group_gdpr_officer,1,0,0,0 13 | access_gdpr_inventory_state_manager,gdpr.inventory.state.manager,model_gdpr_inventory_state,base.group_gdpr_manager,1,1,1,1 14 | access_gdpr_lawsection_user,gdpr.lawsection.user,model_gdpr_lawsection,base.group_gdpr_user,1,0,0,0 15 | access_gdpr_lawsection_officer,gdpr.lawsection.officer,model_gdpr_lawsection,base.group_gdpr_officer,1,1,1,1 16 | access_gdpr_lawsection_manager,gdpr.lawsection.manager,model_gdpr_lawsection,base.group_gdpr_manager,1,1,1,1 17 | access_gdpr_category_user,gdpr.category.user,model_gdpr_category,base.group_gdpr_user,1,0,0,0 18 | access_gdpr_category_officer,gdpr.category.officer,model_gdpr_category,base.group_gdpr_officer,1,1,1,1 19 | access_gdpr_category_manager,gdpr.category.manager,model_gdpr_category,base.group_gdpr_manager,1,1,1,1 20 | access_gdpr_bp_user,gdpr.bp.user,model_gdpr_bp,base.group_gdpr_user,1,0,0,0 21 | access_gdpr_bp_officer,gdpr.bp.officer,model_gdpr_bp,base.group_gdpr_officer,1,1,1,1 22 | access_gdpr_bp_manager,gdpr.bp.manager,model_gdpr_bp,base.group_gdpr_manager,1,1,1,1 23 | access_gdpr_security_user,gdpr.security.user,model_gdpr_security,base.group_gdpr_user,1,0,0,0 24 | access_gdpr_security_officer,gdpr.security.officer,model_gdpr_security,base.group_gdpr_officer,1,1,1,1 25 | access_gdpr_security_manager,gdpr.security.manager,model_gdpr_security,base.group_gdpr_manager,1,1,1,1 26 | access_gdpr_restrict_method_user,gdpr.restrict_method.user,model_gdpr_restrict_method,base.group_gdpr_user,1,0,0,0 27 | access_gdpr_restrict_method_officer,gdpr.restrict_method.officer,model_gdpr_restrict_method,base.group_gdpr_officer,1,1,1,1 28 | access_gdpr_restrict_method_manager,gdpr.restrict_method.manager,model_gdpr_restrict_method,base.group_gdpr_manager,1,1,1,1 29 | gdpr_data_type_user,gdpr.data_type.user,model_gdpr_data_type,base.group_gdpr_user,1,0,0,0 30 | gdpr_data_type_officer,gdpr.data_type.officer,model_gdpr_data_type,base.group_gdpr_officer,1,1,1,1 31 | gdpr_data_type_manager,gdpr.data_type.manager,model_gdpr_data_type,base.group_gdpr_manager,1,1,1,1 32 | gdpr_role_user,gdpr.role.user,model_gdpr_role,base.group_gdpr_user,1,0,0,0 33 | gdpr_role_officer,gdpr.role.officer,model_gdpr_role,base.group_gdpr_officer,1,1,1,1 34 | gdpr_role_manager,gdpr.role.manager,model_gdpr_role,base.group_gdpr_manager,1,1,1,1 35 | gdpr_subject_user,gdpr.subject.user,model_gdpr_subject,base.group_gdpr_user,1,0,0,0 36 | gdpr_subject_officer,gdpr.subject.officer,model_gdpr_subject,base.group_gdpr_officer,1,1,1,1 37 | gdpr_subject_manager,gdpr.subject.manager,model_gdpr_subject,base.group_gdpr_manager,1,1,1,1 38 | gdpr_system_user,gdpr.system.user,model_gdpr_system,base.group_gdpr_user,1,0,0,0 39 | gdpr_system_officer,gdpr.system.officer,model_gdpr_system,base.group_gdpr_officer,1,1,1,1 40 | gdpr_system_manager,gdpr.system.manager,model_gdpr_system,base.group_gdpr_manager,1,1,1,1 41 | -------------------------------------------------------------------------------- /gdpr_inventory/static/src/img/contract.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vertelab/odoo-gdpr/252aeca3c1b2dfc4827fa8f68b7221f54ec1a520/gdpr_inventory/static/src/img/contract.jpg -------------------------------------------------------------------------------- /gdpr_mass_mailing/__init__.py: -------------------------------------------------------------------------------- 1 | import gdpr 2 | -------------------------------------------------------------------------------- /gdpr_mass_mailing/__openerp__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | ############################################################################## 3 | # 4 | # OpenERP, Open Source Management Solution, third party addon 5 | # Copyright (C) 2004-2017 Vertel AB (). 6 | # 7 | # This program is free software: you can redistribute it and/or modify 8 | # it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | # 20 | ############################################################################## 21 | 22 | { 23 | 'name': 'Mass Mailing GDPR', 24 | 'version': '0.1', 25 | 'category': 'Other', 26 | 'summary': 'GDRP-compliant mailing lists', 27 | 'description': """ 28 | 29 | * GDPR Inventory 30 | 31 | """, 32 | 'images': ['static/description/gdpr.png'], 33 | 'license': 'AGPL-3', 34 | 'author': 'Vertel AB', 35 | 'website': 'http://www.vertel.se', 36 | 'depends': ['gdpr_inventory', 'mass_mailing'], 37 | 'data': [ 38 | 'gdpr_view.xml', 39 | 'template.xml', 40 | 'security/ir.model.access.csv', 41 | ], 42 | 'application': False, 43 | 'installable': True, 44 | } 45 | # vim:expandtab:smartindent:tabstop=4s:softtabstop=4:shiftwidth=4: 46 | -------------------------------------------------------------------------------- /gdpr_mass_mailing/gdpr.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | ############################################################################## 3 | # 4 | # OpenERP, Open Source Management Solution, third party addon 5 | # Copyright (C) 2004-2017 Vertel AB (). 6 | # 7 | # This program is free software: you can redistribute it and/or modify 8 | # it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | # 20 | ############################################################################## 21 | from openerp import models, fields, api, _, http 22 | from datetime import timedelta 23 | 24 | from openerp.addons.mass_mailing.controllers.main import MassMailController 25 | from openerp.http import request 26 | 27 | import logging 28 | _logger = logging.getLogger(__name__) 29 | 30 | # https://www.privacy-regulation.eu 31 | class MailMassMailingList(models.Model): 32 | _inherit = 'mail.mass_mailing.list' 33 | 34 | #consent_ids = fields.One2many(string='Recipients', comodel_name='gdpr.consent') 35 | gdpr_id = fields.Many2one(string='GDPR Inventory', comodel_name='gdpr.inventory') 36 | 37 | 38 | class MailMassMailing(models.Model): 39 | _inherit = 'mail.mass_mailing' 40 | 41 | gdpr_id = fields.Many2one(string='GDPR Inventory', comodel_name='gdpr.inventory') 42 | gdpr_domain = fields.Text(string='GDPR Object IDs', compute='get_gdpr_domain') 43 | gdpr_consent = fields.Selection(selection=[('given', 'Given'), ('withdrawn', 'Withdrawn'), ('missing', 'Missing')], string='Consent State') 44 | gdpr_lawsection_consent = fields.Boolean(related='gdpr_id.lawsection_id.consent') 45 | recipients = fields.Integer(readonly=True) 46 | gdpr_mailing_list_ids = fields.Many2many(comodel_name='gdpr.mail.mass_mailing.list', string='GDPR Mailing Lists') 47 | gdpr_consent_collected = fields.Many2many(string='Collected GDPR Inventory', comodel_name='gdpr.inventory') 48 | wp_cond_consent_ids = fields.Many2many(comodel_name='gdpr.inventory', string='Conditional', relation='mail_mass_mailing_gdpr_inventory_cond_rel', column1='mailing_id', column2='gdpr_id', help='Conditional Consents for Web Page', domain="[('lawsection_id.consent', '=', True)]") 49 | wp_uncond_consent_ids = fields.Many2many(comodel_name='gdpr.inventory', string='Unconditional', relation='mail_mass_mailing_gdpr_inventory_uncond_rel', column1='mailing_id', column2='gdpr_id', help='Unconditional Consents for Web Page', domain="[('lawsection_id.consent', '=', True)]") 50 | wp_consent_url = fields.Char(string='Web Page URL', default='$website_consent', help='URL for give consent.', readonly=True) 51 | wp_mailing_title = fields.Char(string='Web Page Title') 52 | wp_mailing_txt = fields.Html(string='Web Page Text') 53 | group_per_object = fields.Boolean(string='Group per object', help='When this is not checked, GDPR objects will show as separate line in the inventories to your recipents.') 54 | # ~ def _wp_mailing_url(self): 55 | # ~ self.wp_mailing_url = '%s' %(self.env['ir.config_parameter'].get_param('web.base.url'), self.id, _('Give Consents')) 56 | # ~ wp_mailing_url = fields.Char(string='Web Page URL', compute='_wp_mailing_url') 57 | 58 | @api.onchange('gdpr_id', 'gdpr_consent') 59 | def get_gdpr_domain(self): 60 | domain = [] 61 | if self.gdpr_id: 62 | if self.gdpr_id.lawsection_id.consent: 63 | if self.gdpr_consent in ['given', 'withdrawn', 'missing']: 64 | object_ids = [d['gdpr_object_id'][0] for d in self.env['gdpr.consent'].search_read([('state', '=', self.gdpr_consent), ('gdpr_id', '=', self.gdpr_id.id)], ['gdpr_object_id'])] 65 | else: 66 | object_ids = list(set(self.gdpr_id.object_ids.mapped('id')) - set(self.env['gdpr.consent'].search([('gdpr_id', '=', self.gdpr_id.id)]).mapped('gdpr_object_id').mapped('id'))) 67 | # ~ _logger.warn(self.env['gdpr.object'].search_read([('id', 'in', object_ids), ('restricted', '=', False)], ['object_res_id'])) 68 | # ~ object_ids = [d['object_res_id'] for d in self.env['gdpr.object'].search_read([('id', 'in', object_ids), ('restricted', '=', False)], ['object_res_id'])] 69 | else: 70 | object_ids = [d['object_res_id'] for d in self.env['gdpr.object'].search_read([('gdpr_id', '=', self.gdpr_id.id), ('restricted', '=', False)], ['object_res_id'])] 71 | domain = [('id', 'in', object_ids)] 72 | self.recipients = len(object_ids) 73 | self.gdpr_domain = domain 74 | 75 | @api.onchange('mailing_model', 'gdpr_mailing_list_ids') 76 | def on_change_gdpr_model_and_list(self): 77 | consents = self.env['gdpr.consent'].browse() 78 | partners = set() 79 | for lst in self.gdpr_mailing_list_ids: 80 | for consent_ids in lst.mapped('gdpr_ids').mapped('consent_ids'): 81 | consents |= consent_ids.filtered(lambda c: c.state == lst.gdpr_consent and c.partner_id.id not in partners) 82 | partners = partners.union(set(consents.mapped('partner_id').mapped('id'))) 83 | if len(consents) > 0: 84 | self.mailing_domain = "[('id', 'in', %s)]" %consents.mapped('id') 85 | 86 | @api.model 87 | def get_recipients(self, mailing): 88 | if mailing.mailing_model == 'gdpr.consent': 89 | consents = self.env['gdpr.consent'].browse() 90 | partners = set() 91 | for lst in mailing.gdpr_mailing_list_ids: 92 | for consent_ids in lst.mapped('gdpr_ids').mapped('consent_ids'): 93 | consents |= consent_ids.filtered(lambda c: c.state == lst.gdpr_consent and c.partner_id.id not in partners) 94 | partners = partners.union(set(consents.mapped('partner_id').mapped('id'))) 95 | return consents.mapped('id') 96 | else: 97 | return super(MailMassMailing, self).get_recipients(mailing) 98 | 99 | @api.one 100 | def create_missing_consents(self): 101 | if self.gdpr_id and self.gdpr_consent == 'missing': 102 | for partner in self.gdpr_id.partner_ids: 103 | if not partner.consent_ids.filtered(lambda c: c.gdpr_id == self.gdpr_id): 104 | for o in self.gdpr_id.object_ids.filtered(lambda o: o.partner_id == partner): 105 | self.env['gdpr.consent'].create({ 106 | 'name': '%s - %s' %(self.gdpr_id.name, partner.name), 107 | 'gdpr_object_id': o.id, 108 | 'partner_id': partner.id, 109 | 'gdpr_id': self.gdpr_id.id, 110 | 'state': self.gdpr_consent, 111 | }) 112 | 113 | 114 | class GDPRMailMassMailingList(models.Model): 115 | _name = 'gdpr.mail.mass_mailing.list' 116 | 117 | name = fields.Char(string='name', required=True) 118 | gdpr_ids = fields.Many2many(comodel_name='gdpr.inventory', string='GDPRs') 119 | gdpr_consent = fields.Selection(selection=[('given', 'Given'), ('withdrawn', 'Withdrawn'), ('missing', 'Missing')], string='Consent State') 120 | consent_nbr = fields.Integer(compute='_get_consent_nbr', string='Number of Contacts') 121 | 122 | @api.one 123 | def _get_consent_nbr(self): 124 | self.consent_nbr = len(self.env['gdpr.consent'].search([('gdpr_id', 'in', self.gdpr_ids.mapped('id')), ('state', '=', self.gdpr_consent)])) 125 | 126 | @api.model 127 | def get_consents(self, mailing): 128 | consents = self.env['gdpr.consent'].browse() 129 | # TODO: handle missing consents 130 | for inventory in mailing.gdpr_ids: 131 | consents |= inventory.consent_ids.filtered(lambda c: c.state == mailing.gdpr_consent) 132 | return consents 133 | 134 | @api.one 135 | def create_missing_consents(self): 136 | for inventory in self.gdpr_ids: 137 | for partner in inventory.partner_ids: 138 | if not partner.consent_ids.filtered(lambda c: c.gdpr_id == inventory): 139 | for o in inventory.object_ids.filtered(lambda o: o.partner_id == partner): 140 | self.env['gdpr.consent'].create({ 141 | 'name': '%s - %s' %(inventory.name, partner.name), 142 | 'gdpr_object_id': o.id, 143 | 'partner_id': partner.id, 144 | 'gdpr_id': inventory.id, 145 | 'state': self.gdpr_consent, 146 | }) 147 | 148 | @api.multi 149 | def show_consents(self): 150 | return { 151 | 'type': 'ir.actions.act_window', 152 | 'res_model': 'gdpr.consent', 153 | 'view_type': 'form', 154 | 'view_mode': 'tree', 155 | 'view_id': self.env.ref('gdpr_inventory.view_gdpr_consent_tree').id, 156 | 'target': 'current', 157 | 'domain': [('id', 'in', self.get_consents(self).mapped('id'))], 158 | 'context': {}, 159 | } 160 | 161 | 162 | class MailMail(models.Model): 163 | _inherit = 'mail.mail' 164 | 165 | @api.model 166 | def send_get_mail_body(self, mail, partner=None): 167 | """ Override to add the full website version URL to the body. """ 168 | body = super(MailMail, self).send_get_mail_body(mail, partner=partner) 169 | if mail.model != 'mail.mass_mailing.contact' and partner: 170 | return body.replace('$website_consent', _('Click here to review this consent
') %(self.env['ir.config_parameter'].get_param('web.base.url'), mail.mailing_id.id, partner.id)) 171 | else: 172 | return body 173 | 174 | @api.model 175 | def _get_unsubscribe_url(self, mail, email_to, msg=None): 176 | res = super(MailMail, self)._get_unsubscribe_url(mail, email_to, msg) 177 | if not (mail.mailing_id.wp_cond_consent_ids or mail.mailing_id.wp_uncond_consent_ids): # Not Collecting consents 178 | return res 179 | 180 | 181 | 182 | 183 | 184 | class gdpr_consent(models.Model): 185 | _inherit = 'gdpr.consent' 186 | 187 | _mail_mass_mailing = _('GDPR Consents') 188 | 189 | 190 | class MassMailController(MassMailController): 191 | 192 | @http.route(['/mail/mailing//unsubscribe'], type='http', auth='public', website=True) 193 | def mailing(self, mailing_id, email=None, res_id=None, **post): 194 | res = super(MassMailController, self).mailing(mailing_id, email, res_id, **post) 195 | if res.get_data() == 'OK': 196 | mailing = request.env['mail.mass_mailing'].sudo().browse(mailing_id) 197 | if mailing.mailing_model == 'mail.mass_mailing.contact': 198 | list_ids = [l.id for l in mailing.contact_list_ids] 199 | records = request.env[mailing.mailing_model].sudo().search([('list_id', 'in', list_ids), ('id', '=', res_id), ('email', 'ilike', email)]) 200 | consent = request.env['gdpr.consent'].sudo().search([('record_id', '=', '%s,%s' % (mailing.mailing_model, records.id))]) 201 | if consent: 202 | consent.sudo().remove("User unsubscribed through %s (referer: %s)" % (request.httprequest.path, request.httprequest.referrer)) 203 | elif mailing.mailing_model == 'gdpr.consent' and res_id: 204 | consent = request.env['gdpr.consent'].sudo().browse(int(res_id)) 205 | consent.remove("User unsubscribed through %s (referer: %s)" % (request.httprequest.path, request.httprequest.referrer)) 206 | elif mailing.gdpr_id and res_id: 207 | consent = request.env['gdpr.consent'].sudo().search([ 208 | ('record_id', '=', '%s,%s' % (mailing.mailing_model, res_id)), 209 | ('partner_id.email', '=', email), 210 | ('gdpr_id', '=', mailing.gdpr_id.id)]) 211 | if consent: 212 | consent.sudo().remove("User unsubscribed through %s (referer: %s)" % (request.httprequest.path, request.httprequest.referrer)) 213 | else: 214 | consent = request.env['gdpr.consent'].sudo().create([ 215 | ('record_id', '=', '%s,%s' % (mailing.mailing_model, res_id)), 216 | ('partner_id.email', '=', email), 217 | ('gdpr_id', '=', mailing.gdpr_id.id), 218 | ('state', '=', 'withdrawn')]) 219 | return request.website.render('gdpr_mass_mailing.consent_thanks', {'inventory': mailing.gdpr_id if mailing.gdpr_id else consent.gdpr_id, 'confirm': 0}) 220 | 221 | @http.route(['/mail/consent//partner/'], type='http', auth='public', website=True) 222 | def mailing_consents(self, mailing_id, partner_id, **post): 223 | mailing = request.env['mail.mass_mailing'].sudo().browse(mailing_id) 224 | partner = request.env['res.partner'].sudo().browse(partner_id) 225 | if mailing and partner: 226 | cond_consent_inventories = mailing.wp_cond_consent_ids 227 | uncond_consent_inventories = mailing.wp_uncond_consent_ids 228 | if mailing and partner: 229 | return request.website.render('gdpr_mass_mailing.mailing_consents', { 230 | 'mailing': mailing, 231 | 'partner': partner, 232 | 'consent_inventories': cond_consent_inventories + uncond_consent_inventories, 233 | 'group_per_object': mailing.group_per_object, 234 | }) 235 | 236 | @http.route(['/mail/consent/confirm'], type='json', auth='public', website=True) 237 | def consent_confirm(self, inventory_id=0, object_id=0, consent_id=0, partner_id=0, mailing_title='', confirm=False, **kw): 238 | inventory = request.env['gdpr.inventory'].sudo().browse(int(inventory_id)) 239 | partner = request.env['res.partner'].sudo().browse(int(partner_id)) 240 | if inventory and partner: 241 | object = request.env['gdpr.object'].browse(object_id) 242 | if confirm: 243 | if object: 244 | consent = request.env['gdpr.consent'].sudo().add(inventory, object[0], partner=partner, name='%s - %s' %(inventory.name, partner.name), msg=mailing_title) 245 | return 'ok' 246 | else: 247 | return 'error' 248 | elif consent_id != 0: 249 | request.env['gdpr.consent'].sudo().browse(consent_id).remove(mailing_title) 250 | else: 251 | return 'error' 252 | return 'ok' 253 | else: 254 | return 'error' 255 | 256 | @http.route(['/mail/consent//thanks'], type='http', auth='public', website=True) 257 | def mail_consent_thanks(self, mailing_id=0, **post): 258 | mailing = request.env['mail.mass_mailing'].sudo().browse(mailing_id) 259 | if mailing: 260 | return request.website.render('gdpr_mass_mailing.mailing_consent_thanks', {'mailing': mailing}) 261 | 262 | @http.route(['/mail/consent//confirm/'], type='http', auth='public', website=True) 263 | def object_consent(self, consent_id, confirm, **post): 264 | # Wizard to get consent on specified object and purpose (inventory). Mail should have two links: given/withdrawn. If consent is missing, wizard creates it. 265 | consent = request.env['gdpr.consent'].browse(int(consent_id)) 266 | if confirm == 1: 267 | request.env['gdpr.consent'].sudo().add(consent.gdpr_id, consent.record_id, partner=consent.partner_id) 268 | else: 269 | consent.remove(_('Per mail')) 270 | return request.website.render('gdpr_mass_mailing.consent_thanks', {'inventory': consent.gdpr_id, 'confirm': confirm}) 271 | -------------------------------------------------------------------------------- /gdpr_mass_mailing/gdpr_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | mail.mass_mailing.gdpr.form 6 | mail.mass_mailing 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 21 | 22 |
23 |
26 |
27 | 28 | {'model_field': 'mailing_model', 'gdpr_domain_field': 'gdpr_domain'} 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 |
43 |
44 | 45 | mail.mass_mailing.list.gdpr.form 46 | mail.mass_mailing.list 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 152 | 153 |
154 |
155 | -------------------------------------------------------------------------------- /website_gdpr/__init__.py: -------------------------------------------------------------------------------- 1 | import gdpr 2 | -------------------------------------------------------------------------------- /website_gdpr/__openerp__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | ############################################################################## 3 | # 4 | # OpenERP, Open Source Management Solution, third party addon 5 | # Copyright (C) 2004-2017 Vertel AB (). 6 | # 7 | # This program is free software: you can redistribute it and/or modify 8 | # it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | # 20 | ############################################################################## 21 | 22 | { 23 | 'name': 'Website GDPR', 24 | 'version': '0.1', 25 | 'category': 'Other', 26 | 'summary': 'Portal and GDRP-information', 27 | 'description': """ 28 | 29 | * GDPR Website 30 | 31 | """, 32 | 'images': ['static/description/event_participant.jpg'], 33 | 'author': 'Vertel AB', 34 | 'website': 'http://www.vertel.se', 35 | 'depends': [ 36 | 'website', 37 | 'gdpr_inventory', 38 | 'website_document_metadata', 39 | ], 40 | 'data': [ 41 | 'gdpr_view.xml', 42 | 'templates.xml', 43 | ], 44 | 'demo': ['gdpr_demo.xml'], 45 | 'application': False, 46 | 'installable': True, 47 | } 48 | # vim:expandtab:smartindent:tabstop=4s:softtabstop=4:shiftwidth=4: 49 | -------------------------------------------------------------------------------- /website_gdpr/gdpr.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | ############################################################################## 3 | # 4 | # OpenERP, Open Source Management Solution, third party addon 5 | # Copyright (C) 2004-2017 Vertel AB (). 6 | # 7 | # This program is free software: you can redistribute it and/or modify 8 | # it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | # 20 | ############################################################################## 21 | from openerp import models, fields, api, _ 22 | from datetime import timedelta 23 | from openerp import http 24 | from openerp.http import request 25 | 26 | import logging 27 | _logger = logging.getLogger(__name__) 28 | 29 | # https://www.privacy-regulation.eu 30 | class gdpr_inventory(models.Model): 31 | _inherit = 'gdpr.inventory' 32 | 33 | website_desc = fields.Html(string="Website Description", translation=True, track_visibility='onchange', translate=True) 34 | website_published = fields.Boolean(string='Website Published') 35 | parent_id = fields.Many2one(comodel_name="gdpr.inventory") 36 | sequence = fields.Integer(string='Sequence') 37 | website_inventory_ids = fields.One2many(comodel_name='gdpr.inventory',inverse_name='parent_id',string="Related inventories",help='Related inventories that is included in this webdescription',) 38 | @api.one 39 | def _website_lawsection_list(self): 40 | lawsections = [n.lower() for n in set([self.lawsection_id.name] + self.website_inventory_ids.mapped('lawsection_id').mapped('name'))] 41 | if len(lawsections) > 1: 42 | self.website_lawsection_list = (_('%s and %s.') % (', '.join(lawsections[:-1]),lawsections[-1])).capitalize() + '*' 43 | else: 44 | self.website_lawsection_list = lawsections[0].capitalize() + '.*' 45 | website_lawsection_list = fields.Char(compute='_website_lawsection_list') 46 | 47 | 48 | class gdpr_category(models.Model): 49 | _inherit = 'gdpr.category' 50 | 51 | website_published = fields.Boolean(string='Website Published') 52 | website_desc = fields.Html(string="Website Description", translation=True, track_visibility='onchange', translate=True) 53 | @api.one 54 | def _website_inventory_ids(self): 55 | self.website_inventory_ids = self.inventory_ids.with_context(state_id=self.env.ref('gdpr_inventory.inventory_state_active')).filtered(lambda i: i.website_published == True and i.state_id == i._context.get('state_id')).sorted(lambda i: i.sequence) 56 | website_inventory_ids = fields.One2many(comodel_name='gdpr.inventory',compute='_website_inventory_ids') 57 | 58 | 59 | class GDPRController(http.Controller): 60 | 61 | @http.route(['/gdpr/main/'], type='http', auth="public", website=True) 62 | def gdpr_main(self, partner=None, **post): 63 | inventories = request.env['gdpr.inventory'].search_read( 64 | [ 65 | ('partner_ids', 'in', partner.id), 66 | ('state_id', '=', request.env.ref('gdpr_inventory.inventory_state_active').id), 67 | ('website_published', '=', True) 68 | ], 69 | ['name', 'website_desc', 'state_id']) 70 | return request.website.render('website_gdpr.gdpr_personal_portal', {'inventories': inventories, 'partner': partner.name}) 71 | 72 | @http.route(['/gdpr/inventories'], type='http', auth="public", website=True) 73 | def gdpr_inventories(self, partner=None, **post): 74 | return request.website.render('website_gdpr.gdrp_inventories', { 75 | 'categories': request.env['gdpr.category'].sudo().search([('website_published', '=', True)]), 76 | }) 77 | -------------------------------------------------------------------------------- /website_gdpr/gdpr_demo.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |
7 |

We store data of our customers that we have ongoing contracts with. It is important for us not to store more information and not longer that is nececery for delever our service to you.

8 |

Use our GDPR portal if you want to see what personal data we have on you.

9 |
10 |
11 | 12 |
13 | 14 | 15 |
16 |

We use pictures taken at events with employees and customers that is or could be published for marketing purpuses in social media and at out website.

17 |

Every picture that we have, published or not, have a concent from each person that is visible and recognizeable.

18 |

Use our GDPR portal if you want to redraw any given concent och just see what personal data we have on you.

19 |
20 |
21 | 22 |
23 |
24 |
25 | -------------------------------------------------------------------------------- /website_gdpr/gdpr_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | gdpr.inventory.form 9 | gdpr.inventory 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | gdpr.inventory.tree 30 | gdpr.inventory 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | gdpr.inventory.filter 44 | gdpr.inventory 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | gdpr.category.webform 62 | gdpr.category 63 | 64 | 65 |
66 | 67 |
68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 |
78 |
79 | 80 | 81 |
82 |
83 | -------------------------------------------------------------------------------- /website_gdpr/i18n/sv.po: -------------------------------------------------------------------------------- 1 | # Translation of Odoo Server. 2 | # This file contains the translation of the following modules: 3 | # * website_gdpr 4 | # 5 | msgid "" 6 | msgstr "" 7 | "Project-Id-Version: Odoo Server 8.0-20171009\n" 8 | "Report-Msgid-Bugs-To: \n" 9 | "POT-Creation-Date: 2018-05-16 10:21+0000\n" 10 | "PO-Revision-Date: 2018-05-16 12:23+0200\n" 11 | "Last-Translator: <>\n" 12 | "Language-Team: \n" 13 | "MIME-Version: 1.0\n" 14 | "Content-Type: text/plain; charset=UTF-8\n" 15 | "Content-Transfer-Encoding: 8bit\n" 16 | "Plural-Forms: \n" 17 | "Language: sv\n" 18 | "X-Generator: Poedit 2.0.4\n" 19 | 20 | #. module: website_gdpr 21 | #: code:addons/website_gdpr/gdpr.py:42 22 | #, python-format 23 | msgid "%s and %s." 24 | msgstr "%s samt %s." 25 | 26 | #. module: website_gdpr 27 | #: view:website:website_gdpr.gdpr_main_page 28 | msgid "Consent" 29 | msgstr "Samtycke" 30 | 31 | #. module: website_gdpr 32 | #: view:website:website.layout 33 | msgid "GDPR" 34 | msgstr "" 35 | 36 | #. module: website_gdpr 37 | #: model:ir.model,name:website_gdpr.model_gdpr_category 38 | msgid "GDPR Category" 39 | msgstr "" 40 | 41 | #. module: website_gdpr 42 | #: view:website:website_gdpr.gdrp_inventories 43 | msgid "GDPR Inventories" 44 | msgstr "" 45 | 46 | #. module: website_gdpr 47 | #: model:ir.model,name:website_gdpr.model_gdpr_inventory 48 | msgid "GDPR Inventory" 49 | msgstr "" 50 | 51 | #. module: website_gdpr 52 | #: view:website:website_gdpr.gdrp_inventories 53 | msgid "Here you can read about all types of personal data processing we do when we deliver our service to public. We try minimize what data we collect and store and removes it when it is no longer necessary to store" 54 | msgstr "" 55 | 56 | #. module: website_gdpr 57 | #: view:website:website_gdpr.gdpr_main_page 58 | msgid "Inventory" 59 | msgstr "Inventarie" 60 | 61 | #. module: website_gdpr 62 | #: field:gdpr.inventory,parent_id:0 63 | msgid "Parent id" 64 | msgstr "Förälder" 65 | 66 | #. module: website_gdpr 67 | #: field:gdpr.inventory,website_inventory_ids:0 68 | msgid "Related inventories" 69 | msgstr "Relaterade inventeringar" 70 | 71 | #. module: website_gdpr 72 | #: help:gdpr.inventory,website_inventory_ids:0 73 | msgid "Related inventories that is included in this webdescription" 74 | msgstr "Relaterade inventeringar som inkluderas i denna webbeskrivning" 75 | 76 | #. module: website_gdpr 77 | #: view:website:website_gdpr.gdrp_inventories 78 | msgid "This is a compilation of our personal data processing" 79 | msgstr "Detta är en sammanställning av vår personuppgiftsbehandling" 80 | 81 | #. module: website_gdpr 82 | #: field:gdpr.category,website_desc:0 83 | #: view:gdpr.inventory:website_gdpr.view_gdpr_inventory_form 84 | #: field:gdpr.inventory,website_desc:0 85 | msgid "Website Description" 86 | msgstr "Webbplatsbeskrivning" 87 | 88 | #. module: website_gdpr 89 | #: view:website:website_gdpr.gdrp_inventories 90 | msgid "Purpose for the Treatment" 91 | msgstr "Syftet med behandlingen" 92 | 93 | #. module: website_gdpr 94 | #: view:website:website_gdpr.gdrp_inventories 95 | msgid "Lawsection for the Treatment" 96 | msgstr "Laglig grund för behandling" 97 | 98 | #. module: website_gdpr 99 | #: field:gdpr.inventory,website_published:0 100 | msgid "Website Published" 101 | msgstr "Publicerad" 102 | 103 | #. module: website_gdpr 104 | #: field:gdpr.inventory,website_lawsection_list:0 105 | msgid "Website lawsection list" 106 | msgstr "Webbplats lista med laglig grund" 107 | -------------------------------------------------------------------------------- /website_gdpr/i18n/website_gdpr.pot: -------------------------------------------------------------------------------- 1 | # Translation of Odoo Server. 2 | # This file contains the translation of the following modules: 3 | # * website_gdpr 4 | # 5 | msgid "" 6 | msgstr "" 7 | "Project-Id-Version: Odoo Server 8.0-20171009\n" 8 | "Report-Msgid-Bugs-To: \n" 9 | "POT-Creation-Date: 2018-05-16 10:21+0000\n" 10 | "PO-Revision-Date: 2018-05-16 10:21+0000\n" 11 | "Last-Translator: <>\n" 12 | "Language-Team: \n" 13 | "MIME-Version: 1.0\n" 14 | "Content-Type: text/plain; charset=UTF-8\n" 15 | "Content-Transfer-Encoding: \n" 16 | "Plural-Forms: \n" 17 | 18 | #. module: website_gdpr 19 | #: code:addons/website_gdpr/gdpr.py:41 20 | #, python-format 21 | msgid "%s and %s" 22 | msgstr "" 23 | 24 | #. module: website_gdpr 25 | #: view:website:website_gdpr.gdpr_main_page 26 | msgid "Consent" 27 | msgstr "" 28 | 29 | #. module: website_gdpr 30 | #: view:website:website.layout 31 | msgid "GDPR" 32 | msgstr "" 33 | 34 | #. module: website_gdpr 35 | #: model:ir.model,name:website_gdpr.model_gdpr_category 36 | msgid "GDPR Category" 37 | msgstr "" 38 | 39 | #. module: website_gdpr 40 | #: view:website:website_gdpr.gdrp_inventories 41 | msgid "GDPR Inventories" 42 | msgstr "" 43 | 44 | #. module: website_gdpr 45 | #: model:ir.model,name:website_gdpr.model_gdpr_inventory 46 | msgid "GDPR Inventory" 47 | msgstr "" 48 | 49 | #. module: website_gdpr 50 | #: view:website:website_gdpr.gdrp_inventories 51 | msgid "Here you can read about all types of personal data processing we do when we deliver our service to public. We try minimize what data we collect and store and removes it when it is no longer necessary to store" 52 | msgstr "" 53 | 54 | #. module: website_gdpr 55 | #: view:website:website_gdpr.gdpr_main_page 56 | msgid "Inventory" 57 | msgstr "" 58 | 59 | #. module: website_gdpr 60 | #: field:gdpr.inventory,parent_id:0 61 | msgid "Parent id" 62 | msgstr "" 63 | 64 | #. module: website_gdpr 65 | #: field:gdpr.inventory,website_inventory_ids:0 66 | msgid "Related inventories" 67 | msgstr "" 68 | 69 | #. module: website_gdpr 70 | #: help:gdpr.inventory,website_inventory_ids:0 71 | msgid "Related inventories that is included in this webdescription" 72 | msgstr "" 73 | 74 | #. module: website_gdpr 75 | #: view:website:website_gdpr.gdrp_inventories 76 | msgid "This is a compilation of our personal data processing" 77 | msgstr "" 78 | 79 | #. module: website_gdpr 80 | #: field:gdpr.category,website_desc:0 81 | #: view:gdpr.inventory:website_gdpr.view_gdpr_inventory_form 82 | #: field:gdpr.inventory,website_desc:0 83 | msgid "Website Description" 84 | msgstr "" 85 | 86 | #. module: website_gdpr 87 | #: field:gdpr.inventory,website_published:0 88 | msgid "Website Published" 89 | msgstr "" 90 | 91 | #. module: website_gdpr 92 | #: field:gdpr.inventory,website_lawsection_list:0 93 | msgid "Website lawsection list" 94 | msgstr "" 95 | 96 | -------------------------------------------------------------------------------- /website_gdpr/static/src/css/main.css: -------------------------------------------------------------------------------- 1 | /*================== 2 | Website GDPR 3 | ==================*/ 4 | 5 | /* 6 | Swith 7 | */ 8 | 9 | .switch { 10 | position: relative; 11 | display: inline-block; 12 | width: 60px; 13 | height: 34px; 14 | } 15 | 16 | .switch input {display:none;} 17 | 18 | .slider { 19 | position: absolute; 20 | cursor: pointer; 21 | top: 0; 22 | left: 0; 23 | right: 0; 24 | bottom: 0; 25 | background-color: #ccc; 26 | -webkit-transition: .4s; 27 | transition: .4s; 28 | } 29 | 30 | .slider:before { 31 | position: absolute; 32 | content: ""; 33 | height: 26px; 34 | width: 26px; 35 | left: 4px; 36 | bottom: 4px; 37 | background-color: white; 38 | -webkit-transition: .4s; 39 | transition: .4s; 40 | } 41 | 42 | input:checked + .slider { 43 | background-color: #2196F3; 44 | } 45 | 46 | input:focus + .slider { 47 | box-shadow: 0 0 1px #2196F3; 48 | } 49 | 50 | input:checked + .slider:before { 51 | -webkit-transform: translateX(26px); 52 | -ms-transform: translateX(26px); 53 | transform: translateX(26px); 54 | } 55 | 56 | /* Rounded sliders */ 57 | .slider.round { 58 | border-radius: 34px; 59 | } 60 | 61 | .slider.round:before { 62 | border-radius: 50%; 63 | } 64 | 65 | #gdpr_inventories .gdpr_inventory > div { 66 | padding: 10px; 67 | background-color: #ddd; 68 | height: 300px; 69 | overflow: hidden; 70 | } 71 | -------------------------------------------------------------------------------- /website_gdpr/templates.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 49 | 88 | 95 | 100 | 101 | 102 | --------------------------------------------------------------------------------