diff --git a/foerderbarometer/constants.py b/foerderbarometer/constants.py new file mode 100644 index 0000000..0eef96f --- /dev/null +++ b/foerderbarometer/constants.py @@ -0,0 +1,33 @@ +TYPE_ALL = 'ALL' + +TYPE_BIB = 'BIB' # Bibliotheksstipendium +TYPE_ELIT = 'ELIT' # eLiteraturstipendium +TYPE_SOFT = 'SOFT' # Softwarestipendium +TYPE_MAIL = 'MAIL' # E-Mail-Adresse +TYPE_IFG = 'IFG' # Kostenübernahme IFG-Anfrage +TYPE_LIT = 'LIT' # Literaturstipendium +TYPE_LIST = 'LIST' # Mailingliste +TYPE_TRAV = 'TRAV' # Reisekosten +TYPE_VIS = 'VIS' # Visitenkarten +TYPE_PROJ = 'PROJ' # Projektförderung + +TYPES = [ + TYPE_BIB, + TYPE_ELIT, + TYPE_SOFT, + TYPE_MAIL, + TYPE_IFG, + TYPE_LIT, + TYPE_LIST, + TYPE_TRAV, + TYPE_VIS, + TYPE_PROJ, +] + +RECIPIENT_APPLICANT = 'applicant' +RECIPIENT_STAFF = 'staff' + +RECIPIENTS = [ + RECIPIENT_APPLICANT, + RECIPIENT_STAFF, +] diff --git a/foerderbarometer/settings.py b/foerderbarometer/settings.py index 0141963..c51fc4a 100644 --- a/foerderbarometer/settings.py +++ b/foerderbarometer/settings.py @@ -6,6 +6,8 @@ from dotenv import load_dotenv from input.utils.settings import env, password_validators +from .constants import * + BASE_DIR = Path(__file__).parents[1] load_dotenv(BASE_DIR / '.env') @@ -165,3 +167,26 @@ NUTZUNGSBEDINGUNGEN_MAILINGLISTEN = 'static/input/nutzungsbedingungen-mailinglis NUTZUNGSBEDINGUNGEN_LITERATURSTIPENDIUM = 'static/input/nutzungsbedingungen-literaturstipendium.pdf' NUTZUNGSBEDINGUNGEN_OTRS = 'static/input/2025_Nutzungsvereinbarung_OTRS.docx.pdf' NUTZUNGSBEDINGUNGEN_VISITENKARTEN = 'static/input/nutzungsbedingungen-visitenkarten.pdf' + +MAIL_ATTACHMENT_CACHE_DIR = env('MAIL_ATTACHMENT_CACHE_DIR', BASE_DIR / 'var' / 'mail-attachments') +MAIL_ATTACHMENT_TTL_SECONDS = env('MAIL_ATTACHMENT_TTL_SECONDS', 24 * 60 * 60) +MAIL_ATTACHMENT_URLS = { + RECIPIENT_APPLICANT: { + TYPE_ALL: [], + TYPE_VIS: [ + 'https://foerderung.wikimedia.de/static/input/nutzungsbedingungen-visitenkarten.pdf', + ], + TYPE_MAIL: [ + 'https://foerderung.wikimedia.de/static/input/nutzungsbedingungen-mail.pdf', + ], + TYPE_LIST: [ + 'https://foerderung.wikimedia.de/static/input/nutzungsbedingungen-mailinglisten.pdf', + ], + TYPE_LIT: [ + 'https://foerderung.wikimedia.de/static/input/nutzungsbedingungen-literaturstipendium.pdf', + ], + }, + RECIPIENT_STAFF: { + TYPE_ALL: [], + }, +} diff --git a/input/admin.py b/input/admin.py index aa9e9ea..39bf13b 100755 --- a/input/admin.py +++ b/input/admin.py @@ -1,9 +1,11 @@ import csv from django.contrib import admin -from django.db import models +from django.db import models, transaction from django.http import HttpResponse +from input.utils.mail import send_decision_mails + from .forms import BaseProjectForm from .models import ( Account, @@ -22,6 +24,7 @@ from .models import ( BusinessCard, List, Literature, + TYPE_PROJ, ) @@ -83,7 +86,7 @@ class ProjectAdminForm(BaseProjectForm): super().__init__(*args, **kwargs) for field, model in self.categories.items(): - if self.initial[f'{field}_other']: + if self.initial.get(f'{field}_other'): self.initial[field] = [*self.initial[field], model.other] def clean(self): @@ -100,8 +103,7 @@ class ProjectAdminForm(BaseProjectForm): return cleaned_data -@admin.register(Project) -class ProjectAdmin(admin.ModelAdmin): +class BaseProjectAdmin(admin.ModelAdmin): save_as = True form = ProjectAdminForm search_fields = ('name', 'pid','finance_id', 'realname', 'start', 'end', 'participants_estimated', 'participants_real', 'cost', 'status', 'end_quartal') @@ -158,21 +160,42 @@ class ProjectAdmin(admin.ModelAdmin): class Media: js = ('dropdown/js/otrs_link.js',) - granted = True + granted: bool def get_queryset(self, request): return super().get_queryset(request).filter(granted=self.granted) +@admin.register(Project) +class ProjectAdmin(BaseProjectAdmin): + granted = True + + @admin.register(ProjectRequest) -class ProjectRequestAdmin(ProjectAdmin): +class ProjectRequestAdmin(BaseProjectAdmin): granted = None + def save_model(self, request, obj: ProjectRequest, form: ProjectAdminForm, change: bool): + super().save_model(request, obj, form, change) + + if obj.granted is None: + return None + + transaction.on_commit(lambda: send_decision_mails(obj)) + + return obj.granted + @admin.register(ProjectDeclined) -class ProjectDeclinedAdmin(ProjectAdmin): +class ProjectDeclinedAdmin(BaseProjectAdmin): granted = False + def has_add_permission(self, request): + return False + + def has_change_permission(self, request, obj=None): + return False + @admin.register(BusinessCard) class BusinessCardAdmin(RequestURLBeforeInternNotesMixin, admin.ModelAdmin): diff --git a/input/management/commands/sendmails.py b/input/management/commands/sendmails.py index 15cac47..654d46a 100755 --- a/input/management/commands/sendmails.py +++ b/input/management/commands/sendmails.py @@ -2,13 +2,13 @@ from datetime import date, timedelta from django.core.management import CommandError from django.core.management.base import BaseCommand -from django.template.loader import get_template from django.core.mail import BadHeaderError -from django.core.mail import EmailMultiAlternatives from django.conf import settings from input.models import Project, Library, HonoraryCertificate, Travel, Email,\ BusinessCard, List, IFG, Literature +from input.utils.mail import send_email + class Command(BaseCommand): ''' mails will be sent here: @@ -34,15 +34,11 @@ class Command(BaseCommand): 'name': name, 'pid': pid, 'SURVEY_PREFIX': settings.SURVEY_PREFIX, } - txt_mail_template = get_template('input/survey_mail.txt') - html_mail_template = get_template('input/survey_mail.html') + + subject = 'Dein Feedback zur Förderung durch Wikimedia Deutschland' + try: - subject, from_email, to = 'Dein Feedback zur Förderung durch Wikimedia Deutschland', settings.IF_EMAIL, email - text_content = txt_mail_template.render(context) - html_content = html_mail_template.render(context) - msg = EmailMultiAlternatives(subject, text_content, from_email, [to], bcc=[settings.SURVEY_EMAIL]) - msg.attach_alternative(html_content, "text/html") - msg.send() + send_email('survey_mail', context, subject, email, bcc=[settings.SURVEY_EMAIL]) #print('survey mail would have been send') #survey_mail = EmailMessage('Dein Feedback zur Förderung durch Wikimedia Deutschland', @@ -70,21 +66,14 @@ class Command(BaseCommand): .exclude(end_mail_send = True)\ .filter(mail_state = 'NONE') - txt_mail_template = get_template('input/if_end_of_project.txt') - html_mail_template = get_template('input/if_end_of_project.html') - + subject = 'Projektende erreicht' + recipient = settings.IF_EMAIL for project in old: - context = {'project': project} - context['URL_PREFIX'] = settings.EMAIL_URL_PREFIX + context = {'project': project, 'URL_PREFIX': settings.EMAIL_URL_PREFIX} try: - subject, from_email, to = 'Projektende erreicht', settings.IF_EMAIL, settings.IF_EMAIL - text_content = txt_mail_template.render(context) - html_content = html_mail_template.render(context) - msg = EmailMultiAlternatives(subject, text_content, from_email, [to]) - msg.attach_alternative(html_content, "text/html") - msg.send() + send_email('if_end_of_project', context, subject, recipient) #print('end of project mail would have been sent') #send_mail('Projektende erreicht', @@ -110,33 +99,19 @@ class Command(BaseCommand): approved_end = Project.objects.filter(status = 'END')\ .exclude(end_mail_send = True)\ .filter(mail_state = 'INF') - txt_mail_template = get_template('input/if_end_of_project_approved.txt') - html_mail_template = get_template('input/if_end_of_project_approved.html') - txt_informMail_template = get_template('input/if_end_of_project_orginformed.txt') - html_informMail_template = get_template('input/if_end_of_project_orginformed.html') # send the mail to project.email, which would be the mail of the volunteer filling out the form for project in approved_end: - context = {'project': project} - context['URL_PREFIX'] = settings.EMAIL_URL_PREFIX - + context = {'project': project, 'URL_PREFIX': settings.EMAIL_URL_PREFIX} try: - subject, from_email, to = 'Projektende erreicht', settings.IF_EMAIL, project.email - text_content = txt_mail_template.render(context) - html_content = html_mail_template.render(context) - msg = EmailMultiAlternatives(subject, text_content, from_email, [to]) - msg.attach_alternative(html_content, "text/html") - msg.send() + send_email('if_end_of_project_approved', context, 'Projektende erreicht', project.email) + #print('if and of project approved mail would have been sent') - inform_subject, inform_from_email, inform_to = 'Projektorganisator*in wurde informiert', settings.IF_EMAIL, settings.IF_EMAIL - inform_text_content = txt_informMail_template.render(context) - inform_html_content = html_informMail_template.render(context) - inform_msg = EmailMultiAlternatives(inform_subject, inform_text_content, inform_from_email, [inform_to]) - inform_msg.attach_alternative(html_content, "text/html") - inform_msg.send() + send_email('if_end_of_project_orginformed', context, 'Projektorganisator*in wurde informiert', settings.IF_EMAIL) + #print('if end of project orginformed mail would have been sent') #send_mail('Projektende erreicht', @@ -168,25 +143,15 @@ class Command(BaseCommand): .exclude(end_mail_send = True)\ .filter(mail_state = 'INF') - html_mail_template = get_template('input/if_not_of_project_approved.html') - txt_mail_template = get_template('input/if_not_of_project_approved.txt') - - txt_informMail_template = get_template('input/if_end_of_project_orginformed.txt') - html_informMail_template = get_template('input/if_end_of_project_orginformed.html') # send the mail to project.email, which would be the mail of the volunteer that filled out the form for project in approved_notHappened: - context = {'project': project} - context['URL_PREFIX'] = settings.EMAIL_URL_PREFIX - try: - subject, from_email, to = 'Projektende erreicht', settings.IF_EMAIL, project.email - text_content = txt_mail_template.render(context) - html_content = html_mail_template.render(context) - msg = EmailMultiAlternatives(subject, text_content, from_email, [to]) - msg.attach_alternative(html_content, "text/html") - msg.send() - #print('if not of project approved end mail would have been sent') + context = {'project': project, 'URL_PREFIX': settings.EMAIL_URL_PREFIX} + try: + send_email('if_not_of_project_approved', context, 'Projektende erreicht', project.email) + + #print('if not of project approved end mail would have been sent') #send_mail('Projektende erreicht', # mail_template.render(context), @@ -194,12 +159,8 @@ class Command(BaseCommand): # [project.email], # fail_silently=False) - inform_subject, inform_from_email, inform_to = 'Projektorganisator*in wurde informiert', settings.IF_EMAIL, settings.IF_EMAIL - inform_text_content = txt_informMail_template.render(context) - inform_html_content = html_informMail_template.render(context) - inform_msg = EmailMultiAlternatives(inform_subject, inform_text_content, inform_from_email, [inform_to]) - inform_msg.attach_alternative(html_content, "text/html") - inform_msg.send() + send_email('if_end_of_project_orginformed', context, 'Projektorganisator*in wurde informiert', settings.IF_EMAIL) + #print('if not of project approved end mail orginformed would have been sent') #send_mail('Projektorganisator*in wurde informiert', diff --git a/input/models.py b/input/models.py index 567e675..45f38e9 100755 --- a/input/models.py +++ b/input/models.py @@ -11,6 +11,9 @@ from django.utils.functional import cached_property, classproperty from django.utils.html import format_html from django.utils.safestring import mark_safe +from foerderbarometer.constants import * + + EMAIL_STATES = { 'NONE': 'noch keine Mail versendet', 'INF': 'die Benachrichtigung zur Projektabschlussmail wurde versendet', @@ -403,17 +406,6 @@ def type_link(path, label): ) -TYPE_BIB = 'BIB' -TYPE_ELIT = 'ELIT' -TYPE_MAIL = 'MAIL' -TYPE_IFG = 'IFG' -TYPE_LIT = 'LIT' -TYPE_LIST = 'LIST' -TYPE_TRAV = 'TRAV' -TYPE_SOFT = 'SOFT' -TYPE_VIS = 'VIS' -TYPE_PROJ = 'PROJ' - TYPE_CHOICES = { TYPE_BIB: type_link('Zugang_zu_Fachliteratur#Bibliotheksstipendium', 'Bibliotheksstipendium'), TYPE_ELIT: type_link('Zugang_zu_Fachliteratur#eLiteraturstipendium', 'eLiteraturstipendium'), diff --git a/input/templates/input/ifg_volunteer_mail.html b/input/templates/input/ifg_volunteer_mail.html deleted file mode 100755 index bd7f989..0000000 --- a/input/templates/input/ifg_volunteer_mail.html +++ /dev/null @@ -1,34 +0,0 @@ - -
-Hallo {{data.realname}}, -Hallo {{ data.realname }},
+ +Deine Förderanfrage {{project.name}} wurde leider abgelehnt.
+ +Fragen? community@wikimedia.de
+ + diff --git a/input/templates/mails/approval_denied_applicant.txt b/input/templates/mails/approval_denied_applicant.txt new file mode 100644 index 0000000..55a8df6 --- /dev/null +++ b/input/templates/mails/approval_denied_applicant.txt @@ -0,0 +1,5 @@ +Hallo {{ data.realname }}, + +deine Förderanfrage {{project.name}} wurde leider abgelehnt. + +Fragen? community@wikimedia.de diff --git a/input/templates/mails/approval_denied_staff.html b/input/templates/mails/approval_denied_staff.html new file mode 100644 index 0000000..3281b63 --- /dev/null +++ b/input/templates/mails/approval_denied_staff.html @@ -0,0 +1,7 @@ + + +Hallo Team Community-Konferenzen & Förderung,
+ +Die Förderanfrage {{project.name}} von {{ data.realname }} wurde abgelehnt.
+ + \ No newline at end of file diff --git a/input/templates/mails/approval_denied_staff.txt b/input/templates/mails/approval_denied_staff.txt new file mode 100644 index 0000000..2a96ae9 --- /dev/null +++ b/input/templates/mails/approval_denied_staff.txt @@ -0,0 +1,3 @@ +Hallo Team Community-Konferenzen & Förderung, + +die Förderanfrage {{project.name}} von {{ data.realname }} wurde abgelehnt. diff --git a/input/templates/mails/approval_granted_applicant.html b/input/templates/mails/approval_granted_applicant.html new file mode 100644 index 0000000..c768a73 --- /dev/null +++ b/input/templates/mails/approval_granted_applicant.html @@ -0,0 +1,10 @@ + + +Hallo {{ data.realname }},
+ +Deine Förderanfrage {{project.name}} wurde bewilligt.
+ +Das Team Community-Konferenzen & Förderung meldet sich bald bei dir.
+ Fragen? community@wikimedia.de
Hallo Team Community-Konferenzen & Förderung,
+ +Die Förderanfrage {{project.name}} von {{ data.realname }} wurde bewilligt.
+ + \ No newline at end of file diff --git a/input/templates/mails/approval_granted_staff.txt b/input/templates/mails/approval_granted_staff.txt new file mode 100644 index 0000000..5fd989b --- /dev/null +++ b/input/templates/mails/approval_granted_staff.txt @@ -0,0 +1,3 @@ +Hallo Team Community-Konferenzen & Förderung, + +die Förderanfrage {{project.name}} von {{ data.realname }} wurde bewilligt. diff --git a/input/templates/input/if_end_of_project.html b/input/templates/mails/if_end_of_project.html similarity index 100% rename from input/templates/input/if_end_of_project.html rename to input/templates/mails/if_end_of_project.html diff --git a/input/templates/input/if_end_of_project.txt b/input/templates/mails/if_end_of_project.txt similarity index 100% rename from input/templates/input/if_end_of_project.txt rename to input/templates/mails/if_end_of_project.txt diff --git a/input/templates/input/if_end_of_project_approved.html b/input/templates/mails/if_end_of_project_approved.html similarity index 100% rename from input/templates/input/if_end_of_project_approved.html rename to input/templates/mails/if_end_of_project_approved.html diff --git a/input/templates/input/if_end_of_project_approved.txt b/input/templates/mails/if_end_of_project_approved.txt similarity index 100% rename from input/templates/input/if_end_of_project_approved.txt rename to input/templates/mails/if_end_of_project_approved.txt diff --git a/input/templates/input/if_end_of_project_orginformed.html b/input/templates/mails/if_end_of_project_orginformed.html similarity index 100% rename from input/templates/input/if_end_of_project_orginformed.html rename to input/templates/mails/if_end_of_project_orginformed.html diff --git a/input/templates/input/if_end_of_project_orginformed.txt b/input/templates/mails/if_end_of_project_orginformed.txt similarity index 100% rename from input/templates/input/if_end_of_project_orginformed.txt rename to input/templates/mails/if_end_of_project_orginformed.txt diff --git a/input/templates/input/if_mail.html b/input/templates/mails/if_mail.html similarity index 79% rename from input/templates/input/if_mail.html rename to input/templates/mails/if_mail.html index 92107f9..31237ba 100755 --- a/input/templates/input/if_mail.html +++ b/input/templates/mails/if_mail.html @@ -1,10 +1,11 @@ -Hallo Team Communitys und Engagement, -Hallo Team Community-Konferenzen & Förderung,
+ +es gibt eine neue Anfrage von {{ data.realname }}.
+ +{{ data.username|default:data.realname }} ({{ data.email }}) fragt an: {{ data.type_label|striptags }}
+ {% if data.choice in data.grant %}Zum Eintrag in der Förderdatenbank:
{% if data.choice == 'BIB' %}
{{data.url_prefix}}/admin/input/library/{{data.pk}}/change
{% elif data.choice == 'ELIT'%}
@@ -46,13 +46,15 @@ Zum Eintrag in der Förderdatenbank:
{% elif data.choice == 'VIS'%}
{{data.url_prefix}}/admin/input/businesscard/{{data.pk}}/change
{% endif %}
-
+
Zum Genehmigen hier klicken: + {{data.url_prefix}}{% url 'authorize' data.choice data.pk %} +
+ +Zum Ablehnen hier klicken: + {{data.url_prefix}}{% url 'deny' data.choice data.pk %} +
diff --git a/input/templates/input/if_mail.txt b/input/templates/mails/if_mail.txt similarity index 100% rename from input/templates/input/if_mail.txt rename to input/templates/mails/if_mail.txt diff --git a/input/templates/input/if_not_of_project_approved.html b/input/templates/mails/if_not_of_project_approved.html similarity index 100% rename from input/templates/input/if_not_of_project_approved.html rename to input/templates/mails/if_not_of_project_approved.html diff --git a/input/templates/input/if_not_of_project_approved.txt b/input/templates/mails/if_not_of_project_approved.txt similarity index 100% rename from input/templates/input/if_not_of_project_approved.txt rename to input/templates/mails/if_not_of_project_approved.txt diff --git a/input/templates/mails/ifg_volunteer_mail.html b/input/templates/mails/ifg_volunteer_mail.html new file mode 100755 index 0000000..5652db1 --- /dev/null +++ b/input/templates/mails/ifg_volunteer_mail.html @@ -0,0 +1,47 @@ + + +Hallo {{ data.username|default:data.realname }},
+ +vielen Dank für deine Anfrage ({{ data.type_label|striptags }}), die bei uns eingegangen ist.
+ +Dies ist eine automatisch generierte E-Mail. Im Folgenden findest du deine Formulareingaben nochmals zu deiner Übersicht: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 23–24 | 10963 Berlin
+ Zentrale: +49 30 5771162-0
+ 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!
+ 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 .