Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Open sidebar
elixir
daisy
Commits
d1e82780
Commit
d1e82780
authored
Sep 15, 2021
by
Jacek Lebioda
Browse files
feat: email reporting
parent
89e2e6ee
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
116 additions
and
20 deletions
+116
-20
core/reporting.py
core/reporting.py
+47
-3
core/templates/report_email.txt
core/templates/report_email.txt
+33
-0
core/tests/email_reporter/test_reporter.py
core/tests/email_reporter/test_reporter.py
+2
-1
elixir_daisy/settings.py
elixir_daisy/settings.py
+2
-0
notification/email_sender.py
notification/email_sender.py
+28
-14
notification/tests/test_email.py
notification/tests/test_email.py
+4
-2
No files found.
core/reporting.py
View file @
d1e82780
...
...
@@ -2,6 +2,7 @@ from functools import reduce
from
operator
import
concat
from
typing
import
List
,
Type
,
Union
from
django.conf
import
settings
from
django.db.models
import
Model
from
django.db.models.query
import
QuerySet
from
django.db.models.manager
import
Manager
...
...
@@ -11,10 +12,18 @@ from core.models.dataset import Dataset
from
core.models.data_declaration
import
DataDeclaration
from
core.models.project
import
Project
from
core.models.user
import
User
from
notification.email_sender
import
send_the_email
def
cast_to_queryset
(
object
:
Union
[
Model
,
List
[
Model
],
QuerySet
],
klass
:
Type
=
None
):
"""Casts the object, or a list of objects to a queryset"""
"""
Casts the parameter to a queryset.
Accepts:
- the object (of Model)
- a list of objects
- a Queryset (e.g. Project.objects.all())
- a Manager (e.g. Project.objects)
"""
if
object
is
None
:
return
None
if
klass
is
None
:
...
...
@@ -63,6 +72,10 @@ class ReportParameters:
class
ReportParametersCollector
:
@
classmethod
def
generate_for_user
(
cls
,
user
:
User
):
"""
Generates the `ReportParameters` containing given User's entities -
projects, datasets, data declarations and issues.
"""
projects
=
Project
.
objects
.
filter
(
local_custodians__id
=
user
.
id
)
# TODO: What exactly needs to be collected here:
# 1) datasets whose local_custodian is the User
...
...
@@ -91,11 +104,42 @@ class ReportRenderer:
self
.
data_declarations
=
report_parameters
.
data_declarations
self
.
projects
=
report_parameters
.
projects
def
render
(
self
):
def
render_html
(
self
):
return
self
.
_render
(
'report_email.html'
)
def
render_txt
(
self
):
return
self
.
_render
(
'report_email.txt'
)
def
_render
(
self
,
template_name
):
context
=
{
'projects'
:
self
.
projects
,
'datasets'
:
self
.
datasets
,
'data_declarations'
:
self
.
data_declarations
,
'issues'
:
self
.
issues
}
return
render_to_string
(
'report_email.html'
,
context
)
return
render_to_string
(
template_name
,
context
)
def
get_users_to_receive_emails
(
force
=
False
):
should_continue
=
getattr
(
settings
,
'EMAIL_REPORTS_ENABLED'
,
False
)
if
force
or
should_continue
:
return
User
.
objects
.
filter
(
email__contains
=
'@'
)
else
:
return
[]
def
generate_and_send_reports
(
force
=
False
):
list_of_users
=
get_users_to_receive_emails
(
force
)
for
user
in
list_of_users
:
generate_and_send_report_to
(
user
)
def
generate_and_send_report_to
(
user
:
User
):
report_params
=
ReportParametersCollector
.
generate_for_user
(
user
)
html_contents
=
ReportRenderer
(
report_params
).
render_html
()
txt_contents
=
ReportRenderer
(
report_params
).
render_txt
()
send_the_email
(
settings
.
EMAIL_DONOTREPLY
,
user
.
email
,
'Report'
,
txt_contents
,
html_contents
)
\ No newline at end of file
core/templates/report_email.txt
0 → 100644
View file @
d1e82780
DAISY report (Generated at: {% now "Y/m/j" %})
This report contains all records for which you were appointed as a local custodian,
and highlights any issues in the records (found by an automatic validation rules).
The list has been created to raise awareness of missing or incomplete records and other necessary information required
for compliance with GDPR.
General overview:
Projects count: {{ projects | length }}
Datasets count: {{ datasets | length }}
Data declarations count: {{ data_declarations | length }}
Issues found: {{ issues | length }}
Detailed overview:
{% for project in projects.all %}
Project: {{ project.title }} ({{ project.acronym }})
{% for dataset in project.datasets.all %}
Dataset: {{ dataset.title }}
Data types: {{ dataset_data_types }} (TODO:)
Data declaration count: {{ dataset.data_declarations | length }}
Data locations: {{ dataset_data_locations }} (TODO:)
{% endfor %}
{% endfor %}
Issues found:
{% for issue in issues %}
{{ issue.code }}: {{ issue.description }}
{{ issue.object_title }}
{{ issue.url }}
{% endfor %}
\ No newline at end of file
core/tests/email_reporter/test_reporter.py
View file @
d1e82780
...
...
@@ -50,7 +50,8 @@ def test_report_renderer():
params
=
ReportParameters
(
list_of_projects
)
report_renderer
=
ReportRenderer
(
params
)
rendered_html
=
report_renderer
.
render
()
rendered_html
=
report_renderer
.
render_html
()
_
=
report_renderer
.
render_txt
()
assert
PROJECT_ACRONYM
in
rendered_html
assert
PROJECT_TITLE
in
rendered_html
...
...
elixir_daisy/settings.py
View file @
d1e82780
...
...
@@ -22,6 +22,8 @@ INSTANCE_LABEL = None
# Override of the layout's primary color (used in e.g. navbar), e.g. '#076505'
INSTANCE_PRIMARY_COLOR
=
None
EMAIL_REPORTS_ENABLED
=
False
AUTH_USER_MODEL
=
'core.User'
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
...
...
notification/email_sender.py
View file @
d1e82780
"""
Template for
email
Some routines concerning
e
-
mail
generation and sending
"""
from
django.urls
import
reverse
from
django.conf
import
settings
from
django.core.mail
import
send_mail
,
EmailMultiAlternatives
from
django.template.loader
import
render_to_string
from
django.
conf
import
settings
from
django.
urls
import
reverse
SUBJECT_PREFIX
=
'[DAISY]'
SUBJECT_PREFIX
=
'[DAISY]'
def
send_
the_
email
(
sender_email
,
recipients
,
subject
,
template
,
context
):
def
send_email
_from_template
(
sender_email
,
recipients
,
subject
,
template
,
context
):
"""
S
end an email
to the recipents using the
template
s,
Generates and s
end
s
an email
message from html/txt
template
"""
# recipients can be a list or single email
if
not
isinstance
(
recipients
,
(
list
,
tuple
)):
recipients
=
[
recipients
]
# update context with server full url if it's not present already
# Update context with server's full url if it's not present already
if
'server_url'
not
in
context
:
context
[
'server_url'
]
=
'%s://%s'
%
(
settings
.
SERVER_SCHEME
,
settings
.
SERVER_URL
)
if
'profile_url'
not
in
context
:
context
[
'profile_url'
]
=
reverse
(
'profile'
)
# prepare email
subject
=
f
"
{
SUBJECT_PREFIX
}
{
subject
}
"
# Prepare the email
text_message
=
render_to_string
(
'%s.txt'
%
template
,
context
)
html_message
=
render_to_string
(
'%s.html'
%
template
,
context
)
return
send_the_email
(
sender_email
,
recipients
,
subject
,
text_message
,
html_message
)
def
send_the_email
(
sender_email
,
recipients
,
subject
,
text_message
,
html_message
=
None
):
"""
Send an email to the recipents using given txt and html messages
"""
# Recipients can be a list or single email
if
not
isinstance
(
recipients
,
(
list
,
tuple
)):
recipients
=
[
recipients
]
_send_the_email
(
sender_email
,
recipients
,
subject
,
text_message
,
html_message
,
False
)
def
_send_the_email
(
sender_email
,
recipients
,
subject
,
text_message
,
html_message
,
fail_silently
):
msg
=
EmailMultiAlternatives
(
subject
,
text_message
,
sender_email
,
recipients
)
msg
.
attach_alternative
(
html_message
,
'text/html'
)
msg
.
send
(
fail_silently
=
False
)
\ No newline at end of file
if
html_message
is
not
None
:
msg
.
attach_alternative
(
html_message
,
'text/html'
)
msg
.
send
(
fail_silently
=
fail_silently
)
\ No newline at end of file
notification/tests/test_email.py
View file @
d1e82780
from
notification.email_sender
import
send_the_email
from
django.conf
import
settings
from
notification.email_sender
import
send_email_from_template
def
test_send_email
(
celery_session_worker
):
"""
Check if at least it does not throw errors
"""
send_the_email
(
settings
.
EMAIL_DONOTREPLY
,
[],
'Title of the email'
,
'notification/notification_report'
,
{})
\ No newline at end of file
send_email_from_template
(
settings
.
EMAIL_DONOTREPLY
,
[],
'Title of the email'
,
'notification/notification_report'
,
{})
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment