Browse Source

[10.0][IMP] privacy_consent: Add full manual + dates

Adds a full manual mode for more flexibility
Adds accepted and refusal dates
pull/40/head
Denis Roussel 4 years ago
parent
commit
f8982662ba
  1. 10
      privacy_consent/models/privacy_activity.py
  2. 38
      privacy_consent/models/privacy_consent.py
  3. 2
      privacy_consent/readme/CONTRIBUTORS.rst
  4. 3
      privacy_consent/readme/USAGE.rst
  5. 52
      privacy_consent/tests/test_consent.py
  6. 36
      privacy_consent/views/privacy_consent.xml

10
privacy_consent/models/privacy_activity.py

@ -29,10 +29,16 @@ class PrivacyActivity(models.Model):
compute="_compute_consent_count",
)
consent_required = fields.Selection(
[("auto", "Automatically"), ("manual", "Manually")],
[("auto", "Automatically"),
("manual", "Manually"),
("full_manual", "Full Manual")],
"Ask subjects for consent",
help="Enable if you need to track any kind of consent "
"from the affected subjects",
"from the affected subjects\n"
"[Automatically] Generates consent and send email "
"automatically.\n"
"[Manually] Generates consent and allow to send email manually\n"
"[Full manual] Allow to manage consents steps manually.",
)
consent_template_id = fields.Many2one(
"mail.template",

38
privacy_consent/models/privacy_consent.py

@ -24,6 +24,7 @@ class PrivacyConsent(models.Model):
)
accepted = fields.Boolean(
track_visibility="onchange",
inverse="_inverse_accepted",
help="Indicates current acceptance status, which can come from "
"subject's last answer, or from the default specified in the "
"related data processing activity.",
@ -48,6 +49,10 @@ class PrivacyConsent(models.Model):
required=True,
track_visibility="onchange",
)
consent_required = fields.Selection(
related="activity_id.consent_required",
readonly=True,
)
state = fields.Selection(
selection=[
("draft", "Draft"),
@ -59,6 +64,14 @@ class PrivacyConsent(models.Model):
required=True,
track_visibility="onchange",
)
accepted_date = fields.Datetime(
readonly=True,
help="The date at which the consent was done",
)
refusal_date = fields.Datetime(
readonly=True,
help="The date at which the consent was refused",
)
def _track_subtype(self, init_values):
"""Return specific subtypes."""
@ -119,9 +132,23 @@ class PrivacyConsent(models.Model):
)
action.run()
@api.multi
def _inverse_accepted(self):
"""
When accepted, set accepted date to now.
Whend refused, set refusal date to now.
:return:
"""
now = fields.Datetime.now()
accepted_consents = self.filtered("accepted")
accepted_consents.update({"accepted_date": now})
(self - accepted_consents).update({"refusal_date": now})
@api.model
def create(self, vals):
"""Run server action on create."""
if vals.get("accepted"):
vals.update()
result = super(PrivacyConsent,
self.with_context(mail_create_nolog=True)).create(vals)
# Sync the default acceptance status
@ -185,3 +212,14 @@ class PrivacyConsent(models.Model):
"accepted": answer,
"last_metadata": metadata,
})
def action_set_awaiting(self):
self.write({
"state": "sent",
})
def action_set_accepted(self):
self.action_answer(True)
def action_set_refused(self):
self.action_answer(False)

2
privacy_consent/readme/CONTRIBUTORS.rst

@ -1,3 +1,5 @@
* `Tecnativa <https://www.tecnativa.com>`_:
* Jairo Llopis
* Denis Roussel <denis.roussel@acsone.eu>

3
privacy_consent/readme/USAGE.rst

@ -13,6 +13,9 @@ New options for data processing activities:
* *Automatic* enables this module's full power: send all consent requests
to selected partners automatically, every day and under your demand.
* *Full Manual* tells the activity that you will want to create and send the
consent requests manually, and can manage consent states manually.
#. When you do this, all the consent-related options appear. Configure them:
* A smart button tells you how many consents have been generated, and lets you

52
privacy_consent/tests/test_consent.py

@ -3,12 +3,15 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from contextlib import contextmanager
import mock
from odoo.exceptions import ValidationError
from odoo.tests.common import HttpCase
from odoo import fields
class ActivityCase(HttpCase):
def setUp(self):
super(ActivityCase, self).setUp()
# HACK https://github.com/odoo/odoo/issues/12237
@ -76,6 +79,16 @@ class ActivityCase(HttpCase):
"server_action_id": self.update_opt_out.id,
})
self.activity_full_manual = self.env["privacy.activity"].create({
"name": "activity_full_manual",
"description": "I'm activity 4",
"subject_find": True,
"subject_domain": repr([("id", "in", self.partners[1:].ids)]),
"consent_required": "full_manual",
"default_consent": False,
"server_action_id": self.update_opt_out.id,
})
# HACK https://github.com/odoo/odoo/issues/12237
# TODO Remove hack in v12
def tearDown(self):
@ -251,3 +264,42 @@ class ActivityCase(HttpCase):
"""Cannot create mail template without needed links."""
with self.assertRaises(ValidationError):
self.activity_manual.consent_template_id.body_html = "No links :("
def test_consent_states(self):
"""
Test states, accepted and refusal dates
:return:
"""
now = "2020-01-01 12:00:00"
result = self.activity_full_manual.action_new_consents()
consents = self.env[result["res_model"]].search(result["domain"])
consents.action_set_awaiting()
self.assertEquals(consents.mapped("state"), ["sent", "sent"])
first_consent = consents[0]
second_consent = consents[1]
with mock.patch.object(fields.Datetime, "now") as mock_now:
mock_now.return_value = now
first_consent.action_set_accepted()
self.assertEquals(
"answered",
first_consent.state
)
self.assertTrue(first_consent.accepted)
self.assertEquals(
now,
first_consent.accepted_date,
)
with mock.patch.object(fields.Datetime, "now") as mock_now:
mock_now.return_value = now
second_consent.action_set_refused()
self.assertEquals(
"answered",
second_consent.state
)
self.assertFalse(second_consent.accepted)
self.assertEquals(
now,
second_consent.refusal_date,
)

36
privacy_consent/views/privacy_consent.xml

@ -16,6 +16,28 @@
class="oe_highlight"
string="Ask for consent"
/>
<button
type="object"
name="action_set_awaiting"
class="oe_highlight"
attrs="{'invisible': ['|', ('consent_required', '!=', 'full_manual'), ('state', '!=', 'draft')]}"
string="Set to Awaiting"
/>
<button
type="object"
name="action_set_accepted"
class="oe_highlight"
attrs="{'invisible': ['|', ('consent_required', '!=', 'full_manual'), ('state', 'not in', ('draft', 'sent'))]}"
string="Accepted"
/>
<button
type="object"
name="action_set_accepted"
class="oe_highlight"
attrs="{'invisible': ['|', ('consent_required', '!=', 'full_manual'), ('state', 'not in', ('draft', 'sent'))]}"
string="Refused"
/>
<field name="consent_required" invisible="1"/>
<field name="state" widget="statusbar"/>
</header>
<sheet>
@ -34,10 +56,16 @@
</button>
</div>
<group>
<field name="partner_id"/>
<field name="activity_id"/>
<field name="accepted"/>
<field name="last_metadata"/>
<group>
<field name="partner_id"/>
<field name="activity_id"/>
<field name="accepted"/>
<field name="last_metadata"/>
</group>
<group>
<field name="accepted_date"/>
<field name="refusal_date"/>
</group>
</group>
</sheet>
<div class="oe_chatter">

Loading…
Cancel
Save