Compare commits

..

10 Commits

Author SHA1 Message Date
Oliver Zander 8abc051a59 full width related labels for all product change forms 2025-11-21 13:01:25 +00:00
Oliver Zander b156ee0067 fixed form data for project funding 2025-11-21 13:01:15 +00:00
Oliver Zander 85cb2368cc fixed validation 2025-11-21 13:01:15 +00:00
Oliver Zander f9898ee9b5 removed unnecessary code 2025-11-21 13:01:15 +00:00
Oliver Zander d8b8f28442 improved literature form validation 2025-11-21 13:01:15 +00:00
Oliver Zander 73cd0ff906 properly clean selfbuy data 2025-11-21 13:01:15 +00:00
Oliver Zander 20e5be26c0 added test for failed extern redirect 2025-11-21 13:01:15 +00:00
Oliver Zander 803c94137d fixed typing for help texts in application type 2025-11-21 13:01:15 +00:00
Oliver Zander c0a98d09cd added test for unknown applicant name 2025-11-21 13:01:15 +00:00
Oliver Zander f5c9b0c76c WM-18: improved mails & added full form data 2025-11-21 13:01:15 +00:00
10 changed files with 190 additions and 199 deletions

View File

@ -157,6 +157,9 @@ class BaseProjectAdmin(admin.ModelAdmin):
class Media:
js = ('dropdown/js/otrs_link.js',)
css = {
'all': ['css/full-width-related-labels.css'],
}
granted: bool

View File

