diff --git a/input/forms.py b/input/forms.py
index a832a76..c6074fb 100755
--- a/input/forms.py
+++ b/input/forms.py
@@ -1,10 +1,11 @@
+from django import forms
from django.conf import settings
-from django.forms import ModelForm, ChoiceField, RadioSelect, BooleanField, CharField, EmailField
from django.contrib.admin.widgets import AdminDateWidget
+from django.forms import ModelForm, ChoiceField, RadioSelect, BooleanField, CharField, EmailField
from django.forms.renderers import DjangoTemplates
from django.utils.html import format_html
from django.utils.safestring import mark_safe
-from django import forms
+
from .models import ProjectRequest, PROJECT_CATEGORIES, WIKIMEDIA_CHOICES
from .models import (
@@ -90,7 +91,6 @@ class CommonOrderMixin(forms.Form):
class ExternForm(FdbForm):
-
choice = ChoiceField(choices=TYPE_CHOICES.items(), widget=RadioSelect,
label='Was möchtest Du beantragen?')
@@ -103,24 +103,22 @@ class ExternForm(FdbForm):
exclude = ('username', 'granted', 'granted_date', 'survey_mail_send', 'service_id', 'survey_mail_date', 'mail_state')
-INTERN_CHOICES = {'PRO': 'Projektsteckbrief',
- 'HON': 'Ehrenamtsbescheinigung, Akkreditierung oder Redaktionsbestätigung',
- 'TRAV': 'Reisekostenerstattung'}
+INTERN_CHOICES = {
+ 'PRO': 'Projektsteckbrief',
+ 'HON': 'Ehrenamtsbescheinigung, Akkreditierung oder Redaktionsbestätigung',
+ 'TRAV': 'Reisekostenerstattung',
+}
+
class InternForm(FdbForm):
- choice = ChoiceField(choices = INTERN_CHOICES.items(), widget=RadioSelect,
- label = 'Was möchtest Du eingeben?')
+ choice = ChoiceField(choices=INTERN_CHOICES.items(), widget=RadioSelect,
+ label='Was möchtest Du eingeben?')
class Meta:
model = ConcreteVolunteer
exclude = ('granted', 'granted_date', 'survey_mail_send', 'survey_mail_date', 'mail_state')
-HOTEL_CHOICES = {'TRUE': mark_safe('Hotelzimmer benötigt'),
- 'FALSE': mark_safe('Kein Hotelzimmer benötigt')
- }
-
-
class BaseApplicationForm(FdbForm):
"""
Base form for all external applications.
@@ -147,9 +145,17 @@ class BaseApplicationForm(FdbForm):
settings.DATAPROTECTION, settings.FOERDERRICHTLINIEN))
+HOTEL_CHOICES = {
+ 'TRUE': mark_safe('Hotelzimmer benötigt'),
+ 'FALSE': mark_safe('Kein Hotelzimmer benötigt'),
+}
+
+
class TravelForm(BaseApplicationForm, CommonOrderMixin):
# TODO: add some javascript to show/hide other-field
+ hotel = ChoiceField(label='Hotelzimmer benötigt:', choices=HOTEL_CHOICES.items(), widget=RadioSelect())
+
# this is the code, to change required to false if needed
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
@@ -162,16 +168,18 @@ class TravelForm(BaseApplicationForm, CommonOrderMixin):
class Meta:
model = Travel
- exclude = ('granted', 'granted_date', 'survey_mail_send', 'realname', 'email', 'survey_mail_date', 'project', 'request_url', 'payed_for_hotel_by', 'payed_for_travel_by', 'intern_notes', 'mail_state' )
- widgets = {'checkin': AdminDateWidget(),
- 'checkout': AdminDateWidget(),}
fields = ['project_name', 'transport', 'travelcost', 'checkin', 'checkout', 'hotel', 'notes']
- hotel = ChoiceField(label='Hotelzimmer benötigt:', choices=HOTEL_CHOICES.items(), widget=RadioSelect())
+ exclude = ('granted', 'granted_date', 'survey_mail_send', 'realname', 'email', 'survey_mail_date', 'project',
+ 'request_url', 'payed_for_hotel_by', 'payed_for_travel_by', 'intern_notes', 'mail_state')
+ widgets = {
+ 'checkin': AdminDateWidget,
+ 'checkout': AdminDateWidget,
+ }
class Media:
js = ('dropdown/js/otrs_link.js',)
css = {
- 'all': ('css/dateFieldNoNowShortcutInTravels.css',)
+ 'all': ('css/dateFieldNoNowShortcutInTravels.css',)
}
@@ -208,6 +216,7 @@ class HonoraryCertificateForm(FdbForm):
model = HonoraryCertificate
fields = ['request_url', 'project']
exclude = ['intern_notes']
+
class Media:
js = ('dropdown/js/otrs_link.js',)
@@ -242,20 +251,23 @@ class LiteratureForm(BaseApplicationForm, CommonOrderMixin):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['selfbuy_give_data'].required = True
+
class Meta:
model = Literature
fields = ['cost', 'info', 'source', 'notes', 'selfbuy', 'selfbuy_data', 'selfbuy_give_data', 'terms_accepted']
exclude = ['intern_notes', 'survey_mail_send', 'mail_state']
+
class Media:
js = ('dropdown/js/literature.js',)
-ADULT_CHOICES = {'TRUE': mark_safe('Ich bin volljährig.'),
- 'FALSE': mark_safe('Ich bin noch nicht volljährig.')
- }
+
+ADULT_CHOICES = {
+ 'TRUE': mark_safe('Ich bin volljährig.'),
+ 'FALSE': mark_safe('Ich bin noch nicht volljährig.'),
+}
class EmailForm(BaseApplicationForm, CommonOrderMixin):
-
termstoaccept = settings.NUTZUNGSBEDINGUNGEN_EMAIL_SERVICE
# this is the code, to change required to false if needed
@@ -266,20 +278,19 @@ class EmailForm(BaseApplicationForm, CommonOrderMixin):
adult = ChoiceField(label='Volljährigkeit', choices=ADULT_CHOICES.items(), widget=RadioSelect())
-
-
# TODO: add some javascript to show/hide other-field
class Meta:
model = Email
fields = ['domain', 'address', 'other', 'adult', 'terms_accepted']
exclude = ['intern_notes', 'survey_mail_send', 'mail_state']
+
class Media:
js = ('dropdown/js/mail.js',)
-
class BusinessCardForm(BaseApplicationForm, CommonOrderMixin):
termstoaccept = settings.NUTZUNGSBEDINGUNGEN_VISITENKARTEN
+
# this is the code, to change required to false if needed
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
@@ -290,16 +301,18 @@ class BusinessCardForm(BaseApplicationForm, CommonOrderMixin):
model = BusinessCard
exclude = ['intern_notes', 'survey_mail_send', 'mail_state']
fields = ['project', 'data', 'variant', 'url_of_pic', 'send_data_to_print', 'sent_to', 'terms_accepted']
+
class Media:
js = ('dropdown/js/businessCard.js',)
class ListForm(BaseApplicationForm, CommonOrderMixin):
termstoaccept = settings.NUTZUNGSBEDINGUNGEN_MAILINGLISTEN
+
class Meta:
model = List
fields = ['domain', 'address', 'terms_accepted']
- exclude = ['intern_notes', 'survey_mail_send','mail_state']
+ exclude = ['intern_notes', 'survey_mail_send', 'mail_state']
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
diff --git a/input/models.py b/input/models.py
index 9f5c89a..2b415c6 100755
--- a/input/models.py
+++ b/input/models.py
@@ -1,15 +1,20 @@
from datetime import date
+from django.contrib.contenttypes.models import ContentType
+from django.core.exceptions import ValidationError
+from django.core.validators import MaxValueValidator
from django.db import models
+from django.db.models.signals import pre_save
+from django.dispatch import receiver
from django.utils.html import format_html
from django.utils.safestring import mark_safe
-from django.core.exceptions import ValidationError
-from django.core.validators import MinValueValidator, MaxValueValidator
-EMAIL_STATES = {'NONE': 'noch keine Mail versendet',
- 'INF': 'die Benachrichtigung zur Projektabschlussmail wurde versendet',
- 'CLOSE': 'die Projektabschlussmail wurde versendet',
- 'END': 'alle automatischen Mails, auch surveyMail, wurden versendet'}
+EMAIL_STATES = {
+ 'NONE': 'noch keine Mail versendet',
+ 'INF': 'die Benachrichtigung zur Projektabschlussmail wurde versendet',
+ 'CLOSE': 'die Projektabschlussmail wurde versendet',
+ 'END': 'alle automatischen Mails, auch surveyMail, wurden versendet',
+}
class TermsConsentMixin(models.Model):
@@ -35,7 +40,6 @@ class Volunteer(models.Model):
mail_state = models.CharField(max_length=6, choices=EMAIL_STATES.items(), default='NONE')
survey_mail_send = models.BooleanField(default=False, verbose_name='Keine Umfragemail schicken')
-
@classmethod
def set_granted(cl, key, b):
obj = cl.objects.get(pk=key)
@@ -47,7 +51,6 @@ class Volunteer(models.Model):
abstract = True
-
class Extern(Volunteer):
''' abstract basis class for all data entered by extern volunteers '''
@@ -57,7 +60,7 @@ class Extern(Volunteer):
# the following Fields are not supposed to be edited by users
service_id = models.CharField(max_length=15, null=True, blank=True)
- def save(self,*args,**kwargs):
+ def save(self, *args, **kwargs):
# we don't call save with args/kwargs to avoid UNIQUE CONSTRAINT errors
# but maybe there is a better solution?
super().save()
@@ -67,18 +70,21 @@ class Extern(Volunteer):
class Meta:
abstract = True
+
class ConcreteExtern(Extern):
''' needed because we can't initiate abstract base classes in the view'''
pass
+
class Account(models.Model):
- code = models.CharField('Kostenstelle', max_length=5, default='DEF',
- null=False, primary_key = True)
+ code = models.CharField('Kostenstelle', max_length=5, default='DEF', null=False, primary_key=True)
description = models.CharField('Beschreibung', max_length=60, default='NO DESCRIPTION')
intern_notes = models.TextField(max_length=1000, blank=True, verbose_name='interne Anmerkungen')
+
def __str__(self):
return f'{self.code} {self.description}'
+
class Project(Volunteer):
end_mail_send = models.BooleanField(default=False, verbose_name='Keine Projektabschlussmail schicken')
name = models.CharField(max_length=200, verbose_name='Name des Projekts')
@@ -97,12 +103,11 @@ class Project(Volunteer):
insurance_technic = models.BooleanField(default=False, verbose_name='Technikversicherung Ausland')
support = models.CharField(max_length=300, blank=True, null=True, verbose_name='Betreuungsperson und Vertretung')
cost = models.IntegerField(blank=True, null=True, verbose_name='Kosten')
- account = models.ForeignKey('Account', on_delete=models.CASCADE, null=True, to_field='code', db_constraint = False)
- granted_from = models.CharField(max_length=100,null=True,verbose_name='Bewilligt von')
- notes = models.TextField(max_length=1000,null=True,blank=True,verbose_name='Anmerkungen')
+ account = models.ForeignKey('Account', on_delete=models.CASCADE, null=True, to_field='code', db_constraint=False)
+ granted_from = models.CharField(max_length=100, null=True, verbose_name='Bewilligt von')
+ notes = models.TextField(max_length=1000, null=True, blank=True, verbose_name='Anmerkungen')
intern_notes = models.TextField(max_length=1000, blank=True, verbose_name='interne Anmerkungen')
-
# the following Fields are not supposed to be edited by users
pid = models.CharField(max_length=15, null=True, blank=True)
status = models.CharField(max_length=3,choices=(('RUN', 'läuft'),('END','beendet'),('NOT','nicht stattgefunden')),default='RUN')
@@ -110,66 +115,59 @@ class Project(Volunteer):
project_of_year = models.IntegerField(default=0)
end_quartal = models.CharField(max_length=15, null=True, blank=True, verbose_name='Quartal Projekt Ende')
+ def save(self, *args, **kwargs):
- def save(self,*args,**kwargs):
-
- generate_finance_id=False
+ generate_finance_id = False
'''we generate the autogenerated fields here'''
# we don't call save with args/kwargs to avoid UNIQUE CONSTRAINT errors
# but maybe there is a better solution?
if not self.pk:
- print ('NO PK THERE');
- generate_finance_id=True
+ print('NO PK THERE')
+ generate_finance_id = True
super().save()
else:
orig = type(self).objects.get(pk=self.pk) # Originaldaten aus der DB abrufen
if orig.start.year != self.start.year:
- generate_finance_id=True
+ generate_finance_id = True
if orig.account.code != self.account.code:
if str(self.account.code) == '21111':
- generate_finance_id=True
+ generate_finance_id = True
else:
self.finance_id = str(self.account.code)
-
-
-
-
if generate_finance_id:
- print ('MUST GENERATE FINANCE ID')
+ print('MUST GENERATE FINANCE ID')
year = self.start.year
projects = Project.objects.filter(start__year=year)
if not projects:
self.project_of_year = 1
- #self.pid = str(self.start.year) + '-' + str(self.account.code) + str(self.project_of_year).zfill(3)
+ # self.pid = str(self.start.year) + '-' + str(self.account.code) + str(self.project_of_year).zfill(3)
else:
# get the project of year number of latest entry
projects = projects.order_by('-project_of_year')[0]
# add one to value of latest entry
self.project_of_year = int(projects.project_of_year) + 1
-# self.pid = str(self.start.year) + '-' + str(self.account.code) + str(self.project_of_year).zfill(3)
-
+ # self.pid = str(self.start.year) + '-' + str(self.account.code) + str(self.project_of_year).zfill(3)
if str(self.account.code) == '21111':
self.finance_id = str(self.account.code) + '-' + str(self.project_of_year).zfill(3)
else:
self.finance_id = str(self.account.code)
-# print (('Current PID',self.pid))
+ # print (('Current PID',self.pid))
if not self.pid:
self.pid = str(self.account.code) + str(self.pk).zfill(8)
# self.pid = str(self.account.code) + str(self.pk).zfill(3)
- print (('Hallo Leute! Ich save jetzt mal MIT PID DANN!!!',self.pid))
+ print(('Hallo Leute! Ich save jetzt mal MIT PID DANN!!!', self.pid))
if self.end:
self.end_quartal = f'Q{self.end.month // 4 + 1}'
super().save()
-
def __str__(self):
return f'{self.pid} {self.name}'
@@ -178,33 +176,41 @@ class Intern(Volunteer):
'''abstract base class for data entry from /intern (except Project)'''
request_url = models.URLField(max_length=2000, verbose_name='Antrag (URL)')
intern_notes = models.TextField(max_length=1000, blank=True, verbose_name='interne Anmerkungen')
+
class Meta:
abstract = True
+
class ConcreteVolunteer(Volunteer):
''' needed because we can't initiate abstract base classes in the view'''
pass
+
class HonoraryCertificate(Intern):
''' this class is also used for accreditations '''
project = models.ForeignKey(Project, null=True, blank=True, on_delete=models.SET_NULL)
+
def __str__(self):
return 'Certificate for ' + self.realname
-TRANSPORT_CHOICES = {'BAHN': 'Bahn',
- 'NONE': 'Keine Fahrtkosten',
- 'OTHER': 'Sonstiges (mit Begründung)'}
+TRANSPORT_CHOICES = {
+ 'BAHN': 'Bahn',
+ 'NONE': 'Keine Fahrtkosten',
+ 'OTHER': 'Sonstiges (mit Begründung)',
+}
-PAYEDBY_CHOICES = {'WMDE': 'WMDE',
- 'REQU': 'Antragstellender Mensch'}
+PAYEDBY_CHOICES = {
+ 'WMDE': 'WMDE',
+ 'REQU': 'Antragstellender Mensch',
+}
-HOTEL_CHOICES = {'TRUE': mark_safe('Hotelzimmer benötigt'),
- 'FALSE': mark_safe('Kein Hotelzimmer benötigt')
- }
+HOTEL_CHOICES = {
+ 'TRUE': mark_safe('Hotelzimmer benötigt'),
+ 'FALSE': mark_safe('Kein Hotelzimmer benötigt'),
+}
-from django.contrib.contenttypes.models import ContentType
class Travel(Extern):
# 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
@@ -225,27 +231,15 @@ class Travel(Extern):
# use content type model to get the end date for the project foreign key
project_end_quartal = models.CharField(max_length=15, null=True, blank=True, verbose_name='Quartal Projekt Ende')
-from django.db.models.signals import pre_save
-from django.dispatch import receiver
@receiver(pre_save, sender=Travel, dispatch_uid='get_project_end')
-def getProjectEnd(sender, instance, **kwargs):
- #instance.project_end = instance.project.end
-
+def get_project_end(sender, instance, **kwargs):
if instance.project:
instance.project_end = instance.project.end
instance.project_end_quartal = instance.project.end_quartal
-# using pre save instead
-# def save(self,*args,**kwargs):
-# '''we generate the autogenerated fields here'''
-# # we don't call save with args/kwargs to avoid UNIQUE CONSTRAINT errors
-# # but maybe there is a better solution?
-# intern_notes
-# project_end = self.checkout
-# super(Travel, self).save(*args,**kwargs)
-#abstract base class for Library and IFG
+# abstract base class for Library and IFG
class Grant(Extern):
cost = models.CharField(max_length=10, verbose_name='Kosten',
help_text='Bitte gib die ungefähr zu erwartenden Kosten in Euro an.')
@@ -291,6 +285,7 @@ TYPE_CHOICES = {
LIBRARY_TYPES = TYPE_BIB, TYPE_ELIT, TYPE_SOFT
LIBRARY_TYPE_CHOICES = [(choice, TYPE_CHOICES[choice]) for choice in LIBRARY_TYPES]
+
# same model is used for Library, ELitStip and Software!
class Library(Grant):
TYPE = TYPE_BIB
@@ -332,9 +327,10 @@ class Software(Library):
proxy = True
-SELFBUY_CHOICES = {'TRUE': mark_safe('Ich möchte das Werk selbst kaufen und per Kostenerstattung bei Wikimedia Deutschland abrechnen.'),
- 'FALSE': mark_safe('Ich möchte, dass Wikimedia Deutschland das Werk für mich kauft'),
- }
+SELFBUY_CHOICES = {
+ 'TRUE': mark_safe('Ich möchte das Werk selbst kaufen und per Kostenerstattung bei Wikimedia Deutschland abrechnen.'),
+ 'FALSE': mark_safe('Ich möchte, dass Wikimedia Deutschland das Werk für mich kauft'),
+}
class Literature(TermsConsentMixin, Grant):
@@ -351,19 +347,24 @@ class Literature(TermsConsentMixin, Grant):
Telefonnummer, E-Mail-Adresse usw.). Trenne die einzelnen Angaben durch Zeilenumbrüche.'))
intern_notes = models.TextField(max_length=1000, blank=True, verbose_name='interne Anmerkungen')
+
class IFG(Grant):
url = models.URLField(max_length=2000, verbose_name='URL',
- help_text='Bitte gib den Link zu deiner Anfrage bei Frag den Staat an.')
+ help_text='Bitte gib den Link zu deiner Anfrage bei Frag den Staat an.')
intern_notes = models.TextField(max_length=1000, blank=True, verbose_name='interne Anmerkungen')
def __str__(self):
return 'IFG-Anfrage von ' + self.realname
-DOMAIN_CHOICES = {'PEDIA': '@wikipedia.de',
- 'BOOKS': '@wikibooks.de',
- 'QUOTE': '@wikiquote.de',
- 'SOURCE': '@wikisource.de',
- 'VERSITY': '@wikiversity.de',}
+
+DOMAIN_CHOICES = {
+ 'PEDIA': '@wikipedia.de',
+ 'BOOKS': '@wikibooks.de',
+ 'QUOTE': '@wikiquote.de',
+ 'SOURCE': '@wikisource.de',
+ 'VERSITY': '@wikiversity.de',
+}
+
class Domain(Extern):
domain = models.CharField(max_length=10,
@@ -373,42 +374,54 @@ class Domain(Extern):
class Meta:
abstract = True
-MAIL_CHOICES = {'REALNAME': 'Vorname.Nachname',
- 'USERNAME': 'Username',
- 'OTHER': 'Sonstiges:'}
-ADULT_CHOICES = {'TRUE': mark_safe('Ich bin volljährig.'),
- 'FALSE': mark_safe('Ich bin noch nicht volljährig.')
- }
+MAIL_CHOICES = {
+ 'REALNAME': 'Vorname.Nachname',
+ 'USERNAME': 'Username',
+ 'OTHER': 'Sonstiges:',
+}
+
+ADULT_CHOICES = {
+ 'TRUE': mark_safe('Ich bin volljährig.'),
+ 'FALSE': mark_safe('Ich bin noch nicht volljährig.'),
+}
+
class Email(TermsConsentMixin, Domain):
address = models.CharField(max_length=50,
- choices=MAIL_CHOICES.items(),
- default='USERNAME', verbose_name='Adressbestandteil',
- help_text=mark_safe('Bitte gib hier den gewünschten Adressbestandteil an,
der sich vor der Domain befinden soll.'))
+ choices=MAIL_CHOICES.items(),
+ default='USERNAME', verbose_name='Adressbestandteil',
+ help_text=mark_safe('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='FALSE')
+ 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='FALSE')
intern_notes = models.TextField(max_length=1000, blank=True, verbose_name='interne Anmerkungen')
+
class List(TermsConsentMixin, Domain):
address = models.CharField(max_length=50, default='NO_ADDRESS',
verbose_name='Adressbestandteil für Projektmailingliste',
help_text=mark_safe('Bitte gib hier den gewünschten Adressbestandteil an,
der sich vor der Domain befinden soll.'))
intern_notes = models.TextField(max_length=1000, blank=True, verbose_name='interne Anmerkungen')
-PROJECT_CHOICE = {'PEDIA': 'Wikipedia',
- 'SOURCE': 'Wikisource',
- 'BOOKS': 'Wikibooks',
- 'QUOTE': 'Wikiquote',
- 'VERSITY': 'Wikiversity',
- 'VOYAGE': 'Wikivoyage',
- 'DATA': 'Wikidata',
- 'NEWS': 'Wikinews',
- 'COMMONS': 'Wikimedia Commons'}
-BC_VARIANT = {'PIC': 'mit Bild',
- 'NOPIC': 'ohne Bild'}
+PROJECT_CHOICE = {
+ 'PEDIA': 'Wikipedia',
+ 'SOURCE': 'Wikisource',
+ 'BOOKS': 'Wikibooks',
+ 'QUOTE': 'Wikiquote',
+ 'VERSITY': 'Wikiversity',
+ 'VOYAGE': 'Wikivoyage',
+ 'DATA': 'Wikidata',
+ 'NEWS': 'Wikinews',
+ 'COMMONS': 'Wikimedia Commons',
+}
+
+BC_VARIANT = {
+ 'PIC': 'mit Bild',
+ 'NOPIC': 'ohne Bild',
+}
+
class BusinessCard(TermsConsentMixin, Extern):
project = models.CharField(max_length=20, choices=PROJECT_CHOICE.items(),
@@ -426,7 +439,7 @@ class BusinessCard(TermsConsentMixin, Extern):
variant = models.CharField(max_length=5, choices=BC_VARIANT.items(),
default='NOPIC', verbose_name='Variante',
help_text=mark_safe('so sehen die Varianten aus: \
- mit Bild ohne Bild' ))
+ mit Bild ohne Bild'))
url_of_pic = models.CharField(max_length=200, verbose_name='Url des Bildes', default='', help_text='Bitte gib die Wikimedia-Commons-URL des Bildes an.')
@@ -467,6 +480,7 @@ validate_cost = MaxValueValidator(
),
)
+
# Application for project funding < 1000 EUR
class ProjectRequest(Volunteer):
name = models.CharField('Name des Projekts', max_length=200)