diff --git a/input/forms.py b/input/forms.py
index 20b0746..de6fc83 100644
--- a/input/forms.py
+++ b/input/forms.py
@@ -26,6 +26,7 @@ class ProjectForm(FdbForm):
widgets = {'start': AdminDateWidget(),
'end': AdminDateWidget(),}
+
class ExternForm(FdbForm):
choice = ChoiceField(choices=TYPE_CHOICES.items(), widget=RadioSelect,
@@ -39,6 +40,7 @@ class ExternForm(FdbForm):
model = ConcreteExtern
exclude = ('granted', 'granted_date', 'survey_mail_send', 'service_id', 'survey_mail_date')
+
INTERN_CHOICES = {'PRO': 'Projektsteckbrief',
'HON': 'Ehrenamtsbescheinigung, Akkreditierung oder Redaktionsbestätigung',
'TRAV': 'Reisekostenerstattung'}
@@ -51,11 +53,12 @@ class InternForm(FdbForm):
model = ConcreteVolunteer
exclude = ('granted', 'granted_date', 'survey_mail_send', 'survey_mail_date')
+
class TravelForm(FdbForm):
# TODO: add some javascript to show/hide other-field
class Meta:
model = Travel
- exclude = ('granted', 'granted_date', 'survey_mail_send', 'realname', 'email', 'survey_mail_date')
+ exclude = ('granted', 'granted_date', 'survey_mail_send', 'realname', 'email', 'survey_mail_date', 'project', 'request_url', 'payed_for_hotel_by', 'payed_for_travel_by' )
widgets = {'checkin': AdminDateWidget(),
'checkout': AdminDateWidget(),}
@@ -82,6 +85,7 @@ class CheckForm(FdbForm):
label=format_html("Ich stimme den Nutzungsbedingungen zu",
NUTZUNGSBEDINGUNGEN))
+
class LiteratureForm(CheckForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
@@ -115,7 +119,9 @@ class BusinessCardForm(CheckForm):
class Media:
js = ('dropdown/js/base.js',)
+
class ListForm(CheckForm):
class Meta:
model = List
fields = ['domain', 'address']
+
diff --git a/input/management/commands/sendmails.py b/input/management/commands/sendmails.py
index 8471f43..243c396 100644
--- a/input/management/commands/sendmails.py
+++ b/input/management/commands/sendmails.py
@@ -4,6 +4,7 @@ import sys
from django.core.management.base import BaseCommand, CommandError
from django.template.loader import get_template
from django.core.mail import send_mail, BadHeaderError, EmailMessage
+from django.core.mail import EmailMultiAlternatives
from django.conf import settings
from input.models import Project, Library, HonoraryCertificate, Travel, Email,\
@@ -112,7 +113,8 @@ class Command(BaseCommand):
approved_notHappened = Project.objects.filter(status = 'NOT')\
.exclude(end_mail_send = False)
- mail_template = get_template('input/if_not_of_project_approved.txt')
+ html_mail_template = get_template('input/if_not_of_project_approved.html')
+ txt_mail_template = get_template('input/if_not_of_project_approved.txt')
informMail_template = get_template('input/if_end_of_project_orginformed.txt')
# send the mail to project.email, which would be the mail of the volunteer that filled out the form
@@ -121,11 +123,20 @@ class Command(BaseCommand):
context = {'project': project}
context['URLPREFIX'] = settings.URLPREFIX
try:
- send_mail('Projektende erreicht',
- mail_template.render(context),
- IF_EMAIL,
- [project.email],
- fail_silently=False)
+ subject, from_email, to = 'Projektende erreicht', 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_mail('Projektende erreicht',
+ # mail_template.render(context),
+ # IF_EMAIL,
+ # [project.email],
+ # fail_silently=False)
send_mail('Projektorganisator*in wurde informiert',
informMail_template.render(context),
IF_EMAIL,
diff --git a/input/migrations/0066_email_adult.py b/input/migrations/0066_email_adult.py
new file mode 100644
index 0000000..419a9b4
--- /dev/null
+++ b/input/migrations/0066_email_adult.py
@@ -0,0 +1,18 @@
+# Generated by Django 4.1.2 on 2022-11-17 11:12
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('input', '0065_alter_literature_selfbuy_and_more'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='email',
+ name='adult',
+ field=models.CharField(choices=[('TRUE', 'Ich bin volljährig.'), ('FALSE', 'Ich bin noch nicht volljährig.'), ('NONE', 'Nichts ausgewählt')], default='NONE', max_length=10, verbose_name='Volljährigkeit'),
+ ),
+ ]
diff --git a/input/migrations/0067_travel_project_name_alter_library_type.py b/input/migrations/0067_travel_project_name_alter_library_type.py
new file mode 100644
index 0000000..5cbcb7a
--- /dev/null
+++ b/input/migrations/0067_travel_project_name_alter_library_type.py
@@ -0,0 +1,23 @@
+# Generated by Django 4.1.2 on 2022-11-17 15:41
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('input', '0066_email_adult'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='travel',
+ name='project_name',
+ field=models.CharField(blank=True, max_length=50, null=True, verbose_name='Projektname:'),
+ ),
+ migrations.AlterField(
+ model_name='library',
+ name='type',
+ field=models.CharField(choices=[('BIB', 'Bibliotheksstipendium'), ('ELIT', 'eLiteraturstipendium'), ('MAIL', 'E-Mail-Adresse'), ('IFG', 'Kostenübernahme IFG-Anfrage'), ('LIT', 'Literaturstipendium'), ('LIST', 'Mailingliste'), ('SOFT', 'Softwarestipendium'), ('VIS', 'Visitenkarten'), ('TRAV', 'Reisekosten')], default='BIB', max_length=4),
+ ),
+ ]
diff --git a/input/migrations/0068_travel_hotel.py b/input/migrations/0068_travel_hotel.py
new file mode 100644
index 0000000..82fd575
--- /dev/null
+++ b/input/migrations/0068_travel_hotel.py
@@ -0,0 +1,18 @@
+# Generated by Django 4.1.2 on 2022-11-17 15:48
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('input', '0067_travel_project_name_alter_library_type'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='travel',
+ name='hotel',
+ field=models.BooleanField(default=False, verbose_name='Hotelzimmer benötigt:'),
+ ),
+ ]
diff --git a/input/migrations/0069_alter_travel_transport.py b/input/migrations/0069_alter_travel_transport.py
new file mode 100644
index 0000000..77538db
--- /dev/null
+++ b/input/migrations/0069_alter_travel_transport.py
@@ -0,0 +1,18 @@
+# Generated by Django 4.1.2 on 2022-11-17 15:58
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('input', '0068_travel_hotel'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='travel',
+ name='transport',
+ field=models.CharField(choices=[('BAHN', 'Bahn'), ('NONE', 'Keine Fahrtkosten'), ('OTHER', 'Sonstiges (mit Begründung)')], default='BAHN', max_length=5, verbose_name='Transportmittel:'),
+ ),
+ ]
diff --git a/input/migrations/0070_alter_travel_project.py b/input/migrations/0070_alter_travel_project.py
new file mode 100644
index 0000000..fe82970
--- /dev/null
+++ b/input/migrations/0070_alter_travel_project.py
@@ -0,0 +1,19 @@
+# Generated by Django 4.1.2 on 2022-11-17 16:13
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('input', '0069_alter_travel_transport'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='travel',
+ name='project',
+ field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='input.project'),
+ ),
+ ]
diff --git a/input/models.py b/input/models.py
index d1f6589..a92ff61 100644
--- a/input/models.py
+++ b/input/models.py
@@ -144,14 +144,17 @@ PAYEDBY_CHOICES = {'WMDE': 'WMDE',
'REQU': 'Antragstellender Mensch'}
class Travel(Intern):
- project = models.ForeignKey(Project, on_delete=models.CASCADE)
- transport = models.CharField(max_length=5, choices=TRANSPORT_CHOICES.items(), default='BAHN')
+ # project variable is now null true and blank true, which means it can be saved without project id to be later on filled out by admins
+ project = models.ForeignKey(Project, on_delete=models.CASCADE, null=True, blank=True)
+ project_name = models.CharField(max_length=50, null=True, blank=True, verbose_name='Projektname:')
+ transport = models.CharField(max_length=5, choices=TRANSPORT_CHOICES.items(), default='BAHN', verbose_name='Transportmittel:')
other_transport = models.CharField(max_length=200, null=True, blank=True, verbose_name='Sonstige Transportmittel (mit Begründung)')
travelcost = models.CharField(max_length=10, default="0", verbose_name="Fahrtkosten")
checkin = models.DateField(blank=True, null=True, verbose_name='Check In')
checkout = models.DateField(blank=True, null=True, verbose_name='Check Out')
payed_for_hotel_by = models.CharField(max_length=4, choices=PAYEDBY_CHOICES.items(), blank=True, null=True, verbose_name='Kostenauslage Hotel durch')
payed_for_travel_by = models.CharField(max_length=4, choices=PAYEDBY_CHOICES.items(), blank=True, null=True, verbose_name='Kostenauslage Fahrt durch')
+ hotel = models.BooleanField(default=False, verbose_name='Hotelzimmer benötigt:')
notes = models.TextField(max_length=1000, blank=True)
@@ -174,6 +177,7 @@ TYPE_CHOICES = {'BIB': format_html('Mailingliste'),
'SOFT': format_html('Softwarestipendium'),
'VIS': format_html('Visitenkarten'),
+ 'TRAV': format_html('Reisekosten'),
}
# same model is used for Library, ELitStip and Software!
@@ -232,6 +236,11 @@ MAIL_CHOICES = {'REALNAME': 'Vorname.Nachname',
'USERNAME': 'Username',
'OTHER': 'Sonstiges:'}
+ADULT_CHOICES = {'TRUE': format_html('Ich bin volljährig.'),
+ 'FALSE': format_html('Ich bin noch nicht volljährig.'),
+ 'NONE': format_html('Nichts ausgewählt')
+ }
+
class Email(Domain):
address = models.CharField(max_length=50,
choices=MAIL_CHOICES.items(),
@@ -239,6 +248,7 @@ class Email(Domain):
help_text=format_html("Bitte gib hier den gewünschten Adressbestandteil an,
der sich vor der Domain befinden soll."))
other = models.CharField(max_length=50,blank=True,null=True, verbose_name="Sonstiges")
+ adult = models.CharField( max_length=10, verbose_name='Volljährigkeit', choices=ADULT_CHOICES.items(), default='NONE')
class List(Domain):
address = models.CharField(max_length=50, default='NO_ADDRESS',
diff --git a/input/views.py b/input/views.py
index cadf55a..e86ebbf 100644
--- a/input/views.py
+++ b/input/views.py
@@ -16,7 +16,7 @@ from django.utils.html import format_html
from .forms import ProjectForm, ExternForm, LibraryForm, IFGForm, LiteratureForm,\
HonoraryCertificateForm, InternForm, TravelForm, EmailForm,\
ListForm, BusinessCardForm, INTERN_CHOICES
-from .models import Project, TYPE_CHOICES, Library, Literature
+from .models import Project, TYPE_CHOICES, Library, Literature, Travel
from .settings import IF_EMAIL
def auth_deny(choice,pk,auth):
@@ -26,6 +26,8 @@ def auth_deny(choice,pk,auth):
Literature.set_granted(pk,auth)
elif choice == 'IFG':
IFG.set_granted(pk,auth)
+ elif choice == 'TRAV':
+ Travel.set_granted(pk,auth)
else:
return HttpResponse(f'ERROR! UNKNOWN CHOICE TYPE! {choice}')
return False
@@ -134,6 +136,7 @@ LABEL_CHOICES = {'BIB': format_html('Bibliothek'),
'LIST': format_html('Mailingliste'),
'SOFT': format_html('Software'),
'VIS': format_html('Visitenkarten'),
+ 'TRAV': format_html('Reisekosten'),
}
HELP_CHOICES = {'BIB': format_html("In welchem Zeitraum möchtest du recherchieren oder
wie lange ist der Bibliotheksausweis gültig?"),
@@ -178,6 +181,8 @@ class ExternView(CookieWizardView):
elif choice == 'LIST':
form = ListForm(data)
form.fields['domain'].help_text = format_html("Mit welcher Domain, bzw. für welches Wikimedia-Projekt,
möchtest du eine Mailingliste beantragen?")
+ elif choice == 'TRAV':
+ form = TravelForm(data)
else:
raise RuntimeError(f'ERROR! UNKNOWN FORMTYPE {choice} in ExternView')
self.choice = choice