@ -5,6 +5,7 @@ from django.forms import ModelForm
from django.forms.renderers import DjangoTemplates
from django.utils.html import format_html
from django.utils.safestring import mark_safe
from django.utils.translation import gettext_lazy as trans
from .models import (
Project,
@ -263,10 +264,6 @@ class TermsForm(BaseApplicationForm):
class LiteratureForm(TermsForm):
terms_accepted_url = settings.NUTZUNGSBEDINGUNGEN_LITERATURSTIPENDIUM
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['selfbuy_give_data'].required = True
class Meta:
model = Literature
fields = [
@ -285,6 +282,24 @@ class LiteratureForm(TermsForm):
class Media:
js = ('dropdown/js/literature.js',)
def clean(self):
cleaned_data = TermsForm.clean(self)
if self.errors:
return cleaned_data
if cleaned_data['selfbuy'] == 'TRUE':
cleaned_data['selfbuy_data'] = ''
cleaned_data['selfbuy_give_data'] = False
return cleaned_data
for field in 'selfbuy_data', 'selfbuy_give_data':
if not cleaned_data.get(field):
self.add_error(field, trans('This field is required.'))
return cleaned_data
ADULT_CHOICES = {
'TRUE': mark_safe('Ich bin volljährig.'),

View File

@ -0,0 +1,3 @@
.related-widget-wrapper div label {
width: auto;
}

View File

@ -1,10 +0,0 @@
{% extends 'admin/change_form.html' %}
{% block extrastyle %}
{{ block.super }}
<style>
.related-widget-wrapper div label {
width: auto;
}
</style>
{% endblock %}

View File

@ -1,60 +1,26 @@
<html>
<html lang="de">
<body>
<p>Hallo Team Community-Konferenzen &amp; Förderung,</p>
<p>es gibt eine neue Anfrage von {{ data.realname }}.</p>
<p>{{ data.username|default:data.realname }} ({{ data.email }}) fragt an: {{ data.type_label|striptags }}</p>
<p>{{ data.username|default:data.realname }} ({{ data.email }}) fragt an: {{ type_label }}</p>
{% if data.choice in data.grant %}<br>
Vorraussichtliche Kosten: {{data.cost}}<br>
Anmerkungen: {{data.notes}} {% endif %} {% if data.choice in data.domain %}<br>
Domain: <a href="{{data.domain}}">{{data.domain}}</a><br>
Adressenbestandteil: {{data.address}} <br> {% endif %} {% if data.choice == 'BIB' %}
Bibliothek: {{data.library}}<br>
Dauer: {{data.duration}} <br> {% elif data.choice == 'ELIT' %}
Datenbank: {{data.library}}<br>
Dauer: {{data.duration}} <br> {% elif data.choice == 'SOFT' %}
Software: {{data.library}}<br>
Dauer: {{data.duration}} <br> {% elif data.choice == 'IFG'%}
Anfrage-URL: <a href="{{data.url}}">{{data.url}}</a> <br> {% elif data.choice == 'LIT'%}
Info zum Werk: {{data.info}}<br>
Bezugsquelle: {{data.source}} <br> {% elif data.choice == 'MAIL'%}
Adressenbestandteil frei gewählt: {{data.other}} <br> {% elif data.choice == 'VIS'%}
Wikimedia-Projekt: {{data.project}}<br>
Persönliche Daten: {{data.data}}<br>
Variante: {{data.variant}}<br>
Sendungsadrese: {{data.send_to}} <br> {% endif %}
<p>
{% for label, value in form_data.items %}
{{ label }}: {{ value }} <br />
{% endfor %}
</p>
<p>Zum Eintrag in der Förderdatenbank:
{% if data.choice == 'BIB' %}
<a href="{{data.url_prefix}}/admin/input/library/{{data.pk}}/change">{{data.url_prefix}}/admin/input/library/{{data.pk}}/change</a>
{% elif data.choice == 'ELIT'%}
<a href="{{data.url_prefix}}/admin/input/library/{{data.pk}}/change">{{data.url_prefix}}/admin/input/library/{{data.pk}}/change</a>
{% elif data.choice == 'LIT'%}
<a href="{{data.url_prefix}}/admin/input/literature/{{data.pk}}/change">{{data.url_prefix}}/admin/input/literature/{{data.pk}}/change</a>
{% elif data.choice == 'MAIL'%}
<a href="{{data.url_prefix}}/admin/input/email/{{data.pk}}/change">{{data.url_prefix}}/admin/input/email/{{data.pk}}/change</a>
{% elif data.choice == 'IFG'%}
<a href="{{data.url_prefix}}/admin/input/ifg/{{data.pk}}/change">{{data.url_prefix}}/admin/input/ifg/{{data.pk}}/change</a>
{% elif data.choice == 'LIST'%}
<a href="{{data.url_prefix}}/admin/input/list/{{data.pk}}/change">{{data.url_prefix}}/admin/input/list/{{data.pk}}/change</a>
{% elif data.choice == 'TRAV'%}
<a href="{{data.url_prefix}}/admin/input/travel/{{data.pk}}/change">{{data.url_prefix}}/admin/input/travel/{{data.pk}}/change</a>
{% elif data.choice == 'SOFT'%}
<a href="{{data.url_prefix}}/admin/input/library/{{data.pk}}/change">{{data.url_prefix}}/admin/input/library/{{data.pk}}/change</a>
{% elif data.choice == 'VIS'%}
<a href="{{data.url_prefix}}/admin/input/businesscard/{{data.pk}}/change">{{data.url_prefix}}/admin/input/businesscard/{{data.pk}}/change</a>
<p>Zum Eintrag in der Förderdatenbank: <a href="{{ urls.admin }}">{{ urls.admin }}</a></p>
{% if urls.authorize %}
<p>Zum Genehmigen hier klicken: <a href="{{ urls.authorize }}">{{ urls.authorize }}</a></p>
{% endif %}
</p>
<p>Zum Genehmigen hier klicken:
<a href="{{data.url_prefix}}{% url 'authorize' data.choice data.pk %}">{{data.url_prefix}}{% url 'authorize' data.choice data.pk %}</a>
</p>
<p>Zum Ablehnen hier klicken:
<a href="{{data.url_prefix}}{% url 'deny' data.choice data.pk %}">{{data.url_prefix}}{% url 'deny' data.choice data.pk %}</a>
</p>
{% if urls.deny %}
<p>Zum Ablehnen hier klicken: <a href="{{ urls.deny }}">{{ urls.deny }}</a></p>
{% endif %}
</body>
</html>

View File

@ -1,52 +1,12 @@
Hallo Team Communitys und Engagement,
Hallo Team Community-Konferenzen & Förderung,
es gab einen neuen Antrag von {{data.realname}}.
es gibt eine neue Anfrage von {{ data.realname }}.
Der Nutzer mit dem Username {{data.username}} ({{data.email}}) fragt ein_e {{data.type_label|striptags}} an.
{% if data.choice in data.grant %}
Vorraussichtliche Kosten: {{data.cost}}
Anmerkungen: {{data.notes}} {% endif %} {% if data.choice in data.domain %}
Domain: {{data.domain}}
Adressenbestandteil: {{data.address}} {% endif %} {% if data.choice == 'BIB' %}
Bibliothek: {{data.library}}
Dauer: {{data.duration}} {% elif data.choice == 'ELIT' %}
Datenbank: {{data.library}}
Dauer: {{data.duration}} {% elif data.choice == 'SOFT' %}
Software: {{data.library}}
Dauer: {{data.duration}} {% elif data.choice == 'IFG'%}
Anfrage-URL: {{data.url}} {% elif data.choice == 'LIT'%}
Info zum Werk: {{data.info}}
Bezugsquelle: {{data.source}} {% elif data.choice == 'MAIL'%}
Adressenbestandteil frei gewählt: {{data.other}} {% elif data.choice == 'VIS'%}
Wikimedia-Projekt: {{data.project}}
Persönliche Daten: {{data.data}}
Variante: {{data.variant}}
Sendungsadrese: {{data.send_to}} {% endif %}
{{ data.username|default:data.realname }} ({{ data.email }}) fragt an: {{ type_label }}
Zum Eintrag in der Förderdatenbank:
{% if data.choice == 'BIB' %}
<a href="{{data.url_prefix}}/admin/input/library/{{data.pk}}/change">{{data.url_prefix}}/admin/input/library/{{data.pk}}/change</a>
{% elif data.choice == 'ELIT'%}
<a href="{{data.url_prefix}}/admin/input/library/{{data.pk}}/change">{{data.url_prefix}}/admin/input/library/{{data.pk}}/change</a>
{% elif data.choice == 'LIT'%}
<a href="{{data.url_prefix}}/admin/input/literature/{{data.pk}}/change">{{data.url_prefix}}/admin/input/literature/{{data.pk}}/change</a>
{% elif data.choice == 'MAIL'%}
<a href="{{data.url_prefix}}/admin/input/email/{{data.pk}}/change">{{data.url_prefix}}/admin/input/email/{{data.pk}}/change</a>
{% elif data.choice == 'IFG'%}
<a href="{{data.url_prefix}}/admin/input/ifg/{{data.pk}}/change">{{data.url_prefix}}/admin/input/ifg/{{data.pk}}/change</a>
{% elif data.choice == 'LIST'%}
<a href="{{data.url_prefix}}/admin/input/list/{{data.pk}}/change">{{data.url_prefix}}/admin/input/list/{{data.pk}}/change</a>
{% elif data.choice == 'TRAV'%}
<a href="{{data.url_prefix}}/admin/input/travel/{{data.pk}}/change">{{data.url_prefix}}/admin/input/travel/{{data.pk}}/change</a>
{% elif data.choice == 'SOFT'%}
<a href="{{data.url_prefix}}/admin/input/library/{{data.pk}}/change">{{data.url_prefix}}/admin/input/library/{{data.pk}}/change</a>
{% elif data.choice == 'VIS'%}
<a href="{{data.url_prefix}}/admin/input/businesscard/{{data.pk}}/change">{{data.url_prefix}}/admin/input/businesscard/{{data.pk}}/change</a>
{% endif %}
{% for label, value in form_data.items %}{{ label }}: {{ value }}
{% endfor %}
Zum Genehmigen hier klicken: {{data.url_prefix}}{% url 'authorize' data.choice data.pk %}
Zu Ablehnen hier klicken: {{data.url_prefix}}{% url 'deny' data.choice data.pk %}
Stets zu Diensten, Deine Förderdatenbank
Zum Eintrag in der Förderdatenbank: {{ urls.admin }}
{% if urls.authorize %}Zum Genehmigen hier klicken: {{ urls.authorize }}{% endif %}
{% if urls.deny %}Zum Ablehnen hier klicken: {{ urls.deny }}{% endif %}

View File

@ -1,29 +1,14 @@
<html>
<html lang="de">
<body>
<p>Hallo {{ data.username|default:data.realname }},</p>
<p>Hallo {{ applicant_name }},</p>
<p>vielen Dank für deine Anfrage ({{ data.type_label|striptags }}), die bei uns eingegangen ist.</p>
<p>vielen Dank für deine Anfrage ({{ type_label }}), die bei uns eingegangen ist.</p>
Dies ist eine automatisch generierte E-Mail. Im Folgenden findest du deine Formulareingaben nochmals zu deiner Übersicht:<br>
{% if data.choice in data.grant %}<br>
Vorraussichtliche Kosten: {{data.cost}}<br>
Anmerkungen: {{data.notes}} {% endif %} {% if data.choice in data.domain %}<br>
Domain: <a href="{{data.domain}}">{{data.domain}}</a><br>
Adressenbestandteil: {{data.address}} {% endif %} {% if data.choice == 'BIB' %}<br>
Bibliothek: {{data.library}}<br>
Dauer: {{data.duration}} {% elif data.choice == 'ELIT' %}<br>
Datenbank: {{data.library}}<br>
Dauer: {{data.duration}} {% elif data.choice == 'SOFT' %}<br>
Software: {{data.library}}<br>
Dauer: {{data.duration}} {% elif data.choice == 'IFG'%}<br>
Anfrage-URL: <a href="{{data.url}}">{{data.url}}</a> {% elif data.choice == 'LIT'%}<br>
Info zum Werk: {{data.info}}<br>
Bezugsquelle: {{data.source}} {% elif data.choice == 'MAIL'%}<br>
Adressenbestandteil frei gewählt: {{data.other}} {% elif data.choice == 'VIS'%}<br>
Wikimedia-Projekt: {{data.project}}<br>
Persönliche Daten: {{data.data}}<br>
Variante: {{data.variant}}<br>
Sendungsadrese: {{data.send_to}} {% endif %}<br>
{% for label, value in form_data.items %}
{{ label }}: {{ value }} <br />
{% endfor %}
<p>Das Team Community-Konferenzen &amp; Förderung wird sich um deine Anfrage kümmern und sich in den nächsten Tagen bei dir melden. Wenn du Fragen hast, wende dich gern jederzeit an <a href="mailto:community@wikimedia.de">community@wikimedia.de</a>.</p>
@ -44,4 +29,4 @@ Sendungsadrese: {{data.send_to}} {% endif %}<br>
<p>Datenschutzerklärung:<br>
Soweit Sie uns personenbezogene Daten mitteilen, verarbeiten wir diese Daten gemäß unserer <a href="https://www.wikimedia.de/datenschutz/">Datenschutzerklärung </a>.</p>
</body>
</html>
</html>

View File

@ -1,29 +1,22 @@
Hallo {{data.realname}},
Hallo {{ applicant_name }},
wir haben Deine Anfrage ({{data.type_label|striptags}}) erhalten.
{% if data.choice in data.grant %}
Vorraussichtliche Kosten: {{data.cost}}
Anmerkungen: {{data.notes}} {% endif %} {% if data.choice in data.domain %}
Domain: {{data.domain}}
Adressenbestandteil: {{data.address}} {% endif %} {% if data.choice == 'BIB' %}
Bibliothek: {{data.library}}
Dauer: {{data.duration}} {% elif data.choice == 'ELIT' %}
Datenbank: {{data.library}}
Dauer: {{data.duration}} {% elif data.choice == 'SOFT' %}
Software: {{data.library}}
Dauer: {{data.duration}} {% elif data.choice == 'IFG'%}
Anfrage-URL: {{data.url}} {% elif data.choice == 'LIT'%}
Info zum Werk: {{data.info}}
Bezugsquelle: {{data.source}} {% elif data.choice == 'MAIL'%}
Adressenbestandteil frei gewählt: {{data.other}} {% elif data.choice == 'VIS'%}
Wikimedia-Projekt: {{data.project}}
Persönliche Daten: {{data.data}}
Variante: {{data.variant}}
Sendungsadrese: {{data.send_to}} {% endif %}
vielen Dank für deine Anfrage ({{type_label}}), die bei uns eingegangen ist.
Das Team Comunitys und Engagement wird sich um die Bearbeitung deiner Anfrage kümmern
und sich in den nächsten Tagen bei dir melden. Solltest du Rückfragen haben,
wende dich gern an community@wikimedia.de.
{% for label, value in form_data.items %}{{ label }}: {{ value }}
{% endfor %}
Viele Grüße, dein freundliches aber komplett unmenschliches automatisches
Formularbeantwortungssystem.
Das Team Community-Konferenzen & Förderung wird sich um deine Anfrage kümmern und sich in den nächsten Tagen bei dir melden. Wenn du Fragen hast, wende dich gern jederzeit an community@wikimedia.de.
--
Wikimedia Deutschland e. V. | Tempelhofer Ufer 2324 | 10963 Berlin
Zentrale: +49 30 5771162-0
https://wikimedia.de
Unsere Vision ist eine Welt, in der alle Menschen am Wissen der Menschheit teilhaben, es nutzen und mehren können. Helfen Sie uns dabei!
https://spenden.wikimedia.de
Wikimedia Deutschland Gesellschaft zur Förderung Freien Wissens e. V. Eingetragen im Vereinsregister des Amtsgerichts Charlottenburg, VR 23855 B. Als gemeinnützig anerkannt durch das Finanzamt für Körperschaften I Berlin, Steuernummer 27/029/42207. Geschäftsführende Vorständin: Franziska Heine.
Datenschutzerklärung:
Soweit Sie uns personenbezogene Daten mitteilen, verarbeiten wir diese Daten gemäß unserer Datenschutzerklärung (https://www.wikimedia.de/datenschutz/).

View File

@ -1,13 +1,16 @@
import random
from django.forms import model_to_dict
from django.shortcuts import resolve_url
from django.test import TestCase
from input.models import Library, TYPE_PROJ
from foerderbarometer.constants import *
from input.models import Library, ProjectCategory, WikimediaProject
from input.utils.testing import create_superuser, login, request
from input.views import TYPES
from input.views import PROJECT_FUNDING, TYPES, ApplicationView
PATHS = {TYPES[path].code: path for path in TYPES}
PATHS[TYPE_PROJ] = PROJECT_FUNDING[0].path
CODES = list(PATHS)
@ -27,6 +30,9 @@ class AnonymousViewTestCase(TestCase):
request(self, 'extern', expected_url=url, data={'url': url})
def test_extern_invalid_url(self):
request(self, 'extern', data={'url': 'https://domain.not/allowed/to/be/redirected/'})
@classmethod
def get_step_data(cls, choice, **data):
return {
@ -59,15 +65,15 @@ class AnonymousViewTestCase(TestCase):
def test_extern_types(self):
types = [
('BIB', 'Bibliotheksausweis'),
('ELIT', 'Online-Ressource'),
('MAIL', 'Mailadresse beantragen'),
('IFG', 'gewonnenen Informationen'),
('LIT', 'Literatur verwenden'),
('LIST', 'Mailingliste beantragen'),
('TRAV', 'Transportmittel'),
('SOFT', 'Lizenz'),
('VIS', 'DIN 5008'),
(TYPE_BIB, 'Bibliotheksausweis'),
(TYPE_ELIT, 'Online-Ressource'),
(TYPE_MAIL, 'Mailadresse beantragen'),
(TYPE_IFG, 'gewonnenen Informationen'),
(TYPE_LIT, 'Literatur verwenden'),
(TYPE_LIST, 'Mailingliste beantragen'),
(TYPE_TRAV, 'Transportmittel'),
(TYPE_SOFT, 'Lizenz'),
(TYPE_VIS, 'DIN 5008'),
(TYPE_PROJ, 'Projektförderung'),
]
@ -79,7 +85,7 @@ class AnonymousViewTestCase(TestCase):
self.assertContains(response, text)
def test_extern_travel(self):
self.helper_extern('TRAV', 'Transportmittel', {
self.helper_extern(TYPE_TRAV, 'Transportmittel', {
'project_name': 'Test',
'transport': 'BAHN',
'travelcost': 10,
@ -90,27 +96,27 @@ class AnonymousViewTestCase(TestCase):
})
def test_extern_lit(self):
self.helper_extern('LIT', 'Literatur verwenden', {
self.helper_extern(TYPE_LIT, 'Literatur verwenden', {
'cost': 20,
'info': 'Test',
'source': 'Test',
'notes': '',
'selfbuy': 'TRUE',
'selfbuy_data': 'NONE',
'selfbuy': 'FALSE',
'selfbuy_data': 'Test',
'selfbuy_give_data': True,
'check': True,
'terms_accepted': True,
})
def test_extern_lit_without_consent_fails(self):
response = self.helper_extern_base('LIT', 'Literatur verwenden', {
response = self.helper_extern_base(TYPE_LIT, 'Literatur verwenden', {
'cost': 20,
'info': 'Test',
'source': 'Test',
'notes': '',
'selfbuy': 'TRUE',
'selfbuy_data': 'NONE',
'selfbuy_give_data': True,
'selfbuy_data': '',
'selfbuy_give_data': False,
'check': False,
})
@ -124,9 +130,32 @@ class AnonymousViewTestCase(TestCase):
'notes': '',
})
def test_extern_proj(self):
category = ProjectCategory.objects.order_by('?').first()
wikimedia_project = WikimediaProject.objects.order_by('?').first()
self.helper_extern(TYPE_PROJ, 'Projektförderung', {
'name': 'Test',
'description': 'Test',
'categories': [category.id, 0],
'categories_other': 'Test',
'wikimedia_projects': [wikimedia_project.id, 0],
'wikimedia_projects_other': 'Test',
'start': '2025-01-01',
'end': '2025-01-02',
'participants_estimated': 1,
'cost': 20,
})
def test_extern_invalid_code(self):
request(self, 'extern', args=['invalid'], status_code=404)
def test_unknown_name(self):
obj = Library(type=Library.TYPE)
data = model_to_dict(obj)
name = ApplicationView.get_recipient_name(obj, data)
self.assertEqual(name, 'Unbekannt')
class AuthenticatedViewTestCase(TestCase):

View File

@ -1,12 +1,20 @@
import datetime
from dataclasses import dataclass
from smtplib import SMTPException
from typing import Optional
from urllib.parse import urljoin
from django.forms import ChoiceField, Field
from django.shortcuts import render, redirect
from django.http import HttpResponse, Http404
from django.urls import reverse
from django.utils.choices import flatten_choices
from django.utils.formats import date_format
from django.utils.functional import cached_property
from django.utils.http import url_has_allowed_host_and_scheme
from django.utils.safestring import mark_safe
from django.utils.text import get_text_list
from django.core.mail import BadHeaderError
from django.conf import settings
from django.contrib.auth.decorators import login_required
@ -14,6 +22,7 @@ from django.views.generic import TemplateView
from django.views.generic.edit import FormView
from django.utils.html import strip_tags
from input.utils.admin import admin_url_name
from input.utils.mail import build_email, collect_and_attach
from .forms import (
@ -43,6 +52,8 @@ from .models import (
TYPE_SOFT,
TYPE_TRAV,
TYPE_VIS,
Project,
ProductCategoryFormField,
)
HELP_TEXTS = {
@ -76,13 +87,13 @@ class ApplicationType:
form_class: type[BaseApplicationForm]
link: str
label: Optional[str] = None
help_texts: Optional[str] = None
help_texts: Optional[dict] = None
def __post_init__(self):
if self.label is None:
self.label = TYPE_CHOICES[self.code]
if self.help_texts is None:
if self.help_texts is None: # pragma: no branch
self.help_texts = HELP_TEXTS.get(self.code)
@property
@ -243,14 +254,7 @@ class ApplicationView(FormView):
def prepare_data(self, form):
# Collect cleaned data and mark the current type
data = {**form.cleaned_data, 'choice': self.type_code}
# Special rule for literature applications
if self.type_code == TYPE_LIT and data.get('selfbuy') == 'TRUE':
data['selfbuy_give_data'] = 'False'
return data
return {**form.cleaned_data, 'choice': self.type_code}
def save_obj(self, form, data):
# Save model instance
@ -286,19 +290,9 @@ class ApplicationView(FormView):
def send_mail(self, obj, data):
# Prepare minimal mail context and send mails
type_label_html = self.type_info.label
type_label_plain = strip_tags(type_label_html)
data['pk'] = obj.pk
data['url_prefix'] = settings.EMAIL_URL_PREFIX
data['type_label'] = type_label_html
context = {'data': data}
applicant_name = self.get_recipient_name(obj, data)
context = self.get_email_context(obj, data)
applicant_subject = 'Deine Förderanfrage bei Wikimedia Deutschland'
staff_subject = f'Anfrage {type_label_plain} von {applicant_name}'
staff_subject = 'Anfrage {type_label} von {applicant_name}'.format(**context)
try:
self.send_email('applicant', 'ifg_volunteer_mail', applicant_subject, data['email'], context)
@ -310,6 +304,59 @@ class ApplicationView(FormView):
obj.delete()
return HttpResponse('Error in sending mails (probably wrong address?). Data not saved!')
def get_email_context(self, obj, data):
return {
'data': data,
'urls': self.get_urls(obj),
'form_data': self.get_form_data(obj, data),
'applicant_name': self.get_recipient_name(obj, data),
'type_label': self.sanitize_label(self.type_info.label),
}
def get_urls(self, obj, **urls):
urls['admin'] = self.get_absolute_url(admin_url_name(obj, 'change'), obj.id)
if isinstance(obj, Project):
urls['authorize'] = urls['deny'] = None
else:
urls['authorize'] = self.get_absolute_url('authorize', self.type_info.code, obj.id)
urls['deny'] = self.get_absolute_url('deny', self.type_info.code, obj.id)
return urls
@staticmethod
def get_absolute_url(view, *args):
return urljoin(settings.EMAIL_URL_PREFIX, reverse(view, args=args))
def get_form_data(self, obj, data):
return {
self.sanitize_label(field.label): self.format_value(field.field, field.initial)
for field in self.type_info.form_class(initial=data)
}
@staticmethod
def sanitize_label(label: str):
label = strip_tags(label)
words = str.split(label)
return ' '.join(words)
@staticmethod
def format_value(field: Field, value):
if isinstance(field, ProductCategoryFormField):
value = get_text_list(value, 'und')
elif isinstance(field, ChoiceField):
choices = flatten_choices(field.choices)
value = dict(choices).get(value, value)
elif isinstance(value, bool):
value = '' if value else ''
elif isinstance(value, datetime.date):
value = date_format(value)
elif value in field.empty_values:
value = ''
return value
def send_email(self, kind, template_name, subject, recipient, context, *, fail_silently=False):
email = build_email(template_name, context, subject, recipient)