2025-10-07 17:44:28 +00:00
|
|
|
|
from django.conf import settings
|
|
|
|
|
|
from django.core.mail import EmailMultiAlternatives
|
|
|
|
|
|
from django.template.loader import get_template
|
|
|
|
|
|
from django.utils.html import strip_tags
|
2025-10-17 10:06:23 +00:00
|
|
|
|
|
|
|
|
|
|
from input.models import TYPE_CHOICES
|
|
|
|
|
|
|
|
|
|
|
|
from .attachments import collect_attachment_paths, attach_files
|
|
|
|
|
|
|
|
|
|
|
|
__all__ = [
|
2025-10-17 12:51:18 +00:00
|
|
|
|
'build_email',
|
|
|
|
|
|
'send_email',
|
2025-10-17 10:06:23 +00:00
|
|
|
|
'collect_attachment_paths',
|
|
|
|
|
|
'attach_files',
|
|
|
|
|
|
'send_decision_mail',
|
|
|
|
|
|
'send_staff_decision_mail',
|
|
|
|
|
|
]
|
2025-10-07 17:44:28 +00:00
|
|
|
|
|
|
|
|
|
|
|
2025-10-17 12:51:18 +00:00
|
|
|
|
def build_email(template_name: str, context: dict, subject: str, *recipients: str, **kwargs):
|
|
|
|
|
|
body = get_template(f'mails/{template_name}.txt').render(context)
|
|
|
|
|
|
html = get_template(f'mails/{template_name}.html').render(context)
|
|
|
|
|
|
|
|
|
|
|
|
kwargs.setdefault('from_email', settings.IF_EMAIL)
|
|
|
|
|
|
|
|
|
|
|
|
kwargs['subject'] = subject
|
|
|
|
|
|
kwargs['body'] = body
|
|
|
|
|
|
kwargs['to'] = recipients
|
|
|
|
|
|
|
|
|
|
|
|
email = EmailMultiAlternatives(**kwargs)
|
|
|
|
|
|
|
|
|
|
|
|
email.attach_alternative(html, 'text/html')
|
|
|
|
|
|
|
|
|
|
|
|
return email
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def send_email(template_name: str, context: dict, subject: str, *recipients: str, fail_silently=False, **kwargs):
|
|
|
|
|
|
return build_email(template_name, context, subject, *recipients, **kwargs).send(fail_silently)
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-10-07 17:44:28 +00:00
|
|
|
|
def _type_labels(choice: str):
|
|
|
|
|
|
"""
|
|
|
|
|
|
Resolve the human-readable type label.
|
|
|
|
|
|
Returns (HTML label, plain text label).
|
|
|
|
|
|
"""
|
|
|
|
|
|
html = TYPE_CHOICES.get(choice, choice)
|
2025-10-17 12:15:56 +00:00
|
|
|
|
plain = strip_tags(html)
|
2025-10-07 17:44:28 +00:00
|
|
|
|
return html, plain
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _decision_context(obj, choice_code: str) -> dict:
|
|
|
|
|
|
"""
|
|
|
|
|
|
Build a minimal, consistent context for decision mails (applicant & staff).
|
|
|
|
|
|
Also exposes the full project object as 'project' for template access.
|
|
|
|
|
|
"""
|
|
|
|
|
|
type_html, type_plain = _type_labels(choice_code)
|
|
|
|
|
|
realname = getattr(obj, 'realname', '') or getattr(obj, 'email', '')
|
|
|
|
|
|
return {
|
|
|
|
|
|
'data': {
|
|
|
|
|
|
'realname': realname,
|
2025-10-17 12:15:56 +00:00
|
|
|
|
'type_label': type_html,
|
|
|
|
|
|
'type_label_plain': type_plain,
|
2025-10-07 17:44:28 +00:00
|
|
|
|
'name': getattr(obj, 'name', None),
|
|
|
|
|
|
},
|
|
|
|
|
|
'project': obj,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def send_decision_mail(obj, choice_code: str, granted: bool) -> None:
|
|
|
|
|
|
"""
|
|
|
|
|
|
Send a decision email to the applicant after manual approval/denial.
|
|
|
|
|
|
Uses: input/approval_granted.(txt|html) or input/approval_denied.(txt|html)
|
|
|
|
|
|
"""
|
|
|
|
|
|
recipient = getattr(obj, 'email', None)
|
|
|
|
|
|
if not recipient:
|
|
|
|
|
|
return # no recipient -> skip
|
|
|
|
|
|
|
|
|
|
|
|
ctx = _decision_context(obj, choice_code)
|
2025-10-17 12:51:18 +00:00
|
|
|
|
template_suffix = 'granted' if granted else 'denied'
|
2025-10-07 17:44:28 +00:00
|
|
|
|
|
|
|
|
|
|
project_name = getattr(obj, 'name', None) or '(ohne Projektnamen)'
|
|
|
|
|
|
decision_word = 'bewilligt' if granted else 'abgelehnt'
|
|
|
|
|
|
subject = f'Deine Förderanfrage „{project_name}“ – {decision_word}'
|
|
|
|
|
|
|
2025-10-17 12:51:18 +00:00
|
|
|
|
return send_email(f'approval_{template_suffix}', ctx, subject, recipient)
|
2025-10-07 17:44:28 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def send_staff_decision_mail(obj, choice_code: str, granted: bool) -> None:
|
|
|
|
|
|
"""
|
|
|
|
|
|
Send a decision email to the internal team (staff) after approval/denial.
|
|
|
|
|
|
Uses: input/approval_granted_staff.(txt|html) or input/approval_denied_staff.(txt|html)
|
|
|
|
|
|
"""
|
|
|
|
|
|
ctx = _decision_context(obj, choice_code)
|
2025-10-17 12:51:18 +00:00
|
|
|
|
template_suffix = 'granted' if granted else 'denied'
|
2025-10-07 17:44:28 +00:00
|
|
|
|
|
|
|
|
|
|
project_name = getattr(obj, 'name', None) or '(ohne Projektnamen)'
|
|
|
|
|
|
decision_word = 'bewilligt' if granted else 'abgelehnt'
|
|
|
|
|
|
subject = f'Entscheidung: {project_name} ({decision_word})'
|
|
|
|
|
|
|
2025-10-17 12:51:18 +00:00
|
|
|
|
return send_email(f'approval_{template_suffix}_staff', ctx, subject, settings.IF_EMAIL)
|