foerderbarometer/input/utils/mail/__init__.py

98 lines
3.0 KiB
Python
Raw Normal View History

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__ = [
'collect_attachment_paths',
'attach_files',
'send_decision_mail',
'send_staff_decision_mail',
]
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)
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,
'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)
base = 'input/approval_granted' if granted else 'input/approval_denied'
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}'
txt = get_template(f'{base}.txt').render(ctx)
html = get_template(f'{base}.html').render(ctx)
msg = EmailMultiAlternatives(
subject,
txt,
settings.IF_EMAIL,
[recipient],
)
msg.attach_alternative(html, 'text/html')
msg.send()
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)
base = 'input/approval_granted_staff' if granted else 'input/approval_denied_staff'
project_name = getattr(obj, 'name', None) or '(ohne Projektnamen)'
decision_word = 'bewilligt' if granted else 'abgelehnt'
subject = f'Entscheidung: {project_name} ({decision_word})'
txt = get_template(f'{base}.txt').render(ctx)
html = get_template(f'{base}.html').render(ctx)
msg = EmailMultiAlternatives(
subject,
txt,
settings.IF_EMAIL,
[settings.IF_EMAIL],
)
msg.attach_alternative(html, 'text/html')
msg.send()